VersaMCU/src/config/macro_config.cpp

82 lines
2.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// macro_config.cpp
// NVM-Zugriff für die Makro-Tabelle (Row 0+1, 0x1FB000x1FCFF, 512 Bytes).
// Nutzt dieselben NVMCTRL-Hilfsfunktionen wie nvm_config.cpp (dupliziert,
// da static kein gemeinsamer Header für interne NVM-Helfer).
#include "macro_config.h"
#include <Arduino.h>
#include <string.h>
static const uint32_t k_macro_addr = 0x1FB00UL; // Row 0+1 (zwei Rows à 256B)
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;
return nvm_wait();
}
static bool nvm_erase_row(uint32_t addr)
{
if (!nvm_wait()) return false;
NVMCTRL->ADDR.reg = addr / 2;
return nvm_exec(NVMCTRL_CTRLA_CMD_ER);
}
static bool nvm_write_page(uint32_t addr, const uint8_t* data)
{
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;
return nvm_exec(NVMCTRL_CTRLA_CMD_WP);
}
bool macro_config_load(SMacroTable& tbl)
{
memcpy(&tbl, reinterpret_cast<const void*>(k_macro_addr), sizeof(tbl));
// Prüfen ob beide Rows noch gelöscht sind (alle 0xFF = nie beschrieben)
const uint8_t* raw = reinterpret_cast<const uint8_t*>(&tbl);
bool all_ff = true;
for (uint16_t i = 0; i < sizeof(tbl); i++) {
if (raw[i] != 0xFF) { all_ff = false; break; }
}
if (all_ff) {
memset(&tbl, 0, sizeof(tbl)); // Leere Tabelle als Default
return false;
}
return true;
}
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 →
// direkter uint32_t*-Cast würde auf Cortex-M0+ einen HardFault auslösen.
uint8_t aligned_buf[512] __attribute__((aligned(4)));
memcpy(aligned_buf, &tbl, sizeof(tbl));
NVMCTRL->CTRLB.bit.MANW = 1;
// Beide Rows löschen (Row 0: 0x1FB00, Row 1: 0x1FC00)
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++) {
if (!nvm_write_page(k_macro_addr + p * 64, aligned_buf + p * 64)) return false;
}
return true;
}