Algorithme de journalisation circulaire léger (de type système de fichiers) pour le stockage flash

8

Je travaille actuellement sur un projet qui implique la journalisation rapide et continue d'une métrique plutôt spécifique à l'application sur une longue durée de vie. Pour ce faire, j'ai fini par utiliser un NXP M0 et une puce flash 32 Mo SPI. L'enregistrement est continu et doit durer de nombreuses années sur le terrain (10+), et est périodiquement vérifié par un humain pour repérer les tendances. Finalement, le tampon se remplit et commence à remplacer les anciennes données, ce qui est parfaitement correct. J'ai trouvé un algorithme simple pour parcourir tout le périphérique flash pour trouver la tête actuelle après une mise sous tension (le périphérique est mis hors tension assez fréquemment hors de mon contrôle) afin que la journalisation puisse simplement continuer là où elle s'était arrêtée. Je peux simplement utiliser la force brute à travers cette promenade et le faire avec ~ 4s comme pire scénario.

Cela m'a fait penser, y a-t-il des systèmes de fichiers structurés en journaux qui sont adaptés aux périphériques flash et aux microcontrôleurs? JFFS et tous les autres FS Log Structured FS bien connus que j'imagine seraient un peu lourds pour un simple microcontrôleur (cela dépend bien sûr de l'application). Pour être plus précis, j'aimerais connaître tous les algorithmes conçus spécifiquement pour être un journal circulaire avec un temps de recherche de tête rapide et / ou tous ceux conçus pour un système de fichiers "traditionnel" sur un périphérique flash pouvant être exécuté sur un microcontrôleur. Traditionnel dans ce sens étant comparable à quelque chose comme JFFS où il existe une structure de données qui représente une collection de fichiers à accès aléatoire mutables dans un espace de noms hiérarchique.

Kris Bahnsen
la source
FAT32 ou FAT16 sur une carte SD est-il trop lent?
vicatcu
2
Cette question est entièrement sur le sujet ici, mais si vous n'obtenez pas de bonnes réponses, StackOverflow peut probablement vous aider. Espérons que nous pourrons obtenir de bonnes réponses ici!
Kellenjb
@vicatcu Ce n'est pas trop lent, car mon application, la carte SD plus le connecteur est plus coûteuse et les cartes SD peuvent être moins fiables. Kellenjb Je ne savais pas trop où le mettre. Comme beaucoup de questions de conception intégrées, ce genre de problème se situe au milieu. Si cela ne se passe pas bien ici, je le déplacerais avec plaisir.
Kris Bahnsen
Est-ce une puce flash brute? Si oui, comment gérez-vous les blocs morts? Une grande partie de la mise en œuvre de Flash FS concerne les blocs morts. Si vous pensez que JFFS / JFFS2 est trop lourd, vous voudrez peut-être consulter YAFFS. Cela ressemble à un système de fichiers très simple au moins, donc il devrait être assez léger.
Leo
Oui, ça l'est. Les blocs défectueux ne sont pas terribles dans cette application particulière car leur durée de vie est si longue que les données extraites ne sont qu'une tendance approximative, et dans la plupart des cas, je doute que la journalisation soit utilisée.
Kris Bahnsen

Réponses:

2

structure de données de corde

Je suis fasciné par la structure des données de corde. J'ai un projet de loisir essayant de l'adapter à un microcontrôleur avec seulement quelques octets de RAM accrochés à une énorme mémoire Flash, afin que je puisse insérer et supprimer et autrement éditer arbitrairement du texte de longueur variable dans d'énormes fichiers texte. Fichiers texte beaucoup trop volumineux pour tenir dans la RAM. Effacer la dernière moitié du fichier et la réécrire sur flash, décalé d'un octet, chaque fois que j'insère ou supprime un caractère au milieu d'un fichier texte de plusieurs mégaoctets, serait beaucoup trop lent, mais la structure des données de la corde peut le faire beaucoup plus rapidement. Étant donné que la structure de données de la corde peut représenter des fichiers à longueur variable à accès aléatoire mutables comme des morceaux de longueur fixe immuables, cela semble être une bonne correspondance pour la mémoire flash - toutes les modifications sont écrites de façon circulaire. Hélas, tous les bugs ne sont pas encore résolus dans mon code. :-(

journaux chronologiques de longueur fixe

J'ai réussi à faire fonctionner un système de journaux circulaires similaire, pour un produit que j'ai aidé à développer.

J'ai simplement écrit des enregistrements de longueur fixe l'un après l'autre, remplissant le flash comme un tableau circulaire.

(Avec un flash complètement vierge, j'ai commencé à écrire des enregistrements sur environ 3 blocs avant la fin du tableau, afin que je puisse tester le bouclage circulaire après que seulement quelques enregistrements de données ont été stockés, plutôt que de commencer à l'enregistrement zéro et d'attendre un mois de données à écrire avant de découvrir qu'il y avait un bug dans mon code de bouclage).

Je me suis assuré qu'il y avait toujours au moins 2 "blocs d'effacement" effacés prêts à être écrits. Après avoir écrit un enregistrement, s'il n'y avait que 2 "blocs effacés" qui étaient vides, j'ai effacé inconditionnellement le plus ancien bloc de données - le 3ème bloc des données les plus anciennes après les 2 "blocs effacés". (Vers la fin de la mémoire flash, "après" signifie "boucler jusqu'au début de la mémoire flash.) (Peut-être qu'un seul bloc effacé aurait été suffisant - j'oublie pourquoi je pensais avoir besoin d'au moins 2 et parfois 3) .

J'oublie exactement le nombre d'enregistrements que j'ai mis dans chaque "bloc d'effacement", mais je me suis assuré que je n'avais jamais d'enregistrements chevauchant deux blocs d'effacement - les 2 premiers octets de chaque bloc d'effacement de flash étaient soit la valeur "effacée" 0xFFFF, soit les deux premiers octets d'une somme de contrôle Fletcher-16 (qui n'est jamais 0xFFFF) dans l'en-tête de chaque enregistrement.

Cela a permis de scanner rapidement la prochaine fois qu'il s'est mis sous tension et de trouver la tête du journal circulaire - je n'ai eu qu'à regarder les deux premiers octets de chaque bloc d'effacement pour faire la distinction entre les blocs "effacés" et "données". (J'étais un peu inquiet à propos d'une "panne de courant au milieu de l'effacement d'un bloc" provoquant l'effacement des deux premiers octets à 0xFFFF mais laissant des octets non effacés au milieu du bloc, j'ai donc écrit du code pour que le microcontrôleur vérifie pour cela et redémarrez le processus "effacer un bloc").

Veuillez me dire si vous trouvez d'autres structures de données ou systèmes de fichiers compatibles avec le flash.

davidcary
la source
Votre approche ressemble quelque peu à la mienne. Je suggérerais cependant d'ajouter une autre petite touche: réservez quelques octets dans chaque bloc pour indiquer qu'il a été "démarré" et qu'il est "plein". Tous les blocs, à l'exception des blocs effacés, doivent avoir les bits "démarrés" programmés. Lorsqu'il est temps d'effacer un bloc, définissez l'octet "complet" sur le dernier octet de données, puis effacez le bloc, puis définissez immédiatement le bit "commencé" du bloc effacé le plus ancien. Au démarrage, si vous voyez que le "dernier" bloc est "plein", plutôt que "commencé", refaites l'effacement.
supercat
Une telle approche peut sembler exagérée, mais si un bloc flash est partiellement effacé, il est possible que les octets décident arbitrairement de lire FF ou autre chose. Le fait qu'un bloc apparaisse vide ne garantit pas que des bits n'y "apparaîtront" pas spontanément. Si vous perdez de l'énergie pendant un effacement, attendez un peu au prochain démarrage, puis répétez l'effacement même si le bloc apparaît vide .
supercat
Merci pour l'info, je vais y regarder un peu plus en profondeur lorsque je frappe le code du stockage flash et je vous informe de ce qui se passe.
Kris Bahnsen
@supercat: Merci, cela semble être une excellente idée.
davidcary
@davidcary: Je ne sais pas si j'ai jamais eu un bloc qui est apparu totalement vide et ne l'était pas, mais j'ai eu un bloc qui donnerait des résultats différents lors de lectures consécutives. Il est possible que le bloc ait été lu de manière incorrecte car vide, mon code a essayé de le programmer de toute façon, ce qui a entraîné un étrange méli-mélo de nouvelles données programmées et d'anciennes ordures à effacement interrompu. Dans tous les cas, un scénario où un bloc apparaîtrait parfois vierge n'est guère irréaliste.
supercat
0

Cela fait pas mal d'années, mais je voulais faire un suivi à ce sujet au cas où quelqu'un d'autre se promènerait. Il semble qu'il y ait quelques projets de nos jours, qui sont activement maintenus (en janvier 2020) et qui sont des systèmes de fichiers destinés aux microcontrôleurs ciblés sur le flash NOR SPI.

Notez que je ne les ai testés à aucun titre, mais ils font exactement ce que la question d'origine recherchait: "... structure de données qui représente une collection de fichiers à accès aléatoire mutables ..."

https://github.com/ARMmbed/littlefs - Créé par ARM, licence BSD

https://github.com/joembedded/JesFs - ne semble pas vraiment être sous licence, mais a été très spécifiquement conçu pour le flash SPI NOR.

Kris Bahnsen
la source