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

Point to const struct array

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



Joined: 27 Aug 2011
Posts: 22
Location: Baltimore, MD

View user's profile Send private message

Point to const struct array
PostPosted: Mon Oct 31, 2011 7:23 am     Reply with quote

I created a typdef struct for a calibration table.
Code:

typedef struct {
   signed int16 ipVal; // filtered ADC value
   float32 opVal;      // corresponding real value as floating point
   } calRecord;

I then created a const array of calibration records...
Code:

const calRecord calDT670[144] = {
{181,   5000},            // count : temperature x 10 (k)
{225,   4900.116713},
{270,   4801.94981}....

If I address the table directly I can read the records without issue. The problem is that I need to create a number of these tables and access them with pointers. I can't seem to figure out how to get a pointer to point to a const struct array. Any help would be appreciated.
Ttelmah



Joined: 11 Mar 2010
Posts: 19550

View user's profile Send private message

PostPosted: Mon Oct 31, 2011 8:25 am     Reply with quote

Use rom, rather than const. (rom, not #ROM).

It's all down to the memory structure of the PIC, and history.
The PIC, has separate memory spaces for the program and code. Not the single linear memory space of chips like the 808x, etc..
Historically older PICs, could not directly read their ROM.

So when CCS first implemented const data tables, they 'cheated', and simulated the effect, using the method that worked within the PIC limitations, and generated a program that returned the bytes required. As such though it meant that a pointer could not be constructed to these.
To help avoid this being too much of a limitation, a 'shortcut' was added to the language, where using the construct (say):

putc("fred");

resulted in the putc function being called four times, with each character in turn.

Latter when running in ANSI emulation mode, the meaning of 'const' was changed to be compliant with this, being a RAM based table, that is 'read only'. To these a pointer can be constructed, but it means that the table has to be copied into RAM at runtime. Costly on RAM space. This is what happens if you switch the compiler to ANSI mode.

However CCS also decided that on the latter chips that did allow code to access the ROM, they would implement a form that did support pointers, and this is given by using the rom keyword, rather than const keyword. It makes things slightly bulkier, since extra code has to be added to support this, but does generally work.

So you have:

CCS mode
const data tables - small but no pointer support.
rom data tables - code larger, but supports pointers.

ANSI mode
const data tables - copied to RAM, and support pointers, but uses a lot of RAM
rom data tables - stored in ROM.

You can also switch the mode of ROM storage so all const tables allow pointers, using:

#device const=ROM

This though prevents the old CCS 'shortcut' usage where calling a function that expects an integer, with a constant string, repeatedly calls the function for each character in the string.

This is documented in the readme.txt with the compiler.

Best Wishes
uslimey



Joined: 27 Aug 2011
Posts: 22
Location: Baltimore, MD

View user's profile Send private message

pointer to const struct array
PostPosted: Mon Oct 31, 2011 8:39 am     Reply with quote

I tried the rom method described...
Code:

calRecord rom calDT670[144] = {
{181,   5000},            // count : temperature x 10 (k)
{225,   4900.116713},
{270,   4801.94981}....

I still can't get the pointer to point to the table correctly...

Maybe I am missing something... The pointer is declared as follows...
Code:

calRecord *calData;
...
calData = calDT670;

I tried accessing records as follows...
Code:

result = *calData[0].opVal /// DOESN'T WORK
result = (*calData)[0].opVal /// DOESN'T WORK
result = *calData[0]->opVal /// DOESN'T WORK

Any ideas?
Ttelmah



Joined: 11 Mar 2010
Posts: 19550

View user's profile Send private message

PostPosted: Mon Oct 31, 2011 8:42 am     Reply with quote

Look at the readme.
The point is what you have is a _rom_ pointer. Remember what I said about the data space of the chip. Something has to tell the code that this is rom, not ram. So you have to construct pointers as:

rom *fred;

fred is a pointer to rom etc...

It is in the readme.

Best Wishes
uslimey



Joined: 27 Aug 2011
Posts: 22
Location: Baltimore, MD

View user's profile Send private message

PostPosted: Mon Oct 31, 2011 8:58 am     Reply with quote

Tried...

rom *pointer;

resulted in a compile error... "...expecting a ("

in the ref manual the example for a pointer to a const using the follwoing syntax...

const char *cptr;

This only works with character data types...

Still stuck!
uslimey



Joined: 27 Aug 2011
Posts: 22
Location: Baltimore, MD

View user's profile Send private message

PostPosted: Mon Oct 31, 2011 9:24 am     Reply with quote

Seems like the pointer to the rom struct array should be declared as follows:
Code:

calRecord rom *calData;
calData = calDT670; //Current Record;

but here's the gotcha... the record values CANNOT be accessed with any of the following:
Code:

ipValue = *calData.ipVal;
ipValue = (*caldata).ipVal;
ipValue = *calData->ipVal;

However if I create a new variable of the structure type I can access the members.

For example,
Code:

calRecord LastRecord = *calData;
ipValue = LastRecord.ipVal;
opValue = LasRecord.opVal;

Hopefully this will help someone else!

Thanks.
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

PostPosted: Tue Nov 01, 2011 12:48 am     Reply with quote

uslimey wrote:
Code:

ipValue = *calData.ipVal;
ipValue = (*caldata).ipVal;
ipValue = *calData->ipVal;

For the first, the dot has precedence over the asterisk, so the code is effectively:
Code:
ipValue = *(calData.ipVal);
which isn't going to work. The second variant should work, but as you're trying to dereference a rom pointer, I could understand that not working given the PIC architecture.

The third variant is also wrong, it should simply be:
Code:
ipValue = calData->ipVal;
I would expect that to work.

Having said all that, I've frequently found your workaround of assigning a structure to a temporary local RAM variable to be extremely helpful in cutting down code size, and for that reason is my preferred method in most cases.
_________________
Andrew
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