nvcu_storage.c
Le contrôleur NVMC permet d'écrire la flash applicative sans SoftDevice : ce programme persiste un compteur et une calibration dans la dernière page, effacée puis réécrite à chaque sauvegarde. Idéal pour mémoriser des réglages.
Matériel requis
Une carte nRF52840-MDK (Nordic nRF52840, Cortex-M4F @ 64 MHz, 1 Mo flash / 256 Ko RAM, BLE 5 + 802.15.4) avec son debugger intégré, programmée en C sous nRF5 SDK v17 et SoftDevice S140. nRF52840-MDK seule ; LED P0.06 pour le témoin de compteur.
Câblage
Aucun câblage. Vérifier la carte de mémoire du linker : la page 0xFF000 ne doit pas être utilisée par le programme.
Fonctionnement
La flash s'efface par page (4 Ko) puis s'écrit par mots alignés ; le magic word valide le contenu au démarrage. Écrire trop souvent use la flash (≈ 10 000 cycles).
Exécution
Ouvrir l'exemple correspondant du nRF5 SDK v17 (target custom_board), coller ce code dans main.c, compiler avec Segger Embedded Studio ou Makefile gcc, puis programmer via le debugger intégré (flash_nrf.py ou IDE).
Variantes
Passer au module FDS/NFDS (journaling multi-enregistrements) pour des écritures fréquentes, ou logger en SPI/QSPI externe.
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 (;;) { }
}