RF Log — Flash wear optimization

Interactive explainer of how RF Log journals RX/TX events without wearing out the SPI NOR flash.

Current event (in RAM)
TypeRX
Duration00:12
S-meterS7
Battery7.98 V
Flash writes during the event 0
On end → 1 entry (32 B) appended to the ring
Flash ring of 8 sectors Eight sectors in a ring numbered 1 to 8; each sector is 4 KiB, holds 128 events and carries its own erase-cycle budget shown as a count out of 100k; the write head rides the rim, power-on markers are rare purple ticks, and a sector is erased only when the head returns after a full lap. 1 sector 4 KiB 128 events
0
Slots written
0
Program commands
0
Sector erases
0
Power-on markers
1 · 1
Lap · sector
Flash wear at simulated rate — 1 event / 10 s ≈ 32.5 years
Wear after 10 years: 5% 11,852 days to 100k erase cycles
Blank slot (0xFF) Traffic entry (RX/TX) Power-on marker Write head Erase

RF Log — journaliser sans user la Flash

Le point de départ. RF Log tient un journal des événements RX et TX de la radio : fréquence, durée, S-mètre (ou puissance en TX), tension batterie. Sur un appareil embarqué, ce genre de fonctionnalité pose tout de suite une question légitime : à force d'écrire, est-ce qu'on ne va pas user la mémoire Flash ? La réponse courte est non — et c'est le fruit d'une conception pensée autour des contraintes physiques de la Flash, pas d'un simple « on écrit et on verra ».

Comprendre la Flash, c'est comprendre deux opérations différentes

Le journal vit dans la Flash SPI externe (PY25Q16HB), une mémoire NOR. Une NOR sait faire deux choses qui n'ont rien à voir en termes d'usure :

  • Programmer : dans un emplacement vierge (tous les bits à 1, soit 0xFF), on peut faire passer des bits de 1 vers 0. C'est rapide, et surtout cela ne consomme aucun cycle d'endurance supplémentaire (on verra plus bas pourquoi).
  • Effacer : pour repasser des bits de 0 à 1, il n'existe pas d'opération fine. Il faut effacer un secteur entier de 4 Kio d'un coup. C'est l'opération lente et usante : le fabricant garantit environ 100 000 cycles d'effacement par secteur, pas plus.

Autrement dit, ce qui abîme la Flash, ce ne sont pas les écritures — ce sont les effacements. Toute la stratégie de RF Log consiste donc à écrire beaucoup, mais à effacer le moins possible.

Pourquoi la Flash s'use

Une cellule Flash n'est pas un simple interrupteur : c'est un transistor à grille flottante, une grille conductrice entièrement isolée par une fine couche d'oxyde. L'information, ce sont des électrons piégés sur cette grille — et c'est précisément parce qu'ils y restent prisonniers que la mémoire conserve ses données hors tension.

Le problème vient du trajet de ces électrons. Pour programmer ou effacer une cellule, il faut les forcer à traverser la couche d'oxyde isolante, sous un champ électrique intense : c'est l'effet tunnel.

L'effet tunnel est un phénomène quantique : il permet à une particule de franchir une barrière théoriquement infranchissable en physique classique — ici, précisément, un isolant qu'aucun électron ne devrait pouvoir traverser. Mais ce passage a un prix : à chaque traversée, l'isolant encaisse, le matériau accumule des défauts, et quelques électrons restent définitivement coincés à l'intérieur.

Cette dégradation est cumulative et irréversible. La charge parasite décale les tensions de seuil, l'écart entre un 0 et un 1 se resserre, la cellule devient plus difficile à effacer, et l'oxyde finit par fuir — elle ne retient plus sa charge. C'est cette limite physique que le fabricant borne en annonçant environ 100 000 cycles de programmation/effacement.

Et c'est bien un cycle complet qui se compte : une cellule ne peut être reprogrammée qu'après l'effacement de son secteur. Le nombre d'effacements d'un secteur est donc exactement son nombre de cycles d'usure. Écrire dans un emplacement vierge ne consomme pas de cycle supplémentaire : cela ne fait que compléter la moitié « programmation » d'un cycle déjà ouvert par l'effacement précédent. D'où la stratégie : repousser l'effacement le plus loin possible.

Trois principes de conception

  1. Rien ne s'écrit pendant l'événement. Tant qu'une réception ou une émission est en cours, tout est tenu en RAM : la durée s'incrémente, le S-mètre et la tension sont suivis en direct. Une seule entrée est écrite en Flash, à la fin de l'événement. Pas d'écriture périodique, pas d'enregistrement à chaque mesure du signal.
  2. On n'écrit que dans du vierge : append-only. Chaque entrée fait exactement 32 octets et va se poser dans le prochain emplacement encore vierge. Comme on ne fait que descendre des bits de 1 vers 0 dans une case propre, aucun effacement n'est nécessaire pour ajouter une entrée. Une entrée = deux commandes de programmation (les 32 octets, puis un octet de validation), zéro effacement.
  3. Un anneau circulaire de 8 secteurs. La zone occupe 32 Kio, soit 8 secteurs de 4 Kio = 1 024 emplacements (128 par secteur). On remplit le secteur 1, puis le 2, et ainsi de suite, sans jamais rien effacer sur le premier tour. Ce n'est qu'en revenant sur un secteur déjà utilisé, après un tour complet, qu'on l'efface — une seule fois — avant d'y réécrire.

Le résultat, en chiffres

Sur un tour complet de l'anneau : 1 024 nouvelles entrées, 2 048 commandes de programmation… mais seulement 8 effacements (un par secteur). Chaque secteur n'est donc effacé qu'une fois toutes les 1 024 entrées. En repartant des 100 000 cycles garantis :

100 000 × 1 024 ≈ 102 400 000 entrées avant d'atteindre l'endurance nominale d'un secteur.

Ce chiffre mérite qu'on s'y arrête, car il repose sur un point essentiel : l'endurance se compte par secteur, pas pour la puce entière. Chaque secteur dispose de son propre budget de 100 000 cycles, indépendamment de ses voisins — le secteur 1 peut être à 90 000 cycles pendant que le secteur 2 est encore neuf. L'usure est une dégradation matérielle des cellules de ce secteur précis ; rien n'est mutualisé.

Et c'est précisément ce qui rend l'anneau payant. En n'utilisant qu'un seul secteur, il faudrait l'effacer toutes les 128 entrées : il serait épuisé après 100 000 × 128 = 12,8 millions d'entrées. En tournant sur huit secteurs, chacun n'est effacé qu'une fois par tour de 1 024 entrées, et l'on atteint 102,4 millions — soit exactement huit fois plus. La rotation ne diminue pas le nombre total d'effacements : elle les répartit sur huit budgets indépendants au lieu d'en épuiser un seul. C'est du wear leveling, et il est ici parfaitement uniforme : les huit secteurs vieillissent au même rythme et arriveront en fin de vie ensemble.

Le corollaire vaut d'être noté : si les 100 000 cycles étaient un budget global de la puce, faire tourner l'écriture sur huit secteurs n'apporterait strictement rien.

Pour rendre ça concret :

  • un événement enregistré par minute, en continu → ≈ 195 ans ;
  • un événement toutes les 10 secondes≈ 32 ans ;
  • un événement chaque seconde, 24 h/24 → ≈ 3,2 ans (une radio dont le squelch s'ouvre et se referme sans interruption).

Même un effacement manuel complet du journal ne coûte qu'un cycle par secteur : en vidant RF Log une fois par jour, il faudrait environ 274 ans pour épuiser un secteur.

Un détail qui compte : les marqueurs POWER ON

À chaque démarrage, un marqueur est déposé pour séparer les événements — il occupe bien un emplacement physique, mais il ne compte pas comme du trafic (l'utilisateur voit jusqu'à 512 événements RX/TX). Et si le journal se termine déjà par un marqueur, on n'en rajoute pas : pas de séparateurs vides empilés au fil des redémarrages.

En une phrase

RF Log écrit une entrée par événement dans un anneau circulaire, en n'utilisant que des emplacements vierges, ce qui réduit les effacements — la seule opération qui use vraiment la Flash — à un strict minimum. La durée de vie qui en résulte dépasse très largement celle de la radio elle-même.

RF Log — journaling without wearing out the flash

The starting point. RF Log keeps a log of the radio's RX and TX events: frequency, duration, S-meter (or power on TX), battery voltage. On an embedded device, this kind of feature immediately raises a fair question: with all that writing, won't it wear out the flash? The short answer is no — and that comes from a design built around the physical constraints of flash, not a "write it and see" approach.

Understanding flash means understanding two different operations

The log lives in the external SPI flash (PY25Q16HB), a NOR memory. A NOR chip does two things that are worlds apart in terms of wear:

  • Program: in a blank slot (all bits at 1, i.e. 0xFF), you can flip bits from 1 to 0. This is fast and, crucially, consumes no additional endurance cycle (more on why below).
  • Erase: to bring bits back from 0 to 1, there is no fine-grained operation. You must erase a whole 4 KiB sector at once. This is the slow and wearing operation: the datasheet guarantees roughly 100,000 erase cycles per sector, no more.

In other words, what damages the flash is not the writes — it is the erases. So RF Log's whole strategy is to write a lot, but erase as little as possible.

Why flash wears out

A flash cell is not a simple switch: it is a floating-gate transistor, a conductive gate entirely isolated by a thin oxide layer. The stored information is electrons trapped on that gate — and it is precisely because they stay imprisoned there that the memory keeps its data with the power off.

The trouble is the path those electrons take. To program or erase a cell, they must be forced through the insulating oxide layer under an intense electric field: this is quantum tunnelling.

Tunnelling is a quantum phenomenon: it lets a particle cross a barrier that classical physics deems strictly impassable — here, precisely, an insulator no electron should be able to get through. But that crossing comes at a price: every time, the insulator takes the hit, the material accumulates defects, and a few electrons end up permanently stuck inside it.

This degradation is cumulative and irreversible. The stray charge shifts the threshold voltages, the margin between a 0 and a 1 narrows, the cell becomes harder to erase, and the oxide eventually leaks — it no longer holds its charge. That physical limit is what the manufacturer bounds by rating the part at roughly 100,000 program/erase cycles.

And it is a full cycle that counts: a cell can only be reprogrammed after its sector has been erased. The number of erases of a sector is therefore exactly its number of wear cycles. Writing into a blank slot consumes no extra cycle: it merely completes the "program" half of a cycle already opened by the previous erase. Hence the strategy: push the erase as far away as possible.

Three design principles

  1. Nothing is written during the event. While a reception or transmission is ongoing, everything is held in RAM: the duration ticks up, the S-meter and voltage are tracked live. A single entry is written to flash, when the event ends. No periodic writes, no record on every signal measurement.
  2. We only write into blank space: append-only. Each entry is exactly 32 bytes and lands in the next still-blank slot. Since we only pull bits from 1 to 0 in a clean slot, no erase is needed to add an entry. One entry = two program commands (the 32 bytes, then a one-byte commit), zero erases.
  3. A circular ring of 8 sectors. The area spans 32 KiB, i.e. 8 sectors of 4 KiB = 1,024 slots (128 per sector). We fill sector 1, then 2, and so on, without ever erasing anything on the first lap. Only when the head returns to an already-used sector, after a full lap, is that sector erased — once — before being rewritten.

The payoff, in numbers

Over one full lap of the ring: 1,024 new entries, 2,048 program commands… but only 8 erases (one per sector). Each sector is therefore erased just once every 1,024 entries. Starting from the 100,000 guaranteed cycles:

100,000 × 1,024 ≈ 102,400,000 entries before reaching a sector's rated endurance.

That figure is worth pausing on, because it rests on a key point: endurance is rated per sector, not for the chip as a whole. Each sector has its own budget of 100,000 cycles, independent of its neighbours — sector 1 can sit at 90,000 cycles while sector 2 is still pristine. The wear is physical damage to the cells of that particular sector; nothing is shared.

And that is exactly what makes the ring pay off. Using a single sector, it would have to be erased every 128 entries: it would be exhausted after 100,000 × 128 = 12.8 million entries. Rotating over eight sectors, each one is erased only once per lap of 1,024 entries, and we reach 102.4 million — exactly eight times more. The rotation does not reduce the total number of erases: it spreads them over eight independent budgets instead of draining a single one. That is wear levelling, and here it is perfectly uniform: all eight sectors age at the same rate and reach end of life together.

The corollary is worth stating: if those 100,000 cycles were a global budget for the chip, rotating writes over eight sectors would gain nothing at all.

To make it concrete:

  • one event logged every minute, continuously → ≈ 195 years;
  • one event every 10 seconds≈ 32 years;
  • one event every second, 24/7 → ≈ 3.2 years (a radio whose squelch opens and closes without pause).

Even a full manual wipe of the log costs only one cycle per sector: clearing RF Log once a day would take about 274 years to exhaust a sector.

One detail that matters: the POWER ON markers

At each boot, a marker is written to separate events — it does consume a physical slot, but it is not counted as traffic (the user sees up to 512 RX/TX events). And if the log already ends with a marker, no new one is added: no empty separators piling up across reboots.

In one sentence

RF Log writes one entry per event into a circular ring, using only blank slots, which keeps erases — the only operation that truly wears the flash — to a strict minimum. The resulting lifetime far exceeds that of the radio itself.