8 Step macro and profile switching fully working

This commit is contained in:
2026-04-13 22:34:54 +02:00
parent 098a166a9f
commit 433d61c29f
10 changed files with 204 additions and 193 deletions
+23 -13
View File
@@ -9,28 +9,37 @@
static const uint32_t k_macro_addr = 0x1FB00UL; // Row 0+1 (zwei Rows à 256B)
static void nvm_wait() { while (!NVMCTRL->INTFLAG.bit.READY) {} }
static void nvm_exec(uint16_t cmd)
static bool nvm_wait()
{
// ~400ms Timeout bei 48MHz, konservativ 4 Zyklen pro Loop-Iteration
uint32_t timeout = 48000000UL / 4 * 400 / 1000; // ≈ 4 800 000
while (!NVMCTRL->INTFLAG.bit.READY) {
if (--timeout == 0) return false;
}
return true;
}
static bool nvm_exec(uint16_t cmd)
{
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | cmd;
nvm_wait();
return nvm_wait();
}
static void nvm_erase_row(uint32_t addr)
static bool nvm_erase_row(uint32_t addr)
{
nvm_wait();
if (!nvm_wait()) return false;
NVMCTRL->ADDR.reg = addr / 2;
nvm_exec(NVMCTRL_CTRLA_CMD_ER);
return nvm_exec(NVMCTRL_CTRLA_CMD_ER);
}
static void nvm_write_page(uint32_t addr, const uint8_t* data)
static bool nvm_write_page(uint32_t addr, const uint8_t* data)
{
nvm_exec(NVMCTRL_CTRLA_CMD_PBC);
if (!nvm_exec(NVMCTRL_CTRLA_CMD_PBC)) return false;
volatile uint32_t* dst = reinterpret_cast<volatile uint32_t*>(addr);
const uint32_t* src = reinterpret_cast<const uint32_t*>(data);
for (uint8_t i = 0; i < 64 / 4; i++) dst[i] = src[i];
NVMCTRL->ADDR.reg = addr / 2;
nvm_exec(NVMCTRL_CTRLA_CMD_WP);
return nvm_exec(NVMCTRL_CTRLA_CMD_WP);
}
bool macro_config_load(SMacroTable& tbl)
@@ -50,7 +59,7 @@ bool macro_config_load(SMacroTable& tbl)
return true;
}
void macro_config_save(const SMacroTable& tbl)
bool macro_config_save(const SMacroTable& tbl)
{
// Auf 4-Byte-ausgerichteten Puffer kopieren bevor nvm_write_page ihn als uint32_t* liest.
// SMacroTable ist __attribute__((packed)) und könnte unaligned liegen →
@@ -61,11 +70,12 @@ void macro_config_save(const SMacroTable& tbl)
NVMCTRL->CTRLB.bit.MANW = 1;
// Beide Rows löschen (Row 0: 0x1FB00, Row 1: 0x1FC00)
nvm_erase_row(k_macro_addr);
nvm_erase_row(k_macro_addr + 256);
if (!nvm_erase_row(k_macro_addr)) return false;
if (!nvm_erase_row(k_macro_addr + 256)) return false;
// 8 Pages à 64B schreiben
for (uint8_t p = 0; p < 8; p++) {
nvm_write_page(k_macro_addr + p * 64, aligned_buf + p * 64);
if (!nvm_write_page(k_macro_addr + p * 64, aligned_buf + p * 64)) return false;
}
return true;
}