flash_internal: fix, EEPROM now grows from the end since invalidating does not work
This commit is contained in:
parent
b7e72bba67
commit
becf280d9a
|
@ -31,8 +31,6 @@
|
|||
#include "flash_internal.h" // flash storage library API
|
||||
#include "global.h" // global definitions
|
||||
|
||||
/** number of flash pages, located at the end of flash memory, to use for EEPROM functionality */
|
||||
static uint16_t flash_internal_eeprom_pages = 0;
|
||||
/** flash page size */
|
||||
static uint16_t flash_internal_page = 0;
|
||||
/** end address of flash */
|
||||
|
@ -228,45 +226,40 @@ int32_t flash_internal_write(uint32_t address, const uint8_t *buffer, size_t siz
|
|||
return written;
|
||||
}
|
||||
|
||||
/* the EEPROM allocated area is erased at first
|
||||
* the EEPROM data starts at the end of the allocated memory
|
||||
* each time it is written, the next data segment is placed before the existing one
|
||||
* a data segment start with the size, which help detecting the segment since the data can be the same as erased data (0xffff)
|
||||
*/
|
||||
void flash_internal_eeprom_setup(uint16_t pages)
|
||||
{
|
||||
flash_internal_eeprom_pages = pages; // just need to remember the number of pages
|
||||
if (0 == flash_internal_page || 0 == flash_internal_end) {
|
||||
flash_internal_init(); // get page size and flash end
|
||||
}
|
||||
|
||||
// get allocated memory address
|
||||
if ((uint32_t)&__flash_end >= FLASH_BASE) { // check if the end for the internal flash is enforced by the linker script
|
||||
flash_internal_eeprom_start = (uint32_t)&__flash_end - flash_internal_eeprom_pages * flash_internal_page_size();
|
||||
} else {
|
||||
flash_internal_eeprom_start = (FLASH_BASE + DESIG_FLASH_SIZE * 1024) - flash_internal_eeprom_pages * flash_internal_page_size();
|
||||
flash_internal_eeprom_start = 0; // reset start address
|
||||
flash_internal_eeprom_address = 0; // reset EEPROM address
|
||||
if (pages > DESIG_FLASH_SIZE * 1024 / flash_internal_page) { // not enough pages are available
|
||||
return;
|
||||
}
|
||||
flash_internal_eeprom_start -= flash_internal_eeprom_start % flash_internal_page_size(); // ensure it starts at start of page
|
||||
flash_internal_eeprom_start = flash_internal_end - flash_internal_page * pages; // set EEPROM start (page aligned)
|
||||
|
||||
// find EEPROM in flash
|
||||
flash_internal_eeprom_address = flash_internal_eeprom_start; // by default start with start of allocated flash memory
|
||||
for (uint32_t addr = flash_internal_eeprom_start; addr < flash_internal_eeprom_start + flash_internal_eeprom_pages * flash_internal_page_size() - 2; addr += 2) {
|
||||
if (0 != *(uint16_t*)addr) { // 0 is invalidated flash
|
||||
flash_internal_eeprom_address = addr; // we found a valid address, which should be the size of the EEPROM
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint16_t size = *(uint16_t*)flash_internal_eeprom_address;
|
||||
if (size + 2U > flash_internal_eeprom_pages * flash_internal_page_size()) { // there is not enough space
|
||||
flash_internal_eeprom_address = flash_internal_eeprom_start; // set back to start
|
||||
}
|
||||
if (0 != size && flash_internal_eeprom_address + 2U + size > flash_internal_eeprom_start + flash_internal_eeprom_pages * flash_internal_page_size()) { // the size seems to be valid to there is not enough remaining space
|
||||
flash_internal_eeprom_address = flash_internal_eeprom_start; // set back to start
|
||||
}
|
||||
// find EEPROM in flash (first non-erased word)
|
||||
for (flash_internal_eeprom_address = flash_internal_eeprom_start; flash_internal_eeprom_address < flash_internal_end && 0xffff == *(uint16_t*)flash_internal_eeprom_address; flash_internal_eeprom_address += 2);
|
||||
}
|
||||
|
||||
bool flash_internal_eeprom_read(uint8_t *eeprom, uint16_t size)
|
||||
{
|
||||
// sanity checks
|
||||
if (NULL == eeprom || 0 == size || 0 == flash_internal_eeprom_pages || 0 == flash_internal_eeprom_start || 0 == flash_internal_eeprom_address) {
|
||||
if (NULL == eeprom || 0 == size || 0xffff == size || 0 == flash_internal_eeprom_start || 0 == flash_internal_eeprom_address) {
|
||||
return false;
|
||||
}
|
||||
if (size + 2U > flash_internal_eeprom_pages * flash_internal_page_size()) { // not enough space
|
||||
if (size + 2U > flash_internal_end - flash_internal_eeprom_start) { // not enough space
|
||||
return false;
|
||||
}
|
||||
if (size + 2U > flash_internal_end - flash_internal_eeprom_address) { // EEPROM size is too large
|
||||
return false;
|
||||
}
|
||||
|
||||
if (size != *(uint16_t*)flash_internal_eeprom_address) { // check if size match
|
||||
return false;
|
||||
}
|
||||
|
@ -277,49 +270,38 @@ bool flash_internal_eeprom_read(uint8_t *eeprom, uint16_t size)
|
|||
int32_t flash_internal_eeprom_write(const uint8_t *eeprom, uint16_t size)
|
||||
{
|
||||
// sanity checks
|
||||
if (NULL == eeprom || 0 == size || 0 == flash_internal_eeprom_pages || 0 == flash_internal_eeprom_start || 0 == flash_internal_eeprom_address) {
|
||||
if (NULL == eeprom || 0 == size || 0xffff == size || 0 == flash_internal_eeprom_start || 0 == flash_internal_eeprom_address) {
|
||||
return -1;
|
||||
}
|
||||
if (size + 2U > flash_internal_eeprom_pages * flash_internal_page_size()) { // not enough space
|
||||
if (size + 2U > flash_internal_end - flash_internal_eeprom_start) { // not enough space
|
||||
return -2;
|
||||
}
|
||||
|
||||
uint16_t current_size = *(uint16_t*)flash_internal_eeprom_address;
|
||||
if (size == current_size) { // check if it already the same
|
||||
bool identical = true;
|
||||
for (uint16_t i = 0; i < size; i++) {
|
||||
if (eeprom[i] != *((uint8_t*)flash_internal_eeprom_address + 2 + i)) {
|
||||
identical = false;
|
||||
break;
|
||||
if (flash_internal_eeprom_start + size + 2U > flash_internal_eeprom_address) { // there is not enough free space
|
||||
// erase all EEPROM allocated pages
|
||||
flash_unlock(); // unlock flash to be able to erase it
|
||||
for (uint32_t page_start = flash_internal_eeprom_start; page_start < flash_internal_end; page_start += flash_internal_page) {
|
||||
flash_erase_page(page_start); // erase current page
|
||||
if (flash_get_status_flags() != FLASH_SR_EOP) { // operation went wrong
|
||||
flash_lock(); // lock back flash to protect it
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
if (identical) { // no need to write since it's identical
|
||||
return size;
|
||||
}
|
||||
flash_internal_eeprom_address = flash_internal_end; // put address back as the end
|
||||
}
|
||||
flash_internal_eeprom_address -= (size + 2U); // get new start of data segment
|
||||
if (flash_internal_eeprom_address % 2) { // have segment word aligned
|
||||
flash_internal_eeprom_address--;
|
||||
}
|
||||
if (flash_internal_eeprom_address < flash_internal_eeprom_start) { // just to be sure
|
||||
return -4;
|
||||
}
|
||||
|
||||
// one optimisation would be to check if we just need to flip bits to 0, than we could reuse the same location
|
||||
|
||||
// invalidate current EEPROM
|
||||
const uint8_t zero[2] = {0, 0};
|
||||
flash_internal_write(flash_internal_eeprom_address, zero, 2, false);
|
||||
flash_internal_eeprom_address += 2;
|
||||
while (current_size && flash_internal_eeprom_address < flash_internal_eeprom_start + flash_internal_eeprom_pages * flash_internal_page_size()) {
|
||||
flash_internal_write(flash_internal_eeprom_address, zero, 2, false);
|
||||
current_size -= 2;
|
||||
flash_internal_eeprom_address += 2;
|
||||
}
|
||||
|
||||
// go to start if there is not enough remaining space
|
||||
if (flash_internal_eeprom_address + size + 2U > flash_internal_eeprom_start + flash_internal_eeprom_pages * flash_internal_page_size()) {
|
||||
flash_internal_eeprom_address = flash_internal_eeprom_start;
|
||||
}
|
||||
|
||||
int32_t rc = flash_internal_write(flash_internal_eeprom_address, (uint8_t*)&size, 2, false);
|
||||
int32_t rc = flash_internal_write(flash_internal_eeprom_address, (uint8_t*)&size, 2, false); // write size
|
||||
if (2 != rc) {
|
||||
return (-10 + rc);
|
||||
}
|
||||
rc = flash_internal_write(flash_internal_eeprom_address + 2, eeprom, size, false);
|
||||
rc = flash_internal_write(flash_internal_eeprom_address + 2, eeprom, size, false); // write data
|
||||
if (size != rc) {
|
||||
return (-10 + rc);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue