|
|
View previous topic :: View next topic |
Author |
Message |
freeman3020
Joined: 23 Oct 2015 Posts: 7
|
Using rom as constant |
Posted: Tue Nov 03, 2015 7:56 am |
|
|
Hi again,
I have test this code
Code: | #include <16F628.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOPUT //No Power Up Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES PROTECT //Code protected from reads
#define use_portb_lcd TRUE
#use delay(clock=20000000,RESTART_WDT)
#use rs232(baud=115200,parity=N,bits=8,UART1,errors, stream = sms)
char rom version[] = "PRODUCT ID V1.01";
char rom *ptr;
void display_string(rom *str)
{
printf("%s \r", str);
}
//=====================
void main()
{
ptr = version;
printf("ptr = %lx \r", ptr);
display_string(version);
display_string(ptr);
while(1);
} |
I got reference from here :
https://www.ccsinfo.com/forum/viewtopic.php?p=146223&sid=04f081ae04230eea19c3fa20dd731174#146223
but I got error on proteus : Program or eprom data has invalid address
?? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9255 Location: Greensville,Ontario
|
|
Posted: Tue Nov 03, 2015 9:01 am |
|
|
"but I got error on proteus "
well what makes you think proteus is 100% perfect program ???
Please see PIC101 sticky...
Jay |
|
|
freeman3020
Joined: 23 Oct 2015 Posts: 7
|
|
Posted: Tue Nov 03, 2015 9:29 am |
|
|
temtronic wrote: | "but I got error on proteus "
well what makes you think proteus is 100% perfect program ???
Please see PIC101 sticky...
Jay |
sorry , but I test also in real hardware , no output?
it's not proteus problem |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19569
|
|
Posted: Tue Nov 03, 2015 12:22 pm |
|
|
If you just want to use pointers to ROM based strings, then don't use rom. Just declare them as 'const', and add the header line near the fuses "#DEVICE PASS_STRINGS=IN_RAM". This tells the compiler to automatically 'virtualise' strings stored in ROM, and pass them as if they were in RAM. Easier and more reliable in general. The use of rom pointers requires _functions_ declared to use rom pointers. You can't use them 'interchangeably' with RAM pointers.
Critical question also is 'what compiler version'. This ability works to different amounts in different compilers. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 03, 2015 2:40 pm |
|
|
The example in his link uses the 16F1824, but he has changed it to a 16F628.
Looking at the .LST file, I can see that for the 16F1824, CCS sets the
EEPGD bit, to read from program memory.
When the program is compiled for the 16F628, CCS attempts to do this
but there is no EEPGD bit in the 16F628, so it just puts a '-' in the .LST file.
The 16F628 has no ability to read its own program memory.
Quote: |
0048: MOVF @READ_PROGRAM_MEMORY8.P2,W
0049: MOVWF @77
004A: BCF STATUS.C
004B: BSF STATUS.RP0
004C: BSF EECON1.-
004D: BSF EECON1.RD
004E: NOP
004F: NOP
0050: MOVF EEDATA,W
0051: MOVWF INDF
0052: INCF FSR,F
0053: INCF EEADR,F
0054: BTFSC STATUS.Z
0055: INCF TXSTA,F
0056: DECFSZ @77,F
0057: GOTO 04D |
This test was done with CCS compiler vs. 5.051. |
|
|
freeman3020
Joined: 23 Oct 2015 Posts: 7
|
|
Posted: Tue Nov 03, 2015 2:59 pm |
|
|
Ttelmah wrote: | If you just want to use pointers to ROM based strings, then don't use rom. Just declare them as 'const', and add the header line near the fuses "#DEVICE PASS_STRINGS=IN_RAM". This tells the compiler to automatically 'virtualise' strings stored in ROM, and pass them as if they were in RAM. Easier and more reliable in general. The use of rom pointers requires _functions_ declared to use rom pointers. You can't use them 'interchangeably' with RAM pointers.
Critical question also is 'what compiler version'. This ability works to different amounts in different compilers. |
I tried as you said, I got strange string ..
Is this mean rom and pass in ram require special chip? regarding PCM programmer post |
|
|
freeman3020
Joined: 23 Oct 2015 Posts: 7
|
|
Posted: Tue Nov 03, 2015 3:06 pm |
|
|
PCM programmer wrote: | The example in his link uses the 16F1824, but he has changed it to a 16F628.
Looking at the .LST file, I can see that for the 16F1824, CCS sets the
EEPGD bit, to read from program memory.
When the program is compiled for the 16F628, CCS attempts to do this
but there is no EEPGD bit in the 16F628, so it just puts a '-' in the .LST file.
The 16F628 has no ability to read its own program memory.
Quote: |
0048: MOVF @READ_PROGRAM_MEMORY8.P2,W
0049: MOVWF @77
004A: BCF STATUS.C
004B: BSF STATUS.RP0
004C: BSF EECON1.-
004D: BSF EECON1.RD
004E: NOP
004F: NOP
0050: MOVF EEDATA,W
0051: MOVWF INDF
0052: INCF FSR,F
0053: INCF EEADR,F
0054: BTFSC STATUS.Z
0055: INCF TXSTA,F
0056: DECFSZ @77,F
0057: GOTO 04D |
This test was done with CCS compiler vs. 5.051. |
if 16f628 can't read from program memory , how compiler copy from rom to ram using
memcpy(tmpMsg,msg5,sizeof(msg5));
where msg5 is char const array? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19569
|
|
Posted: Tue Nov 03, 2015 3:19 pm |
|
|
This gets a little complex.
The older PIC's can't read their own program memory.
On these CCS generates a const array, by generating a _program_ that stores the values as RETLW instructions, and then if you want (say) the 30th byte, the program is called with '29', and does a indexed jump forward by 29 to the 30th RETLW instruction, and returns the required byte (phew).
The strcpy/memcpy functions, are _overloaded_ (have two different versions), and if asked to copy a value from the ROM to RAM, instead of doing a direct copy, do the required repeated calls to the function, and write the resulting bytes back to RAM. Effectively hiding this extra complexity from you.
CCS are trying to give you the 'important parts' of the ability to store things in ROM, on chips that can't actually read such data.
In the manual for strcpy:
"src may be either a pointer to a RAM array of characters or it may be a constant string".
Use of pointers to ROM, requires a chip that can directly read it's own ROM. Problem is that the program approach only works if you call the program at the start!...
I must admit so few chips now don't allow this, that I failed to spot he was using one of the old ones that didn't. |
|
|
tinley
Joined: 09 May 2006 Posts: 67
|
|
Posted: Thu Nov 19, 2015 5:07 am |
|
|
Ttelmah wrote: | If you just want to use pointers to ROM based strings, then don't use rom. Just declare them as 'const', and add the header line near the fuses "#DEVICE PASS_STRINGS=IN_RAM". This tells the compiler to automatically 'virtualise' strings stored in ROM, and pass them as if they were in RAM. Easier and more reliable in general. The use of rom pointers requires _functions_ declared to use rom pointers. You can't use them 'interchangeably' with RAM pointers.
Critical question also is 'what compiler version'. This ability works to different amounts in different compilers. |
I am trying to copy constant tables in ROM into ram using pointers.
PCD V5.051 PIC24FJ256DA206
This works:
const char arial_8pt[1111]={0,1,2,3,4,5,etc........};
memcpy (FONT_IN_RAM, arial_8pt, TABLE_SIZE);
This doesn't:
char *FONT_TABLE = arial_8pt;
memcpy (FONT_IN_RAM, FONT_TABLE, TABLE_SIZE);
Is there a way of doing this please?
I tried "#DEVICE PASS_STRINGS=IN_RAM" amongst much else and pulling hair out!
Cheers |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19569
|
|
Posted: Thu Nov 19, 2015 5:22 am |
|
|
You need to use rom, not const.
The point is that const is not designed to have pointers constructed to it. The memcpy ability to use const, relies on memcpy 'knowing' that it is talking to a const. By trying to use an actual pointer variable, you are destroying this overload. Your variable says it is a pointer to RAM, and it isn't....
Code: |
rom char arial_8pt[1111]={0,1,2,3,4,5,etc........};
rom char *FONT_TABLE = arial_8pt;
memcpy (FONT_IN_RAM, FONT_TABLE, TABLE_SIZE);
|
'rom' constructs a constant, designed to have rom pointers constructed to it.
Your pointer then needs to be a rom pointer.
memcpy, then knows what it is dealing with. |
|
|
tinley
Joined: 09 May 2006 Posts: 67
|
|
Posted: Thu Nov 19, 2015 7:38 am |
|
|
Hi Ttelmah, Thank you very much for your reply.
Unfortunately it compiles but doesn't work!
Without an #ORG, it changes the location of the table to the end of ROM instead of near the beginning and it does alter the structure of the table...
But *FONT_TABLE is still not returning the table? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19569
|
|
Posted: Thu Nov 19, 2015 9:06 am |
|
|
It will alter the structure of the table, the rom table is built so it can be accessed using pointers, while the const table has the extra code added so it can be accessed as a program. and rom declarations normally are put near the end of the memory.
As a question, why do you actually want to copy it to RAM?.
Given that you can access it with rom pointers, it can be used from ROM just as easily.
Problem is that memcpy as written for the PIC24, is explicitly written to _only_ access RAM. It uses the direct RAM to RAM transfer ability, and this is why the manual says it only copies to/from RAM. strcpy, is overloaded to handle ROM pointers.
Just do your own version of memcpy, to handle ROM data. Something like:
Code: |
void rommemcpy(unsigned int8 * dest,rom char * source, unsigned int16 count)
{
if (count==0 return;
do {
*dest++=*source++;
} while (--count);
}
|
With this, and the rom font (in my case, just called 'font'), if merrily works with:
Code: |
char buffer[256];
rom char * fontptr;
fontptr=font;
rommemcpy (buffer, fontptr, sizeof(font));
|
|
|
|
tinley
Joined: 09 May 2006 Posts: 67
|
|
Posted: Fri Nov 20, 2015 7:20 am |
|
|
The built in display controller can only access font tables in RAM on the PIC24FJxxxDAxxx chips.
Whilst there is plenty of ROM to store fonts, the ram can only store a couple at a time, so I need to transfer font tables on the fly.
Thanks for the code. Ironically I was using a loop to copy before changing it to memcpy, but your code looks more elegant than mine, so I shall use it!
Thank you! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19569
|
|
Posted: Fri Nov 20, 2015 8:09 am |
|
|
A good reason.
Annoyingly, the overload ability, on the current releases doesn't seem to be able to tell between a rom pointer, and a normal pointer. I'm sure it did a while ago, when I was doing something similar. I was going to write an overloaded version, that would automatically switch between memcpy, and the rom version, depending on the types of the pointer passed, but the overload doesn't want to work... |
|
|
tinley
Joined: 09 May 2006 Posts: 67
|
|
Posted: Fri Nov 20, 2015 8:47 am |
|
|
Thanks Ttelmah,
I can confirm that works when the typo is fixed!!!
Code: |
if (count==0) return;
|
Thank you very much for your help. |
|
|
|
|
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
|