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 "flash_internal.h" // flash storage library API
|
||||||
#include "global.h" // global definitions
|
#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 */
|
/** flash page size */
|
||||||
static uint16_t flash_internal_page = 0;
|
static uint16_t flash_internal_page = 0;
|
||||||
/** end address of flash */
|
/** 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;
|
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)
|
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
|
flash_internal_eeprom_start = 0; // reset start 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_address = 0; // reset EEPROM address
|
||||||
flash_internal_eeprom_start = (uint32_t)&__flash_end - flash_internal_eeprom_pages * flash_internal_page_size();
|
if (pages > DESIG_FLASH_SIZE * 1024 / flash_internal_page) { // not enough pages are available
|
||||||
} else {
|
return;
|
||||||
flash_internal_eeprom_start = (FLASH_BASE + DESIG_FLASH_SIZE * 1024) - flash_internal_eeprom_pages * flash_internal_page_size();
|
|
||||||
}
|
}
|
||||||
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
|
// find EEPROM in flash (first non-erased word)
|
||||||
flash_internal_eeprom_address = flash_internal_eeprom_start; // by default start with start of allocated flash memory
|
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);
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool flash_internal_eeprom_read(uint8_t *eeprom, uint16_t size)
|
bool flash_internal_eeprom_read(uint8_t *eeprom, uint16_t size)
|
||||||
{
|
{
|
||||||
// sanity checks
|
// 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;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size != *(uint16_t*)flash_internal_eeprom_address) { // check if size match
|
if (size != *(uint16_t*)flash_internal_eeprom_address) { // check if size match
|
||||||
return false;
|
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)
|
int32_t flash_internal_eeprom_write(const uint8_t *eeprom, uint16_t size)
|
||||||
{
|
{
|
||||||
// sanity checks
|
// 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;
|
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;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t current_size = *(uint16_t*)flash_internal_eeprom_address;
|
if (flash_internal_eeprom_start + size + 2U > flash_internal_eeprom_address) { // there is not enough free space
|
||||||
if (size == current_size) { // check if it already the same
|
// erase all EEPROM allocated pages
|
||||||
bool identical = true;
|
flash_unlock(); // unlock flash to be able to erase it
|
||||||
for (uint16_t i = 0; i < size; i++) {
|
for (uint32_t page_start = flash_internal_eeprom_start; page_start < flash_internal_end; page_start += flash_internal_page) {
|
||||||
if (eeprom[i] != *((uint8_t*)flash_internal_eeprom_address + 2 + i)) {
|
flash_erase_page(page_start); // erase current page
|
||||||
identical = false;
|
if (flash_get_status_flags() != FLASH_SR_EOP) { // operation went wrong
|
||||||
break;
|
flash_lock(); // lock back flash to protect it
|
||||||
|
return -3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (identical) { // no need to write since it's identical
|
flash_internal_eeprom_address = flash_internal_end; // put address back as the end
|
||||||
return size;
|
}
|
||||||
}
|
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
|
int32_t rc = flash_internal_write(flash_internal_eeprom_address, (uint8_t*)&size, 2, false); // write size
|
||||||
|
|
||||||
// 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);
|
|
||||||
if (2 != rc) {
|
if (2 != rc) {
|
||||||
return (-10 + 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) {
|
if (size != rc) {
|
||||||
return (-10 + rc);
|
return (-10 + rc);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue