eeprom_stm32: implement denser emulation, default to 4k

This commit is contained in:
Ilya Zhuravlev 2021-07-11 14:44:46 -04:00
parent cdf16e79a3
commit ae1d581ca7
3 changed files with 65 additions and 44 deletions

View file

@ -22,6 +22,10 @@
#include "dynamic_keymap.h" #include "dynamic_keymap.h"
#include "via.h" // for default VIA_EEPROM_ADDR_END #include "via.h" // for default VIA_EEPROM_ADDR_END
#ifdef STM32_EEPROM_ENABLE
# include "eeprom_stm32.h"
#endif
#ifdef VIAL_ENABLE #ifdef VIAL_ENABLE
#include "vial.h" #include "vial.h"
#endif #endif
@ -41,6 +45,8 @@
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 4095 # define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 4095
# elif defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATtiny85__) # elif defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATtiny85__)
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 511 # define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 511
# elif defined(FEE_DENSITY_BYTES)
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR FEE_DENSITY_BYTES-1
# else # else
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 1023 # define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 1023
# endif # endif

View file

@ -21,18 +21,24 @@
#include <string.h> #include <string.h>
#include "eeprom_stm32.h" #include "eeprom_stm32.h"
/* In-memory contents of emulated eeprom for faster access */ #define SNAPSHOT_START (FEE_BASE_ADDRESS)
#define SNAPSHOT_END (FEE_BASE_ADDRESS+FEE_SNAPSHOT_SIZE)
#define WRITELOG_START (SNAPSHOT_END)
#define WRITELOG_END (WRITELOG_START+FEE_WRITELOG_SIZE)
/* In-memory contents of emulated eeprom for direct faster access */
static uint8_t DataBuf[FEE_DENSITY_BYTES]; static uint8_t DataBuf[FEE_DENSITY_BYTES];
/* Pointer to the first available slot within flash area */ /* Pointer to the first available slot within the writelog */
static uint8_t *empty_slot; static uint8_t *empty_slot;
void EEPROM_Init(void) { void EEPROM_Init(void) {
memset(DataBuf, 0, sizeof(DataBuf)); /* First, load the snapshot directly from flash */
memcpy(DataBuf, (void*)FEE_BASE_ADDRESS, FEE_SNAPSHOT_SIZE);
/* Load emulated eeprom contents from flash into memory */ /* Then, process writelog to update DataBuf entries */
uint8_t *addr; uint8_t *addr;
for (addr = (uint8_t*)FEE_PAGE_BASE_ADDRESS; addr < (uint8_t*)FEE_LAST_PAGE_ADDRESS; addr += 4) { for (addr = (uint8_t*)WRITELOG_START; addr < (uint8_t*)WRITELOG_END; addr += 4) {
uint16_t address; uint16_t address;
uint8_t value; uint8_t value;
memcpy(&address, addr, sizeof(address)); memcpy(&address, addr, sizeof(address));
@ -46,16 +52,16 @@ void EEPROM_Init(void) {
empty_slot = addr; empty_slot = addr;
} }
/* Clear flash contents (doesn't touch in-memory DataBuf) */ /* Erase flash contents so we can put updated data in (doesn't touch in-memory DataBuf) */
static void eeprom_clear(void) { static void eeprom_clear(void) {
FLASH_Unlock(); FLASH_Unlock();
for (uint32_t page_num = 0; page_num < FEE_DENSITY_PAGES; ++page_num) for (uint32_t erase_address = SNAPSHOT_START; erase_address < WRITELOG_END; erase_address += FEE_PAGE_SIZE)
FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page_num * FEE_PAGE_SIZE)); FLASH_ErasePage(erase_address);
FLASH_Lock(); FLASH_Lock();
empty_slot = (void*)FEE_PAGE_BASE_ADDRESS; empty_slot = (void*)WRITELOG_START;
} }
/* Erase emulated eeprom */ /* Erase emulated eeprom */
@ -67,29 +73,28 @@ void EEPROM_Erase(void) {
static void eeprom_writedatabyte(uint16_t Address, uint8_t DataByte); static void eeprom_writedatabyte(uint16_t Address, uint8_t DataByte);
/* Dump in-memory contents into flash */ /* Dump in-memory eeprom contents into the snapshot area */
static void eeprom_restore(void) { static void eeprom_write_snapshot(void) {
for (uint32_t i = 0; i < FEE_DENSITY_BYTES; ++i) { FLASH_Unlock();
/* don't bother writing zeroes */
if (DataBuf[i]) { for (uint32_t i = 0; i < FEE_DENSITY_BYTES; i += 2) {
eeprom_writedatabyte(i, DataBuf[i]); uint16_t halfword;
} memcpy(&halfword, &DataBuf[i], sizeof(halfword));
FLASH_ProgramHalfWord(SNAPSHOT_START + i, halfword);
} }
FLASH_Lock();
} }
static void eeprom_writedatabyte(uint16_t Address, uint8_t DataByte) { static void eeprom_writedatabyte(uint16_t Address, uint8_t DataByte) {
/* if couldn't find an empty spot, we must re-initialize emulated eeprom */ /* if couldn't find an empty spot, we must re-initialize emulated eeprom */
if (empty_slot >= (uint8_t*)FEE_LAST_PAGE_ADDRESS) { if (empty_slot >= (uint8_t*)WRITELOG_END) {
/* ensure that the following call to eeprom_restore will write our desired byte value */
DataBuf[Address] = DataByte;
/* fully erase emulated eeprom */ /* fully erase emulated eeprom */
eeprom_clear(); eeprom_clear();
/* and then write DataBuf contents back into flash */ /* and then write DataBuf contents back into flash */
eeprom_restore(); eeprom_write_snapshot();
/* don't need to do anything else as eeprom_restore already wrote our value */
return; return;
} }
@ -106,7 +111,7 @@ static void eeprom_writedatabyte(uint16_t Address, uint8_t DataByte) {
empty_slot += 4; empty_slot += 4;
} }
void EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte) { static void EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte) {
/* if the address is out-of-bounds, do nothing */ /* if the address is out-of-bounds, do nothing */
if (Address >= FEE_DENSITY_BYTES) if (Address >= FEE_DENSITY_BYTES)
return; return;
@ -115,14 +120,14 @@ void EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte) {
if (DataBuf[Address] == DataByte) if (DataBuf[Address] == DataByte)
return; return;
/* perform the write into flash memory */
eeprom_writedatabyte(Address, DataByte);
/* keep DataBuf cache in sync */ /* keep DataBuf cache in sync */
DataBuf[Address] = DataByte; DataBuf[Address] = DataByte;
/* perform the write into flash memory */
eeprom_writedatabyte(Address, DataByte);
} }
uint8_t EEPROM_ReadDataByte(uint16_t Address) { static uint8_t EEPROM_ReadDataByte(uint16_t Address) {
uint8_t DataByte = 0x00; uint8_t DataByte = 0x00;
if (Address < FEE_DENSITY_BYTES) if (Address < FEE_DENSITY_BYTES)

View file

@ -37,11 +37,10 @@
# define MCU_STM32F072CB # define MCU_STM32F072CB
#elif defined(EEPROM_EMU_STM32F042x6) #elif defined(EEPROM_EMU_STM32F042x6)
# define MCU_STM32F042K6 # define MCU_STM32F042K6
#else
# error "not implemented."
#endif #endif
#ifndef EEPROM_PAGE_SIZE /* The page_size * density_pages should provide 8k of space, split 4k/4k between snapshot and writelog in the default config */
#ifndef FEE_DENSITY_PAGES
# if defined(MCU_STM32F103RB) || defined(MCU_STM32F042K6) # if defined(MCU_STM32F103RB) || defined(MCU_STM32F042K6)
# define FEE_PAGE_SIZE (uint16_t)0x400 // Page size = 1KByte # define FEE_PAGE_SIZE (uint16_t)0x400 // Page size = 1KByte
# define FEE_DENSITY_PAGES 8 // How many pages are used # define FEE_DENSITY_PAGES 8 // How many pages are used
@ -49,11 +48,13 @@
# define FEE_PAGE_SIZE (uint16_t)0x800 // Page size = 2KByte # define FEE_PAGE_SIZE (uint16_t)0x800 // Page size = 2KByte
# define FEE_DENSITY_PAGES 4 // How many pages are used # define FEE_DENSITY_PAGES 4 // How many pages are used
# else # else
# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." # error "No MCU type specified and FEE_DENSITY_PAGES not defined.\
Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)\
or define FEE_DENSITY_PAGES yourself."
# endif # endif
#endif #endif
#ifndef EEPROM_START_ADDRESS #ifndef FEE_MCU_FLASH_SIZE
# if defined(MCU_STM32F103RB) || defined(MCU_STM32F072CB) # if defined(MCU_STM32F103RB) || defined(MCU_STM32F072CB)
# define FEE_MCU_FLASH_SIZE 128 // Size in Kb # define FEE_MCU_FLASH_SIZE 128 // Size in Kb
# elif defined(MCU_STM32F042K6) # elif defined(MCU_STM32F042K6)
@ -65,23 +66,32 @@
# elif defined(MCU_STM32F303CC) # elif defined(MCU_STM32F303CC)
# define FEE_MCU_FLASH_SIZE 256 // Size in Kb # define FEE_MCU_FLASH_SIZE 256 // Size in Kb
# else # else
# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." # error "No MCU type specified and FEE_MCU_FLASH_SIZE not defined.\
Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)\
or define FEE_MCU_FLASH_SIZE yourself."
# endif # endif
#endif #endif
/* Start of the emulated eeprom flash area */ #ifndef FEE_BASE_ADDRESS
#define FEE_PAGE_BASE_ADDRESS ((uint32_t)(0x8000000 + FEE_MCU_FLASH_SIZE * 1024 - FEE_DENSITY_PAGES * FEE_PAGE_SIZE)) /* Start of the emulated eeprom flash area, place it at the end of the flash memory */
/* End of the emulated eeprom flash area */ #define FEE_BASE_ADDRESS ((uint32_t)(0x8000000 + FEE_MCU_FLASH_SIZE * 1024 - FEE_DENSITY_PAGES * FEE_PAGE_SIZE))
#define FEE_LAST_PAGE_ADDRESS (FEE_PAGE_BASE_ADDRESS + (FEE_PAGE_SIZE * FEE_DENSITY_PAGES)) #endif
/* Size of emulated eeprom */
#define FEE_DENSITY_BYTES 1024 #ifndef FEE_SNAPSHOT_SIZE
/* Size of eeprom snapshot, in bytes. This is equal to emulated eeprom size. */
#define FEE_SNAPSHOT_SIZE 4096
#endif
#ifndef FEE_WRITELOG_SIZE
/* Size of eeprom writelog, in bytes */
#define FEE_WRITELOG_SIZE 4096
#endif
/* Flash word value after erase */ /* Flash word value after erase */
#define FEE_EMPTY_WORD ((uint16_t)0xFFFF) #define FEE_EMPTY_WORD ((uint16_t)0xFFFF)
_Static_assert(FEE_DENSITY_PAGES * FEE_PAGE_SIZE >= FEE_DENSITY_BYTES * 8, /* Size of emulated eeprom */
"flash memory for emulated eeprom is too small; for correct functionality ensure it is at least 8x FEE_DENSITY_BYTES"); #define FEE_DENSITY_BYTES FEE_SNAPSHOT_SIZE
void EEPROM_Init(void); void EEPROM_Init(void);
void EEPROM_Erase(void); void EEPROM_Erase(void);
void EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte);
uint8_t EEPROM_ReadDataByte(uint16_t Address);