nvcu_storage.c

nRF52840-MDK (id boards.json: nrf52840-mdk) · Archivo : nvcu_storage.c · Lenguaje : C · Uso : Conserver des données en flash avec le NVCU

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

← Volver a la ficha