NVOL es un registro de flash persistente, a menudo denominado emulación de EEPROM. Ofrece una API básica para leer y escribir pares de clave/valor indexados hacia y desde una memoria flash, similar a un registro. Es importante mencionar que tanto la clave como el valor se almacenan en Flash, lo que permite la modificación del registro durante el tiempo de ejecución. Algunas de las características de NVOL incluyen:
La biblioteca proporciona dos opciones para administrar el almacenamiento de datos: Opción 1: Guarde inmediatamente las entradas para flash siempre que se cambie. Opción 2: Almacene las entradas en RAM y guarde para flash de memoria a pedido.
La desventaja de una memoria flash es que no se puede borrar ni escribir en bytes individuales. La memoria flash solo se puede borrar y escribir en grandes bloques. Un tamaño de bloque de borrado típico puede ser 4K o 8K bytes. Para NVOL, las implementaciones Flash deberían admitir escrituras parciales, donde un bloque borrado se puede escribir varias veces, siempre que los bits solo cambiaran de "1" (estado borrado) a "0" (estado programado).
Para el flash, la página se considera el tamaño de bloque más pequeño que se puede borrar. Cada sector puede estar compuesto por una o más de estas páginas.
El primer sector se borra inicialmente. Las nuevas entradas de registro se agregan secuencialmente al flash. Cuando se actualiza una entrada, la entrada anterior se marca como inválida y se escribe una nueva entrada en la siguiente dirección flash disponible. Una vez que el primer sector alcanza la capacidad, todas las entradas válidas se copian al segundo sector y se borra el primer sector. Este proceso se repite.
NVOL maneja y realiza un seguimiento de las entradas válidas y sus ubicaciones en Flash. Los sectores se administran dinámicamente.
Las macros están disponibles para crear instancias estáticas de NVOL, que luego se pueden usar con la API. Un ejemplo de una declaración sería:
#define NVOL3_REGISTRY_START 0
#define NVOL3_REGISTRY_SECTOR_SIZE STORAGE_32K
#define NVOL3_REGISTRY_SECTOR_COUNT 2
#define REGISTRY_KEY_LENGTH 24
#define REGISTRY_VALUE_LENGT_MAX 224
NVOL3_INSTANCE_DECL(_regdef_nvol3_entry,
ramdrv_read, ramdrv_write, ramdrv_erase,
NVOL3_REGISTRY_START,
NVOL3_REGISTRY_START + NVOL3_REGISTRY_SECTOR_SIZE,
NVOL3_REGISTRY_SECTOR_SIZE,
REGISTRY_KEY_LENGTH, /*key_size*/
DICTIONARY_KEYSPEC_BINARY(6), /*dictionary key_type (24 char string)*/
53, /*hashsize*/
REGISTRY_VALUE_LENGT_MAX, /*data_size*/
0, /*local_size (no cache in RAM)*/
0, /*tallie*/
NVOL3_SECTOR_VERSION /*version*/
) ;
Esto crea un NVOL con dos sectores 32K al comienzo del flash. El tamaño total de la clave, incluido el encabezado de entrada, es de 256 bytes. Esto no es un requisito, pero la alineación debe tenerse en cuenta. El diccionario de búsqueda tiene un tamaño hash de 53. Además, esta instancia no almacenará ningún valor en RAM ( local_size = 0 ), por lo que siempre los leerá desde Flash cuando sea necesario.
En la demostración se utiliza el controlador NVRAMDRV que emulación como memoria flash en RAM, las funciones de acceso son RAMDRV_READ, RAMDRV_WRITE y RAMDRV_ERASE configuradas para esta instancia.
Ahora _regdef_nvol3_entry se puede usar con la API NVOL. La API NVOL está ligeramente invitada, por lo que se proporciona un ejemplo de registro simple.
El ejemplo de prueba proporcionado se puede compilar y ejecutar en un espacio de código GitHub. Simplemente abra un espacio de códigos para este repostor y escriba make en el terminal que se abre (si el terminal no está abierto, use ctrl + ` para abrir el terminal). Ahora puede comenzar el ejemplo de NVOL escribiendo ./build/nvol en el terminal. Todos los comandos se pueden ejecutar en el terminal del CodeSpace.
Cuando se inicia el programa de ejemplo, se abrirá un shell de comando y mostrará lo siguiente:
@navaro /workspaces/nvol (main) $ ./build/nvol
REG : : resetting _regdef_nvol3_entry
NVOL3 : : '_regdef_nvol3_entry' 0 / 255 records loaded
Navaro corshell Demo v 'Jan 16 2023'
use 'help' or '?' for help.
# >
Primero, ejecutaremos un script simple para llenar nuestro registro con valores. En el tipo de solicitud:
source ./test/reg.sh
Esto debería llenar el registro con valores. ¿Para enumerar todos los comandos para probar el tipo de registro ? reg , debe mostrar la siguiente lista:
# >? reg
reg [key] [value]
regadd <key> <value>
regdel <key>
regerase
regstats
regtest [repeat]
# >
Ahora podemos usar el comando REG para ver y actualizar el registro:
# >reg
player.age: Ancient
player.gender: Otherworldly
player.level: legendary
player.location: Mount Olympus
player.name: cool_cat
player.points: 9000
player.power: invisibility
player.species: Dragon
player.status: awakened
player.weapon: lightning bolt
test: 123
user.address: 123 Main St.
user.age: 30
user.children: 0
user.email: [email protected]
user.favorite_color: blue
user.gender: male
user.marital_status: single
user.name: John Smith
user.occupation: contributor
user.phone_number: 555-555-5555
21 entries found.
# >reg user.favorite_color yellow
OK
# >reg user.favorite_color
user.favorite_color: yellow
# >regdel user.gender
OK
# >reg player
player.age: Ancient
player.gender: Otherworldly
player.level: legendary
player.location: Mount Olympus
player.name: cool_cat
player.points: 9000
player.power: invisibility
player.species: Dragon
player.status: awakened
player.weapon: lightning bolt
10 entries found.
# >regstats
NVOL3 : : '_regdef_nvol3_entry' 20 / 255 records loaded
record : 256 recordsize
: 0x000000 1st sector version 0x0155 flags 0xaaaaffff
: 0x010000 2nd sector version 0x0000 flags 0xffffffff
: 0x010000 sector size
: 20 loaded
: 20 inuse
: 2 invalid
: 0 error
: 640 lookup table bytes
: 53 dict hash size
: dict hash - max 2, empty 34, used 19
Todos estos comandos se implementan en src/registry/registrycmd.c . La implementación es intuitiva y autoexplicada y no debe requerir más explicaciones.
El shell es un proyecto en sí mismo, pero solo se incluye en este ejemplo para fines de demostración. Es fácil de extender. Usar ? Para ver la lista completa de comandos implementados para este ejemplo.
Cuando el registro utiliza las cadenas para indexar las entradas, la tabla de cadenas usa valores enteros. Este enfoque requiere menos recursos de RAM.
Para este ejemplo, también hay un script para llenar la tabla de cadenas con valores. En el tipo de solicitud:
source ./test/strtab.sh
Nuevamente, ahora podemos enumerar la tabla de cadenas con un comando simple:
# >strtab
0000 ENGLISH
0001 The end of the world is our playground.
0002 The company is family. The family is the company.
0003 Escape the mundane. Embrace the extraordinary.
0004 Work hard, live easy.
0005 The future is now. Join us.
0006 There is no I in team. But there is in severance.
0007 We're not just a company. We're a movement.
0008 Success is a journey, not a destination.
0009 Innovation starts with you.
0010 Welcome to the beginning of something great.
0100 DUTCH
0101 Het einde van de wereld is onze speeltuin.
0102 Het bedrijf is familie. De familie is het bedrijf.
0103 Ontsnap aan het alledaagse. Omarm het buitengewone.
0104 Hard werken, makkelijk leven.
0105 De toekomst is nu. Doe met ons mee.
0106 Er is geen ik in team. Maar wel in ontslagvergoeding.
0107 We zijn niet alleen een bedrijf. We zijn een beweging.
0108 Succes is een reis, geen bestemming.
0109 Innovatie begint bij jou.
0110 Welkom bij het begin van iets groots.
0999 test
23 entries found.
# >
Al igual que el registro, el ejemplo de la tabla de cadenas se registra con la biblioteca de sustitución de cadenas para reemplazar los valores de índice delimitados con <> con la cadena en la tabla de cadenas. Por ejemplo:
# >echo "<1>"
The end of the world is our playground.
# >
La demostración utiliza un controlador de emulación para flash en RAM. Esto se implementa en "CRC/Drivers/Ramdrv.h/C".
En el mismo directorio, se produce un controlador de muestra para un chip de flash real en los archivos "spiflash.h/c". Esto se implementó utilizando el controlador Chibios/Hal SPI y debería ser un buen punto de partida para portar NVOL a su propia plataforma.