Tiny Flash -Datenbank für MCU.
Bei der täglichen Entwicklung von Mikrocontrollern sind immer einige Informationen erforderlich. Zu diesem Zeitpunkt ist eine Lösung für den Mikrocontroller -Flash -Speicher erforderlich. Derzeit gibt es viele Lösungen für den Mikrocontroller -Speicher, wie z. Und es ist selten, dass Flash -Schreibfehler in Betracht gezogen werden.
In den tatsächlichen Produkten kann das Blitzschreiben von eingebetteten Produkten durch verschiedene Faktoren (batteriebetrieben, unerwarteter Stromausfall, Temperatur usw.) beeinflusst werden und ist nicht sehr stabil. Sobald ein Fehler auftritt, führt er zu einer Reihe von Produktproblemen.
Im Gegensatz zu vielen anderen KV-Datenbanken wird jede Variable, die in TinyFlashDB gespeichert werden muss, in einem separaten Mikrocontroller-Blitzsektor zugewiesen, und die variable Länge ist unveränderlich.
Daher ist TinyFlashDB nur zum Speichern mehrerer wichtiger Variablen (z. B. IAP-Jump-Flag, System-Stromausfallzeit usw.) geeignet und eignet sich nicht für eine Datenspeicherung in großem Maßstab (groß angelegte Datenspeicherung kann EasyFlash usw. verwenden).
TinyFlashdb wurde entwickelt, um die Auswirkungen von Schreibfehlern zu berücksichtigen, Sicherheitsgarantien innerhalb seiner Fähigkeiten zu verfolgen, Ressourcenbeschäftigung so weit wie möglich (weniger als 1 KB-Code einzuschätzen) und Universalität wie möglich (kann auf 8-Bit-Computer wie 51, STM32L4-Serien, die nicht in umgekehrten Reihenfolge, in umgekehrten Reihenfolge, in umgekehrten Reihenfolge,, einige triaktionierte Mikrocontroller und andere ordentliche 32-Bit-Computer, portiert werden.
const tfdb_index_t test_index = {
. end_byte = 0x00 ,
. flash_addr = 0x4000 ,
. flash_size = 256 ,
. value_length = 2 ,
}; /* c99写法,如果编译器不支持,可自行改为c89写法 */
tfdb_addr_t addr = 0 ; /*addr cache*/
uint8_t test_buf [ TFDB_ALIGNED_RW_BUFFER_SIZE ( 2 , 1 )]; /*aligned_value_size*/
uint16_t test_value ;
void main ()
{
TFDB_Err_Code result ;
result = tfdb_set ( & test_index , test_buf , & addr , & test_value );
if ( result == TFDB_NO_ERR )
{
printf ( "set ok, addr:%xn" , addr );
}
addr = 0 ; /* reset addr cache, to see tfdb_get. */
result = tfdb_get ( & test_index , test_buf , & addr , & test_value );
if ( result == TFDB_NO_ERR )
{
printf ( "get ok, addr:%x, value:%xn" , addr , test_value );
}
} typedef struct _tfdb_index_struct {
tfdb_addr_t flash_addr ; /* the start address of the flash block */
uint16_t flash_size ; /* the size of the flash block */
uint8_t value_length ; /* the length of value that saved in this flash block */
uint8_t end_byte ; /* must different to TFDB_VALUE_AFTER_ERASE */
/* 0x00 is recommended for end_byte, because almost all flash is 0xff after erase. */
} tfdb_index_t ;Strukturfunktion: In TinyFlashDB erfordern API -Operationen den angegebenen Parameterindex. Diese Indexstruktur speichert die Adresse von Flash, die Größe des Blitzes, die Länge der gespeicherten Variablen und das Endflag. Diese Informationen werden beim Lesen des Flash -Sektors überprüft.
TFDB_Err_Code tfdb_get ( const tfdb_index_t * index , uint8_t * rw_buffer , tfdb_addr_t * addr_cache , void * value_to ); Funktionsfunktion: Erhalten Sie eine Variable mit einer angegebenen variablen Länge im Index aus dem Sektor, auf den nach index hingewiesen wurde. Die Überprüfung des Flash-Header-Datenverifizierungsfehlers initialisiert Flash nicht neu.
index : Indexzeiger für den TFDB -Betrieb.
Parameter rw_buffer : Schreiben und lesen Cache. Alle Flash -Operationen kopieren schließlich die sortierten Daten in den Puffer und rufen dann tfdb_port_write oder tfdb_port_read zum Lesen und Schreiben auf. Wenn der Chip spezielle Anforderungen für den Cache für schriftliche Datenbereiche (z. B. 4-Byte-Ausrichtung, 256-Byte-Ausrichtung usw.) enthält, kann der variable Zeiger, der die Anforderungen entspricht, an die Funktion über diesen Parameter übergeben werden. Mindestens 4 Bytes in Länge.
Parameter addr_cache : Kann NULL oder ein Zeiger auf die Adress -Cache -Variable sein. Wenn addr_cache nicht NULL ist und nicht 0 ist, wird addr_cache als erfolgreich angesehen, überprüfen Sie den Flash -Header nicht mehr und die Daten werden direkt aus der Adresse addr_cache gelesen.
Parameter value_to : Die Adresse zum Speichern des Dateninhalts.
Rückgabewert: TFDB_NO_ERR ist erfolgreich, andere scheitern.
TFDB_Err_Code tfdb_set ( const tfdb_index_t * index , uint8_t * rw_buffer , tfdb_addr_t * addr_cache , void * value_from ); Funktionsfunktion: Schreiben Sie eine Variable mit einer angegebenen variablen Länge in den Index in den Sektor, auf den durch index hingewiesen wird, und der Fehler mit den Flash -Header -Datenüberprüfungen ist wiederum geändert und Flash wird neu initialisiert.
index : Indexzeiger für den TFDB -Betrieb.
Parameter rw_buffer : Schreiben und lesen Cache. Alle Flash -Operationen kopieren schließlich die sortierten Daten in den Puffer und rufen dann tfdb_port_write oder tfdb_port_read zum Lesen und Schreiben auf. Wenn der Chip spezielle Anforderungen für den Cache für schriftliche Datenbereiche (z. B. 4-Byte-Ausrichtung, 256-Byte-Ausrichtung usw.) enthält, kann der variable Zeiger, der die Anforderungen entspricht, an die Funktion über diesen Parameter übergeben werden. Mindestens 4 Bytes in Länge.
Parameter addr_cache : Kann NULL oder ein Zeiger auf die Adress -Cache -Variable sein. Wenn addr_cache nicht NULL ist und nicht 0 ist, wird addr_cache als erfolgreich angesehen, überprüfen Sie den Flash -Header nicht mehr und die Daten werden direkt aus der Adresse addr_cache gelesen.
Parameter value_from : Der zu gespeicherte Dateninhalt.
Rückgabewert: TFDB_NO_ERR ist erfolgreich, andere scheitern.
Die TFDB -Dual -API wird basierend auf tfdb_set und tfdb_get eingekapselt. tfdb dual ruft tfdb_set und tfdb_get auf und fügt zwei Bytes SEQ an die Vorderseite der Daten hinzu. In der TFDB -Dual beträgt die am längsten unterstützte Speicher variable Länge 253 Bytes.
Gleichzeitig muss die TFDB-Dual-API zwei Puffer bereitstellen, und sie muss aligned_value_size werden.
typedef struct _my_test_params_struct
{
uint32_t aa [ 2 ];
uint8_t bb [ 16 ];
} my_test_params_t ;
my_test_params_t my_test_params = {
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18
};
tfdb_dual_index_t my_test_tfdb_dual = {
. indexes [ 0 ] = {
. end_byte = 0x00 ,
. flash_addr = 0x08077000 ,
. flash_size = 256 ,
. value_length = TFDB_DUAL_VALUE_LENGTH ( sizeof ( my_test_params_t )),
},
. indexes [ 1 ] = {
. end_byte = 0x00 ,
. flash_addr = 0x08077100 ,
. flash_size = 256 ,
. value_length = TFDB_DUAL_VALUE_LENGTH ( sizeof ( my_test_params_t )),
},
};
tfdb_dual_cache_t my_test_tfdb_dual_cache = { 0 };
void my_test_tfdb_dual_func ()
{
uint32_t rw_buffer [ TFDB_DUAL_ALIGNED_RW_BUFFER_SIZE ( TFDB_DUAL_VALUE_LENGTH ( sizeof ( my_test_params_t )), 4 )];
uint32_t rw_buffer_bak [ TFDB_DUAL_ALIGNED_RW_BUFFER_SIZE ( TFDB_DUAL_VALUE_LENGTH ( sizeof ( my_test_params_t )), 4 )];
TFDB_Err_Code err ;
for ( uint8_t i = 0 ; i < 36 ; i ++ )
{
err = tfdb_dual_get ( & my_test_tfdb_dual , ( uint8_t * ) rw_buffer , ( uint8_t * ) rw_buffer_bak , & my_test_tfdb_dual_cache , & my_test_params );
if ( err == TFDB_NO_ERR )
{
printf ( "read okncache seq1:0x%04x, seq2:0x%04xnaddr1:0x%08x, addr2:0x%08xn" , my_test_tfdb_dual_cache . seq [ 0 ], my_test_tfdb_dual_cache . seq [ 1 ], my_test_tfdb_dual_cache . addr_cache [ 0 ], my_test_tfdb_dual_cache . addr_cache [ 1 ]);
}
else
{
printf ( "read err:%dn" , err );
}
my_test_params . aa [ 0 ] ++ ;
my_test_params . aa [ 1 ] ++ ;
for ( uint8_t i = 0 ; i < 16 ; i ++ )
{
my_test_params . bb [ i ] ++ ;
}
memset ( & my_test_tfdb_dual_cache , 0 , sizeof ( my_test_tfdb_dual_cache )); /* 测试无地址缓存写入 */
err = tfdb_dual_set ( & my_test_tfdb_dual , ( uint8_t * ) rw_buffer , ( uint8_t * ) rw_buffer_bak , & my_test_tfdb_dual_cache , & my_test_params );
if ( err == TFDB_NO_ERR )
{
printf ( "write okncache seq1:0x%04x, seq2:0x%04xnaddr1:0x%08x, addr2:0x%08xn" , my_test_tfdb_dual_cache . seq [ 0 ], my_test_tfdb_dual_cache . seq [ 1 ], my_test_tfdb_dual_cache . addr_cache [ 0 ], my_test_tfdb_dual_cache . addr_cache [ 1 ]);
}
else
{
printf ( "write err:%dn" , err );
}
memset ( & my_test_tfdb_dual_cache , 0 , sizeof ( my_test_tfdb_dual_cache )); /* 测试无地址缓存读取 */
}
} typedef struct _tfdb_dual_index_struct
{
tfdb_index_t indexes [ 2 ];
} tfdb_dual_index_t ;
typedef struct _tfdb_dual_cache_struct
{
tfdb_addr_t addr_cache [ 2 ];
uint16_t seq [ 2 ];
} tfdb_dual_cache_t ; Strukturfunktion: In der TinyFlashDB -Dual erfordern API -Operationen den angegebenen index , index zwei tfdb_index_t speichert.
TFDB_Err_Code tfdb_dual_get ( const tfdb_dual_index_t * index , uint8_t * rw_buffer , uint8_t * rw_buffer_bak , tfdb_dual_cache_t * cache , void * value_to );Funktionsfunktion: Erhalten Sie eine Variable mit einer angegebenen variablen Länge im Index aus dem Sektor, auf den nach Index hingewiesen wurde. Die Überprüfung des Flash-Header-Datenverifizierungsfehlers initialisiert Flash nicht neu.
index : Indexzeiger für den TFDB -Betrieb.
Parameter rw_buffer : Schreiben und lesen Cache. Alle Flash -Operationen kopieren schließlich die sortierten Daten in den Puffer und rufen dann tfdb_port_write oder tfdb_port_read zum Lesen und Schreiben auf. Wenn der Chip spezielle Anforderungen für den Cache für schriftliche Datenbereiche (z. B. 4-Byte-Ausrichtung, 256-Byte-Ausrichtung usw.) enthält, kann der variable Zeiger, der die Anforderungen entspricht, an die Funktion über diesen Parameter übergeben werden. Mindestens 4 Bytes in Länge.
Parameter rw_buffer_bak : Schreiben und lesen Cache. Alle Flash -Operationen kopieren schließlich die sortierten Daten in den Puffer und rufen dann tfdb_port_write oder tfdb_port_read zum Lesen und Schreiben auf. Wenn der Chip spezielle Anforderungen für den Cache für schriftliche Datenbereiche (z. B. 4-Byte-Ausrichtung, 256-Byte-Ausrichtung usw.) enthält, kann der variable Zeiger, der die Anforderungen entspricht, an die Funktion über diesen Parameter übergeben werden. Mindestens 4 Bytes in Länge.
Parameter cache : Kann nicht NULL sein, es muss ein zwischen tfdb_dual_cache_t definierter zwischengespeicherter Zeiger sein. Wenn die Daten im cache legal sind, wird berücksichtigt, dass cache erfolgreich initialisiert wurde und die Daten direkt aus dem Flash -Block und der Adresse cache gelesen werden.
Parameter value_to : Die Adresse zum Speichern des Dateninhalts.
Rückgabewert: TFDB_NO_ERR ist erfolgreich, andere scheitern.
TFDB_Err_Code tfdb_dual_set ( const tfdb_dual_index_t * index , uint8_t * rw_buffer , uint8_t * rw_buffer_bak , tfdb_dual_cache_t * cache , void * value_from );Funktionsfunktion: Schreiben Sie eine Variable mit einer angegebenen variablen Länge in den Index in den Sektor, auf den durch den Index hingewiesen wird, und der Fehler mit den Flash -Header -Datenüberprüfungen ist wiederum geändert und Flash wird neu initialisiert.
index : Indexzeiger für den TFDB -Betrieb.
Parameter rw_buffer : Schreiben und lesen Cache. Alle Flash -Operationen kopieren schließlich die sortierten Daten in den Puffer und rufen dann tfdb_port_write oder tfdb_port_read zum Lesen und Schreiben auf. Wenn der Chip spezielle Anforderungen für den Cache für schriftliche Datenbereiche (z. B. 4-Byte-Ausrichtung, 256-Byte-Ausrichtung usw.) enthält, kann der variable Zeiger, der die Anforderungen entspricht, an die Funktion über diesen Parameter übergeben werden. Mindestens 4 Bytes in Länge.
Parameter rw_buffer_bak : Schreiben und lesen Cache. Alle Flash -Operationen kopieren schließlich die sortierten Daten in den Puffer und rufen dann tfdb_port_write oder tfdb_port_read zum Lesen und Schreiben auf. Wenn der Chip spezielle Anforderungen für den Cache für schriftliche Datenbereiche (z. B. 4-Byte-Ausrichtung, 256-Byte-Ausrichtung usw.) enthält, kann der variable Zeiger, der die Anforderungen entspricht, an die Funktion über diesen Parameter übergeben werden. Mindestens 4 Bytes in Länge.
Parameter cache : Kann nicht NULL sein, es muss ein zwischen tfdb_dual_cache_t definierter zwischengespeicherter Zeiger sein. Wenn die Daten im cache legal sind, wird berücksichtigt, dass cache erfolgreich initialisiert wurde und die Daten direkt aus dem Flash -Block und der Adresse cache gelesen werden.
Parameter value_from : Der zu gespeicherte Dateninhalt.
Rückgabewert: TFDB_NO_ERR ist erfolgreich, andere scheitern.
Wenn Sie den oben genannten Code beobachten, können Sie feststellen, dass die von tfdb_index_t definierten index für winzige FlashDB -Vorgänge erfordern.
Nach der Initialisierung von Flash sind die Header -Informationen 4 Bytes, so dass nur 1, 2, 4 und 8 Byte -Operationen unterstützt werden:
Der Header wird gelesen, wenn der Header initialisiert wird, sodass die erste Anforderung für die Daten, auf die rw_buffer in der Funktion hingewiesen wurde, mindestens 4 Bytes beträgt. Wenn die Mindestschreibeinheit 8 Bytes beträgt, beträgt die erste Anforderung mindestens 8 Bytes.
| Erster Byte | Zweites Byte | Byte 3 | Viertes Byte und andere ausgerichtete Bytes |
|---|---|---|---|
| Flash_Size höhere 8-Bit-Bytes | Flash_Size niedrige 8-Bit-Bytes | Value_length | end_byte |
Wenn Daten gespeichert werden, wird sie gemäß den von rw_buffer in der Funktion unterstützten Byte -Operationen ausgerichtet, sodass die zweiten Daten zumindest in der folgenden Funktion aligned_value_size werden müssen:
aligned_value_size = index -> value_length + 2 ; /* data + verify + end_byte */
#if ( TFDB_WRITE_UNIT_BYTES == 2 )
/* aligned with TFDB_WRITE_UNIT_BYTES */
aligned_value_size = (( aligned_value_size + 1 ) & 0xfe );
#elif ( TFDB_WRITE_UNIT_BYTES == 4 )
/* aligned with TFDB_WRITE_UNIT_BYTES */
aligned_value_size = (( aligned_value_size + 3 ) & 0xfc );
#elif ( TFDB_WRITE_UNIT_BYTES == 8 )
/* aligned with TFDB_WRITE_UNIT_BYTES */
aligned_value_size = (( aligned_value_size + 7 ) & 0xf8 );
#endif| Erster value_length Bytes | Value_Length+1 Byte | value_length+2 Bytes | Andere ausgerichtete Bytes |
|---|---|---|---|
| value_from Data Inhalt | Value_From Summe Überprüfung | end_byte | end_byte |
Nach jedem Schreiben wird es zur Überprüfung vorgelesen. Wenn die Überprüfung fehlschlägt, wird weiterhin versucht, unter der nächsten Adresse zu schreiben. Bis die maximale Anzahl von Schreibvorgängen (tfdb_write_max_retry) erreicht ist oder der Headerüberprüfungsfehler falsch ist.
Beim Lesen von Daten wird es auch berechnet und überprüft. Wenn es nicht verabschiedet wird, wird es weiter gelesen, bis die neuesten Daten, die die Überprüfung bestanden haben, zurückgegeben wird, oder der Lesung schlägt fehl.
Es gibt nur 3 rechtliche Werte für den Zwei-Byte-SEQ an der Vorderseite der Daten, 0x00ff-> 0x0ff0-> 0xff00.
Dieser Zyklus wiederholt sich, indem wir den SEQ der neuesten Variablen in den beiden Blöcken lesen, können wir bestimmen, welcher Flash -Sektor der neueste Wert ist, der im Flash -Sektor gespeichert ist.
Wenn der neueste Wert im ersten Sektor gespeichert wird, wird das nächste Schreiben im zweiten Sektor geschrieben und umgekehrt.
TFDB_Err_Code tfdb_port_read ( tfdb_addr_t addr , uint8_t * buf , size_t size );
TFDB_Err_Code tfdb_port_erase ( tfdb_addr_t addr , size_t size );
TFDB_Err_Code tfdb_port_write ( tfdb_addr_t addr , const uint8_t * buf , size_t size ); /* use string.h or self functions */
#define TFDB_USE_STRING_H 1
#if TFDB_USE_STRING_H
#include "string.h"
#define tfdb_memcpy memcpy
#define tfdb_memcmp memcmp
#define TFDB_MEMCMP_SAME 0
#else
#define tfdb_memcpy
#define tfdb_memcmp
#define TFDB_MEMCMP_SAME
#endif
#define TFDB_DEBUG printf
/* The data value in flash after erased, most are 0xff, some flash maybe different.
* if it's over 1 byte, please be care of little endian or big endian. */
#define TFDB_VALUE_AFTER_ERASE 0xff
/* The size of TFDB_VALUE_AFTER_ERASE, only support 1 / 2 / 4.
* This value must not bigger than TFDB_WRITE_UNIT_BYTES. */
#define TFDB_VALUE_AFTER_ERASE_SIZE 1
/* the flash write granularity, unit: byte
* only support 1(stm32f4)/ 2(CH559)/ 4(stm32f1)/ 8(stm32L4) */
#define TFDB_WRITE_UNIT_BYTES 8 /* @note you must define it for a value */
/* @note the max retry times when flash is error ,set 0 will disable retry count */
#define TFDB_WRITE_MAX_RETRY 32
/* must not use pointer type. Please use uint32_t, uint16_t or uint8_t. */
typedef uint32_t tfdb_addr_t ;Nach dem Entfernen von Debug -Druckinformationen belegt die Ressource wie folgt:
Keil -o2 -Kompilierungsoptimierungsoptionen
Code ( inc . data ) RO Data RW Data ZI Data Debug Object Name
154 0 0 0 0 2621 tfdb_port . o
682 0 0 0 0 4595 tinyflashdb . oGCC -OS -Kompilierungsoptimierungsoptionen
. text . tfdb_port_read
0x00000000000039b4 0x1a ./ Drivers / TFDB / tfdb_port . o
0x00000000000039b4 tfdb_port_read
. text . tfdb_port_erase
0x00000000000039ce 0x46 ./ Drivers / TFDB / tfdb_port . o
0x00000000000039ce tfdb_port_erase
. text . tfdb_port_write
0x0000000000003a14 0x5c ./ Drivers / TFDB / tfdb_port . o
0x0000000000003a14 tfdb_port_write
. text . tfdb_check
0x0000000000003a70 0x56 ./ Drivers / TFDB / tinyflashdb . o
0x0000000000003a70 tfdb_check
. text . tfdb_init
0x0000000000003ac6 0x56 ./ Drivers / TFDB / tinyflashdb . o
0x0000000000003ac6 tfdb_init
. text . tfdb_set
0x0000000000003b1c 0x186 ./ Drivers / TFDB / tinyflashdb . o
0x0000000000003b1c tfdb_set
. text . tfdb_get
0x0000000000003ca2 0x11c ./ Drivers / TFDB / tinyflashdb . o
0x0000000000003ca2 tfdb_get Bare Metall-Migrationsroutine, RT-Thread kann unter Bezugnahme verwendet werden:
STM32F429IGT6
CH583
QQ -Kommunikationsgruppe: 562090553