Reputation: 133
When I apply these function on my code, I can write and read data on STM32 on-chip EEPROM.
#define EEPROM_BASE_ADDR 0x08080000
#define EEPROM_BYTE_SIZE 0x03FF
.
//Byte write
void EEPROM_WRITE(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
{
uint16_t i;
HAL_StatusTypeDef status = HAL_OK;
HAL_FLASHEx_DATAEEPROM_Unlock();
for(i=0;i<len;i++)
{
status +=HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EEPROM_BASE_ADDR+BiasAddress+i, *Data);
Data++;
}
HAL_FLASHEx_DATAEEPROM_Lock();
}
.
//Byte read
void EEPROM_READ(uint16_t BiasAddress,uint8_t *Buffer,uint16_t Len)
{
uint8_t *wAddr;
wAddr=(uint8_t *)(EEPROM_BASE_ADDR+BiasAddress);
while(Len--)
{
*Buffer++=*wAddr++;
}
}
My problem is that only one byte EEPROM write process taking too much time (6.57ms). How can I decrease this?
Upvotes: 2
Views: 2178
Reputation: 93556
The data sheet states 3.28ms typical to erase, and the same to write. 2 x 3.28 = 6.56ms which matches your observation.
You can halve the effective time, by not re-writing and rather simply writing successive values sequentially, using the last written value as the current read value. You would have to scan on start-up, to find the last valid value written, and eventually you will suffer a hit of having to erase a much larger block.
When you do write the EEPROM, if the real-time performance and precision of your application is critical, be sure to use only double-word write/erase operations to avoid bus-stalls:
From RM0038:
During a write/erase operation to the NVM (except Half Page programming or Double-word erase/write), any attempt to read the same bank of NVM stalls the bus. The read operation is executed correctly once the programming operation is completed. This means that code or data fetches cannot be performed while a write/erase operation is ongoing in the same bank.
A solution to this problem is to use an RTOS kernel and have a background service thread dedicated to writing to the EEPROM so that other higher priority threads can continue to do useful work concurrently. You might simply pass write instruction (address+length+data) messages on a queue for servicing in the background. The problem is that if you attempt to concurrently read the EEPROM whilst a write operation is in progress you may encounter the bus-stall issue mentioned above as well as data consistency issues.
A safer solution that also solves the performance issue would be for the EEPROM service to maintain a RAM "cache" copy of the EEPROM (or part of it) such that write instructions modify the RAM (in the calling thread context) then pass the write requests to the background EEPROM writer thread. Then the application reads from the RAM copy rather than from the EEPROM (via an accessor function - not directly). You would need a mutex to ensure data consistency, but the effect would be to decouple EEPROM read/write performance from application performance and from application threads, EEPROM operations would appear to be as fast as RAM operations (less the API call and mutex overhead)
You might in any case also need some data integrity check mechanism if you cannot guarantee power security during an EEPROM update. Maintaining two EEPROM copies of the data with a sequence number that is written last is a simple way of achieving power-fail consistency. The EEPROM thread would in that case write the entire RAM cache (with a re-startable write-back delay) in one go to alternate dual-redundant blocks. On start-up, the "active" block is the one with the highest value valid sequence number, and is copied to the RAM cache.
If your system can retain power (battery backup for example), you will get better non-volatile storage performance from the 32 x 32bit (128 byte) backup-register block - if that is sufficient for your application.
An external serial (SPI or I2C)EEPROM would have similar write/erase latency but without the bus stalling issue, and possibly greater endurance. Moreover you can typically pass a 64 byte "page" and program that in one operation taking no longer than a single byte. Moreover the RTOS service thread solution described above can be used for external EEPROM too, and you can use DMA or interrupt driven communication for concurrency.
Alternative non-volatile memory technologies such as FRAM (ferro-electric RAM) are faster.
Upvotes: 2