Q: Status of external EEPROM Support

ChibiOS public support forum for all topics not covered by a specific support forum.

Moderators: RoccoMarco, lbednarz, utzig, tfAteba, barthess

robert_o
Posts: 48
Joined: Fri Feb 17, 2017 11:25 pm
Has thanked: 1 time
Been thanked: 5 times

Q: Status of external EEPROM Support

Postby robert_o » Mon Mar 19, 2018 10:10 am

Just a Question:
It is a little difficult to get a picture of external EEPROM (24 or 25 Type, SPI or I2C) drivers. I found the following examples:
https://github.com/ChibiOS/ChibiOS-Contrib/tree/master/testhal/STM32/STM32F3xx/EEProm
https://github.com/timonwong/ChibiOS-EEPROM
https://github.com/barthess/24aa
and there is also some code in trunk/os/ex.
What i need: A possibility to store configuration data (structs) in a non-volatile storage. For now i have an external RTC (DS2331) with a 24C32 EEPROM on-board: https://www.ebay.de/itm/272449019914 and i want to use it.
Some guidance please.
Thank you.

User avatar
Giovanni
Site Admin
Posts: 14455
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: Q: Status of external EEPROM Support

Postby Giovanni » Mon Mar 19, 2018 10:14 am

Hi,

There is no official EEPROM driver, what we have is a Flash driver and a "Managed Storage" module. All the links you found are external contributions and have to be discussed with authors.

Giovanni

robert_o
Posts: 48
Joined: Fri Feb 17, 2017 11:25 pm
Has thanked: 1 time
Been thanked: 5 times

Re: Q: Status of external EEPROM Support

Postby robert_o » Mon Mar 19, 2018 10:25 am

Thank you for your reply. Quick as always :)
Did you mean the discussion here: http://www.chibios.com/forum/viewtopic.php?t=3320 ?
I think this is the code in trunk/os/ex right?
Can i use this for I2C EEPROM 24c32?
I know this is not really Chibios Support, it would just be nice to have some directions here and maybe some examples.
best regards,
robert.

User avatar
Giovanni
Site Admin
Posts: 14455
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: Q: Status of external EEPROM Support

Postby Giovanni » Mon Mar 19, 2018 11:24 am

Hi,

That is a flash driver, EEPROM has different requirements, there are no sectors, erase operation etc.

Giovanni

mobyfab
Posts: 483
Joined: Sat Nov 19, 2011 6:47 pm
Location: Le Mans, France
Has thanked: 21 times
Been thanked: 30 times

Re: Q: Status of external EEPROM Support

Postby mobyfab » Fri Mar 23, 2018 3:23 pm

Hi,

You can use the contrib eeprom driver, it does exactly what you need.

robert_o
Posts: 48
Joined: Fri Feb 17, 2017 11:25 pm
Has thanked: 1 time
Been thanked: 5 times

Re: Q: Status of external EEPROM Support

Postby robert_o » Fri Mar 23, 2018 10:05 pm

Thank you, mobyfab.
I actually did exactliy that and i now have the driver patially working but still have some questions.

First: this is my code for writing my variabls to eeprom:
i made a struct with arrays of pointer to whatever and sizes of the array elements:

Code: Select all

typedef struct {
  void* ptr[3];
  uint16_t sz[3];
} eeprom_data_t;

the three pointers point to the following:

Code: Select all

#define LENGTH 11
typedef struct{
  float in[LENGTH];        // Array of x-coordinates
  float out[LENGTH];       // Array of y-coordinates
  uint8_t t_length; // Number of data points
} table_1d_t ;

typedef struct {
  uint8_t screen;  // screen
  uint8_t bl;      // backlight
  uint8_t con;     // contrast
} DisplayData_t;

typedef struct {
  float corr_mult;  // ADC Factors
  int16_t corr_add;
  uint8_t principle;
} correction_t;

And this are the values:

Code: Select all

correction_t corr_val[6] = {
  {1.2, 0, 1},
  {1.5, 0, 1},
  {0.876, 0, 1},
  {1.0, 0, 3},
  {1.9, 0, 2},
  {0.5, 12, 3}
};
table_1d_t tables[4] = {
  {
   {0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}, //in
   {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}, //out
   11 //length
  },
  {
   {0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}, //in
   {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}, //out
   11 //length
  },
  {
   {0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}, //in
   {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}, //out
   11, //length
  },
  {
   {0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}, //in
   {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}, //out
   11 //length
  }
};
DisplayData_t DisplayData = {
  0,  //screen
  127, //backlight
  50 //contrast
};
eeprom_data_t ee_data = {
     {tables, &DisplayData, corr_val},  //pointers to structs, array of structs,...
     {sizeof(table_1d_t)*4, sizeof(DisplayData_t), sizeof(correction_t)*6} //sizes
};


Code: Select all

void cmd_dumpvar(BaseSequentialStream *chp, int argc, char *argv[]){
  (void)argc;
  (void)* argv;
  uint16_t sz, bs, szc;
  uint16_t i, idx, adr;
  int16_t pos;
  uint8_t* p;
  uint8_t* b;
  uint8_t buf[EEPROM_PAGE_SIZE];
  uint8_t temp;
  b=buf;
  chprintf(chp, "Dumps Struct Variable\r\n");
  sz = sizeof(ee_data.ptr)/sizeof(void*); //How many pointers are there
  chprintf(chp, "Pointers: %d\r\n", sz);
  szc = 0;                                 //reset total size
  adr = EEPROM_SETTINGS_START;             //set start address
  pos = eepfs_lseek(&EepromFile, adr);
  if (pos != eepfs_getposition(&EepromFile)){
    chprintf(chp, "EEPROM fseek Error\r\n");
    return;
  }
  for (idx = 0; idx<sz; idx++){           //go through all the pointers
    bs = ee_data.sz[idx];                //size of this data
    szc += bs;
    chprintf(chp, "size of ptr: %d\r\n", bs);
  }
  chprintf(chp, "size complete: %d\r\n", szc);
  chprintf(chp, "%d pages\r\n", szc/EEPROM_PAGE_SIZE);
  chprintf(chp, "%d rest\r\n", szc%EEPROM_PAGE_SIZE);
  if (szc > EEPROM_SETTINGS_SIZE){
    chprintf(chp, "size too big for eeprom!\r\n");
    return;
  }
  idx = 0;
  bs = ee_data.sz[idx];                 //reusing variable
  p=(uint8_t*)ee_data.ptr[idx];         //move pointer to first data bloc
  for (i=0; i<szc; i++){                //go through ALL the bytes
    if (i >= bs){                       //we are at the end of one bloc
      chprintf(chp, "old val: %x\r\n", temp);
      p=(uint8_t*)ee_data.ptr[idx++];   //move pointer to next data bloc
      bs += ee_data.sz[idx];            //calculate next boundary
      chprintf(chp, "next bloc: %d\r\n", i);
      chprintf(chp, "new val: %x\r\n", *p);
    }

    if ((i % EEPROM_PAGE_SIZE == 0) && (i>0)){ //if buffer is full...

      fileStreamWrite(&EepromFile, buf, EEPROM_PAGE_SIZE);
      b=buf;                                   //reset buffer
      chThdSleepMilliseconds(100);
      chprintf(chp, "Page written\r\n");
      adr += EEPROM_PAGE_SIZE;            //next page
      pos = eepfs_lseek(&EepromFile, adr);
      if (pos != eepfs_getposition(&EepromFile)){
        chprintf(chp, "EEPROM fseek Error\r\n");
        return;
      }
    }
    if (i%8 == 0){                      //beautyfy the output a little
      cli_println("");
    }
    chprintf(chp, "%x ", *p);           //print val

    *b = *p;                            //copy to buffer
    temp = *p;
    b++;
    p++;
  }
  cli_println("");
  if (szc > adr){
    chprintf(chp, "More Data to write, szc: %d, adr: %d, pos: %d\r\n", szc, adr, eepfs_getposition(&EepromFile));
  }
  fileStreamWrite(&EepromFile, buf, (szc-adr));
  for (i=0;i<szc-adr; i++){
    chprintf(chp, "%x ", buf[i]);           //print val
  }
  cli_println("");
}

my Questions:
    do i have to take care of the time the eprom needs to write or can i dump the whole buffer to fileStreamWrite?
    do i have to read first and compare to avoid uneccessary writes or does the driver do that?
    is fileStreamWrite the correct function to write many bytes and do i have to take care of the page size?

Thats all for now.
When i manage to finish the eprom read i will post the code on bitbucket:
https://bitbucket.org/100prozent/rob-rt-stm32f100-discovery-shell-eeprom/src/default/

mobyfab
Posts: 483
Joined: Sat Nov 19, 2011 6:47 pm
Location: Le Mans, France
Has thanked: 21 times
Been thanked: 30 times

Re: Q: Status of external EEPROM Support

Postby mobyfab » Tue Mar 27, 2018 6:11 pm

You should replicate what's in the demo.

You need to use SPIEepromFileOpen or I2CEepromFileOpen provided with the configs including eeprom size, page write time, etc. That way you can write any size of data directly.
You have to compare what you want to write, the driver does not check that.
fileStreamWrite works fine.

robert_o
Posts: 48
Joined: Fri Feb 17, 2017 11:25 pm
Has thanked: 1 time
Been thanked: 5 times

Re: Q: Status of external EEPROM Support

Postby robert_o » Tue Mar 27, 2018 8:52 pm

Thank you, the driver works fine. The demo is unfortunately for a SPI EPROM but i figured out how to use it.
To reduce the write occurences i could read one bloc into RAM, compare byte by byte and write only the different ones, would you agree?
The bitbucket link contains my code for writing a configuration and reading it back.
I have implemented:
-data is saved by pointing to the data set and supplying the size (see my last post for the struct)
-easy to maintain, no counting bytes no unions, no taking care of byte order,...
-doesn't matter if the struct is packed or not
-implemented checksum and version

todo:
-read back data and change only different ones
-better checksum algorithm
-more testing

when i am finished i will post in user projects.
Thank you all for your help and for an amazing operating system.
best regards,
robert

User avatar
HDKLog
Posts: 41
Joined: Thu Aug 18, 2016 12:36 am
Been thanked: 2 times

Re: Q: Status of external EEPROM Support

Postby HDKLog » Tue Mar 27, 2018 9:01 pm

Hello robert_o.
You can adapt any Arduino Driver to use in ChibiOS , just change Arduino SPI driver (I2C or whatever Interface) calls to ChibiOS HAL driver calls. EEPROM is volatile memory which will not erase after power cycle. Unlike Flash EEPROM has more small blocks which you can modify (8 bit , 16 bit , 32 bit blocks size, dephends on manufacturer and EEPROM type, see in Datasheet). Each block has its Address. Each EEPROM chip has communication Interface via specific Interface(SPI, I2C and so on). If you want to write Struct or any C type of data (float, int32_t, char and so on including arrays), you just need to reference on this types like on arrays of memory and send them byte by byte or few bytes if block size is more than 8 bit. for example if you want to send float variable to EEPROM for storage, you can do so like this:

Code: Select all

float my_var = 3.14; //32 bit float

EEPROM_Write(0, (uint8_t *)my_var,  sizeof(my_var)) //EEPROM library function takes address, reference  of memory and memory size in bytes



same about data structs:

Code: Select all


struct MyCostomStruct my_struct; //32 bit float

EEPROM_Write(20, (uint8_t *)my_struct,  sizeof(my_struct))  //EEPROM library function takes address, reference  of memory and memory size in bytes


mobyfab
Posts: 483
Joined: Sat Nov 19, 2011 6:47 pm
Location: Le Mans, France
Has thanked: 21 times
Been thanked: 30 times

Re: Q: Status of external EEPROM Support

Postby mobyfab » Wed Mar 28, 2018 3:44 pm

robert_o wrote:Thank you, the driver works fine. The demo is unfortunately for a SPI EPROM but i figured out how to use it.
To reduce the write occurences i could read one bloc into RAM, compare byte by byte and write only the different ones, would you agree?
The bitbucket link contains my code for writing a configuration and reading it back.
I have implemented:
-data is saved by pointing to the data set and supplying the size (see my last post for the struct)
-easy to maintain, no counting bytes no unions, no taking care of byte order,...
-doesn't matter if the struct is packed or not
-implemented checksum and version

todo:
-read back data and change only different ones
-better checksum algorithm
-more testing

when i am finished i will post in user projects.
Thank you all for your help and for an amazing operating system.
best regards,
robert


You can check my code here: https://github.com/fpoussin/MotoLink/bl ... /storage.c
I use the STM32's hardware CRC and implemented wear leveling for "table" (arrays) functions. ("writeTablesToEE", "readTablesFromEE", etc)

You can do a simple function to read data and compare before writing.
Byte by byte might be slower but you will have less writes than page by page.


Return to “General Support”

Who is online

Users browsing this forum: No registered users and 11 guests