2026-05-29 3:43 AM
I have a problem with saving settings to flash memory on STM32L4P5CGUX.
I made a settings menu for my project, and the settings should be stored in flash so they stay after power off. The problem is that only one setting gets saved — always the first one, no matter which setting I change.
After restarting the device, the other settings are lost or not loaded correctly.
What could cause this issue?
/**
* @file SettingsManager.c
* @brief Persistent settings - stable version based on eeprom_emul.c
*/
#include "SettingsManager.h"
#include "stm32l4xx_hal.h"
#include <string.h>
/* Flash record (8 bytes) */
typedef struct __attribute__((packed)) {
uint16_t magic;
uint8_t tempUnit;
uint8_t showEnv;
uint8_t colorScheme;
uint8_t language;
uint8_t saveCounter;
uint8_t reserved;
} Settings_FlashRecord_t;
_Static_assert(sizeof(Settings_FlashRecord_t) == 8, "Settings_FlashRecord_t must be 8 bytes!");
static Settings_t settings;
static const Settings_t defaults = {
.tempUnit = 0,
.showEnv = 0,
.colorScheme = 0,
.language = 0
};
static void flash_load(void)
{
const Settings_FlashRecord_t* rec = (const Settings_FlashRecord_t*)SETTINGS_FLASH_ADDRESS;
if (rec->magic == SETTINGS_MAGIC)
{
settings.tempUnit = rec->tempUnit;
settings.showEnv = rec->showEnv;
settings.colorScheme = rec->colorScheme;
settings.language = rec->language;
}
else
{
settings = defaults;
}
}
void Settings_Init(void)
{
flash_load();
}
/* ================================================ */
/* Save - modeled exactly after eeprom_emul.c */
/* ================================================ */
static bool flash_save(void)
{
Settings_FlashRecord_t rec;
memset(&rec, 0xFF, sizeof(rec));
rec.magic = SETTINGS_MAGIC;
rec.tempUnit = settings.tempUnit;
rec.showEnv = settings.showEnv;
rec.colorScheme = settings.colorScheme;
rec.language = settings.language;
rec.saveCounter = 0x55; // diagnostic marker
if (HAL_FLASH_Unlock() != HAL_OK) {
return false;
}
/* Erase page */
FLASH_EraseInitTypeDef erase_init = {
.TypeErase = FLASH_TYPEERASE_PAGES,
.Banks = SETTINGS_FLASH_BANK,
.Page = SETTINGS_FLASH_PAGE,
.NbPages = 1
};
uint32_t page_error = 0;
HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase_init, &page_error);
if (status != HAL_OK || page_error != 0xFFFFFFFF) {
HAL_FLASH_Lock();
return false;
}
/* Write one doubleword */
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,
SETTINGS_FLASH_ADDRESS,
*(uint64_t*)&rec);
HAL_FLASH_Lock();
return (status == HAL_OK);
}
void Settings_Save(void)
{
flash_save();
}
/* ==================== Getters / Setters ==================== */
uint8_t Settings_GetTempUnit(void) { return settings.tempUnit; }
void Settings_SetTempUnit(uint8_t v) { settings.tempUnit = v; Settings_Save(); }
uint8_t Settings_GetShowEnv(void) { return settings.showEnv; }
void Settings_SetShowEnv(uint8_t v) { settings.showEnv = v; Settings_Save(); }
uint8_t Settings_GetColorScheme(void) { return settings.colorScheme; }
void Settings_SetColorScheme(uint8_t v) { settings.colorScheme = v; Settings_Save(); }
uint8_t Settings_GetLanguage(void) { return settings.language; }
void Settings_SetLanguage(uint8_t v) { settings.language = v; Settings_Save(); }