|
|
View previous topic :: View next topic |
Author |
Message |
rconan
Joined: 13 Dec 2010 Posts: 4
|
String constants as arguments to in-built functions |
Posted: Fri Sep 30, 2011 4:23 pm |
|
|
Hi,
I've tried a number of times to use string-constants as arguments to in-built string functions which don't modify the string.
Whenever I try doing this I get the following error (or similar):
Code: | *** Error 51 "PATH" Line 98(51,58): A numeric expression must appear here |
The code used that gave the above error is:
Code: | void usb_debug_log(unsigned int8 area, unsigned int8 severity, char const message[])
{
sprintf(out_data, "99%3u%3u%48s", area, severity, message);
usb_write();
} |
Does anyone know why this is? Are there any workarounds for this issue to allow passing string constants to such functions? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Sep 30, 2011 4:55 pm |
|
|
If I make your code into a test program, and add the two #device
statements shown below, I get this output in MPLAB simulator:
Test program:
Code: |
#include<16F877.h>
#device PASS_STRINGS=IN_RAM
#device CONST=READ_ONLY
#fuses HS,NOWDT,BROWNOUT,PUT,NOLVP
#use delay(clock=20M)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
char out_data[20];
void usb_debug_log(unsigned int8 area, unsigned int8 severity, char const message[])
{
sprintf(out_data, "99%3u%3u48%s", area, severity, message);
printf("%s", out_data);
}
//======================================
void main()
{
usb_debug_log(5, 6, "PATH");
while(1);
}
|
For information on the #device statements, see the CCS manual:
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf
This was tested with compiler vs. 4.124. |
|
|
rconan
Joined: 13 Dec 2010 Posts: 4
|
|
Posted: Fri Sep 30, 2011 5:14 pm |
|
|
Thanks for the prompt reply.
That seems to fix the problem I was having but raises an incompatibility with the USB HID driver included with CCS.
Seems the usb_hid_desc.h header populates a constant array using values from another constant array (line 241) which, using that #device statement, are stored in RAM which it cannot read from at compile time.
Seems like these two behaviours are mutually exclusive? Is there a way to get around that other than rewriting usb_desc_hid.h to not depend on that behaviour? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Sep 30, 2011 5:25 pm |
|
|
Quote: |
void usb_debug_log(unsigned int8 area, unsigned int8 severity, char const message[]) |
The simple way would be to re-write your function to conform to CCS
standards. Get rid of the 'const' and the brackets for the last parameter,
and just make it be char *message. Then add the #device
PASS_STRINGS=IN_RAM but not the other #device statement. |
|
|
rconan
Joined: 13 Dec 2010 Posts: 4
|
|
Posted: Fri Sep 30, 2011 5:30 pm |
|
|
That works. Kind of a shame this involves an extra step to copy the string into RAM rather than simply passing a pointer to the data in program memory. I guess this is because program memory and RAM aren't in the same address space so it can't do that? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Sep 30, 2011 5:32 pm |
|
|
That's right. |
|
|
rconan
Joined: 13 Dec 2010 Posts: 4
|
|
Posted: Fri Sep 30, 2011 5:37 pm |
|
|
Thanks for all your help. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19480
|
|
Posted: Sat Oct 01, 2011 2:14 am |
|
|
Or, use ROM, rather than CONST.
This is down to history, and the layout of the PIC memory spaces, and CCS 'predating' later standards.
On the earliest PIC's, there is no direct way of accessing data stored in program memory. So for constant data, CCS built a program, that used RETLW instructions, to return the value from the index requested. This format was used for 'const' data.
When they moved to trying to support ANSI style const, several things had to change. First, the PIC's themselves had evolved, and most now offered instructions to read program memory. Const in ANSI, is designed for processors in general where data is in RAM, so the ANSI const construct, just attempts to protect this RAM data from being written. This is the form emulated by the 'PASS_STRINGS_IN_RAM' form.
However the presence of the ability to directly read ROM, does make it potentially possible to have a 'pointer to ROM', but would mean having an extra bit to say that this is to ROM, rather than RAM, or some other way of 'distinguishing' the address space. This is the form generated by the ROM constant.
CCS has the ability to change what the ROM, and CONST keywords actually 'do'. Look at the 'readme.txt' with your compiler. However as you have found, changing the operation of these can easily bring problems.
Best Wishes |
|
|
|
|
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
|