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

Addresses of parameters in internal EEPROM

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



Joined: 22 Aug 2008
Posts: 21

View user's profile Send private message

Addresses of parameters in internal EEPROM
PostPosted: Fri Nov 14, 2014 10:43 am     Reply with quote

Hi,

I want to place some parameters in the pic's internal EEPROM and have them programmed during device programming.
Presently I have a working code but I'm wondering if there would be a better way to do it.

I need to have individual parameter addresses in order to be able to read them with read_eeprom(addr).
Since parameters have different types, I have to manually change the addresses if I add parameters or change types.

In the example below, if I want to change data2 type from int8 to int32 I must change all the #define to update the addresses.
The final program have more than 30 different parameters of mix types. Risk of errors is important.
I need a way to have data1_EEADR to data5_EEADR defined automatically and also have the initialization part updated.

I'm not sure if I could use a structure in EEPROM and how to initialize it.

Code:
#include "18F26K80.h"
#fuses INTRC_IO,NOWDT,MCLR,SOSC_DIG,NOPROTECT,NOPUT,BROWNOUT,NOCPD,STVREN,NOWRT,NOWRTD,NOWRTC,NOWRTB,NOEBTR,NOEBTRB,NOCPB

#define EE_MAP_ADR getenv("EEPROM_ADDRESS")

// parameter addresses in EEPRom
#define data1_EEADR 0x00
#define data2_EEADR 0x01   // previous 1 byte
#define data3_EEADR 0x02   // previous 1 byte
#define data4_EEADR 0x04    // previous 2 bytes
#define data5_EEADR 0x08    // previous 4 bytes

// default parameter values
#define data1_DEFAULT= {0x01}
#define data2_DEFAULT= {0x05}
#define data3_DEFAULT= {0x1122}
#define data4_DEFAULT= {0xAABBCCDD}
#define data5_DEFAULT= {0x13}

int i,j;
long k;
int32 l;

void main(void){
   i= read_eeprom(data1_EEADR);
   j= read_eeprom(data1_EEADR);
   k= read_eeprom(data1_EEADR);
   l= read_eeprom(data1_EEADR);
   while(1);
}

// Initialisation of EEProm
#rom int   EE_MAP_ADR + data1_EEADR= {data1_DEFAULT}
#rom int   EE_MAP_ADR + data2_EEADR= {data2_DEFAULT}
#rom long  EE_MAP_ADR + data3_EEADR= {data3_DEFAULT}
#rom int32 EE_MAP_ADR + data4_EEADR= {data4_DEFAULT}
#rom int   EE_MAP_ADR + data5_EEADR= {data5_DEFAULT}
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Sat Nov 15, 2014 7:08 am     Reply with quote

Quote:

if I want to change data2 type from int8 to int32 I must change all the #define to update the addresses.



the code you present makes no sense to me.

you have totally stumped this chump.

From what you wrote, i can not tell if you are confused about how
to use the CCS compiler directives
OR
by the address scheme of your PIC
OR
about using 'C in general.

this much is certain:
read_eeprom() only returns one byte - no matter what the var type
where you try to stuff it. Examining the .LST file will show you what is going on in your main()
JacquesB



Joined: 22 Aug 2008
Posts: 21

View user's profile Send private message

PostPosted: Mon Nov 17, 2014 8:06 am     Reply with quote

Hi asmboy

Your're right. that's stupid.
the original program is much more complex and I wanted emphasize the definition part and I screwed the main(). (copy paste!)

the main() should have been :
Code:

   i= read_eeprom(data1_EEADR);
   j= read_eeprom(data2_EEADR);
   k= L_int_from_eeprom(data3_EEADR);               // read a long int
   l= LL_in_from_eeprom(data4_EEADR);                  // read a int32
 

Anyway, the code is working OK but I just wanted to know if there is a better way to reserve the adresses in the EEPROM based on the parameter's type.

i,j,k,l are variables that are initialized from parameter values in EEPROM.
The parameter addresses depends on the variable types.
Defining the parameter's addresses the way I did requires manual calculation, thus possible errors.

Another way could be:
Code:

// parameter addresses in EEPRom
#define data1_EEADR 0x00        // address where content of i is taken
#define data2_EEADR data1_EEADR+ sizeof(i)    // address where content of j is taken
#define data3_EEADR data1_EEADR+ sizeof(j)   // address where content of k is taken
#define data4_EEADR data1_EEADR+ sizeof(k)   // address where content of l is taken
#define data5_EEADR data1_EEADR+ sizeof(l)    // address where content of _ is taken

Does it make more sense now?
If not let me know. I may not be using the proper words since english is not my native language.

Thanks
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Mon Nov 17, 2014 9:38 am     Reply with quote

the basic facts are these:
1- all core EEPROM operations are one byte at a time for READ and WRITE
( and they are relatively SLOW to execute on WRITE )

2- its up to YOU to reserve appropriate base addresses and number of bytes of "extent" to hold all the data you wish to store.

3- your code needs to disassemble any numeric type greater than an int8 or byte for storage ( and reassemble it on READ)

4- YOU decide if the bytes that make up a two or more byte numeric type are desired to be in BIG endian format or not . Or any order you choose. The compiler has no tools that control write order.

the details are up to you. The compiler has the tools to turn higher order numeric types into bytes , so there you go.
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Mon Nov 17, 2014 10:16 am     Reply with quote

I'd suggest blocking your configurations together. Do some thought, and if (for instance), there is a config for one part of the code, that is always loaded together, then 'keep it together'. Use a structure to hold the whole config. Then put the entries per line to match the element in the structure (see what I show below), and use the sizes automatically to generate the addresses. So:
Code:

typedef struct
{
    int8 light;
    int16 factor1;
    int8 factor2;
    int16 another; //dummy layout
} config;
typedef struct
{
    int16 another;
    int8 more; //and more
} second_config;

#define CONFIG_ADDR getenv("EEPROM_ADDRESS")
#ROM int8 CONFIG_ADDR = { 0x01,
                     0x04,0x08,
                     0x12,
                     0x02,0x12 } //each line matches a line in the struct
#define SECOND_CONFIG_ADDR CONFIG_ADDR+sizeof(config)
//Address is automatically calculated for the next element.
#ROM int8 SECOND_CONFIG_ADDR = { 0x14, 0x12,
                            0x12 }

//routine to read any size element - int16 if ROM is over 256bytes needed.
void read_struct(char * data, int8 size, int8 address)
{
   int8 count;
   for (count=0;count<size;count++)
      data[count]=read_eeprom(count);
}

void main()
{
   config eeprom_data;
   second_config eeprom_data2; //generate variables to hold data

   read_struct(&eeprom_data,sizeof(config),CONFIG_ADDR);
   read_struct(&eeprom_data2,sizeof(second_config),SECOND_CONFIG_ADDR);
   //and read
   while(TRUE)
   {
     
   }
}
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Mon Nov 17, 2014 10:27 am     Reply with quote

I keep things simple. I try to make all my EEPROM data two types: sixteen bit signed or unsigned and read/write them all as sixteen bit entities. Bytes are too restrictive, though addressing what are effectively byte pairs can get confusing.

I split strings up into two byte substrings and store them in my sixteen bit locations. I don't store as floats, but as scaled integers, sixteen bit naturally.

Its all to make my life simpler, or at least make it possible for me to have a consistent approach to EEPROM storage. I also have some common code that does CRC checking on EEPROM data, ensuring that I can detect corruption of configurations and settings. For the record, so far, my code hasn't detected any, which is a good thing.

One point, V4.xxx compilers defaulted to 16 bit words when using #rom, and you only had to specify the type when using bytes. All V5.xxx compilers default to bytes, and you must specify when you're using 16 bit words. This can make for frustrating incompatibilities between EEPROM code that worked in V4 but doesn't in V5. I now ensure I ALWAYS specify the type and don't rely on the default.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Nov 17, 2014 10:47 am     Reply with quote

I think he would like to:
1. typedef a packed structure in eeprom.
2. Initialize an instance of it.

But I don't think you can do this in CCS.

Failing that, he wants the easiest alternate method.
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Tue Nov 18, 2014 2:51 am     Reply with quote

That's the sort of situation addressmod() would be useful for. Addressmod allows variables, including complex structures to be mapped on to non-internal RAM memories, such as internal and external EEPROM, using simple access, i.e. read and write, routines. Pity it doesn't work too well....

I fight shy of trying to be too "clever" with sort of thing. I like to keep things simple, rather than impose my will on the hardware - e.g. saying this "should" work and I'll move mountains to make it work, and its not "my fault" if it won't - I try to work within its limitations.
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