nvcu_storage.c
El controlador NVMC permite escribir la flash de aplicación sin SoftDevice: este sketch persiste un contador y una calibración en la última página, borrada y reescrita en cada guardado. Ideal para memorizar ajustes.
Hardware
Una placa nRF52840-MDK (Nordic nRF52840, Cortex-M4F @ 64 MHz, 1 MB flash / 256 KB RAM, BLE 5 + 802.15.4) con depurador integrado, programada en C con nRF5 SDK v17 y SoftDevice S140. nRF52840-MDK sola; LED P0.06 como testigo del contador.
Cableado
Sin cableado. Comprobar el mapa de memoria del linker: la página 0xFF000 no debe estar usada por el programa.
Funcionamiento
La flash se borra por páginas de 4 KB y se escribe en palabras alineadas; la palabra mágica valida el contenido al arrancar. Escribir demasiado desgasta la flash (~10 000 ciclos).
Ejecución
Abre el ejemplo equivalente del nRF5 SDK v17 (objetivo custom_board), pega este código en main.c, compila con Segger Embedded Studio o el Makefile de gcc y programa por el depurador integrado.
Variantes
Pasar al módulo FDS/NFDS (journaling multi-registro) para escrituras frecuentes, o registrar en flash externa SPI/QSPI.
nvcu_storage.c
// nRF52840-MDK : sauvegarde d'un compteur dans la page flash dédiée NVCU.
// La flash nRF52840 s'efface par page de 4 Ko : le NVCU gère tout ça.
#include "nrf_nvmc.h"
#include <string.h>
#define PAGE 0x000FF000UL // dernière page applicative (avant boot code)
typedef struct { uint32_t magic; uint32_t compteur; float calibration; } store_t;
static void sauvegarder(const store_t *s) {
nrf_nvmc_page_erase(PAGE);
// Écriture par mots de 32 bits (contrainte de la flash nRF).
const uint32_t *mots = (const uint32_t *)s;
for (unsigned i = 0; i < sizeof(store_t) / 4; i++)
nrf_nvmc_word_write(PAGE + 4 * i, mots[i]);
}
int main(void) {
const store_t *stock = (const store_t *)PAGE;
store_t s;
if (stock->magic == 0xA5A5A5A5UL) {
s = *stock; // reprise de la dernière valeur
} else {
s.magic = 0xA5A5A5A5UL; s.compteur = 0; s.calibration = 1.0f;
sauvegarder(&s);
}
s.compteur++; // ex : compteur de cycles machine
sauvegarder(&s);
// Témoin : la LED clignote (compteur % 4) fois après chaque démarrage.
nrf_gpio_cfg_output(6);
for (uint32_t i = 0; i < (s.compteur % 4) + 1; i++) {
nrf_gpio_pin_set(6); for (volatile int d = 0; d < 2e5; d++);
nrf_gpio_pin_clear(6); for (volatile int d = 0; d < 2e5; d++);
}
for (;;) { }
}