Algoritmo de registro circular ligero (similar a un sistema de archivos) para almacenamiento basado en flash

8

Actualmente estoy trabajando en un proyecto que implica el registro rápido y continuo de una métrica específica de la aplicación durante una larga vida útil. Para hacer esto, terminé usando un NXP M0 y un chip flash SPI de 32MiB. El registro es continuo y debe durar muchos años en el campo (10+), y un ser humano lo revisa periódicamente para detectar tendencias. Finalmente, el búfer se llena y comienza a sobrescribir datos antiguos que están perfectamente bien. Se me ocurrió un algoritmo simple para recorrer todo el dispositivo flash para encontrar la cabeza actual después de un encendido (el dispositivo se apaga con bastante frecuencia fuera de mi control) para que el registro pueda continuar donde se quedó. Solo puedo hacer fuerza bruta a través de este paseo y hacerlo con ~ 4s como el peor de los casos.

Esto me hizo pensar, ¿hay algún sistema de archivos estructurado de registro que esté dirigido a dispositivos flash y microcontroladores? JFFS y todos los otros FS estructurados de registro bien conocidos que imagino serían un poco pesados ​​para un microcontrolador simple (depende de la aplicación, por supuesto). Para ser más específico, me gustaría conocer cualquier algoritmo que esté diseñado específicamente para ser un registro circular con un tiempo de búsqueda rápido y / o cualquiera que esté diseñado para un sistema de archivos "tradicional" en un dispositivo flash que pueda ejecutarse en un microcontrolador Tradicional en este sentido, estar a la par con algo como JFFS donde hay una estructura de datos que representa una colección de archivos de acceso aleatorio mutable en un espacio de nombre jerárquico.

Kris Bahnsen
fuente
¿FAT32 o FAT16 en una tarjeta SD es demasiado lento?
vicatcu
2
Esta pregunta está completamente relacionada con el tema aquí, pero si no obtiene buenas respuestas, StackOverflow probablemente pueda ayudar. ¡Esperemos que podamos obtener algunas buenas respuestas aquí!
Kellenjb
@vicatcu No es que sea demasiado lento, para mi aplicación, la tarjeta SD más el conector son más costosos y las tarjetas SD pueden ser menos confiables. Kellenjb No estaba seguro de dónde ponerlo. Al igual que muchas preguntas de diseño incrustado, este tipo de problemas cae en el medio. Si no va bien aquí, con mucho gusto lo movería.
Kris Bahnsen
¿Es un chip flash sin procesar? Si es así, ¿cómo manejas los bloques muertos? Una gran parte del acuerdo de implementación de Flash FS con bloques muertos. Si cree que JFFS / JFFS2 es demasiado pesado, es posible que desee ver YAFFS. Se siente como un sistema de archivos muy simple al menos, por lo que debería ser bastante ligero.
Leo
Sí lo es. Los bloques defectuosos no son terribles en esta aplicación en particular ya que es tan a largo plazo que los datos extraídos son solo una tendencia aproximada, y en la mayoría de los casos dudo que el registro se use en absoluto.
Kris Bahnsen

Respuestas:

2

estructura de datos de cuerda

Me fascina la estructura de datos de la cuerda.. Tengo un proyecto de pasatiempo que intenta adaptarlo a un microcontrolador con solo unos pocos bytes de RAM conectados a una gran memoria Flash, para que pueda insertar y eliminar y, de lo contrario, editar arbitrariamente texto de longitud variable en grandes archivos de texto. Los archivos de texto son demasiado grandes para caber en la RAM. Borrar la última mitad del archivo y volver a escribirlo en flash, desplazado en un byte, cada vez que inserte o elimine un carácter en el medio de un archivo de texto de varios megabytes, sería demasiado lento, pero la estructura de datos de la cuerda Puede hacer esto mucho más rápido. Dado que la estructura de datos de la cuerda puede representar archivos de longitud variable de acceso aleatorio mutable como piezas inmutables de longitud fija, parece ser una buena combinación para la memoria flash: todas las ediciones se escriben de forma circular. Por desgracia, todos los errores aún no están resueltos en mi código. :-(

registros cronológicos de longitud fija

Obtuve un sistema de registro circular similar funcionando, para un producto que ayudé a desarrollar.

Simplemente escribí registros de longitud fija uno tras otro, llenando flash como una matriz circular.

(Con un flash completamente en blanco, comencé a escribir registros unos 3 bloques antes del final de la matriz, para poder probar el ajuste circular después de que solo se almacenaron unos pocos registros de datos, en lugar de comenzar en el registro cero y esperar un el valor de un mes de datos que se escribirán antes de descubrir que hubo un error en mi código envolvente).

Me aseguré de que siempre hubiera al menos 2 "bloques de borrado" borrados listos para ser escritos. Después de escribir un registro, si solo había 2 "bloques borrados" que estaban vacíos, borraba incondicionalmente el bloque de datos más antiguo: el tercer bloque de datos más antiguos después de los 2 "bloques borrados". (Cerca del final de la memoria flash, "después" significa "envolver hasta el comienzo de la memoria flash). (Quizás un solo bloque borrado hubiera sido adecuado; olvido por qué pensé que necesitaba al menos 2 y, a veces, 3) .

Olvidé exactamente cuántos registros puse en cada "bloque de borrado", pero me aseguré de no tener nunca un registro entre dos bloques de borrado: los primeros 2 bytes de cada bloque de borrado de flash era el valor "borrado" 0xFFFF o los primeros dos bytes de una suma de verificación Fletcher-16 (que nunca es 0xFFFF) en el encabezado de cada registro.

Eso hizo que escanear rápidamente la próxima vez que se encendiera y encontrar el encabezado del registro circular: solo tenía que mirar los dos primeros bytes de cada bloque de borrado para distinguir entre los bloques "borrados" y "datos". (Estaba un poco preocupado por la "falla de energía en el medio de borrar un bloque" que causaba que los dos primeros bytes se borraran a 0xFFFF pero dejaba los bytes no borrados en el medio del bloque, así que escribí el código para que el microcontrolador verificara para esto y reinicie el proceso "borrar un bloque").

Por favor, dígame si encuentra otras estructuras de datos o sistemas de archivos compatibles con flash.

davidcary
fuente
Su enfoque suena algo similar al mío. Sin embargo, sugeriría agregar otro pequeño giro: reserve un par de bytes en cada bloque para indicar que se ha "iniciado" y que está "lleno". Todos los bloques, excepto los bloques borrados, deben tener los bits "iniciados" programados. Cuando llegue el momento de borrar un bloque, configure el byte "completo" en el último byte de datos, luego borre el bloque e inmediatamente configure el bit "iniciado" del bloque borrado más antiguo. En el inicio, si ve que el "último" bloque está "lleno", en lugar de "iniciado", vuelva a borrar.
supercat
Tal enfoque puede parecer excesivo, pero si un bloque flash se borra parcialmente, es posible que los bytes decidan arbitrariamente leer FF u otra cosa. El hecho de que un bloque aparezca en blanco no garantiza que los bits no "aparezcan" espontáneamente allí. Si pierde energía mientras se está borrando, espere un momento en el próximo inicio y luego repita el borrado incluso si el bloque aparece en blanco .
supercat
Gracias por la información, la investigaré un poco más cuando realmente presione el código para el almacenamiento flash y le haga saber lo que sucede.
Kris Bahnsen
@supercat: Gracias, eso suena como una gran idea.
davidcary
@davidcary: No sé si alguna vez tuve un bloque que parecía totalmente en blanco y no lo estaba, pero he tenido un bloque que arrojaría resultados diferentes en lecturas consecutivas. Es posible que el bloque se haya leído incorrectamente como en blanco, mi código intentó programarlo de todos modos, lo que resultó en una mezcla extraña de nuevos datos programados y basura vieja de borrado interrumpido. En cualquier caso, un escenario en el que un bloque a veces aparece en blanco no es realista.
supercat
0

Han pasado bastantes años, pero quería seguir con esto en caso de que alguien más pasara por allí. Parece que hay algunos proyectos en estos días, que se mantienen activamente (a partir de enero de 2020) que son sistemas de archivos destinados a microcontroladores destinados a flash NOR SPI.

Tenga en cuenta que no los he probado en ninguna capacidad, pero hacen exactamente lo que buscaba la pregunta original: "... estructura de datos que representa una colección de archivos de acceso aleatorio mutable ..."

https://github.com/ARMmbed/littlefs - Creado por ARM, con licencia BSD

https://github.com/joembedded/JesFs : realmente no parece tener licencia, pero fue diseñado específicamente para flash SPI NOR.

Kris Bahnsen
fuente