|
|
View previous topic :: View next topic |
Author |
Message |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 04, 2008 11:37 am |
|
|
CCS doesn't allow pointers to constants. If your code is compiled
as shown in the test program below, you will get these error messages:
Quote: |
*** Error 90 Line 14(22,23): Attempt to create a pointer to a constant
*** Error 90 Line 15(23,24): Attempt to create a pointer to a constant
*** Error 90 Line 16(24,25): Attempt to create a pointer to a constant |
Test program:
Code: |
#include <18F452.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include "flex_lcd.c"
#include <string.h>
//====================================
void main()
{
lcd_init();
lcd_putc(strcmp("tes","test")+0x35);
lcd_putc(strcmp("test","test")+0x35);
lcd_putc(strcmp("teste","test")+0x35);
while(1);
} |
However, if you add the statement shown in bold, then it will compile:
Quote: | #include <18F452.h>
#device PASS_STRINGS = IN_RAM
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
|
The #device statement forces the compiler to copy the constant strings
into an internal RAM buffer. So when the strings are passed to strcmp(),
they are now in RAM, not ROM. This effectively does the same thing
as my example code, though it may be better because it does the
copying for you, automatically. You don't have to think about it.
Here's the .LST file. You can see that it's copying the constant data to
a RAM buffer called "STRPARAM".
Code: |
........ lcd_putc(strcmp("tes","test")+0x35);
0212: MOVLW 74
0214: MOVWF @STRPARAM
0216: MOVLW 65
0218: MOVWF @STRPARAM+1
021A: MOVLW 73
021C: MOVWF @STRPARAM+2
021E: CLRF @STRPARAM+3
0220: MOVLW 74
0222: MOVWF @STRPARAM+4
0224: MOVLW 65
0226: MOVWF @STRPARAM+5
0228: MOVLW 73
022A: MOVWF @STRPARAM+6
022C: MOVLW 74
022E: MOVWF @STRPARAM+7
0230: CLRF @STRPARAM+8
0232: CLRF s1+1
0234: MOVLW @STRPARAM
0236: MOVWF s1
0238: CLRF s2+1
023A: MOVLW @STRPARAM+4
023C: MOVWF s2
023E: RCALL 0114 // call strcmp()
0240: MOVLW 35
0242: ADDWF @01,W
0244: MOVWF @@17
0246: MOVWF c
0248: RCALL 01AC // call lcd_putc()
|
|
|
|
adesport
Joined: 03 Apr 2008 Posts: 18 Location: France
|
|
Posted: Fri Apr 04, 2008 11:41 am |
|
|
Thank, that exactly what I was waiting for... |
|
|
Ralf2
Joined: 05 Feb 2009 Posts: 10
|
|
Posted: Mon Jul 14, 2014 11:09 am |
|
|
Why this coded not work???
Code: | /*
A more complex example that creates an array of pointers to constant strings:
*/
const char *strings[] =
{
"HELLO",
"WORLD",
"CONST",
"STRINGS"
};
/*
Access the above const pointers
*/
const char *ptr; // ERROR?
while (i = 0; i < (sizeof(strings) / sizeof(const char *)); i++)
{
ptr = strings[i];
printf("%s", ptr);
} |
The program is page official ccs compiler
https://www.ccsinfo.com/content.php?page=compiler-features
compiler 5.026
Any idea how to fix it?
Thanks |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Mon Jul 14, 2014 11:51 am |
|
|
A search here will find lots of answers.
Obvious first problem you have is trying to make the pointer a constant.
Big problem is that CCS has three/four different ways of handling things, and the behaviour of some commands changes according to the configuration:
There are two different ways of declaring constants.
The first uses the 'const' keyword.
The second uses the 'rom' keyword.
With the 'rom' keyword used for the constant, you can declare a pointer to an element in rom, using
rom char *ptr;
The compiler understands this is a pointer to ROM, rather than being stored in ROM itself.
Then as PCM_programmer points out, you can add the declaration:
PASS_STRINGS=IN_RAM
With this the ROM constants are accessed as if they are in RAM, and the pointer must be to the RAM, not the ROM. Only works for strings though, not general data.
Then it gets more complex, since the declaration 'CONST=READ_ONLY', makes all constants copy to RAM automatically (uses a lot of space...), but be 'read only'. This is the ANSi form.
Then there is another problem. You are trying to declare the constant pointers to constant strings at compile time. CCS doesn't 'know' where constants are held, till after they are all placed.
Your syntax is wrong in the statements inside the while loop declaration. Use for, or rethink your syntax. The calculation also won't work. |
|
|
Ralf2
Joined: 05 Feb 2009 Posts: 10
|
|
Posted: Mon Jul 14, 2014 2:24 pm |
|
|
Hi Ttelmah
So I can not store data type int, float in rom? and create a pointer to these?
only strings |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Mon Jul 14, 2014 2:42 pm |
|
|
No.
Using the 'rom' keyword, you can create pointers to anything in rom. But they have to be rom pointers, and need to be initialised in the code, not at compile time.
So:
Code: |
rom int16 vals[] = {1,2,3,4,5,6,7,8,9};
rom * int16 fred;
fred = &vals[5];
//initialises a rom pointer to the value 6.
|
The core 'reason' is that the PIC has twin memory spaces, not a single linear space (Harvard architecture). It has been discussed here many times. |
|
|
Ralf2
Joined: 05 Feb 2009 Posts: 10
|
|
Posted: Mon Jul 14, 2014 3:45 pm |
|
|
Code: | rom int16 vals[] = {1,2,3,4,5,6,7,8,9};
rom * int16 fred;
fred = &vals[5];
//initialises a rom pointer to the value 6.
|
not work the coded? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 14, 2014 4:08 pm |
|
|
The rom pointer line had a slightly incorrect syntax. I've corrected it and
posted the test program below. IF you run it in MPLAB simulator, you
will get this output, which is correct:
Test program:
Code: | #include <18F4520.h>
#fuses INTRC_IO, BROWNOUT, PUT, NOWDT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
//===================================
void main()
{
rom int16 vals[] = {1,2,3,4,5,6,7,8,9};
rom int16 *fred;
fred = &vals[5]; //initialises a rom pointer to the value 6.
printf("%ld \r", *fred);
while(1);
} |
|
|
|
Ralf2
Joined: 05 Feb 2009 Posts: 10
|
|
Posted: Mon Jul 14, 2014 4:29 pm |
|
|
Thanks PCM
And as I walk the array with pointer?
Because these not work
Code: | for(int i=0; i<10; i++)
printf("%ld \r", *(fred+i));
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 14, 2014 7:07 pm |
|
|
There appears to be a problem in which CCS doesn't like pointer
arithmetic with rom pointers. There might be some trick to make it work.
Instead, I want to ask, what do you really want to do ? Forget rom
pointers for the moment. Just tell me what you want to do. There
will probably be some easier way to do it, if I know what you want. |
|
|
Ralf2
Joined: 05 Feb 2009 Posts: 10
|
|
Posted: Mon Jul 14, 2014 7:33 pm |
|
|
Many thanks for helping PCM Programmer
I want to create a table of integers and character string in rom to access them from the main().
Regards |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 14, 2014 9:24 pm |
|
|
The test program below displays the following output in MPLAB Simulator
for compiler vs. 5.026:
Quote: |
HELLO
WORLD
CONST
STRINGS
|
Test program:
Code: |
#include <18F4520.h>
#fuses INTRC_IO, BROWNOUT, PUT, NOWDT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
#define NUM_STRINGS 4
const char strings[NUM_STRINGS][*] =
{
"HELLO",
"WORLD",
"CONST",
"STRINGS"
};
//===================================
void main()
{
int8 i;
for(i=0; i < NUM_STRINGS; i++)
{
printf("%s \r", strings[i]);
}
while(1);
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Mon Jul 14, 2014 11:46 pm |
|
|
Apologies for the earlier syntax error.
As a comment, treat the pointer as an array.
If you declare the pointer as normal, but then use:
fred[index++]
rather than updating fred itself, it will access the elements.
Why, I don't know, but in CCS the equivalence between pointers and an array, does not work, when dealing with ROM variables.
If you look at the code, it is more difficult to access the ROM (remember that this is not directly accessible using an instruction like RAM, there has to be a 'lookup', and transfer of the data to RAM), so some 'limitations' are not surprising.... |
|
|
Ralf2
Joined: 05 Feb 2009 Posts: 10
|
|
Posted: Tue Jul 15, 2014 12:02 am |
|
|
Thanks PCM Programmer and Ttelmah for help me.
If, the use of pointers to data stored in rom is confused and unclear with ccs
So ask the question in forum |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Tue Jul 15, 2014 12:30 am |
|
|
Very true.
They have added extra abilities (and in some cases unfortunately 'lost' abilities), with the documentation 'poor'.
The one thing that was a 'cracker', which worked a while ago, then became faulty (haven't yet checked it in 026), was 'addressmod'. This allowed you to use variables in any memory (EEPROM, FLASH, or the internal ROM etc.), and provided you remembered the memories limitations on 'write life', use them as if they were in RAM. Allowed you to have a 'near ROM' type of data which was changed infrequently, and was retained until changed.
CCS have improved a little recently on the overall reliability of the compilers, with fewer 'new bugs' appearing with each release, but still does require you to do some 'juggling' in how you handle things if you are not to generate problems. Pointers give problems even in RAM, if complex types are used (structures inside structures, and go a little 'deep' for example), and declaring an array of pointers, with variable length strings, requires the * syntax in the length parameter, in RAM, and has sometimes been unreliable. KISS, is a good way to work in CCS, even if other designs may look much more elegant, they are more likely to lead to problems.... |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|