![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
allenhuffman
Joined: 17 Jun 2019 Posts: 540 Location: Des Moines, Iowa, USA
|
Workaround for pointer to const or rom *? |
Posted: Mon Apr 06, 2020 11:16 am |
|
|
There has been an outstanding issue with CCS dealing with rom * for awhile, and I wondered if anyone has figured out a workaround.
In my case, I have tables of data:
Code: | uint8_t data[100] =
{
0,0,0,0,0 ... 0,0,0
}; |
And I have structures that contain pointers to that data:
Code: | typedef struct
{
// stuff
uint32_t *dataPtr;
}; |
To make this work currently, all our structures are in RAM. But I am now at 90% and need to get things moved.
I have one large structure as a "const" which I access directly with no problems, but the other elements are part of an LCD user interface so the structure has attributes for how that data gets displayed.
Anyone have a good workaround for how I can have a structure point to data in flash and make that work? _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19375
|
|
Posted: Mon Apr 06, 2020 11:25 am |
|
|
Generally, you are using PIC24/33's?.
If so, then:
#device PSV=16
You can then have pointers to all types of consts.
If you are on the PIC16/18, then declare your consts, as 'rom', instead
of const. Then declare your pointers as 'rom *'. |
|
![](templates/subSilver/images/spacer.gif) |
allenhuffman
Joined: 17 Jun 2019 Posts: 540 Location: Des Moines, Iowa, USA
|
|
Posted: Mon Apr 06, 2020 11:56 am |
|
|
Thanks, but unfortunately that doesn't seem to help. I don't know the details of the compiler bug, just that it may take a few months for them to have a fix.
Simple things like this:
Code: | typedef struct
{
int x,y;
const uint8_t *ptr;
} MyStruct;
|
...compile and work fine if the program is small. At some point, they won't even compile -- complains about "const" not being recognized -- even when this declaration is in main.c.
I expect this is related to the compiler bug, am I am hopeful someone has figured out a workaround. _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
![](templates/subSilver/images/spacer.gif) |
jeremiah
Joined: 20 Jul 2010 Posts: 1329
|
|
Posted: Mon Apr 06, 2020 4:59 pm |
|
|
Have you tried switching to function pointers to access constant tables? Something like create a constant table:
Code: |
const unsigned int table[100] = /*stuff*/;
int get_at(unsigned int index){
if(index > 99){
index = 99;
}
return table[index];
}
typedef int(*indexer)(unsigned int);
typedef struct
{
int x,y;
indexer ptr;
} MyStruct;
MyStruct v = {0,1,get_at};
int value = v.indexer(some_index);
|
I don't have the compiler handy here, so that is off the cuff pseudo code that hasn't been compiled. But basically you replace the pointer to the table with a pointer to a function that reads the table for you.
It's mostly just a workaround type solution, not optimal obviously. It's more scaffolding than you would normally want to do, but it may get around your issue.
Another option is to use an enum paired with switch statement to select your table:
Code: |
const unsigned int ctable1[4] = {1,2,3,4};
const unsigned int ctable2[4] = {1,2,3,4};
const unsigned int ctable3[4] = {1,2,3,4};
const unsigned int ctable4[4] = {1,2,3,4};
typedef enum {
TABLE1,
TABLE2,
TABLE3,
TABLE4
} table_selector_t;
unsigned int get_at(table_selector_t table, unsigned int index){
switch(table){
case TABLE1: return ctable1[index]; break;
case TABLE2: return ctable2[index]; break;
case TABLE3: return ctable3[index]; break;
default: return ctable4[index];
}
}
typedef struct
{
int x,y;
table_selector_t selector;
} MyStruct;
MyStruct v = {0,1,TABLE1};
int value = get_at(v.selector, some_index);
|
then you just keep the selector enum value with each struct.
Side note: Make sure you not to take the address of an individual element of a const table pointer or dereference it. I.E. I don't believe CCS fully supports the following:
*table =
address = &table[6];
some_const_struct_pointer->some field
It may or may not work, but the CCS docs usually only allow for bracketed element access for constant tables. That may have changed more recently, but I haven't seen any updates indicating so. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19375
|
|
Posted: Tue Apr 07, 2020 12:06 am |
|
|
If you use PSV, the pointers are just normal pointer. Get rid of the
const keyword in the pointer declaration.
If you declare the pointers as 'const', they have to be resolved at compile
time, not run time. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19375
|
|
Posted: Tue Apr 07, 2020 3:06 am |
|
|
As a separate 'workround', which was a way that I have used in the past,
look at Addressmod.
This is a function designed to allow you to map external memory areas
into the memory supported for variables. However you can use it with the
internal flash memory.
I suspect you are having problems with PSV, possibly because yous chip
has 64K of RAM?. The total addressable RAM 'window' for the PIC24/33
chips is 64K. PSV uses a 16K window into this space. If your chip has more
RAM than 48K, it can get confused. Also it sounds as if your total ROM
needed may be large (again larger than the PSV window).
Now there are going to be 'issues' however you do this.
Remember the program memory space only implements 24bits in
every 32. When PSV is used, it stores values only into the low 16bits
of each 32, making translation relatively easy, but wasting space.
You are going to have to write the read function you call with AddressMod
to automatically handle multiplication by 4/3 of the address, and allow
indexing in bytes into this area (see below).
You can pack the data into the ROM using #IMPORT. I do this with a
number of bitmaps with:
#IMPORT(FILE=.\Logo.bin, RAW, LOCATION=where_stored, BPI=3)
Which puts binary data into the ROM space, packed 3 bytes per word.
My read function, is then:
Code: |
union access {
unsigned int32 whole;
unsigned int8 bytes[4];
}; //union to allow byte access into 32bit word
//routine to give access to ROM stored data - used for bitmap
BYTE getval(unsigned int32 locn, unsigned int32 index)
{
unsigned int32 calc;
union access rdg;
unsigned int8 bval;
//Now I need to calculate the actual cell I need to read, fetch this
//then extract the byte
calc=(index/3)*2;
//This gives the actual cell offset from locn.
read_program_memory(locn+calc, &rdg, 4);
//Gives the 32bit value containing the byte required.
bval=index % 3;
//Now gives the byte number required
return rdg.bytes[bval];
//return the physical byte
}
|
'locn' here is the variable 'where_stored' from the import, which
is where the data has been put in memory. 'index' is the byte number
I want to retrieve from the data. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|