GD32上FAL Flash分区驱动移植及Easyflash与FlashDB移植说明

GD32上FAL Flash分区驱动移植及Easyflash与FlashDB移植说明

  • 效果
  • 移植前提
    • 下载源码
  • 移植过程
    • 加入以下文件及文件夹到工程目录和工程
    • 将demo目录下的接口文件做下修改
    • 修改配置文件fal_cfg.h
    • 复制demo中文件修改内部flash驱动接口
    • 外部SPI Flash的接口配置
  • 测试代码
    • 建议调试打开打印功能
    • 必须的初始化
    • 读写擦除
  • Easyflash的移植
    • 修改fdb的cfg文件
    • 测试代码

效果

GD32上FAL Flash分区驱动移植及Easyflash与FlashDB移植说明_第1张图片
GD32上FAL Flash分区驱动移植及Easyflash与FlashDB移植说明_第2张图片

移植前提

下载源码

前往下载

移植过程

加入以下文件及文件夹到工程目录和工程

GD32上FAL Flash分区驱动移植及Easyflash与FlashDB移植说明_第3张图片
GD32上FAL Flash分区驱动移植及Easyflash与FlashDB移植说明_第4张图片

  • Easyflash工程目录文件添加参考

将demo目录下的接口文件做下修改

GD32上FAL Flash分区驱动移植及Easyflash与FlashDB移植说明_第5张图片

修改配置文件fal_cfg.h

#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_

#define FAL_PART_HAS_TABLE_CFG

#define NOR_FLASH_DEV_NAME             "norflash0"
#define FAL_PART_TABLE_FLASH_DEV_NAME  NOR_FLASH_DEV_NAME
#define FAL_USING_NOR_FLASH_DEV_NAME   "norflash0"
#define FAL_PART_TABLE_END_OFFSET      (2*1024*1024L)

/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev gd32f4_onchip_flash;
extern struct fal_flash_dev nor_flash0;

/* flash device table */
#define FAL_FLASH_DEV_TABLE                                          \
{                                                                    \
    &gd32f4_onchip_flash,                                           \
    &nor_flash0,                                                     \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE                                                               \
{                                                                                    \
    {FAL_PART_MAGIC_WORD,        "app",     "gd32_onchip",         0,   704*1024, 0}, \
    {FAL_PART_MAGIC_WORD,       "param",     "gd32_onchip",   704*1024,  64*1024, 0}, \
    {FAL_PART_MAGIC_WORD, "easyflash", NOR_FLASH_DEV_NAME,         0, 1024*1024, 0}, \
    {FAL_PART_MAGIC_WORD,  "download", NOR_FLASH_DEV_NAME, 1024*1024, 1024*1024, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */

#endif /* _FAL_CFG_H_ */

复制demo中文件修改内部flash驱动接口

更名为:fal_flash_gd32f2_port.c(这个操作依据自己芯片平台非必须)

主要完善以下接口:

  • 内部FLASH的读取,写入,擦除操作
  • 内部FLASH的属性配置

GD32的FLASH操作接口已改为HAL方式,HAL的移植方式参考我的博客https://editor.csdn.net/md/?articleId=106135522

#include 

#include 
#include "flash.h"
/* base address of the flash sectors */
/*bank1*/
#define ADDR_FLASH_SECTOR_0      ((uint32_t)0x08000000) 									/* Base address of Sector 0, 16 K bytes   */
#define ADDR_FLASH_SECTOR_1      ((uint32_t)16*1024+ADDR_FLASH_SECTOR_0) 	/* Base address of Sector 1, 16 K bytes   */
#define ADDR_FLASH_SECTOR_2      ((uint32_t)16*1024+ADDR_FLASH_SECTOR_1) 	/* Base address of Sector 2, 16 K bytes   */
#define ADDR_FLASH_SECTOR_3      ((uint32_t)16*1024+ADDR_FLASH_SECTOR_2) 	/* Base address of Sector 3, 16 K bytes   */
#define ADDR_FLASH_SECTOR_4      ((uint32_t)16*1024+ADDR_FLASH_SECTOR_3) 	/* Base address of Sector 4, 64 K bytes   */
#define ADDR_FLASH_SECTOR_5      ((uint32_t)64*1024+ADDR_FLASH_SECTOR_4) 	/* Base address of Sector 5, 128 K bytes  */
#define ADDR_FLASH_SECTOR_6      ((uint32_t)128*1024+ADDR_FLASH_SECTOR_5) /* Base address of Sector 6, 128 K bytes  */
#define ADDR_FLASH_SECTOR_7      ((uint32_t)128*1024+ADDR_FLASH_SECTOR_6) /* Base address of Sector 7, 128 K bytes  */
#define ADDR_FLASH_SECTOR_8      ((uint32_t)128*1024+ADDR_FLASH_SECTOR_7) /* Base address of Sector 8, 128 K bytes  */
#define ADDR_FLASH_SECTOR_9      ((uint32_t)128*1024+ADDR_FLASH_SECTOR_8) /* Base address of Sector 9, 128 K bytes  */
#define ADDR_FLASH_SECTOR_10     ((uint32_t)128*1024+ADDR_FLASH_SECTOR_9) /* Base address of Sector 10, 128 K bytes */
#define ADDR_FLASH_SECTOR_11     ((uint32_t)128*1024+ADDR_FLASH_SECTOR_10)/* Base address of Sector 11, 128 K bytes */
/*bank2*/
#define ADDR_FLASH_SECTOR_12     ((uint32_t)128*1024+ADDR_FLASH_SECTOR_11)/* Base address of Sector 12, 16 K bytes  */
#define ADDR_FLASH_SECTOR_13     ((uint32_t)16*1024+ADDR_FLASH_SECTOR_12) /* Base address of Sector 13, 16 K bytes  */
#define ADDR_FLASH_SECTOR_14     ((uint32_t)16*1024+ADDR_FLASH_SECTOR_13) /* Base address of Sector 14, 16 K bytes  */
#define ADDR_FLASH_SECTOR_15     ((uint32_t)16*1024+ADDR_FLASH_SECTOR_14) /* Base address of Sector 15, 16 K bytes  */
#define ADDR_FLASH_SECTOR_16     ((uint32_t)16*1024+ADDR_FLASH_SECTOR_15) /* Base address of Sector 16, 64 K bytes  */
#define ADDR_FLASH_SECTOR_17     ((uint32_t)64*1024+ADDR_FLASH_SECTOR_16) /* Base address of Sector 17, 128 K bytes */
#define ADDR_FLASH_SECTOR_18     ((uint32_t)128*1024+ADDR_FLASH_SECTOR_17)/* Base address of Sector 18, 128 K bytes */
#define ADDR_FLASH_SECTOR_19     ((uint32_t)128*1024+ADDR_FLASH_SECTOR_18)/* Base address of Sector 19, 128 K bytes */
#define ADDR_FLASH_SECTOR_20     ((uint32_t)128*1024+ADDR_FLASH_SECTOR_19)/* Base address of Sector 20, 128 K bytes */
#define ADDR_FLASH_SECTOR_21     ((uint32_t)128*1024+ADDR_FLASH_SECTOR_20)/* Base address of Sector 21, 128 K bytes */
#define ADDR_FLASH_SECTOR_22     ((uint32_t)128*1024+ADDR_FLASH_SECTOR_21)/* Base address of Sector 22, 128 K bytes */
#define ADDR_FLASH_SECTOR_23     ((uint32_t)128*1024+ADDR_FLASH_SECTOR_22)/* Base address of Sector 23, 128 K bytes */
#define ADDR_FLASH_SECTOR_24     ((uint32_t)128*1024+ADDR_FLASH_SECTOR_23)/* Base address of Sector 24, 256 K bytes */
#define ADDR_FLASH_SECTOR_25     ((uint32_t)256*1024+ADDR_FLASH_SECTOR_24)/* Base address of Sector 25, 256 K bytes */
#define ADDR_FLASH_SECTOR_26     ((uint32_t)256*1024+ADDR_FLASH_SECTOR_15)/* Base address of Sector 26, 256 K bytes */
#define ADDR_FLASH_SECTOR_27     ((uint32_t)256*1024+ADDR_FLASH_SECTOR_16)/* Base address of Sector 27, 256 K bytes */
#define ADDR_FLASH_ECTOR_MAX		 ((uint32_t)256*1024+ADDR_FLASH_SECTOR_17)/*flash最大地址*/

/**
 * Get the sector of a given address
 *
 * @param address flash address
 *
 * @return The sector of a given address
 */
static uint32_t gd32_get_sector(uint32_t address)
{
    uint32_t sector = 0;

    if ((address < ADDR_FLASH_SECTOR_1) && (address >= ADDR_FLASH_SECTOR_0))
    {
        sector = FLASH_SECTOR_0;
    }
    else if ((address < ADDR_FLASH_SECTOR_2) && (address >= ADDR_FLASH_SECTOR_1))
    {
        sector = FLASH_SECTOR_1;
    }
    else if ((address < ADDR_FLASH_SECTOR_3) && (address >= ADDR_FLASH_SECTOR_2))
    {
        sector = FLASH_SECTOR_2;
    }
    else if ((address < ADDR_FLASH_SECTOR_4) && (address >= ADDR_FLASH_SECTOR_3))
    {
        sector = FLASH_SECTOR_3;
    }
    else if ((address < ADDR_FLASH_SECTOR_5) && (address >= ADDR_FLASH_SECTOR_4))
    {
        sector = FLASH_SECTOR_4;
    }
    else if ((address < ADDR_FLASH_SECTOR_6) && (address >= ADDR_FLASH_SECTOR_5))
    {
        sector = FLASH_SECTOR_5;
    }
    else if ((address < ADDR_FLASH_SECTOR_7) && (address >= ADDR_FLASH_SECTOR_6))
    {
        sector = FLASH_SECTOR_6;
    }
    else if ((address < ADDR_FLASH_SECTOR_8) && (address >= ADDR_FLASH_SECTOR_7))
    {
        sector = FLASH_SECTOR_7;
    }
    else if ((address < ADDR_FLASH_SECTOR_9) && (address >= ADDR_FLASH_SECTOR_8))
    {
        sector = FLASH_SECTOR_8;
    }
    else if ((address < ADDR_FLASH_SECTOR_10) && (address >= ADDR_FLASH_SECTOR_9))
    {
        sector = FLASH_SECTOR_9;
    }
    else if ((address < ADDR_FLASH_SECTOR_11) && (address >= ADDR_FLASH_SECTOR_10))
    {
        sector = FLASH_SECTOR_10;
    }
    else if ((address < ADDR_FLASH_SECTOR_12) && (address >= ADDR_FLASH_SECTOR_11))
    {
        sector = FLASH_SECTOR_11;
    }
    else if ((address < ADDR_FLASH_SECTOR_13) && (address >= ADDR_FLASH_SECTOR_12))
    {
        sector = FLASH_SECTOR_12;
    }
    else if ((address < ADDR_FLASH_SECTOR_14) && (address >= ADDR_FLASH_SECTOR_13))
    {
        sector = FLASH_SECTOR_13;
    }
    else if ((address < ADDR_FLASH_SECTOR_15) && (address >= ADDR_FLASH_SECTOR_14))
    {
        sector = FLASH_SECTOR_14;
    }
    else if ((address < ADDR_FLASH_SECTOR_16) && (address >= ADDR_FLASH_SECTOR_15))
    {
        sector = FLASH_SECTOR_15;
    }
    else if ((address < ADDR_FLASH_SECTOR_17) && (address >= ADDR_FLASH_SECTOR_16))
    {
        sector = FLASH_SECTOR_16;
    }
    else if ((address < ADDR_FLASH_SECTOR_18) && (address >= ADDR_FLASH_SECTOR_17))
    {
        sector = FLASH_SECTOR_17;
    }
    else if ((address < ADDR_FLASH_SECTOR_19) && (address >= ADDR_FLASH_SECTOR_18))
    {
        sector = FLASH_SECTOR_18;
    }
    else if ((address < ADDR_FLASH_SECTOR_20) && (address >= ADDR_FLASH_SECTOR_19))
    {
        sector = FLASH_SECTOR_19;
    }
    else if ((address < ADDR_FLASH_SECTOR_21) && (address >= ADDR_FLASH_SECTOR_20))
    {
        sector = FLASH_SECTOR_20;
    }
    else if ((address < ADDR_FLASH_SECTOR_22) && (address >= ADDR_FLASH_SECTOR_21))
    {
        sector = FLASH_SECTOR_21;
    }
    else if ((address < ADDR_FLASH_SECTOR_23) && (address >= ADDR_FLASH_SECTOR_22))
    {
        sector = FLASH_SECTOR_22;
    }
    else if ((address < ADDR_FLASH_SECTOR_24) && (address >= ADDR_FLASH_SECTOR_23))
    {
        sector = FLASH_SECTOR_23;
    }
    else if ((address < ADDR_FLASH_SECTOR_25) && (address >= ADDR_FLASH_SECTOR_24))
    {
        sector = FLASH_SECTOR_24;
    }
    else if ((address < ADDR_FLASH_SECTOR_26) && (address >= ADDR_FLASH_SECTOR_25))
    {
        sector = FLASH_SECTOR_25;
    }
    else if ((address < ADDR_FLASH_SECTOR_27) && (address >= ADDR_FLASH_SECTOR_26))
    {
        sector = FLASH_SECTOR_26;
    }
	else
	{
		sector = FLASH_SECTOR_27;
	}
    return sector;
}

/**
 * Get the sector size
 *
 * @param sector sector
 *
 * @return sector size
 */
static uint32_t gd32_get_sector_size(uint32_t sector) {
    assert(IS_FLASH_SECTOR(sector));

    switch (sector) {
    case FLASH_SECTOR_0:
    case FLASH_SECTOR_1:
    case FLASH_SECTOR_2:
    case FLASH_SECTOR_3: return 16 * 1024;
    case FLASH_SECTOR_4: return 64 * 1024;
    case FLASH_SECTOR_5: 
    case FLASH_SECTOR_6: 
    case FLASH_SECTOR_7: 
    case FLASH_SECTOR_8: 
    case FLASH_SECTOR_9: 
    case FLASH_SECTOR_10:
    case FLASH_SECTOR_11: return 128 * 1024;
	case FLASH_SECTOR_12:
	case FLASH_SECTOR_13:
	case FLASH_SECTOR_14:
	case FLASH_SECTOR_15: return 16 * 1024;
	case FLASH_SECTOR_16: return 64 * 1024;
	case FLASH_SECTOR_17: 
    case FLASH_SECTOR_18: 
    case FLASH_SECTOR_19: 
    case FLASH_SECTOR_20:
    case FLASH_SECTOR_21: 
	case FLASH_SECTOR_22: 
    case FLASH_SECTOR_23: return 128 * 1024;
	case FLASH_SECTOR_24:
	case FLASH_SECTOR_25: 
	case FLASH_SECTOR_26:
	case FLASH_SECTOR_27: return 256 * 1024;
    default : return 256 * 1024;
    }
}
static int init(void)
{
    /* do nothing now */
}

static int read(long offset, uint8_t *buf, size_t size)
{
    size_t i;
    uint32_t addr = gd32f4_onchip_flash.addr + offset;
    for (i = 0; i < size; i++, addr++, buf++)
    {
        *buf = *(uint8_t *) addr;
    }

    return size;
}

static int write(long offset, const uint8_t *buf, size_t size)
{
    size_t i;
    uint32_t read_data;
    uint32_t addr = gd32f4_onchip_flash.addr + offset;

    HAL_FLASH_Unlock();

    for (i = 0; i < size; i++, buf++, addr++)
    {
        /* write data */
        FLASH_ProgramByte(addr, *buf);
        read_data = *(uint8_t *) addr;
        /* check data */
        if (read_data != *buf)
        {
            return -1;
        }
    }
    HAL_FLASH_Lock();

    return size;
}

/**
  ******************************************************************
  * @brief   获取当前扇区所属bank
  * @param   [in]扇区号
  * @retval  flash bank号
  * @author  aron566
  * @version V1.0
  * @date    2020-6-3
  ******************************************************************
  */
static uint32_t Get_SectorBank(uint32_t Sector)
{
	if(Sector < ADDR_FLASH_SECTOR_12)
	{
		return FLASH_BANK_1;
	}
	else
	{
		return FLASH_BANK_2;
	}
}

static int erase(long offset, size_t size)
{
    HAL_StatusTypeDef flash_status;
    size_t erased_size = 0;
    uint32_t cur_erase_sector;
    uint32_t addr = gd32f4_onchip_flash.addr + offset;

		FLASH_EraseInitTypeDef config;
		uint32_t ERROR = 0;
		config.NbSectors = 1;
		config.TypeErase = FLASH_TYPEERASE_SECTORS;
		config.VoltageRange = FLASH_VOLTAGE_RANGE_4;
	
    /* start erase */
    HAL_FLASH_Unlock();

    /* it will stop when erased size is greater than setting size */
    while (erased_size < size)
    {
        config.Sector = gd32_get_sector(addr + erased_size);
		config.Banks = Get_SectorBank(config.Sector);
        flash_status = HAL_FLASHEx_Erase(&config, &ERROR);
        if (flash_status != HAL_OK)
        {
            return -1;
        }
        erased_size += gd32_get_sector_size(cur_erase_sector);
    }
    HAL_FLASH_Lock();

    return size;
}

const struct fal_flash_dev gd32f4_onchip_flash =
{
    .name       = "gd32_onchip",
    .addr       = ADDR_FLASH_SECTOR_0,
    .len        = ADDR_FLASH_ECTOR_MAX - ADDR_FLASH_SECTOR_0,
    .blk_size   = 256*1024,
    .ops        = {init, read, write, erase},
    .write_gran = 8
};

外部SPI Flash的接口配置

由于操作flash的接口是由sfud万能驱动接口做的,所以参考sfud的移植,当然不移植就需要自己实现外部SPI Flash的读取/写入/擦除驱动。
fal_flash_sfud_port.c修改如下:

#include 
#include 

#define FAL_USING_SFUD_PORT
#ifdef FAL_USING_SFUD_PORT
#ifdef RT_USING_SFUD
#include 
#endif

#ifndef FAL_USING_NOR_FLASH_DEV_NAME
#define FAL_USING_NOR_FLASH_DEV_NAME             "norflash0"
#endif

static int init(void);
static int read(long offset, uint8_t *buf, size_t size);
static int write(long offset, const uint8_t *buf, size_t size);
static int erase(long offset, size_t size);

static sfud_flash_t sfud_dev = NULL;
struct fal_flash_dev nor_flash0 =
{
    .name       = FAL_USING_NOR_FLASH_DEV_NAME,
    .addr       = 0,
    .len        = 8 * 1024 * 1024,
    .blk_size   = 4096,
    .ops        = {init, read, write, erase},
    .write_gran = 1
};

static int init(void)
{

#ifdef RT_USING_SFUD
    /* RT-Thread RTOS platform */
    sfud_dev = rt_sfud_flash_find_by_dev_name(FAL_USING_NOR_FLASH_DEV_NAME);
#else
    /* bare metal platform */
    sfud_dev = sfud_get_device(SFUD_GD25Q16B_DEVICE_INDEX);
#endif

    if (NULL == sfud_dev)
    {
        return -1;
    }

    /* update the flash chip information */
    nor_flash0.blk_size = sfud_dev->chip.erase_gran;
    nor_flash0.len = sfud_dev->chip.capacity;

    return 0;
}

static int read(long offset, uint8_t *buf, size_t size)
{
    assert(sfud_dev);
    assert(sfud_dev->init_ok);
    sfud_read(sfud_dev, nor_flash0.addr + offset, size, buf);

    return size;
}

static int write(long offset, const uint8_t *buf, size_t size)
{
    assert(sfud_dev);
    assert(sfud_dev->init_ok);
    if (sfud_write(sfud_dev, nor_flash0.addr + offset, size, buf) != SFUD_SUCCESS)
    {
        return -1;
    }

    return size;
}

static int erase(long offset, size_t size)
{
    assert(sfud_dev);
    assert(sfud_dev->init_ok);
    if (sfud_erase(sfud_dev, nor_flash0.addr + offset, size) != SFUD_SUCCESS)
    {
        return -1;
    }

    return size;
}
#endif /* FAL_USING_SFUD_PORT */

测试代码

建议调试打开打印功能

在文件fal_def.h中,#define FAL_DEBUG 1

必须的初始化

#include "fal.h"
int main(void)
{
	fal_init();
}

读写擦除

接口都在fal.h中
懒得写了。。。。。。

Easyflash的移植

目前最新版本的Easyflash V5.X或者最新更名的FlashDB 底层调用接口都是FAL,所以实现了FAL移植,Easyflash和FlashDB都无需较大更改,直接加入源码到工程目录即可使用。

需要注意的是:easyflash首先执行初始化sfud,之后是fal初始化,否则flash容量大小会被篡改为0!
当使用操作系统时,注意线程分配的堆栈大小,应>512Byte否则易出现Hardfault错误,坑已踩过!

修改fdb的cfg文件

主要增加宏定义:#define FDB_USING_KVDB与设置FDB_WRITE_GRAN大小

/*
 * Copyright (c) 2020, Armink, 
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 * @brief configuration file
 */

#ifndef _FDB_CFG_H_
#define _FDB_CFG_H_

/* using KVDB feature */
#define FDB_USING_KVDB

#ifdef FDB_USING_KVDB
/* Auto update KV to latest default when current KVDB version number is changed. @see fdb_kvdb.ver_num */
/* #define FDB_KV_AUTO_UPDATE */
#endif

/* using TSDB (Time series database) feature */
#define FDB_USING_TSDB

/* the flash write granularity, unit: bit
 * only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */
#define FDB_WRITE_GRAN                1/* @note you must define it for a value */

/* MCU Endian Configuration, default is Little Endian Order. */
/* #define FDB_BIG_ENDIAN  */ 

/* log print macro. default EF_PRINT macro is printf() */
/* #define FDB_PRINT(...)              my_printf(__VA_ARGS__) */

/* print debug information */
#define FDB_DEBUG_ENABLE

#endif /* _FDB_CFG_H_ */

测试代码

/**
 *  @file database.c
 *
 *  @date 2020/6/9
 *
 *  @author aron566
 *
 *  @copyright None
 *
 *  @brief FlashDB操作
 *
 *  @details 使用该模块有哪些细节注意等
 *
 *  @version v1.0
 */
#ifdef __cplusplus ///
extern "C" {
#endif
/** Includes -----------------------------------------------------------------*/
/* Private includes ----------------------------------------------------------*/
#include "database.h"
#include "flashdb.h"
#include "gd32f4xx.h"
/** Private typedef ----------------------------------------------------------*/
/** Private macros -----------------------------------------------------------*/

/** Private constants --------------------------------------------------------*/
/** Public variables ---------------------------------------------------------*/
/** Private variables --------------------------------------------------------*/
static uint32_t boot_count = 0;
static time_t boot_time[10] = {0, 1, 2, 3};
/* default KV nodes */
static struct fdb_default_kv_node default_kv_table[] = {
        {"username", "armink", 0}, /* string KV */
        {"password", "123456", 0}, /* string KV */
        {"boot_count", &boot_count, sizeof(boot_count)}, /* int type KV */
        {"boot_time", &boot_time, sizeof(boot_time)},    /* int array type KV */
};
/* KVDB object */
static struct fdb_kvdb kvdb = { 0 };
/* TSDB object */
struct fdb_tsdb tsdb = { 0 };
/** Private function prototypes ----------------------------------------------*/
extern void kvdb_basic_sample(fdb_kvdb_t kvdb);
extern void kvdb_type_string_sample(fdb_kvdb_t kvdb);
extern void kvdb_type_blob_sample(fdb_kvdb_t kvdb);
extern void tsdb_sample(fdb_tsdb_t tsdb);
/** Private user code --------------------------------------------------------*/

/** Private application code -------------------------------------------------*/
/*******************************************************************************
*
*       Static code
*
********************************************************************************
*/
static void lock(fdb_db_t db)
{
    __disable_irq();
}

static void unlock(fdb_db_t db)
{
    __enable_irq();
}

static fdb_time_t get_time(void)
{
    static int counts = 0;
    /* Using the counts instead of timestamp.
     * Please change this function to return RTC time.
     */
    return counts++;
}

/** Public application code --------------------------------------------------*/
/*******************************************************************************
*
*       Public code
*
********************************************************************************
*/
/**
 * @file
 * @brief basic KV samples.
 *
 * basic Key-Value Database KV feature samples
 * get and show currnet boot counts
 */

#include 

#ifdef FDB_USING_KVDB

#define FDB_LOG_TAG "[sample][kvdb][basic]"

void kvdb_basic_sample(fdb_kvdb_t kvdb)
{
    struct fdb_blob blob;
    int boot_count = 0;

    { /* GET the KV value */
        /* get the "boot_count" KV value */
        fdb_kv_get_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count)));
        /* the blob.saved.len is more than 0 when get the value successful */
        if (blob.saved.len > 0) {
            FDB_INFO("get the 'boot_count' value is %d\r\n", boot_count);
        } else {
            FDB_INFO("get the 'boot_count' failed\r\n");
        }
    }

    { /* CHANGE the KV value */
        /* increase the boot count */
        boot_count ++;
        /* change the "boot_count" KV's value */
        fdb_kv_set_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count)));
        FDB_INFO("set the 'boot_count' value to %d\r\n", boot_count);
    }
}

#endif /* FDB_USING_KVDB */
/**
 * @file
 * @brief blob KV samples.
 *
 * Key-Value Database blob type KV feature samples
 */

#include 

#ifdef FDB_USING_KVDB
#ifdef FDB_LOG_TAG
#undef FDB_LOG_TAG
#define FDB_LOG_TAG "[sample][kvdb][blob]"
#endif
void kvdb_type_blob_sample(fdb_kvdb_t kvdb)
{
    struct fdb_blob blob;

    { /* CREATE new Key-Value */
        int temp_data = 36;

        /* It will create new KV node when "temp" KV not in database.
         * fdb_blob_make: It's a blob make function, and it will return the blob when make finish.
         */
        fdb_kv_set_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data)));
        FDB_INFO("create the 'temp' blob KV, value is: %d\r\n", temp_data);
    }

    { /* GET the KV value */
        int temp_data = 0;

        /* get the "temp" KV value */
        fdb_kv_get_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data)));
        /* the blob.saved.len is more than 0 when get the value successful */
        if (blob.saved.len > 0) {
            FDB_INFO("get the 'temp' value is: %d\r\n", temp_data);
        }
    }

    { /* CHANGE the KV value */
        int temp_data = 38;

        /* change the "temp" KV's value to 38.1 */
        fdb_kv_set_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data)));
        FDB_INFO("set 'temp' value to %d\r\n", temp_data);
    }

    { /* DELETE the KV by name */
        fdb_kv_del(kvdb, "temp");
        FDB_INFO("delete the 'temp' finish\r\n");
    }
}

#endif /* FDB_USING_KVDB */
/**
 * @file
 * @brief string KV samples.
 *
 * Key-Value Database string type KV feature samples source file.
 */

#include 
#include 

#ifdef FDB_USING_KVDB
#ifdef FDB_LOG_TAG
#undef FDB_LOG_TAG
#define FDB_LOG_TAG "[sample][kvdb][string]"
#endif
void kvdb_type_string_sample(fdb_kvdb_t kvdb)
{
    { /* CREATE new Key-Value */
        char temp_data[10] = "36C";

        /* It will create new KV node when "temp" KV not in database. */
        fdb_kv_set(kvdb, "temp", temp_data);
        FDB_INFO("create the 'temp' string KV, value is: %s\r\n", temp_data);
    }

    { /* GET the KV value */
        char *return_value, temp_data[10] = { 0 };

        /* Get the "temp" KV value.
         * NOTE: The return value saved in fdb_kv_get's buffer. Please copy away as soon as possible.
         */
        return_value = fdb_kv_get(kvdb, "temp");
        /* the return value is NULL when get the value failed */
        if (return_value != NULL) {
            strncpy(temp_data, return_value, sizeof(temp_data));
            FDB_INFO("get the 'temp' value is: %s\r\n", temp_data);
        }
    }

    { /* CHANGE the KV value */
        char temp_data[10] = "38C";

        /* change the "temp" KV's value to "38.1" */
        fdb_kv_set(kvdb, "temp", temp_data);
        FDB_INFO("set 'temp' value to %s\r\n", temp_data);
    }

    { /* DELETE the KV by name */
        fdb_kv_del(kvdb, "temp");
        FDB_INFO("delete the 'temp' finish\r\n");
    }
}

#endif /* FDB_USING_KVDB */
/**
 * @file
 * @brief TSDB samples.
 *
 * Time series log (like TSDB) feature samples source file.
 *
 * TSL is time series log, the TSDB saved many TSLs.
 */

#include 
#include 

#ifdef FDB_USING_TSDB
#ifdef FDB_LOG_TAG
#undef FDB_LOG_TAG
#define FDB_LOG_TAG "[sample][tsdb]"
#endif
struct env_status {
    int temp;
    int humi;
};

static bool query_cb(fdb_tsl_t tsl, void *arg);
static bool set_status_cb(fdb_tsl_t tsl, void *arg);

void tsdb_sample(fdb_tsdb_t tsdb)
{
    struct fdb_blob blob;

    { /* APPEND new TSL (time series log) */
        struct env_status status;

        /* append new log to TSDB */
        status.temp = 36;
        status.humi = 85;
        fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status)));
        FDB_INFO("append the new status.temp (%d) and status.humi (%d)\r\n", status.temp, status.humi);

        status.temp = 38;
        status.humi = 90;
        fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status)));
        FDB_INFO("append the new status.temp (%d) and status.humi (%d)\r\n", status.temp, status.humi);
    }

    { /* QUERY the TSDB */
        /* query all TSL in TSDB by iterator */
        fdb_tsl_iter(tsdb, query_cb, tsdb);
    }

    { /* QUERY the TSDB by time */
        /* prepare query time (from 1970-01-01 00:00:00 to 2020-05-05 00:00:00) */
        struct tm tm_from = { .tm_year = 1970 - 1900, .tm_mon = 0, .tm_mday = 1, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 };
        struct tm tm_to = { .tm_year = 2020 - 1900, .tm_mon = 4, .tm_mday = 5, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 };
        time_t from_time = mktime(&tm_from), to_time = mktime(&tm_to);
        size_t count;
        /* query all TSL in TSDB by time */
        fdb_tsl_iter_by_time(tsdb, from_time, to_time, query_cb, tsdb);
        /* query all FDB_TSL_WRITE status TSL's count in TSDB by time */
        count = fdb_tsl_query_count(tsdb, from_time, to_time, FDB_TSL_WRITE);
        FDB_INFO("query count is: %u\r\n", count);
    }

    { /* SET the TSL status */
        /* Change the TSL status by iterator or time iterator
         * set_status_cb: the change operation will in this callback
         *
         * NOTE: The actions to modify the state must be in order.
         *       FDB_TSL_WRITE -> FDB_TSL_USER_STATUS1 -> FDB_TSL_DELETED -> FDB_TSL_USER_STATUS2
         */
        fdb_tsl_iter(tsdb, set_status_cb, tsdb);
    }
}

static bool query_cb(fdb_tsl_t tsl, void *arg)
{
    struct fdb_blob blob;
    struct env_status status;
    fdb_tsdb_t db = arg;

    fdb_blob_read((fdb_db_t) db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status))));
    FDB_INFO("queried a TSL: time: %ld, temp: %d, humi: %d\r\n", tsl->time, status.temp, status.humi);

    return false;
}

static bool set_status_cb(fdb_tsl_t tsl, void *arg)
{
    fdb_tsdb_t db = arg;

    FDB_INFO("set the TSL (time %ld) status from %d to %d\r\n", tsl->time, tsl->status, FDB_TSL_USER_STATUS1);
    fdb_tsl_set_status(db, tsl, FDB_TSL_USER_STATUS1);

    return false;
}

#endif /* FDB_USING_TSDB */

int databaseInit(void)
{
    fdb_err_t result;

#ifdef FDB_USING_KVDB
    { /* KVDB Sample */
        struct fdb_default_kv default_kv;

        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_lock_set((fdb_db_t)&kvdb, lock, unlock);
        /* Key-Value database initialization
         *
         *       &kvdb: database object
         *       "env": database name
         * "fdb_kvdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
         *              Please change to YOUR partition name.
         * &default_kv: The default KV nodes. It will auto add to KVDB when first initialize successfully.
         *        NULL: The user data if you need, now is empty.
         */
        result = fdb_kvdb_init(&kvdb, "env", "fdb_kvdb1", &default_kv, NULL);

        if (result != FDB_NO_ERR) {
            return -1;
        }

        /* run basic KV samples */
        kvdb_basic_sample(&kvdb);
        /* run string KV samples */
        kvdb_type_string_sample(&kvdb);
        /* run blob KV samples */
        kvdb_type_blob_sample(&kvdb);
    }
#endif /* FDB_USING_KVDB */

#ifdef FDB_USING_TSDB
    { /* TSDB Sample */
        /* set the lock and unlock function if you want */
        fdb_lock_set((fdb_db_t)&tsdb, lock, unlock);
        /* Time series database initialization
         *
         *       &tsdb: database object
         *       "log": database name
         * "fdb_tsdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
         *              Please change to YOUR partition name.
         *    get_time: The get current timestamp function.
         *         128: maximum length of each log
         *        NULL: The user data if you need, now is empty.
         */
        result = fdb_tsdb_init(&tsdb, "log", "fdb_tsdb1", get_time, 128, NULL);

        if (result != FDB_NO_ERR) {
            return -1;
        }

        /* run TSDB sample */
        tsdb_sample(&tsdb);
    }
#endif /* FDB_USING_TSDB */

    return 0;
}
#ifdef __cplusplus ///
}
#endif
/******************************** End of file *********************************/

你可能感兴趣的:(移植应用)