VersaMCU/doc/06_nvm_config.md

69 lines
2.5 KiB
Markdown
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.

# NVM-Konfiguration
**Dateien:** `config/nvm_config.h`, `config/nvm_config.cpp`
## Flash-Layout
| Row | Adresse | Größe | Inhalt |
|---|---|---|---|
| Row 0 | `0x1FE00` | 256 B | SDeviceConfig (223 B genutzt, 33 B Padding) |
| Row 1 | `0x1FF00` | 256 B | SMacroTable (256 B, komplett genutzt) |
Beide Rows sind im Linkerscript vom Code-Bereich ausgeschlossen.
## SDeviceConfig Byte-Layout (223 Byte, packed)
| Offset | Größe | Feld |
|---|---|---|
| 0 | 4 | `magic` = `0x56503202` ('VP2\x02') |
| 4 | 1 | `version` = 2 |
| 5 | 2 | `crc` CRC16-CCITT über Bytes 7222 |
| 7 | 60 | `mx_actions[20]` 20 × 3 B SAction |
| 67 | 36 | `enc_actions[4][3]` 12 × 3 B SAction |
| 103 | 20 | `led_r[20]` |
| 123 | 20 | `led_g[20]` |
| 143 | 20 | `led_b[20]` |
| 163 | 20 | `led_anim[20]` LEDAnim-Typ als uint8_t |
| 183 | 40 | `led_period_ms[20]` uint16_t, little-endian |
| **223** | — | Ende des genutzten Bereichs |
`__attribute__((packed))` ist zwingend. Ohne packed wäre SAction 4 B statt 3 B (Alignment-Padding), was `sizeof(SDeviceConfig)` um 32 B vergrößert und die C#-Deserialisierung in VersaGUI zerstört.
## CRC16-CCITT
- Polynom: `0x1021`, Init: `0xFFFF`
- Berechnet über Bytes 7248 (ab `mx_actions`, nach dem `crc`-Feld selbst)
- Sichert Datenintegrität nach NVM-Schreiben und bei Versionswechsel
## Lese-Logik
```
memcpy aus Flash-Adresse 0x1FE00
if magic != 0x56503202: Defaults laden, return false
if version != 2: Defaults laden, return false
if crc != crc(cfg): Defaults laden, return false
return true
```
Kein Absturz bei ungültiger Config Defaults greifen immer.
## Defaults
- Alle Aktionen: `NONE`
- LEDs: warm-weiß (R=80, G=40, B=0)
- Animation: `COLOR_CYCLE` (Typ 5), Period 4000 ms
## Schreib-Logik (NVM-Mechanik)
SAMD21 NVM: Row = 256 B = 4 Pages à 64 B. Schreiben erfordert:
1. `NVMCTRL->CTRLB.bit.MANW = 1` (manueller Schreib-Modus, kein Auto-Write)
2. Row löschen (`NVMCTRL_CTRLA_CMD_ER`)
3. Page-Buffer löschen (`NVMCTRL_CTRLA_CMD_PBC`)
4. 64 B als `uint32_t*` in Page-Buffer schreiben
5. Page programmieren (`NVMCTRL_CTRLA_CMD_WP`)
6. Schritte 35 viermal (für alle 4 Pages)
> `NVMCTRL->ADDR.reg = addr / 2` NVMCTRL erwartet Wort-Adresse (16-Bit-Worte), nicht Byte-Adresse.
> **Aligned-Buffer-Pflicht**: `nvm_write_page` castet `data` zu `const uint32_t*`. Der Puffer muss `__attribute__((aligned(4)))` sein. Packed Structs sind nicht garantiert aligned → immer via lokalen `uint8_t buf[256] __attribute__((aligned(4)))` + `memcpy` übergeben.