Database flash kecil untuk MCU.
Dalam pengembangan mikrokontroler sehari -hari, beberapa informasi selalu diperlukan. Pada saat ini, solusi untuk penyimpanan flash mikrokontroler diperlukan. Saat ini, ada banyak solusi untuk penyimpanan mikrokontroler, seperti: Easyflash, FlashDB, OSAL_NV, dll. Program mereka sangat besar dan tidak layak menyimpan beberapa variabel. Dan jarang mempertimbangkan kesalahan penulisan flash.
Dalam produk aktual, penulisan flash produk tertanam dapat dipengaruhi oleh berbagai faktor (bertenaga baterai, pemadaman listrik yang tidak terduga, suhu, dll.) Dan tidak terlalu stabil. Setelah kesalahan terjadi, itu akan menyebabkan serangkaian masalah produk.
Tidak seperti banyak database tipe KV lainnya, setiap variabel yang perlu disimpan dalam TinyFlashDB akan dialokasikan sektor flash mikrokontroler yang terpisah, dan panjang variabel tidak dapat diubah.
Oleh karena itu, TinyFlashDB hanya cocok untuk menyimpan beberapa variabel kunci (seperti: bendera lompatan IAP, waktu pemadaman daya sistem, dll.), Dan tidak cocok untuk penyimpanan data skala besar (penyimpanan data skala besar dapat menggunakan EasyFlash, dll.).
TinyFlashDB dirancang untuk mempertimbangkan dampak kesalahan penulisan, mengejar jaminan keamanan dalam kemampuannya, pekerjaan sumber daya sebanyak mungkin (kurang dari 1kB kode menempati), dan universalitas mungkin (dapat diangkut ke komputer 8-bit seperti 51, STM32L4 Series yang tidak dapat ditulis dalam urutan terbalik, beberapa mikro-terancam mikro-kilat dan mikro-kontrol-tiang yang berkedip mikrokontrolrer dan mikro-kontrol yang dierkontrol oleh flash-encryroller dan flash-encryroller dan flash-encryroller dan flash-encryroller dan flash-encryroller microcontrollers lainnya).
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 ;Fungsi Struktur: Di TinyFlashDB, Operasi API memerlukan indeks parameter yang ditentukan. Struktur indeks ini menyimpan alamat flash, ukuran flash, panjang variabel yang disimpan, dan bendera akhir. Informasi ini akan diperiksa saat membaca sektor flash.
TFDB_Err_Code tfdb_get ( const tfdb_index_t * index , uint8_t * rw_buffer , tfdb_addr_t * addr_cache , void * value_to ); Fungsi Fungsi: Dapatkan variabel dengan panjang variabel yang ditentukan dalam indeks dari sektor yang ditunjuk oleh index . Kesalahan verifikasi data header flash tidak akan memulai kembali flash.
index Parameter: Indeks Pointer untuk Operasi TFDB.
Parameter rw_buffer : Tulis dan baca cache. Semua operasi flash akhirnya akan menyalin data yang diurutkan ke buffer, dan kemudian hubungi tfdb_port_write atau tfdb_port_read untuk membaca dan menulis. Ketika chip memiliki persyaratan khusus untuk cache area data tertulis (seperti perataan 4-byte, penyelarasan 256-byte, dll.), Pointer variabel yang memenuhi persyaratan dapat diteruskan ke fungsi untuk digunakan melalui parameter ini. Panjang setidaknya 4 byte.
Parameter addr_cache : bisa NULL , atau pointer ke variabel cache alamat. Ketika addr_cache tidak NULL dan bukan 0, addr_cache dianggap telah diinisialisasi dengan sukses, tidak lagi memeriksa header flash, dan data dibaca langsung dari alamat addr_cache .
Parameter value_to : Alamat untuk menyimpan konten data.
Nilai pengembalian: TFDB_NO_ERR berhasil, yang lain gagal.
TFDB_Err_Code tfdb_set ( const tfdb_index_t * index , uint8_t * rw_buffer , tfdb_addr_t * addr_cache , void * value_from ); Fungsi Fungsi: Tulis variabel dengan panjang variabel yang ditentukan dalam indeks ke sektor yang ditunjuk oleh index , dan kesalahan verifikasi data header flash keliru dan flash diinisialisasi kembali.
index Parameter: Indeks Pointer untuk Operasi TFDB.
Parameter rw_buffer : Tulis dan baca cache. Semua operasi flash akhirnya akan menyalin data yang diurutkan ke buffer, dan kemudian hubungi tfdb_port_write atau tfdb_port_read untuk membaca dan menulis. Ketika chip memiliki persyaratan khusus untuk cache area data tertulis (seperti perataan 4-byte, penyelarasan 256-byte, dll.), Pointer variabel yang memenuhi persyaratan dapat diteruskan ke fungsi untuk digunakan melalui parameter ini. Panjang setidaknya 4 byte.
Parameter addr_cache : bisa NULL , atau pointer ke variabel cache alamat. Ketika addr_cache tidak NULL dan bukan 0, addr_cache dianggap telah diinisialisasi dengan sukses, tidak lagi memeriksa header flash, dan data dibaca langsung dari alamat addr_cache .
Parameter value_from : Konten data yang akan disimpan.
Nilai pengembalian: TFDB_NO_ERR berhasil, yang lain gagal.
API ganda TFDB dienkapsulasi berdasarkan tfdb_set dan tfdb_get . tfdb dual akan menghubungi tfdb_set dan tfdb_get dan menambahkan dua byte SEQ ke depan data, jadi di TFDB Dual, panjang variabel penyimpanan yang didukung terpanjang adalah 253 byte.
Pada saat yang sama, TFDB Dual API perlu menyediakan dua buffer, dan perlu aligned_value_size meningkatkan panjang variabel dua-byte dan kemudian menghitung ulang.
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 ; Fungsi Struktur: Dalam Operasi Dual TinyFlashDB, API memerlukan index parameter yang ditentukan, index menyimpan dua tfdb_index_t .
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 );Fungsi Fungsi: Dapatkan variabel dengan panjang variabel yang ditentukan dalam indeks dari sektor yang ditunjuk oleh indeks. Kesalahan verifikasi data header flash tidak akan memulai kembali flash.
index Parameter: Indeks Pointer untuk Operasi TFDB.
Parameter rw_buffer : Tulis dan baca cache. Semua operasi flash akhirnya akan menyalin data yang diurutkan ke buffer, dan kemudian hubungi tfdb_port_write atau tfdb_port_read untuk membaca dan menulis. Ketika chip memiliki persyaratan khusus untuk cache area data tertulis (seperti perataan 4-byte, penyelarasan 256-byte, dll.), Pointer variabel yang memenuhi persyaratan dapat diteruskan ke fungsi untuk digunakan melalui parameter ini. Panjang setidaknya 4 byte.
Parameter rw_buffer_bak : Tulis dan baca cache. Semua operasi flash akhirnya akan menyalin data yang diurutkan ke buffer, dan kemudian hubungi tfdb_port_write atau tfdb_port_read untuk membaca dan menulis. Ketika chip memiliki persyaratan khusus untuk cache area data tertulis (seperti perataan 4-byte, penyelarasan 256-byte, dll.), Pointer variabel yang memenuhi persyaratan dapat diteruskan ke fungsi untuk digunakan melalui parameter ini. Panjang setidaknya 4 byte.
Parameter cache : Tidak bisa NULL , itu harus menjadi penunjuk cache yang ditentukan oleh tfdb_dual_cache_t . Ketika data dalam cache legal, dianggap bahwa cache telah diinisialisasi dengan sukses dan data dibaca langsung dari blok flash dan alamat cache .
Parameter value_to : Alamat untuk menyimpan konten data.
Nilai pengembalian: TFDB_NO_ERR berhasil, yang lain gagal.
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 );Fungsi Fungsi: Tulis variabel dengan panjang variabel yang ditentukan dalam indeks ke sektor yang ditunjuk oleh indeks, dan kesalahan verifikasi data header flash keliru dan flash diinisialisasi kembali.
index Parameter: Indeks Pointer untuk Operasi TFDB.
Parameter rw_buffer : Tulis dan baca cache. Semua operasi flash akhirnya akan menyalin data yang diurutkan ke buffer, dan kemudian hubungi tfdb_port_write atau tfdb_port_read untuk membaca dan menulis. Ketika chip memiliki persyaratan khusus untuk cache area data tertulis (seperti perataan 4-byte, penyelarasan 256-byte, dll.), Pointer variabel yang memenuhi persyaratan dapat diteruskan ke fungsi untuk digunakan melalui parameter ini. Panjang setidaknya 4 byte.
Parameter rw_buffer_bak : Tulis dan baca cache. Semua operasi flash akhirnya akan menyalin data yang diurutkan ke buffer, dan kemudian hubungi tfdb_port_write atau tfdb_port_read untuk membaca dan menulis. Ketika chip memiliki persyaratan khusus untuk cache area data tertulis (seperti perataan 4-byte, penyelarasan 256-byte, dll.), Pointer variabel yang memenuhi persyaratan dapat diteruskan ke fungsi untuk digunakan melalui parameter ini. Panjang setidaknya 4 byte.
Parameter cache : Tidak bisa NULL , itu harus menjadi penunjuk cache yang ditentukan oleh tfdb_dual_cache_t . Ketika data dalam cache legal, dianggap bahwa cache telah diinisialisasi dengan sukses dan data dibaca langsung dari blok flash dan alamat cache .
Parameter value_from : Konten data yang akan disimpan.
Nilai pengembalian: TFDB_NO_ERR berhasil, yang lain gagal.
Mengamati kode di atas, Anda dapat menemukan bahwa operasi TinyFlashDB memerlukan parameter index yang ditentukan oleh tfdb_index_t .
Setelah flash diinisialisasi, informasi header adalah 4 byte, jadi hanya flash dengan operasi 1, 2, 4, dan 8 byte yang didukung:
Header akan dibaca ketika header diinisialisasi, sehingga persyaratan pertama untuk data yang ditunjukkan oleh rw_buffer dalam fungsi setidaknya 4 byte. Jika unit penulisan minimum adalah 8 byte, persyaratan pertama adalah setidaknya 8 byte.
| Byte pertama | Byte kedua | Byte 3 | Byte keempat dan byte selaras lainnya |
|---|---|---|---|
| flash_size byte 8-bit yang lebih tinggi | flash_size byte 8-bit rendah | value_length | end_byte |
Ketika data disimpan, itu akan diselaraskan menurut operasi byte yang didukung oleh flash, sehingga data kedua yang ditunjukkan oleh rw_buffer dalam fungsi diperlukan untuk setidaknya aligned_value_size byte yang dihitung dalam fungsi berikut:
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| Byte value_length pertama | value_length+1 byte | value_length+2 byte | Byte selaras lainnya |
|---|---|---|---|
| value_dari konten data | verifikasi value_dari jumlah | end_byte | end_byte |
Setelah masing -masing menulis, itu akan dibacakan untuk verifikasi. Jika verifikasi gagal, itu akan terus mencoba menulis di alamat berikutnya. Sampai jumlah maksimum penulisan (tfdb_write_max_retry) tercapai atau kesalahan verifikasi header salah.
Saat membaca data, itu juga akan dihitung dan diperiksa. Jika tidak berlalu, itu akan terus membaca sampai data terbaru yang telah melewati verifikasi dikembalikan, atau pembacaan gagal.
Hanya ada 3 nilai hukum untuk SEQ dua-byte di bagian depan data, 0x00ff-> 0x0ff0-> 0xff00.
Siklus ini berulang -ulang, dengan membaca SEQ dari variabel terbaru di dua blok, kita dapat menentukan sektor flash mana yang merupakan nilai terbaru yang disimpan di sektor flash.
Ketika nilai terbaru disimpan di sektor pertama, tulisan berikutnya akan ditulis di sektor kedua, dan sebaliknya.
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 ;Setelah menghapus informasi pencetakan debug, sumber daya menempati sebagai berikut:
Opsi Optimasi Kompilasi Keil -O2
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 . oOpsi Optimasi Kompilasi GCC -OS
. 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 Rutin migrasi logam telanjang, rt-thread dapat digunakan dengan referensi:
STM32F429IGT6
CH583
Grup Komunikasi QQ: 562090553