CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Problem storing variables in program ROM

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

Problem storing variables in program ROM
PostPosted: Fri Nov 26, 2010 3:42 pm     Reply with quote

Hi all,

I'm using PCWH 4.099, compiling for a PIC18F26J50.

Because the chip lacks EEPROM, I need to store application config data in program ROM. I'm running into some problems doing this.

The data is a range of variables consisting of ints, longs, and arrays of around 300 bytes total (though it will get bigger later on).

I can do this with no problem:
Code:

    char msg[3][64];
    ROM char s_msg[3][64];
...
    write_program_memory(&s_msg,msg,192);
    read_program_memory(&s_msg,msg,192);


But, with a few dozen variables it gets very cumbersome and inefficient to do this for each one. Also, I found that the compiler is putting the ROM variables in the last page of ROM, and if I erase the page (as is recommended in the data sheet), it corrupts the config words.

What I tried first is this (shortened for readability):
Code:
#org 0xF800, 0xFBFF
ROM unsigned int s_speed, s_hangtime, s_cbeepdelay, s_id_volume;
#org default

Unfortunately, the compiler seems to ignore the #org and sticks the data just below the config words, in reverse order. That means if I do an erase_program_memory() it whacks my config words. The symbol file shows me this:
Code:
User Memory space:
 00FFF6-00FFF6  s_speed
 00FFF4-00FFF4  s_hangtime
 00FFF2-00FFF2  s_cbeepdelay
 00FFF0-00FFF0  s_id_volume


Ideally I'd like to be able to just copy the variables from RAM (they're all in a nice neat block) into ROM with write_program_memory(). By doing that I can specify the ROM address. However, when I try that it seems to write to areas I'm not expecting. As a test I tried this:

Code:
write_program_memory(0x00C000,&speed,192);


When i read back the program memory and compare it to the original program, I find that there is nothing around 0xC000:

Code:
:10C00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40
:10C01000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30
:10C02000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20
:10C03000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10
:10C04000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00


But it does seem to have written to the middle of my program:

Code:
  :1022700045004100540045005200200043004F003B
D <! :102280004E00540052004F004C004C0045005200DC
D <! :10229000F76AA00FF66E220EF7220900F550120021
D <! :1022A000E001970233039B03BB039B0333039702B5
D <! :1022B000E00128018C002400050024008C00280186
I !> :10228000000000000000000000000000000000004E
I !> :10229000000000000000000000000000000002003C
I !> :1022A000E000800210000100100290032003900063
I !> :1022B000000008000800000000000000000000000E
  :1022C000F2CF0EF0F29EF76ADA0FF66E220EF722C8


Of course at that point my device promptly dies, since its program is now corrupted.

I've been hammering away at this for over a day now. I'm stumped. Is write_program_eeprom broken in this compiler version? Am I doing something wrong? I can't possibly be the first person to want to store configuration parameters to ROM on EEPROM-less parts, so I know this has to have been addressed before. I did try searching the forums here, but without much luck.

What am I missing here?
Humberto



Joined: 08 Sep 2003
Posts: 1215
Location: Buenos Aires, La Reina del Plata

View user's profile Send private message

PostPosted: Sat Nov 27, 2010 7:52 am     Reply with quote

Hi Dale,

I never used the 26J50, but in order to get a clue to find out this specific problem, I suggest post a short
and compilable code that we can test with differents compiler versions and compare its resulting .hex

Regards,

Humberto
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Sat Nov 27, 2010 12:46 pm     Reply with quote

It would be interesting to see the symbols, listing and statistics from a newer compiler version, if it's not too much trouble. I would like to see if the behavior has changed since 4.099.
Code:

#include <18F26J50.h>
#device adc=8

#FUSES NOWDT                     //No Watch Dog Timer
#FUSES WDT128                    //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_PLL_IO              //Internal RC Osc, no CLKOUT
#FUSES NODEBUG                   //No Debug mode for ICD
#FUSES NOXINST                   //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES STVREN                    //Stack full/underflow will cause reset
#FUSES NOPROTECT                 //Code not protected from reading
#FUSES FCMEN                     //Fail-safe clock monitor enabled
#FUSES IESO                      //Internal External Switch Over mode enabled
#FUSES IOL1WAY                   //Allows only one reconfiguration of peripheral pins
#FUSES PRIMARY                   //Primary clock is system clock when scs=00
#FUSES WPCFG               
#FUSES WPEND                 
#FUSES WPDIS                 
#FUSES NOCPUDIV             
#FUSES LPT1OSC                   //Timer1 configured for low-power operation
#FUSES T1DIG                 
#FUSES MSSPMSK7             
#FUSES PLLDIV2               
#FUSES DSWDT2147483648       
#FUSES DSWDT                 
#FUSES DSBOR                 
#FUSES RTCOSC_T1             
#FUSES DSWDTOSC_INT         
#FUSES WPFP0                 
#FUSES WPFP1                 
#FUSES WPFP2                 
#FUSES WPFP3                 
#FUSES WPFP4                 
#FUSES WPFP5

#use delay(clock=48mhz,internal)
unsigned int  speed, hangtime, cbeepdelay, id_volume, recv_volume, cbeep_speed;
unsigned long int id_time, first_id, beacon_time, cbeep_tone, cwid_tone, watchdog, id_delay;
char msg[3][64];

#org 0xF800, 0xFBFF
ROM unsigned int s_speed, s_hangtime, s_cbeepdelay, s_id_volume, s_recv_volume, s_cbeep_speed;
ROM unsigned long int s_id_time, s_first_id, s_beacon_time, s_cbeep_tone, s_cwid_tone, s_watchdog, s_id_delay;
ROM char s_msg[3][64];
#org default

// This works in the original program.  However, it's looking like
// I will have dozens of parameters to store and retrieve.
void read_params_from_flash(void) {
    read_program_memory(&s_speed,&speed,1);
    read_program_memory(&s_hangtime,&hangtime,1);
    read_program_memory(&s_cbeepdelay,&cbeepdelay,1);
    read_program_memory(&s_id_volume,&id_volume,1);
    read_program_memory(&s_recv_volume,&recv_volume,1);
    read_program_memory(&s_cbeep_speed,&cbeep_speed,1);
    read_program_memory(&s_id_time,&id_time,2);
    read_program_memory(&s_first_id,&first_id,2);
    read_program_memory(&s_beacon_time,&beacon_time,2);
    read_program_memory(&s_cbeep_tone,&cbeep_tone,2);
    read_program_memory(&s_cwid_tone,&cwid_tone,2);
    read_program_memory(&s_watchdog,&watchdog,2);
    read_program_memory(&s_id_delay,&id_delay,2);
    read_program_memory(&s_msg,msg,192);
}

void write_params_to_flash(void) {
// If the ROM parameters were stored in the block
// beginning at F800, the line below would work. 
// Since they're not, it will erase the config words
// along with the parameters.
//    erase_program_eeprom((&s_speed & 0xFC00));
    write_program_memory(&s_speed,&speed,1);
    write_program_memory(&s_hangtime,&hangtime,1);
    write_program_memory(&s_cbeepdelay,&cbeepdelay,1);
    write_program_memory(&s_cbeep_speed,&cbeep_speed,1);
    write_program_memory(&s_id_volume,&id_volume,1);
    write_program_memory(&s_recv_volume,&recv_volume,1);
    write_program_memory(&s_cbeep_speed,&cbeep_speed,1);
    write_program_memory(&s_id_time,&id_time,2);
    write_program_memory(&s_first_id,&first_id,2);
    write_program_memory(&s_beacon_time,&beacon_time,2);
    write_program_memory(&s_cbeep_tone,&cbeep_tone,2);
    write_program_memory(&s_cwid_tone,&cwid_tone,2);
    write_program_memory(&s_watchdog,&watchdog,2);
    write_program_memory(&s_id_delay,&id_delay,2);
    write_program_memory(&s_msg,msg,192);
}

// These don't work for me because the compiler puts the stuff
// in program ROM in reverse order...
void write_by_block(void) {
    write_program_memory(&s_speed,&speed,211);
}

void read_by_block(void) {
    read_program_memory(&s_speed,&speed,211);
}

void main(void) {

    speed = 20;
    hangtime = 25;
    cbeepdelay = 5;
    id_volume = 75;
    recv_volume = 100;
    cbeep_speed = 30;
    id_time = 600;
    first_id = 10;
    beacon_time = 3600;
    cbeep_tone = 2000;
    cwid_tone = 1000;
    watchdog = 240;
    id_delay = 5;
    msg[0] = "This is a test";
    msg[1] = "Another test string";
   
    write_params_to_flash();
    read_params_from_flash();
    write_by_block();
    read_by_block();
}

Compiling this I get the following from the .SYM file:
Code:
User Memory space:
 00FFF6-00FFF6  s_speed
 00FFF4-00FFF4  s_hangtime
 00FFF2-00FFF2  s_cbeepdelay
 00FFF0-00FFF0  s_id_volume
 00FFEE-00FFEE  s_recv_volume
 00FFEC-00FFEC  s_cbeep_speed
 00FFEA-00FFEB  s_id_time
 00FFE8-00FFE9  s_first_id
 00FFE6-00FFE7  s_beacon_time
 00FFE4-00FFE5  s_cbeep_tone
 00FFE2-00FFE3  s_cwid_tone
 00FFE0-00FFE1  s_watchdog
 00FFDE-00FFDF  s_id_delay
 00FF1E-00FFDD  s_msg
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Sun Nov 28, 2010 6:06 pm     Reply with quote

You know, after looking at this for quite some time... I decided to just add a bloody I2C EEPROM to the board and be done with it. I could see how to make it work the way I wanted -- more or less -- with program ROM, but it was always going to be messy and inefficient. I could see it causing headaches for a long time to come when it came time to maintain the code. Since I'm already using I2C, I just had to find space for a TSSOP-8 package on the board.

Saved me almost 2K of program space, which I'm sure will come in handy later on.
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Sun Nov 28, 2010 6:46 pm     Reply with quote

I just recently did this for the 26j50 (and the 26j11) and it works fine -- but there are some things you have to keep in mind (as stated right in the datasheet):


When you are going to write to a space out there, you have to read the ENTIRE page into an array (like unsigned int buffer[1024])

Then you modify what you want... then erase and write it back.

You can also tell the compiler to put NOTHING out in that zone of memory you want.

I'll have to check, but it doesn't require that much memory (2k??!?!) of code to handle it.. but it does require at least one page's worth of RAM (1024bytes - ouch) to handle it.

So it can be done -- and reasonably "pain free".

-Ben

p.s. Also, consider keeping all your "save stuff" inside a structure.. then it's really easy to rattle the location and length of the structure back and forth to program memory and make it easy for the rest of your program to access. It's what I do anyway.
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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