CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

const pointer not working

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
DireSpume



Joined: 07 Jan 2013
Posts: 31

View user's profile Send private message

const pointer not working
PostPosted: Wed Feb 06, 2013 7:59 pm     Reply with quote

I can apparently pass a rom uint32 array (as a rom pointer) to a function and index into it correctly. But if I pass a rom char array, it will not index correctly. Can anyone explain what is going on here? I'm using PCH 4.140.
The code below gives the following output (NUL is 0, i.e. a bogus character):
RomChar, RomChar
NUL, h, 50


Code:

typedef unsigned int32 uint32;

rom char str2[] = "RomChar";
rom uint32 Data[3] = { 40, 50, 60 };

void PrintNTime(rom char* str, rom uint32* ptr)
{
   printf(str);
   printf(", %s\r\n", str);
   printf("%c, %c, %lu\r\n", str[4], str2[4], ptr[1]);
}

void main()
{
   while(1)
   {
      delay_ms(1000);
      PrintNTime(str2, Data);
   }
}
[/code]
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Thu Feb 07, 2013 2:39 am     Reply with quote

1) The "rom" qualifier has no effect in CCS C.

2) The manual includes this entry:

"How can a constant data table be placed in ROM?

--------------------------------------------------------------------------------

The compiler has support for placing any data structure into the device ROM as a constant read-only element. Since the ROM and RAM data paths are separate in the PICĀ® , there are restrictions on how the data is accessed. For example, to place a 10 element BYTE array in ROM use:

BYTE CONST TABLE [10]= {9,8,7,6,5,4,3,2,1,0};

and to access the table use:

x = TABLE [i];

OR

x = TABLE [5];

BUT NOT

ptr = &TABLE [i];

In this case, a pointer to the table cannot be constructed.

Similar constructs using CONST may be used with any data type including structures, longs and floats.

Note that in the implementation of the above table, a function call is made when a table is accessed with a subscript that cannot be evaluated at compile time."

The problem here being that the string constant is treated as a constant string, not as a variable char array that's had a copy of a constant string written to it. To get the effect you probably are looking for you need to
a) define a variable char array big enough and then explicitly copy the constant string to it using strcpy or similar or b) include the directive #device PASS STRINGS=IN_RAM which according to the manual is "a new way to pass constant strings to a function by first copying the string to RAM and then passing a pointer to RAM to the function." In other words doing the same thing as a) except the compiler does the copying for you.

RF Developer
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Thu Feb 07, 2013 12:36 pm     Reply with quote

Er, No.....

rom does have a meaning in CCS.
rom as a construct, is an alternative to const, _which allows pointers to be constructed_.

Look in the readme.txt with the compiler.

ptr=&table[i]. _can_ be constructed with a rom array.

However several key things apply:

The target has to 'know' the target is in ROM.

The format string in printf, _cannot be passed_. The format is parsed at compile time, so this won't work with either ROM or RAM arrays.
%s, expects a RAM char array, so again won't work.
You can produce the same effect, by accessing the characters yourself, just don't use printf. Avoids the need for a RAM buffer.

Best Wishes
DireSpume



Joined: 07 Jan 2013
Posts: 31

View user's profile Send private message

PostPosted: Thu Feb 07, 2013 2:23 pm     Reply with quote

Thanks Ttelmah, I actually learned that the rom qualifier exists from reading one of your responses to another thread. I'm using #device CONST=READ_ONLY because it seems silly to have two keywords that do the exact same thing (more or less), and changing the meaning of an established C keyword is very confusing and generally stupid IMO. Interestingly, I can find no mention of the rom qualifer anywhere in the manual (but it is in the readme.txt).

And I did discover the quirk about passing strings to printf() in the form of a variable doesn't work, and thanks for the explanation on that. I find it interesting that printf() is able to accept RAM pointers, ROM pointers, and string literals with no problem, but if you make your own function that accepts a char* you have to specify rom or ram (not-rom) and can then only accept one or the other. I really wish this stuff was explained in the manual.

Okay, onto the unresolved issue at hand, which is that the code in the OP works for uint32, but not for char. In other words, str2[4] and ptr[1] both work properly, but str[4] does not (returns zero instead of 'h', which I'm assuming is because it's reading the wrong memory space). I've tried it with #device PASS_STRINGS=IN_RAM and without, but no difference.
DireSpume



Joined: 07 Jan 2013
Posts: 31

View user's profile Send private message

PostPosted: Fri Feb 08, 2013 11:53 am     Reply with quote

Okay, I figured it out. There is a bug in printf() when using %c with romstr[] when romstr is a rom pointer. The printf in the following code works fine for every single argument except for the first one, where it prints a NUL character instead of 'k'. Using %u or assigning to a char variable first both work correctly, as do ram pointers with %c.
The result of the following code is "[NUL], k, 107, k, 20, d/r/n".
Code:

typedef unsigned int16 uint16;

rom uint16 data[] = { 10, 20, 30 };
char str1[] = "Spiders";
rom char str2[] = "Snakes";

void PrintStuff(rom char* romstr, char* ramstr, rom uint16* ptr)
{
   char Chr = romstr[3];
   printf("%c, %c, %u, %c, %lu, %c\r\n", romstr[3], Chr, romstr[3], str2[3], ptr[1], ramstr[3]);
}

void main()
{
   while(1)
   {
      delay_ms(1000);
      PrintStuff(str2, str1, data);
   }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Fri Feb 08, 2013 12:12 pm     Reply with quote

I have a 'sneaky suspicion' you will find it works OK with a slightly older compiler. I've had quite a few problems with 4.140 having oddities. 4.137, has proved much more reliable in general for me....

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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