View previous topic :: View next topic |
Author |
Message |
Max
Joined: 15 Dec 2003 Posts: 51 Location: Italy
|
String in ROM to RAM ? |
Posted: Sun Jan 25, 2015 1:46 pm |
|
|
Hello,
in the forum there are many posts but, reading the previous posts, I have not found an answer.
Compiler 5.037 and PIC24EP512GU810
place a simple code to explain:
Code: |
#include <24ep512gu810.h>
#FUSES NOWDT
#FUSES NOBROWNOUT
#FUSES NOJTAG
#FUSES DEBUG
#FUSES HS
#FUSES PR
#FUSES WPRES32
#DEVICE ADC=10
#device ICD=TRUE
#device ICSP=1
#device const=rom
#device PASS_STRINGS=IN_RAM
#use delay(clock=40000000,crystal=8000000)
//uart 2
#pin_select U2TX=PIN_E4
#pin_select U2RX=PIN_E6
#use rs232(UART2, baud=9600, stream=UART2)
void main (void)
{
rom char *version[] ={"AAA","BBB","CCC"};
rom char *ptr;
char string[5];
ptr = version[1];
//strcpy(string,ptr) // Not work
fprintf(UART2,"%s",ptr); // Ok
// fprintf(UART2,"%s",string); // Not work
while(1){
restart_wdt();
}
}
|
the above code works and the fprintf see the content of the char ROM version.
But I need to use the string contained in the version without the 'use of fprintf.
(I have to pass it as a pointer to a function that will display it on a LCD graphic)
if I put ptr does not work, I should probably be able to copy it to a temporary variable on RAM.
how can you do? Strcpy does not work
example not work.
the structure of the function is as follows where s is the pointer to the string passed Code: | ft_void_t Ft_Gpu_CoCmd_Text(Ft_Gpu_Hal_Context_t *phost,ft_int16_t x, ft_int16_t y, ft_int16_t font, ft_uint16_t options, ft_char8_t * s) |
Thank You |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Sun Jan 25, 2015 2:08 pm |
|
|
You can use sprintf() instead of printf() and 'print' to a string (very useful when using printf formatting features), or you can read from the ROM-array char by char into the RAM variable until zero is reached.
There may be more elegant ways though.
Also you might be able to optimize your code and send a ROM pointer to the function (if applicable). |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Sun Jan 25, 2015 2:28 pm |
|
|
You can pass it as a pointer to your function, but the function declaration needs to have it as a ROM pointer.
The key is that ROM pointers are distinct from RAM pointers. Some of the CCS functions are internally overloaded to handle them, some aren't.
If you want to do an equivalent to strcpy, then you can use:
Code: |
#include <24EP256GU810.h>
#FUSES NOWDT
#FUSES NOBROWNOUT
#FUSES NOJTAG
#FUSES DEBUG
#FUSES HS
#FUSES PR
#FUSES WPRES32
#DEVICE ADC=10
#use delay(clock=40000000,crystal=8000000)
//uart 2
#pin_select U1TX=PIN_E4
#pin_select U1RX=PIN_E6
#use rs232(UART2, baud=9600, stream=UART2)
void strromcpy(char *dest, rom char *source)
{
while (*source != '\0')
*(dest++) = *(source++);
*dest='\0';
}
void main (void)
{
rom char *version[] ={"AAA","BBB","CCC"};
char string[5];
strromcpy(string,version[1]);
fprintf(UART2,"%s",string);
while(TRUE)
{
restart_wdt();
}
}
|
You are also making it very complex, by changing the settings several ways. const=rom, changes the default behaviour of const, then PASS_STRINGS also changes this. If you are using the rom directive get rid of both of these.
You are trying to mix three different ways of doing the same thing. Use one or the other.
Last edited by Ttelmah on Tue Jan 27, 2015 9:45 am; edited 1 time in total |
|
|
Max
Joined: 15 Dec 2003 Posts: 51 Location: Italy
|
|
Posted: Mon Jan 26, 2015 2:10 am |
|
|
Hello Ttelmah,
I tried the code but to me it does not work.
I tried with ICD3 in debugger, during the 'execution of resets, never comes to run the line Code: | fprintf(UART2,"%s",string); |
Obviously if the call to the does not reset. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Mon Jan 26, 2015 2:15 am |
|
|
You may have a compiler problem. I tried with 5.028, which I'm currently using as seeming to be more reliable than the latest releases, and it works as posted. Note I'm using the 256 processor (didn't have the 512). |
|
|
Max
Joined: 15 Dec 2003 Posts: 51 Location: Italy
|
|
Posted: Mon Jan 26, 2015 3:26 am |
|
|
I added a forced to exit the while loop:
Code: | void strromcpy(char *dest, rom *source)
{
unsigned int8 t=0;
while ((*source) != '\0'){
*(dest++) = *(source++);
if(t==3)
break;
t++;
}
*dest='\0';
} |
I changed the content in the rom to better understand
Code: | rom char *version[] ={"123","456","789"}; |
and I get the following results printed:
Code: | if t==0 -> 4
if t==1 -> 46
if t==2 -> 467
if t==3 -> 4679
if t==4 -> reset |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Mon Jan 26, 2015 4:02 am |
|
|
The retrieval code is not working. It's jumping forward two characters for every one being retrieved. Force the size to a char in the declaration, it's assuming an int16. It should have the char there (mistype), but on the older compiler, it worked without it.... |
|
|
Max
Joined: 15 Dec 2003 Posts: 51 Location: Italy
|
|
Posted: Mon Jan 26, 2015 7:05 am |
|
|
I haven't understand to what definition are you referring to? Can you explain it with an example, please? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Mon Jan 26, 2015 8:00 am |
|
|
Code: |
void strromcpy(char *dest, rom char *source)
|
|
|
|
Max
Joined: 15 Dec 2003 Posts: 51 Location: Italy
|
|
Posted: Tue Jan 27, 2015 7:21 am |
|
|
Ttelmah wrote: | Code: |
void strromcpy(char *dest, rom char *source)
|
|
Thanks, now works !
only problem that I do not understand is that in 'example above no matter insert Code: | #device PASS_STRINGS = IN_RAM | and gives no error.
While in my application if I do not put Code: | #device PASS_STRINGS = IN_RAM |
the compiler generates me the 'error:
Code: | Attempt to create a pointer to a constant |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Tue Jan 27, 2015 8:45 am |
|
|
Are you declaring the constants as 'rom', or 'const'?.
It matters.
rom, constructs a constant, for which pointers can be constructed. const creates one for which it can't. PASS_STRINGS=IN_RAM, tells the compiler to _automatically_ 'virtualise' pointer accesses to const strings to the RAM address space, so a pointer can be constructed. |
|
|
Max
Joined: 15 Dec 2003 Posts: 51 Location: Italy
|
|
Posted: Tue Jan 27, 2015 12:07 pm |
|
|
I have declared all constants "rom"
I replaced all with |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Tue Jan 27, 2015 3:52 pm |
|
|
So does it work?.
What happens with the example as posted (I have amended the rom declaration in it)?. This runs perfectly for me. |
|
|
Max
Joined: 15 Dec 2003 Posts: 51 Location: Italy
|
|
Posted: Wed Jan 28, 2015 1:06 am |
|
|
Ttelmah wrote: | So does it work?.
What happens with the example as posted (I have amended the rom declaration in it)?. This runs perfectly for me. |
l 'example is fine.
But in my full code generates some 'error Code: | Attempt to create a pointer to a constant |
I checked there are no more "const" all replaced with "rom".
L 'error only eliminated leaving in the define Code: | #device PASS_STRINGS = IN_RAM |
From the support CCS me confirm a problem with this family of processors using the strcpy to copy from ROM to RAM, which should solve short.
They recommend using:
Code: | read_rom_memory (version [1], string, sizeof (string)); |
Tried it and it works ... but it works well
Code: | void strromcpy (char * dest, rom char * source) |
that thou hast recommended
Thank You |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Wed Jan 28, 2015 9:05 am |
|
|
That implies somewhere you are using a simple 'char *', not a 'rom char *' to access the data.
PASS_STRINGS will allow this to be done, but at a cost of making all constant accesses slightly bulkier and slower.
You 'pays your money and takes your choice'.
I prefer to retain full control, and explicitly know how things are accessed. |
|
|
|