|
|
View previous topic :: View next topic |
Author |
Message |
Oznog
Joined: 16 Oct 2004 Posts: 6
|
Pointers to const array |
Posted: Wed Oct 27, 2004 4:04 pm |
|
|
I have a constant struct which uses a pointer to a constant array of data. The data length varies depending on which instance of struct it is. It's for graphical LCD fonts of differing sizes, and some cover only the numbers.
I'm seeing that CCS does not allow pointers to const arrays, and I see no way to implement this.
These arrays must all be accessed in the same way by the LCD driver tasks, it is not practical to make a function access the array directly, it must be a pointer.
The small arrays would use far too much memory if they were all the same size.
The arrays will consume more RAM than in existance if they are not constants.
Is this true that there is no way to access constant arrays via pointers? How on earth would this be worked around? |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Oct 27, 2004 9:26 pm |
|
|
Well the driver could access the elements of the array instead of using a pointer. Just pretend its BASIC
You can copy the const array to a RAM array and use a pointer to the RAM instead. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
Re: Pointers to const array |
Posted: Thu Oct 28, 2004 12:11 am |
|
|
Oznog wrote: | How on earth would this be worked around? |
Store the tables directly into program memory and use assembler code to do table reads.
Andrew |
|
|
Oznog
Joined: 16 Oct 2004 Posts: 6
|
|
Posted: Thu Oct 28, 2004 12:15 am |
|
|
Mark wrote: | Well the driver could access the elements of the array instead of using a pointer. Just pretend its BASIC
You can copy the const array to a RAM array and use a pointer to the RAM instead. |
Um, except both are ridiculously impractical. Certainly there is a way to do this that I'm not seeing? I'm going on the assumption that the compiler can't possibly be this lame. How can you possibly write effective C code with any complexity if you can't make use of data pointers for const data? |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Thu Oct 28, 2004 1:48 am |
|
|
I'm afraid that's the way it is...CCS implements RETLW-based look-up tables for constant arrays, and you can't have a pointer to such a lookup table.
This is probably CCS's biggest shortcoming. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Thu Oct 28, 2004 7:10 am |
|
|
Quote: | Um, except both are ridiculously impractical. |
That's where you would be wrong! It is a limitation of the compiler. Live with it and deal with it. Other people have and I am sure many projects have been completed by doing this. I store all my strings in const arrays and then copy them to RAM when they are needed. It would be nice to use a pointer but CCS just doesn't support it. You can do the table reads yourself. Just load the table pointer, do the read, and then move the value from TABLAT into whereever. |
|
|
Ttelmah Guest
|
Re: Pointers to const array |
Posted: Thu Oct 28, 2004 7:59 am |
|
|
Oznog wrote: | I have a constant struct which uses a pointer to a constant array of data. The data length varies depending on which instance of struct it is. It's for graphical LCD fonts of differing sizes, and some cover only the numbers.
I'm seeing that CCS does not allow pointers to const arrays, and I see no way to implement this.
These arrays must all be accessed in the same way by the LCD driver tasks, it is not practical to make a function access the array directly, it must be a pointer.
The small arrays would use far too much memory if they were all the same size.
The arrays will consume more RAM than in existance if they are not constants.
Is this true that there is no way to access constant arrays via pointers? How on earth would this be worked around? |
One question, has not been asked, which is vital to the 'answer'.
What PIC is involved?.
The reason is that the method of storing data in ROM, changes, with the '18' chips, and even on the '16' chips, some of the flash versions, support the read_program_eeprom function. On chips with this function, you can code a table in ROM, using the #ROM diective, and directly access the values, using an address based on the variable size (a macro based on the 'sizeof' function, would allow this to be coded almost like a normal array access). This would closely emulate a 'pointer', and would be fairly simple to convert.
On the older chips, the 'reason', is that the chip itself does not allow a pointer type access to the data, requiring instead the RETLW access to retrieve a byte. You can partially emulate a pointer type access, by using multiple tables, and your own 'address', which is then used as a character array address, with the data stored as a union, to retrieve the required variable. However it is bulky to code, and CCS elected not to offer this option.
Best Wishes |
|
|
Oznog
Joined: 16 Oct 2004 Posts: 6
|
|
Posted: Thu Oct 28, 2004 1:14 pm |
|
|
Mark wrote: | Quote: | Um, except both are ridiculously impractical. |
That's where you would be wrong! It is a limitation of the compiler. Live with it and deal with it. Other people have and I am sure many projects have been completed by doing this. I store all my strings in const arrays and then copy them to RAM when they are needed. It would be nice to use a pointer but CCS just doesn't support it. You can do the table reads yourself. Just load the table pointer, do the read, and then move the value from TABLAT into whereever. |
I don't see the practicality for stronger apps. I have an LCD I need to dump screens to, it's a 256x128 screen so that's 4k of data right there which is far more space than even exists in RAM. Fonts are used frequently and consist of a const struct with data on font height, char type, etc as well as a the pointer to the const data array of the graphics data itself. So there's a const pointer-within-a-const pointer right there. Such efficient structures are the whole point of doing C. |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1933 Location: Norman, OK
|
|
Posted: Thu Oct 28, 2004 2:30 pm |
|
|
I just completed a large project using a multiline LCD display. I allocated all my strings (more than 60 strings in all) to ROM like the following:
// *************************
// Message Constant Strings
char const WD_MSG[]= {"<W93>"};
char const CLR_ERROR_MSG[]= {"<q000D>"};
char const ACK_MSG[]= {"@"};
char const VERSION_MSG[]= {"<L88>"};
char const GAP_MSG[]= {"<G16EA>"};
char const MODE_MSG[]= {"<M4BD>"};
char const LOOPBACK_TEST_MSG[]= {"<SLOOPBACKDA>"};
....etc...
// *************************
I then used the standard Printf to send a desired string.
printf(ACK_MSG);
I also defined LCD control sequences as constant strings then combined them with other strings for transmission using multiple variables in Printf.
Using this method I implemented a very large number of strings while using only 21% of RAM It worked great for me, put all my strings in ROM and I didnt use a single "pointer".
FWIW... |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Thu Oct 28, 2004 2:57 pm |
|
|
Quote: | I don't see the practicality for stronger apps. I have an LCD I need to dump screens to, it's a 256x128 screen so that's 4k of data right there which is far more space than even exists in RAM. Fonts are used frequently and consist of a const struct with data on font height, char type, etc as well as a the pointer to the const data array of the graphics data itself. So there's a const pointer-within-a-const pointer right there. Such efficient structures are the whole point of doing C.
|
No one said that you can't store the data as constants. You just ain't gonna use a pointer to it. You can still access the data using const arrays. Yeah, yeah I know. You want to embed a constant pointer in the struct too. Well, the way around that is to include a number instead. Then use a switch statement to reference the proper array. It can still be done. Not quite as efficient as a pointer. But hey, if you insist on using a pointer then go buy the HiTech or C18 compiler.
Quote: | I just completed a large project using a multiline LCD display. I allocated all my strings (more than 60 strings in all) to ROM like the following:
|
His project is a bit more complex and involves character maps for defining each character. Tons more complex that just storing strings. But nonetheless, he can still do it if he is creative. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Oct 28, 2004 3:36 pm |
|
|
What he wants to do is to put variable length blocks of bytes (or words)
into program memory, and have the compiler automatically construct
a table of addresses of these blocks. He would prefer that this all be
done at compile time.
Then at runtime, he can use C code to index into the table of block
addresses, and get the address, and then use read_program_eeprom()
to read the data into a ram array. Then he can send the data to his
display device.
The question is, does CCS have the capability to do this ?
I mean, with respect to automatically generating the table of addresses,
with a minimal amount of effort by the programmer when typing in
the data.
I don't know. I played around and came up with the following approach.
This method has the disadvantage that you have to visually check the
size of each block of bytes, and then enter that number into a #define
statement right above the block. Also, there may be some limitation
on the number of #define'd constants in CCS. For 128 characters,
you would need ADDR0 through ADDR127, with the method below.
Code: | #include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#define ADDR0 0x400 // Address of 1st character
#define LEN0 3 // Number of bytes for 1st character
#ROM int8 ADDR0 = {1, 2, 3} // Data for 1st character
#define ADDR1 (ADDR0 + LEN0) // Addr of 2nd char
#define LEN1 5 // Number of bytes for 2nd char
#ROM int8 ADDR1 = {4,5,6,7,8} // Data for 2nd char
#define ADDR2 (ADDR1 + LEN1) // Addr of 3rd char
#define LEN2 2 // Number of bytes for 3rd char
#ROM int8 ADDR2 = {0xA, 0xB} // Data for 3rd char
// Table of ROM addresses for each character.
int16 const char_address[] =
{
ADDR0,
ADDR1,
ADDR2,
};
// Table of lengths of character data.
int16 const char_data_length[] =
{
LEN0,
LEN1,
LEN2,
};
//==================================
void main()
{
int8 i;
int16 addr;
for(i = 0; i < 3; i++)
printf("%lx \n\r", char_address[i]);
for(i = 0; i < 3; i++)
printf("%lx \n\r", char_data_length[i]);
while(1);
} |
|
|
|
Oznog
Joined: 16 Oct 2004 Posts: 6
|
|
Posted: Sun Oct 31, 2004 1:27 am |
|
|
Mark wrote: | No one said that you can't store the data as constants. You just ain't gonna use a pointer to it. You can still access the data using const arrays. Yeah, yeah I know. You want to embed a constant pointer in the struct too. Well, the way around that is to include a number instead. Then use a switch statement to reference the proper array. It can still be done. Not quite as efficient as a pointer. But hey, if you insist on using a pointer then go buy the HiTech or C18 compiler.
|
Forgive me for saying so, but this is so dumb! I mean, you'd be killing the code structure that C is capable of by eliminating the const pointers. It's a bad idea at the build stage too- now any file which needs a structure or array would need to include every instance of that structure, rather than just the struct type! Not to mention the fact that now adding a new instance would mean finding every usage of that structure and modifying the code.
Go to HiTech or C18... no kidding! |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sun Oct 31, 2004 1:59 am |
|
|
Quote: | Forgive me for saying so, but this is so dumb! |
I sure hope you mean not having pointers to const
Quote: | It's a bad idea at the build stage too- now any file which needs a structure or array would need to include every instance of that structure, rather than just the struct type! Not to mention the fact that now adding a new instance would mean finding every usage of that structure and modifying the code.
|
Not quite sure I follow you here. I mean I could have a function that handled all the requests. So it would contain the switch statement. Any modifications would just need to be done there. Not sure what you are talking about "would need to include every instance of that structure". Heck, if you thought about it hard enough, you can come up with many ways to do what you want. You could have function pointers in the struct that could "getvalue", "incpointer", "decpointer". |
|
|
Trampas
Joined: 04 Sep 2004 Posts: 89 Location: NC
|
|
Posted: Sun Oct 31, 2004 7:00 am |
|
|
I think what Oznog is saying is that he has code he is porting to the CCS compiler and finding it will not port easily due to the pointers to const data issue. Therefore it appears that he feels redesigning the code to use alternative methods is not reasonable at this point.
I know that personally in my designs I usually place external flash chips to store data. Usually these flash chips and the compiler do not allow me to have pointers to the data so I just create read/write functions. I try to leave my on chip flash available for code, but then again I am more concerned with development time than manufacturing costs in most of my products.
Trampas |
|
|
|
|
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
|