SFUD、FlashDB测试demo

经过前期将SFUD+FlashDB移植过来,然后验证是否OK,需要编写点demo或应用程序

目录

1. 设计DB表格格式

2. DB初始化代码

3. FlashDB 读写代码

往数据库里写入数据

往数据库里读取数据

4. SFUD 读写代码

5. 其他注意事项

地址规划

Task的stack_size

仿真时的JTAG时钟配置


1. 设计DB表格格式

一般来说用DB,主要key-value比较多,因此你要设计好需要多少个,类型怎么样,初始值是多少。数据库格式要先设计好,换成代码如下:

static uint16_t s_HexFileLen = 0;    /* Hex文件大小,默认0,表示无文件 */
static uint16_t s_BinFileLen = 0;    /* Bin文件大小,默认0,表示无文件 */


/* default KV nodes */ /* 这张表要配置好,根据实际情况输入 */
static struct fdb_default_kv_node default_kv_table[] =
{
    { "soft_ver",   		"V1.0.02 b06",       0                    },
    { "hex_file_len",  &s_HexFileLen,      sizeof(s_HexFileLen)       },
    { "bin_file_len",  &s_BinFileLen,      sizeof(s_BinFileLen)       }
};

/* 字符串+数值型 */

这些都是应用层代码,建议单独一个模块

2. DB初始化代码

要做内容:选择一个 锁(Mutex),开启初始化功能

/* KVDB object */
static struct fdb_kvdb s_Kvdb = { 0 };
/* TSDB object */
static SemaphoreHandle_t s_MutexFDB_kvdb;
/* 初始化标记 */
static uint8_t s_Inited = 0;

//
// 注意看注释掉的代码,本demo使用Freertos里机制。也可以用HAL的mutex,也可以irq
static void lock(fdb_db_t db)
{
    xSemaphoreTake(s_MutexFDB_kvdb, portMAX_DELAY);
	//osMutexWait(FDBMutex_idHandle, osWaitForever);
	//__disable_irq();
}

static void unlock(fdb_db_t db)
{
    xSemaphoreGive(s_MutexFDB_kvdb);
	//osMutexRelease(FDBMutex_idHandle);
	//__enable_irq();
}


void DBInit(void)
{
	if(s_Inited)
	{
		return;
	}
	
	/* KVDB Sample */
	struct fdb_default_kv default_kv;
	fdb_err_t result;
	
//这个必须保证创建好,否则会卡死的
	s_MutexFDB_kvdb = xSemaphoreCreateMutex();
	//mutex_id = osMutexCreate();

	default_kv.kvs = default_kv_table;
	default_kv.num = sizeof(default_kv_table) / sizeof(default_kv_table[0]);
	/* set the lock and unlock function if you want */
	fdb_kvdb_control(&s_Kvdb, FDB_KVDB_CTRL_SET_LOCK, (void *)lock);
	fdb_kvdb_control(&s_Kvdb, FDB_KVDB_CTRL_SET_UNLOCK, (void *)unlock);
	
	s_Kvdb.ver_num = 1;  //这个会第一次将默认值写入,否则表中若没有的话,读取的时候会失败

///"fdb_kvdb1" 这个不能随意修改,要跟 fal_cfg.h 里的一致
	result = fdb_kvdb_init(&s_Kvdb, "env", "fdb_kvdb1", &default_kv, NULL);
	
	if (result != FDB_NO_ERR) {
		printf("KVDB init failed. resoult = %d\n",result);
		return;
	}
	
	s_Inited = 1;
}

注意点,看代码注释,已经很保姆了。

如果不出意外的话,在main中,rtos init之前,调用DBInit,会初始化成功!!

3. FlashDB 读写代码

往数据库里写入数据

// 写入字符串key,eg: DBSetValueBuf("soft_ver","v12.22233.DBG");
void DBSetValueBuf(const char *key,char *buf)
{
	if (!s_Inited)
    {
        DBInit();
    }

    fdb_kv_set(&s_Kvdb, key, buf);
}

// 写入U16 key,eg: DBSetValueU16("hex_file_len",23232);
void DBSetValueU16(const char *key,uint16_t value)
{
	if (!s_Inited)
    {
        DBInit();
    }

    struct fdb_blob blob;
    fdb_kv_set_blob(&s_Kvdb, key, fdb_blob_make(&blob, &value, sizeof(value)));
}

往数据库里读取数据

// eg: 
// char version[20] = {0};
// DBGetValueBuf("soft_ver",version,16);
//
bool DBGetValueBuf(const char *key,char *buf, uint8_t bufSize)
{
	if (!s_Inited)
    {
        DBInit();
    }
	
    char *returnValue;
    returnValue = fdb_kv_get(&s_Kvdb, key);

    if (returnValue == NULL)
    {
        printf("[%s] get failed\n",key);
        return false;
    }
	
	strncpy(buf, returnValue, bufSize);
	return true;
}

4. SFUD 读写代码

    sfud读写通过sufd.h 提供接口进行访问,首先,得调用sfud_init

然后确认好flash起始地址、以及待处理长度

读的话比较简单

    sfud_flash *sfud_dev = NULL;
    sfud_err ret;
	uint16_t readLen = bufSize;
	
    sfud_dev = sfud_get_device(SFUD_W25Q128_DEVICE_INDEX); 
	
	if(sfud_dev == NULL)
	{
		/* device error */
		errorf("SFUD: get device failed.");
		return 0;
	}	
	
		/// startReadAdr 开始地址,readLen 要读取的长度,buf是读取后存放地方

	ret = sfud_read(sfud_dev, startReadAdr, readLen, buf);

写也简单

sfud_flash *sfud_dev = NULL;
    sfud_err ret;
	uint16_t writeLen = bufSize;
	
    sfud_dev = sfud_get_device(SFUD_W25Q128_DEVICE_INDEX); 
	
	if(sfud_dev == NULL)
	{
		/* device error */
		errorf("LoaderWriteData error. get device failed.");
		return 0;
	}		
	
// startWriteAdr 开始写起始地址;writeLen 待写入长度,buf 待写入的内容
		
	ret = sfud_write(sfud_dev, startWriteAdr, writeLen, buf);

sfud_write 是不带擦除的,如果没有擦除过,会写失败的;

一种办法:

      针对批量写入:先擦除待写入的所有区域 

      sfud_erase(sfud_dev,startWriteAdr,len);

另外一种办法:

      调用 sfud_erase_write 接口,这个效率低,但针对“打补丁”比较适合

注意:nor flash擦除次数限制,避免同一个地方经常擦除!!

5. 其他注意事项

地址规划

一般来说flash DB会规划一块区域,其他区域不应该有交叉,否则很乱。实在不行提高flash容量更划算点

Task的stack_size

这个task是指Freertos task的堆栈空间,通过CubeMX配置task默认比较小,稍微多一些逻辑就会超过,问题的关键,不小心超过,有时候未必发现得了,(往往经过多轮run之后会卡死)

默认的是128 words,是很小的。特别是一些针对db业务代码;

如果剩余不足的话,有时候很难发现异常。

仿真时的JTAG时钟配置

如下图,这个地方,默认是10MHz,但实际很不稳定,老连接失败之类,改成2MHz,稳定性加强了很多,这个据说是连接线的质量问题(或供电问题),很奇怪!

SFUD、FlashDB测试demo_第1张图片

你可能感兴趣的:(stm32,SFUD,FlashDB,demo)