nvcu_storage.c

nRF52840-MDK (boards.json id: nrf52840-mdk) · File : nvcu_storage.c · Language : C · Use case : Conserver des données en flash avec le NVCU

The NVMC controller lets application flash be written without the SoftDevice: this sketch persists a counter and a calibration in the last page, erased and rewritten on each save. Ideal for remembering settings.

Hardware

An nRF52840-MDK board (Nordic nRF52840, Cortex-M4F @ 64 MHz, 1 MB flash / 256 KB RAM, BLE 5 + 802.15.4) with onboard debugger, programmed in C with nRF5 SDK v17 and the S140 SoftDevice. nRF52840-MDK alone; LED P0.06 as the counter indicator.

Wiring

No wiring. Check the linker memory map: page 0xFF000 must not be used by the program.

How it works

Flash erases by 4 KB page then writes aligned words; the magic word validates the content at boot. Writing too often wears the flash (~10,000 cycles).

Running it

Open the matching nRF5 SDK v17 example (custom_board target), paste this code into main.c, build with Segger Embedded Studio or the gcc Makefile, then flash through the onboard debugger.

Variants

Move to the FDS/NFDS module (multi-record journaling) for frequent writes, or log to external SPI/QSPI flash.

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 (;;) { }
}

← Back to the board