2026-05-16 5:13 AM
Hi,
FLASH_NVM (rx) : ORIGIN = 0x0801B000, LENGTH = 2K
[magic: uint32_t (4 B)] [Config_t (40 B)] [checksum: uint32_t (4 B)]
The Config_t struct:
typedef struct {
uint16_t volume_shown;
uint16_t client_timeout_ms;
uint16_t cup_detection_threshold;
uint16_t flow_timeout_forward_ms;
uint16_t flow_timeout_backward_ms;
uint16_t foam_ms;
uint16_t foam_decay_minutes;
uint16_t foam_ms_after_decay;
uint16_t steps_forward;
uint16_t steps_backward;
uint16_t step_increment;
uint16_t tick;
uint8_t use_hall_positioning;
uint8_t offline_operation;
uint8_t com_mode;
uint8_t integration_zig;
float adjust;
char serial_number[4];
RGB_Color_t led_color; // 3 bytes (r, g, b)
} Config_t; // sizeof = 40 bytes
FlashStorage_Status_t FlashStorage_Erase(void)
{
FLASH_EraseInitTypeDef erase_config;
uint32_t page_error = 0U;
uint32_t base = storage_base_addr(); // 0x0801B000
uint32_t page = (base - FLASH_BASE) / FLASH_PAGE_SIZE;
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
erase_config.TypeErase = FLASH_TYPEERASE_PAGES;
erase_config.Page = page;
erase_config.NbPages = 1U;
HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase_config, &page_error);
HAL_FLASH_Lock();
return (status == HAL_OK) ? FLASH_STORAGE_OK : FLASH_STORAGE_ERROR_ERASE;
}FlashStorage_Status_t FlashStorage_Write(uint32_t offset, const void *data, uint32_t size)
{
uint32_t address = storage_base_addr() + offset; // 0x0801B000 + 0
const uint64_t *src=(const uint64_t *)data;
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
for (uint32_t i = 0U; i < (size / 8U); i++) {
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, src[i]);
address += 8U;
}
HAL_FLASH_Lock();
return FLASH_STORAGE_OK;
}void Config_SaveToFlash(void)
{
uint8_t buf[128];
uint32_t magic = CONFIG_FLASH_MAGIC;
uint32_t new_checksum = compute_config_checksum(&config, sizeof(Config_t));
if (new_checksum == last_saved_checksum) return;
memset(buf, 0xFF, sizeof(buf));
memcpy(buf, &magic, 4);
memcpy(buf + 4, &config, sizeof(Config_t));
memcpy(buf + 4 + sizeof(Config_t), &new_checksum, 4);
FlashStorage_Erase();
FlashStorage_Write(0, buf, 48);
last_saved_checksum = new_checksum;
}
void Config_RequestSaveToFlash(void) {
save_pending = true;
save_request_tick = xTaskGetTickCount();
}
void Config_ProcessPendingSave(void) {
if (!save_pending) return;
if ((xTaskGetTickCount() - save_request_tick) < pdMS_TO_TICKS(3000)) return;
save_pending = false;
Config_SaveToFlash();
}