STM32G473VET6 FlashDB数据库移植(裸机、片内Flash)

这篇具有很好参考价值的文章主要介绍了STM32G473VET6 FlashDB数据库移植(裸机、片内Flash)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

STM32G473VET6 FlashDB数据库移植(裸机、片内Flash)

此文档也适用于STM32G070

源码下载

此处使用FlashDB官方最新源码

FlashDB: 一款支持 KV 数据和时序数据的超轻量级数据库 (gitee.com)

克隆源码后目录如下

红框中几个为移植必要文件与参考

flashdb,STM32,stm32,数据库,嵌入式硬件

根据FlashDB官方文档可知,FlashDB底层依赖于RT-Thread的FAL组件,所以需要先移植FAL

FlashDB源码中port目录下即为FAL组件源码

移植参考文档

移植 (gitee.io)

flashdb,STM32,stm32,数据库,嵌入式硬件

开始移植

添加FAL组件源码

准备一个HAL库STM32G473工程,配置好LOG打印串口把printf重定向至串口,细节此处略过

添加FAL与FlashDB源码至准备好的工程

如下图所示,目录可自行更改无需与本文档一致,此处仅为演示所用

flashdb,STM32,stm32,数据库,嵌入式硬件

红框中为FAL源码部分,位于FlashDB源码的port/fal目录下的inc与src文件夹中,此处我把头文件与源文件存放在了一个文件夹中

同时复制一份官方原源码中的移植参考代码重命名后放入此文件夹中,参考代码目录如下图

代码位于port/fal/samples/porting目录下

flashdb,STM32,stm32,数据库,嵌入式硬件

添加FlashDB源码

添加过程同上,需添加文件如下

flashdb,STM32,stm32,数据库,嵌入式硬件

以上文件位于FlashDB源码的inc与src目录下。

所有文件添加完成后keil目录如下,不要忘记添加头文件路径,此处详细过程省略。

flashdb,STM32,stm32,数据库,嵌入式硬件

移植FAL

移植FAL很简单,仅需实现对flash的读写擦除三个函数即可,可根据参考例程修改。

此次移植修改如下

STM32G473VE的Flash为512k,根据数据手册可知,此flash为双bank每个bank有128个页每页2k单次擦除最小为一页所以写入是要注意bank与页的计算

同时需注意G473与G070的flash写最小粒度皆为双字

flashdb,STM32,stm32,数据库,嵌入式硬件

修改后代码如下(fal_flash_stm32_port.c)

/*
 * Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <string.h>
#include <fal.h>
#include <stm32g4xx_hal.h>

#define PAGE_SIZE     FLASH_PAGE_SIZE


/*
STM32F1会因容量不同而不同
    小容量和中容量产品主存储块128KB以下,  每页1KB。
    大容量和互联型产品主存储块256KB以上,  每页2KB。

GD32   会因容量不同而不同
    1. Low-density Products     Flash容量从 16KB到  32KB的产品
    2. Medium-density Products  Flash容量从 64KB到 128KB的产品
          全是1K
    3. High-density Products    Flash容量从256KB到 512KB的产品
          全是2K
    4. XL-density Products      Flash容量从768KB到3072KB的产品
          <512K 是2K
          >512K 是4K

雅特力
    全是2K

STM32F4
    STM32F4的flash页尺寸不一样,低地址16KB,高地址32KB或128KB.
*/

static uint32_t GetPage(uint32_t Addr)
{
    uint32_t page = 0;
    page = (Addr-FLASH_BASE) / FLASH_PAGE_SIZE;
    return page;
}

static int init(void)
{
    /* do nothing now */
    return 1;
}


static int ef_err_port_cnt = 0;
int on_ic_read_cnt  = 0;
int on_ic_write_cnt = 0;

void feed_dog(void)
{

}

static int read(long offset, uint8_t *buf, size_t size)
{

    size_t i;
    uint32_t addr = stm32_onchip_flash.addr + offset;

    if( addr%8 != 0)
        ef_err_port_cnt++;

    for (i = 0; i < size; i++, addr++, buf++)
    {
        *buf = *(uint8_t *) addr;
    }
    on_ic_read_cnt++;
    return size;
}


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

    __ALIGN_BEGIN uint64_t write_data __ALIGN_END;
    __ALIGN_BEGIN uint64_t read_data  __ALIGN_END;

    if(addr%8 != 0)
        ef_err_port_cnt++;

    /*
        if((int)buf%4 != 0)
            ef_err_port_cnt++;
    */

    HAL_FLASH_Unlock();
    for (i = 0; i < size; i += 8, buf += 8, addr += 8) {
        memcpy(&write_data, buf, 8); //用以保证HAL_FLASH_Program的第三个参数是内存首地址对齐
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr, write_data);
        read_data = *(uint64_t *)addr;
        if (read_data != write_data) {
            HAL_FLASH_Lock();
            return -1;
        }
        else {
            feed_dog();
        }
    }
    HAL_FLASH_Lock();


    on_ic_write_cnt++;
    return size;
}


static int erase(long offset, size_t size)
{
    uint32_t addr = stm32_onchip_flash.addr + offset;

    HAL_StatusTypeDef flash_status;
    size_t erase_pages, i;
    uint32_t PAGEError = 0;

    erase_pages = size / PAGE_SIZE;//页数量
    if (size % PAGE_SIZE != 0) {
        erase_pages++;
    }

    FLASH_EraseInitTypeDef EraseInitStruct;
    EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.NbPages     = 1;  //一次擦出一个扇区, 以执行一次喂狗,防止超时
    HAL_FLASH_Unlock();
    for (i = 0; i < erase_pages; i++) {
        if(addr + (FLASH_PAGE_SIZE * i)<=0x0803ffff) {//判断当前页所处bank
            EraseInitStruct.Banks = FLASH_BANK_1;
        } else {
            EraseInitStruct.Banks = FLASH_BANK_2;
        }
        EraseInitStruct.Page = GetPage(addr + (FLASH_PAGE_SIZE * i));//计算当前所处页
        flash_status = HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
        if (flash_status != HAL_OK) {
            HAL_FLASH_Lock();
            return -1;
        }
        else {
            //FLash操作可能非常耗时,如果有看门狗需要喂狗,以下代码由用户实现
            feed_dog();
        }
    }
    HAL_FLASH_Lock();

    return size;
}


/*
  "stm32_onchip" : Flash 设备的名字。
  0x08000000: 对 Flash 操作的起始地址。
  1024*1024:Flash 的总大小(1MB)。
  128*1024:Flash 块/扇区大小(因为 STM32F2 各块大小不均匀,所以擦除粒度为最大块的大小:128K)。
  {init, read, write, erase} :Flash 的操作函数。 如果没有 init 初始化过程,第一个操作函数位置可以置空。
  8 : 设置写粒度,单位 bit, 0 表示未生效(默认值为 0 ),该成员是 fal 版本大于 0.4.0 的新增成员。各个 flash 写入粒度不尽相同,可通过该成员进行设置,以下列举几种常见 Flash 写粒度:
  nor flash:  1 bit
  stm32f2/f4: 8 bit
  stm32f1:    32 bit
  stm32l4:    64 bit
 */

//1.定义 flash 设备

const struct fal_flash_dev stm32_onchip_flash =
{
    .name       = "stm32_onchip",
    .addr       = 0x08000000,
    .len        = 512*1024,
    .blk_size   = 2*1024,
    .ops        = {init, read, write, erase},
    .write_gran = 64
};



修改配置头文件(fal_cfg.h)

头文件无需做很大修改,配置一下分区表即可,分区表具体设置细节可参考FlashDB官方文档

flashdb,STM32,stm32,数据库,嵌入式硬件

此处修改完成后如下

/*
 * Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_

#define FAL_DEBUG 1
#define FAL_PART_HAS_TABLE_CFG

/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev stm32_onchip_flash;

/* flash device table */
#define FAL_FLASH_DEV_TABLE                                          \
{                                                                    \
    &stm32_onchip_flash,                                             \
}

/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE                                                                \
{                                                                                     \
    {FAL_PART_MAGIC_WORD,  "fdb_kvdb1",    "stm32_onchip",   230*1024, 16*1024, 0},  \
}
#endif /* FAL_PART_HAS_TABLE_CFG */

#endif /* _FAL_CFG_H_ */

若无需打印LOG信息可把宏#define FAL_DEBUG 1进行注释

FlashDB移植

因为FlashDB依赖于FAL,所以移植完成FAL之后FlashDB的移植工作基本就算完成90%了,

下面仅需修改一下FlashDB的配置文件即可完成移植

修改fdb_cfg.h

把宏#define FDB_USING_TSDB进行注释,因为FlashDB的TSDB还不支持双字写入粒度的flash

添加宏#define FDB_USING_FAL_MODE

修改宏#define FDB_WRITE_GRAN为64(双字写入粒度)

修改完成后如下

/*
 * Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

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

#ifndef _FDB_CFG_H_
#define _FDB_CFG_H_

#define FDB_USING_FAL_MODE

/* 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                 64

/* 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_ */

测试

跑一跑FlashDB的demo,demo可从FlashDB源码例程里面复制(懒得自己写了)

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

    debug_print("==================== kvdb_basic_sample ====================\n");

    { /* 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) {
            debug_print("get the 'boot_count' value is %d\n", boot_count);
        } else {
            debug_print("get the 'boot_count' failed\n");
        }
    }

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

    debug_print("===========================================================\n");
}

flashdb,STM32,stm32,数据库,嵌入式硬件

可以看到FAL分区信息正常,FlashDB每次复位之后键对应的值都会+10,存储成功,移植完成。

EMD

完整工程
STM32G473VET6-HAL库-裸机移植FAL-FlashDB测试工程资源-CSDN文库文章来源地址https://www.toymoban.com/news/detail-811049.html

到了这里,关于STM32G473VET6 FlashDB数据库移植(裸机、片内Flash)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 利用是stm32cubemx实现双极性spwm调制 基于stm32f407vet6

    【双极性SPWM调制讲解以及基于stm32的代码生成-哔哩哔哩】 https://b23.tv/ytFxdkL 双极性spwm调制虽然没有单极性好用,但比单极性要简单易懂一些,以下教程是如何利用stm32实现双极性spwm调制.   •T1,T2不能同时导通,T3,T4也不能同时导通,否则短路烧管子。 •解决方法:T1与T2用高

    2024年02月15日
    浏览(41)
  • stm32f407VET6 系统学习 day01 GPIO 配置

    GPIO,即通用I/O(输入/输出)端口,是STM32可控制的引脚。STM32芯片的GPIO引脚与外部设备连接起来,可实现与外部通讯、控制外部硬件或者采集外部硬件数据的功能。 STM32F407有7组IO。分别为GPIOA~GPIOG,每组IO有16个IO口,共有112个IO口  通常称为 PAx、PBx、PCx、PDx、PEx、PFx、PGx,其中

    2023年04月09日
    浏览(41)
  • STM32的入门——CM3芯片STM32F103VET6的使用和相关外设

    根据《STM32库开发实战指南——基于野火指南者开发板》整理, https://gitee.com/Embedfire-stm32f103-zhinanzhe/ebf_stm32f103_zhinanzhe_ std_tutorial 在整理的过程中,还参考了其他的一些STM32资料 使用了“幕布”这款软件,添加了一些思维导图 整理框架目的: 1.梳理知识脉络 2.复习知识 被动单

    2024年02月03日
    浏览(38)
  • stm32f103VET6和stm32f103c8t6有什么区别?

    我来终结下这个问题。 这两款单片机我都用过,其中无际单片机特训营其中一款wifi报警主机项目就是用了stm32f103c8t6。  stm32f103VET6和stm32f103c8t6都是STMicroelectronics公司推出基于ARM Cortex-M3内核的单片机。 它们在硬件规格和性能上存在一些差异,下面我详细讲解下它们的差异之处

    2024年02月15日
    浏览(43)
  • [STM32] - STM32F407VET6使用STM32CubeMX配置FatFs,以及挂载时返回03错误码问题的解决

    为测试新买的开发板TF卡读写是否正常,使用STM32CubeMX(后简称CubeMX)进行代码构建。生成代码后烧录测试,发现在挂载TF卡时无法成功,返回值为错误3( FR_NOT_READY )。经排查后问题已解决,遂记录配置过程供大家参考,并讲解挂载时返回错误3的解决方式。 ①为了输出TF卡(

    2024年02月22日
    浏览(60)
  • STM32F407VET6使用SPI访问Flash数据返回0xff(先写入数据,再读取数据,却返回0xff,但是通过debug却可以正常输出)

    STM32F407VET6使用SPI访问Flash数据返回0xff(先写入数据,再读取数据,却返回0xff,但是通过debug却可以正常输出) 看了野火的STM32F103VET6板子的SPI操作Flash的视频,用了自己的STM32F407VET6板子试了一下,出现了点问题,在网上看了很久也没有找出原因,现在问题解决了,就写一篇,

    2024年02月15日
    浏览(36)
  • 野火指南者(STM32F103VET6)应用:实现USB虚拟串口(CDC_VPC)

    MCU:STM32F103VET6 开发环境:STM32CubeMX+MDK5   实现USB的虚拟串口不需要去理解USB的底层驱动,只需要STM32CubeMX去配置生成工程即可。在野火的指南者中,是没有这一类的视频和示例的,博主使用这款开发板实现USB虚拟串口。 首先需要打开STM32CubeMX工具。输入开发板MCU对应型号,找

    2024年02月08日
    浏览(37)
  • STM32 利用FlashDB库实现在线扇区数据管理不丢失

    📍FalshDB地址: https://gitee.com/Armink/FlashDB ✨STM32没有片内EEPROM这样的存储区,虽然有备份寄存器,仅可以实现对少量数据的频繁存储,但是依赖备份电源(BAT引脚)为芯片维持供电,才能保持数据的不丢失。FlashDB库利用在线对片内或片外存储扇区进行管理,可以有效的保存数据

    2024年04月12日
    浏览(26)
  • 【STM32】STM32G系列使用CORDIC模块加速计算

    STM32G431系列产品内置了CORDIC运算单元,可以用来加速数学计算,如三角函数、取模、开方等。适合大量数据进行相同的运算操作。配合DMA可以大大节省CPU计算开销。 使用CORDIC模块无需配置参数,若采用DMA方式则只需配置DMA读写通道,配置如下 在代码中对cordic模块进行初始化

    2024年02月12日
    浏览(32)
  • 64MHz 闪存STM32G0B1CEU6(STM32G0B1CCU6)STM32G0B1CBU6引脚配置图、32位微控制器

    STM32G0B1 32位微控制器具有最高512KB嵌入式闪存和144kB RAM存储器。该器件采用48-UFQFPN 引脚封装。它支持USB全速主机/设备、集成USB Type-C控制器和收发器、FDCAN协议以及多达8个UART。 STM32G0 32位微控制器 (MCU) 适合用于消费、工业和家电领域的应用,并可随时用于物联网 (IoT) 解决方案

    2024年02月09日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包