YuanHub 源码分析【一】FlashDB 初始化与项目应用

FlashDB嵌入式数据库之TSDB数据存储解析 FlashDB之TSDB数据存储解析 阅读详情

目录

一、FlashDB 简介

1.1 FlashDB 简介

二、FlashDB 的初始化

2.1 向 FlashDB 输入 FLASH 的配置信息

2.2 FlashDB 的初始化

2.3 框架的数据库初始化流程

2.3.1 main()

2.3.2 HalInit()

2.3.3 AppStoreInit()

2.3.4 FlashdbDatabaseInit()

2.3.5 flashdb_init()

2.3.6 总结

三、参数列表和项目中的初始化

3.1 参数的初始化

2.3.1 main()

3.1.2 HalInit()

3.1.3 AppParamInit()

3.1.4 MotorCtrlInit()

3.1.5  AppStoreInit()

3.1.6 flash_param_update()

3.1.7 app_param_update()

3.1.8 总结

四、使用这些数据

4.1 原理概述

4.2 get() / set() 标准读写接口

4.3 命令配置

4.4 1ms 循环定时储存


一、FlashDB 简介

1.1 FlashDB 简介

FlashDB 是一款超轻量级的嵌入式数据库,专注于提供嵌入式产品的数据存储方案。FlashDB 不仅支持传统的基于文件系统的数据库模式,而且结合了 Flash 的特性,具有较强的性能及可靠性。并在保证极低的资源占用前提下,尽可能延长 Flash 使用寿命。

FlashDB 提供两种数据库模式:

  • 键值数据库 :是一种非关系数据库,它将数据存储为键值 (Key-Value) 对集合,其中键作为唯一标识符。KVDB 操作简洁,可扩展性强。
  • 时序数据库 :时间序列数据库 (Time Series Database , 简称 TSDB) ,它将数据按照 时间顺序存储 。TSDB 数据具有时间戳,数据存储量大,插入及查询性能高。
servo_hub\board_public\flash_db\inc\fdb_def.h

在文件第 24 行:

#define FDB_SW_VERSION                 "2.1.1"

本项目使用 FlashDB 2.1.1

二、FlashDB 的初始化

2.1 向 FlashDB 输入 FLASH 的配置信息

在文件第 3 行:

servo_hub-master\embedded_project\Y01\Board\bsp_flash.c
struct fal_flash_dev nor_flash0 =
{
    .name       = FAL_USING_NOR_FLASH_DEV_NAME,
    .addr       = 0,
    .len        = 8 * 1024 * 1024,
    .blk_size   = 4 * 1024,
    .ops        = {init, read, write, erase},
    .write_gran = FDB_WRITE_GRAN
};

从上到下分别规定了 flash 名字、起始物理地址偏移、总容量、最小擦除单元、四个硬件操作

字段值含义
.name"norflash0"FAL 内部通过这个名字查找设备(分区表里的 "norflash0" 就是对应这里)
.addr0这块 Flash 从地址偏移 0 开始,即整块都可用
.len8MB物理芯片总大小 8MB(实际型号是 GD25Q64,即 GigaDevice 64Mbit = 8MB)
.blk_size4096 (4KB)最小擦除粒度是一个扇区 4KB,erase 操作必须按 4KB 对齐
.ops{init, read, write, erase}{init, read, write, erase}    指向下面 4 个静态函数,是真正操作 SPI 硬件的代码
.write_gran1bitNorFlash 可以按 bit 写入(写 1→0),写粒度最细

在本文件内实现了 init()、read()、write()、erase() 的四个函数,其实现方式均使用 STM32 的 HAL 库实现,在这里不过多赘述。

因为我们将这些数据存储到外挂 FLASH 中,对于 STM32H7 系列芯片来说,访问地址 addr. 就是 0x00。

在文件第 3 行:

servo_hub-master\embedded_project\Y01\Board\fal_cfg.h
/* flash device table */
#define FAL_FLASH_DEV_TABLE     \
{                               \
    &nor_flash0,                \
}

对 nor_flash0 的地址取了一个宏定义。

最后在文件第 19 行:

servo_hub-master\board_public\flash_db\port\fal\src\fal_flash.c
static const struct fal_flash_dev * const device_table[] = FAL_FLASH_DEV_TABLE;

所以 我们的 nor_flash0 变量最终被定义为 fal_flash_dev。

2.2 FlashDB 的初始化

在文件第 26 行:

servo_hub-master\servo_hub-master\embedded_project\Y01\Board\fal_cfg.h

它的作用是把一块大容量的 Flash 芯片像电脑硬盘一样分区。

#define FAL_PART_TABLE                                                                                              \
{                                                                                                                   \
    {FAL_PART_MAGIC_WORD,         "bl",    "norflash0",         0,  128*1024, 0}, /* Bootloader: 128K */            \
    {FAL_PART_MAGIC_WORD,        "app",    "norflash0",  128*1024, 2048*1024, 0}, /* Application: 2048K */          \
    {FAL_PART_MAGIC_WORD, "app_backup",    "norflash0", 2176*1024, 1024*1024, 0}, /* Application Backup: 1024K */   \
    {FAL_PART_MAGIC_WORD,   "kv_param",    "norflash0", 3200*1024, 2048*1024, 0}, /* kv_param: 2048K */             \
    /* ...  more partition norflash0 max size: 8192K */ \
}

在文件第 49 行:

servo_hub-master\board_public\flash_db\port\fal\src\fal_partition.c

此处是 FlashDB 的定义:

static const struct fal_partition partition_table_def[] = FAL_PART_TABLE;

其通过下面的流程:

函数接口和过程工作流程
fal_partition_init()开始的函数

fal_partition_init() 函数中:

partition_table = &partition_table_def[0]

全局指针指向它

fal_partition_init() 函数中:

partition_table_len = 4

记录分区数量

check_and_update_part_cache()

填充 flash 设备缓存

check_and_update_part_cache()函数中:

part_flash_cachel[]

每个分区对应的 flash_dev 指针

最后初始化这个值:

part_flash_cache[]

把它的地址交给运行时的全局指针 partition_table[],后续所有分区操作都走这个指针。

2.3 框架的数据库初始化流程

2.3.1 main()

int main(void)
{
  ...
  // 硬件及应用初始化
  HalInit();
  ...
}

2.3.2 HalInit()

void HalInit(void)
{
    ...
    AppStoreInit();
    ...
}

2.3.3 AppStoreInit()

如果 flash 中有绑定的 key-value 值,并且 flash 中有数据,这个函数会帮我们从 flash 中读取出来到目标结构体中。


void AppStoreInit(void)
{
    flash_param_update(); // 在初次存储KV还未被创建时,将参数默认值更新到kFlashStorage后写入flash
    FlashdbDatabaseInit();

    set_app_Storage_status(FLASH_STORE_STATUS_IDLE);

    set_app_Storage_cmd(FLASH_STORE_CMD_READ_PARAM);
    AppStoreUpdata1ms();
    set_app_Storage_cmd(FLASH_STORE_CMD_READ_ERROR);
    AppStoreUpdata1ms();
    set_app_Storage_cmd(FLASH_STORE_CMD_READ_TQ_FC);
    AppStoreUpdata1ms();
}

2.3.4 FlashdbDatabaseInit()

根据 key 索引注册表,将 key 名称和 结构体绑定。

Key 索引Key 名称存储内容说明
FLASHDB_KEY_INDEX_ALL_PARAMAllParamkFlashStorage全量系统参数(如 PID 参数、电机参数等)
 
FLASHDB_KEY_INDEX_ERROR_RECORDErrorRecordkFlashHistoricalInfo.Error_records_list历史故障记录列表
 
FLASHDB_KEY_INDEX_TQ_FC_TABLETqFcTablekAxisDw.tq_fc_id_InstanceData.rtdwSimulink 生成的运行时数据
static void FlashdbDatabaseInit(void)
{
    if (bsp_flashdb_key_register(FLASHDB_KEY_INDEX_ALL_PARAM, "AllParam", \
            &kFlashStorage, sizeof(kFlashStorage)) != FLASHDB_NO_ERR)
    {
        sys_set_bsp_error_state(ERROR_FLASH_STORE, ERROR_SET);
        return;
    }
    if (bsp_flashdb_key_register(FLASHDB_KEY_INDEX_ERROR_RECORD, "ErrorRecord", \
            &kFlashHistoricalInfo.Error_records_list, \
            sizeof(kFlashHistoricalInfo.Error_records_list)) != FLASHDB_NO_ERR)
    {
        sys_set_bsp_error_state(ERROR_FLASH_STORE, ERROR_SET);
        return;
    }
    if (bsp_flashdb_key_register(FLASHDB_KEY_INDEX_TQ_FC_TABLE, "TqFcTable", \
            &kAxisDw.tq_fc_id_InstanceData.rtdw, \
            sizeof(kAxisDw.tq_fc_id_InstanceData.rtdw)) != FLASHDB_NO_ERR)
    {
        sys_set_bsp_error_state(ERROR_FLASH_STORE, ERROR_SET);
        return;
    }

    if (bsp_flashdb_init() != FLASHDB_NO_ERR)
    {
        sys_set_bsp_error_state(ERROR_FLASH_STORE, ERROR_SET);
        return;
    }
}

这个函数最终往 default_kv_table[] 表里注册了我们的 key 信息,并且又将我们的 kAxisDw 中的地址与之对应关联。

2.3.5 flashdb_init()

这个函数的作用是初始化 FlashDB 键值数据库 (KVDB),用于在 Flash 存储器中持久化保存参数。

/**
  * @brief Flashdb初始化
  * @param void
  * @retval fdb_err_t
  * @note
  */
fdb_err_t flashdb_init(void)
{
    struct fdb_kv kv;
    struct fdb_blob blob;

    default_kv.kvs = default_kv_table;
    default_kv.num = FLASHDB_KEYS_NUM;

    /* set the lock and unlock function if you want */
    fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_LOCK, (void *)lock);
    fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_UNLOCK, (void *)unlock);

    /* Key-Value database initialization
         *
         *       &kvdb: database object
         *   "YuanHub": database name
         *  "kv_param": 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.
         */
    fdb_err_code = fdb_kvdb_init(&kvdb, "YuanHub", "kv_param", &default_kv, NULL);
    if (fdb_err_code != FDB_NO_ERR)
    {
        return fdb_err_code;
    }

    /* check if the default kv nodes are in the kvdb */
    for (uint8_t index = 0; index < default_kv.num; index++)
    {
        if (fdb_kv_get_obj(&kvdb, default_kv.kvs[index].key, &kv) == NULL)
        {
            fdb_err_code = fdb_kv_set_blob(&kvdb, default_kv.kvs[index].key, \
            fdb_blob_make(&blob, default_kv.kvs[index].value, default_kv.kvs[index].value_len));
            if (fdb_err_code != FDB_NO_ERR)
            {
                return fdb_err_code;
            }
        }
    }

    return fdb_err_code;
}

2.3.6 总结和 UML 时序图

至此,FlashDB 初始化完成,流程如下表,我跳过了一部分:

函数接口功能详细说明
main()程序起点。负责调用 HalInit 开启系统硬件与软件环境初始化,是整个生命周期的入口。
HalInit()初始化总调度。按照预设优先级统一编排各功能模块(如时钟、外设、中间件等)的启动顺序,确保底层依赖正确。
AppStoreInit()存储管理总入口。管理所有业务参数的持久化逻辑;初始化完成后会立即将 Flash 数据同步至 RAM,供业务逻辑直接访问。
FlashdbDatabaseInit()业务数据库配置。向底层注册所有需要持久化的 Key-Value(键值对),并正式启动数据库引擎,建立业务逻辑与存储的映射关系。
flashdb_init()库核心启动。负责注册线程安全的互斥锁,执行 FlashDB 核心初始化,并对库中缺失的 Key 执行默认值的补写操作。
fdb_kvdb_init()KVDB 挂载。具体初始化 FlashDB 的 KV 数据库模式,定位并挂载名为 "kv_param" 的 Flash 物理分区。

UML 时序图如下:

三、参数列表和项目中的初始化

3.1 参数的初始化

2.3.1 main()

int main(void)
{
  ...
  // 硬件及应用初始化
  HalInit();
  ...
}

    3.1.2 HalInit()

    void HalInit(void)
    {
        ...
        AppParamInit();
        MotorCtrlInit();  //电机控制相关初始化
        ...
        AppStoreInit();
        ...
    }

    3.1.3 AppParamInit()

    对 kAppStatusInfo 的变量赋初值,这将是存到 flash 当中的结构体:

    void AppParamInit(void)
    {
        // 初始化控制字
        kAppControlWord.Controlword = 0;      // 控制字
        kAppControlWord.Halt_running_cmd = 0; // 运行中暂停控制命令
    
        // 初始化状态信息
        kAppStatusInfo.Statusword = 0;                   // 状态字
        kAppStatusInfo.Error_word = 0;                   // 错误码
        kAppStatusInfo.Alarm_word = 0;                   // 警告码
        kAppStatusInfo.DC_link_circuit_voltage = 0.0f;   // 母线电压当前值
        kAppStatusInfo.Drive_accumulated_heat = 0.0f;    // 驱动器热量累计值
        kAppStatusInfo.Drive_temperature = 0.0f;         // 驱动器当前温度
        kAppStatusInfo.Motor_temperature = 0.0f;         // 电机当前温度
        kAppStatusInfo.Mcu_temperature = 0.0f;           // MCU当前温度
        kAppStatusInfo.Digital_io_inputs_status = 0;     // 数字输入状态
        kAppStatusInfo.Brake_state = BRAKE_STATE_ENGAGED;// 抱闸状态
        
        ...
    }

    3.1.4 MotorCtrlInit()

    对程序的运行变量赋初值,这些变量不写入 flash 中:

    void MotorCtrlInit(void)
    {
        // 对控制层进行初始化
        MotorCtlSmInit(&kAxis, &kAxisDw);
    
        // 初始化硬件默认参数配置
        // 电机参数
        kAxis.pmsm_config.tc_s = 1.0f / CURRENT_FREQUENCY_HZ;  // 电流环周期
        kAxis.pmsm_config.tp_s = 1.0f / POSITION_FREQUENCY_HZ; // 位置速度环周期
        kAxis.pmsm_config.j = PMSM_J;
        kAxis.pmsm_config.b = 0.0001f;
        kAxis.pmsm_config.fc = 0.001f;
        kAxis.pmsm_config.ld = PMSM_Lp2p * 0.5f;
        kAxis.pmsm_config.lq = PMSM_Lp2p * 0.5f;
        kAxis.pmsm_config.peak_current = PMSM_PEAK_CURRENT;
        kAxis.pmsm_config.pn = PMSM_PN;
        kAxis.pmsm_config.r = PMSM_Rp2p * 0.5f;
        kAxis.pmsm_config.rated_current = PMSM_RATED_CURRENT;
        kAxis.pmsm_config.speed_max_rpm = PMSM_SPEED_MAX_RPM;
        kAxis.pmsm_config.enc_line_p_n = PMSM_MOTOR_ENC_LINE_P_N;
        kAxis.pmsm_config.kt = PMSM_TORQUE_CONSTANT_MNM_A * 0.001f;
    }

    3.1.5  AppStoreInit()

    如果 flash 中有绑定的 key-value 值,并且 flash 中有数据,这个函数会帮我们从 flash 中读取出来到目标结构体中:

    void AppStoreInit(void)
    {
        flash_param_update(); // 在初次存储KV还未被创建时,将参数默认值更新到kFlashStorage后写入flash
        FlashdbDatabaseInit();
    
        set_app_Storage_status(FLASH_STORE_STATUS_IDLE);
    
        set_app_Storage_cmd(FLASH_STORE_CMD_READ_PARAM);
        AppStoreUpdata1ms();
        set_app_Storage_cmd(FLASH_STORE_CMD_READ_ERROR);
        AppStoreUpdata1ms();
        set_app_Storage_cmd(FLASH_STORE_CMD_READ_TQ_FC);
        AppStoreUpdata1ms();
    }

    3.1.6 flash_param_update()

    在初次存储 KV 还未被创建时,将参数默认值更新到 kFlashStorage 后写入 flash:

    void flash_param_init(void)
    {
        kFlashStorage.input_shaping_config_wn_Hz = kAxis.input_shaping_config.wn_Hz;
        kFlashStorage.input_shaping_config_run_frq_Hz = kAxis.input_shaping_config.run_frq_Hz;
        kFlashStorage.pos_speed_ctl_config_aff = kAxis.pos_speed_ctl_config.aff;
        kFlashStorage.pos_speed_ctl_config_vff = kAxis.pos_speed_ctl_config.vff;
        kFlashStorage.pos_speed_ctl_config_j_kt = kAxis.pos_speed_ctl_config.j_kt;
        ...
    }

    3.1.7 app_param_update()

    将 kAppControlWord 中结构体的内容同步到 axis 结构体中:

    void app_param_update(void)
    {
        set_app_Controlword(kAppControlWord.Controlword);
        set_app_Statusword(kAppStatusInfo.Statusword);
        set_app_Error_word(kAppStatusInfo.Error_word);
        set_app_Modes_of_operation(kAppOpMode.Modes_of_operation);
        set_app_Load_encoder_resolution(kAppEncoderConfig.Load_encoder_resolution);
        set_app_Motor_encoder_resolution(kAppEncoderConfig.Motor_encoder_resolution);
        ...
    }

    比如在 set_app_Controlword() 函数中,val 被赋值给 kAppControlWord 和 axis 中的结构体内:

    uint32_t set_app_Controlword(uint16_t val)
    {
        ...
        kAppControlWord.Controlword = val;
        /* USER CODE BEGIN set_app_Controlword 1 */
        axis->motor_ctl_sm_input.motor_enable = val;
        /* USER CODE END set_app_Controlword 1 */
        ...
    }

    3.1.8 总结

    项目(函数名)文件及行号数据流向操作的数据层
    AppParamInit()data_param.c:41宏硬编码 -> kAppXxx RAM应用层(CiA 402 对象字典)
    MotorCtrlInit()motor_ctl_loop.c:31宏硬编码 -> kAxis RAM控制层(Simulink 算法数据库)
    AppStoreInit()app_store_param.c:435Flash -> kFlashStorage -> RAM -> 通信数据库存储层(Flash 持久化)
    app_param_update()data_param.c:357kAppXxx RAM -> 通信数据库通信层(数据库同步)

    四、使用这些数据

    4.1 原理概述

    所有模块统一通过标准化的 set/get 接口访问这个仓库,彼此之间完全解耦。

    4.2 get() / set() 标准读写接口

    uint16_t get_app_Controlword(void)
    {
        /* USER CODE BEGIN get_app_Controlword */
        /* USER CODE END get_app_Controlword */
        return kAppControlWord.Controlword;
    }
    uint32_t set_app_Controlword(uint16_t val)
    {
        // 1. 范围检测
        if (val > 3) return APP_PARAM_OUT_OF_RANGE;
    
        // 2. 权限检测(控制层接管时只读)
        if (get_app_Internal_control_authority() == INTERNAL_CONTROL_CTRL)
            return APP_PARAM_READ_ONLY;
    
        // 3. 写入结构体
        kAppControlWord.Controlword = val;
    
        // 4. 立即同步到控制层
        axis->motor_ctl_sm_input.motor_enable = val;
    
        return APP_PARAM_SUCCESS;
    }
    

    4.3 命令配置

    以 Mavlink 的写入值举例:

    void MavlinkRecvCallback(Axis *axis, AxisDw *axis_dw, uint8_t rx_data[], uint32_t len)
    {
    ...
                case MAVLINK_MSG_ID_SystemCmd:
                    mavlink_msg_systemcmd_decode(&msg, (mavlink_systemcmd_t *)&system_cmd_t);
                    set_app_Sys_cmd(system_cmd_t.Sys_cmd);
                    system_cmd_t.Sys_cmd = get_app_Sys_cmd();
                    mavlink_msg_systemcmd_encode(sys_id, comp_id, &send_msg, (mavlink_systemcmd_t *)&system_cmd_t);
                    break;
    ...
    }

    通过 set_app_Sys_cmd() 函数便修改了 kSystemStatus.Storage_status 的值:

    uint32_t set_app_Sys_cmd(uint8_t val)
    {
        /* USER CODE BEGIN set_app_Sys_cmd 0 */
        /* USER CODE END set_app_Sys_cmd 0 */
        kSystemCmd.Sys_cmd = val;
        /* USER CODE BEGIN set_app_Sys_cmd 1 */
        switch (val)
        {
        case APP_SYSTEM_CMD_NONE:
            // Do nothing
            break;
        case APP_SYSTEM_CMD_HOMING:
            // 设置当前位置为系统零点
            // 负载端累计的绝对位置
            // 设置当前目标位置为0
            kAppBaseConfig.Home_position_offset_value = kAppMotionInfo.Position_actual_value_inc;
            set_app_Target_position(0);
    
            break;
        case APP_SYSTEM_CMD_SAVE_CONFIG:
            if (axis->motor_ctl_sm_output.state == MOTOR_CTL_SM_MOTOR_ENABLE)
            {
                set_app_Storage_status(FLASH_STORE_STATUS_WARNING);
                return APP_PARAM_WRITE_STATE_ERROR;
            }
            set_app_Storage_cmd(FLASH_STORE_CMD_WRITE_PARAM);
            break;
        case APP_SYSTEM_CMD_REBOOT:
            bsp_system_reset();
            break;
        case APP_SYSTEM_CMD_SAVE_TQ_FC_TABLE:
            if (axis->motor_ctl_sm_output.state == MOTOR_CTL_SM_MOTOR_ENABLE)
            {
                set_app_Storage_status(FLASH_STORE_STATUS_WARNING);
                return APP_PARAM_WRITE_STATE_ERROR;
            }
            set_app_Storage_cmd(FLASH_STORE_CMD_WRITE_TQ_FC);
            break;
        case APP_SYSTEM_CMD_TQ_FC_TABLE_CLEAR:
            if (axis->motor_ctl_sm_output.state == MOTOR_CTL_SM_MOTOR_ENABLE)
            {
                set_app_Storage_status(FLASH_STORE_STATUS_WARNING);
                return APP_PARAM_WRITE_STATE_ERROR;
            }
            set_app_Storage_cmd(FLASH_STORE_CMD_ERASE_TQ_FC);
            break;
        case APP_SYSTEM_CMD_ERROR_RECORD_CLEAR:
            if (axis->motor_ctl_sm_output.state == MOTOR_CTL_SM_MOTOR_ENABLE)
            {
                set_app_Storage_status(FLASH_STORE_STATUS_WARNING);
                return APP_PARAM_WRITE_STATE_ERROR;
            }
            set_app_Storage_cmd(FLASH_STORE_CMD_ERASE_ERROR);
            break;
        case APP_SYSTEM_CMD_FACTORY_RESET:
            if (axis->motor_ctl_sm_output.state == MOTOR_CTL_SM_MOTOR_ENABLE)
            {
                set_app_Storage_status(FLASH_STORE_STATUS_WARNING);
                return APP_PARAM_WRITE_STATE_ERROR;
            }
            set_app_Storage_cmd(FLASH_STORE_CMD_ERASE_PARAM);
            break;
        default:
            break;
        }
    
        /* USER CODE END set_app_Sys_cmd 1 */
        return APP_PARAM_SUCCESS;
    }

    4.4 1ms 循环定时储存

    最后每隔 1ms调用这个更新函数,根据标志位读或者写入 flash 相关的值:

    /**
     * @brief 非实时任务1ms循环
     */
    void UnrealTimeBase1ms(void)
    {
        ...
    
        // 9. flash参数存储
        AppStoreUpdata1ms();
        ...
    }
    TinyFlashDB:一种超轻量的可纠错的通用单片机Flash存储方案_e2prom flashdb 【代码】TinyFlashDB:一种超轻量的可纠错的通用单片机Flash存储方案_e2prom flashdb。 阅读详情

    相关推荐

    手把手教 - STM32 单片机 FlashDB 软件包的使用

    该开源库也支持运行在 裸机平台。所以只需要将所用到的 Flash 对接到 FAL ,即可完成整个移植工作。

    weixin_46158019的博客 1919

    FLASHDB的tsdb时序数据库代码分析和问题解决

    好好看看FlashDB,在使用过程中读取时存在不太好用的地方,因此深入学习下FlashDB的TSDB的相关代码,看看如何解决工程中的问题。主要我每次取的数据是有上限的,而读取API不能读取条数,都是采用迭代方式,不适合我的项目工程。看看采集什么方式比较好,如果有大牛有好方法,请在评论区里指点下。

    zhejfl的博客 5474

    基于C语言的FlashDB轻量级数据库设计源码

    本源码为基于C语言的FlashDB轻量级数据库设计,包含372个H文件、233个C文件等,共752个文件。该项目旨在为用户提供一个全面、便捷的数据库解决方案,通过C语言的结合,为用户带来高效的KV数据和时序数据存储体验。

    FLASHDB KV数据库源码解析1:fdb_kvdb_init(...)

    FLASHDB KV数据库源码学习1:fdb_kvdb_init(...)

    2301_81122825的博客 2476

    最强解析!CWRU轴承数据集Python实战:从数据加载到模型部署全流程

    本文提供了一份完整的CWRU轴承数据集Python实战指南,涵盖从数据加载、预处理、特征工程到模型构建与训练的全流程。详细解析了如何利用1D-CNN、Transformer等深度学习模型进行轴承故障诊断,并介绍了模型评估、可解释性分析以及通过FastAPI部署模型的实用方法,为工业设备智能运维提供了一套可复用的解决方案。

    time3的博客 365

    深入解析LVDS电平标准在LCD屏接口设计中的关键作用

    本文深入解析了LVDS电平标准在LCD屏接口设计中的核心作用。文章不仅阐释了LVDS低电压差分信号的工作原理、关键电气参数及抗噪优势,还详细对比了VESA与JEIDA两种主流数据格式,并提供了从PCB布局布线到信号调试的实战避坑指南,是确保高速、稳定显示的关键技术参考。

    weixin_28419039的博客 338

    探索单片机存储新境界:TinyFlashDB深度剖析与应用指南

    探索单片机存储新境界:TinyFlashDB深度剖析与应用指南 在微控制器(MCU)的世界里,每一比特的空间都异常珍贵,尤其是当涉及到非易失性存储时。针对这一需求,我们发现了一款简洁而高效的解决方案——TinyFlashDB。这是一套专为MCU量身定做的轻量级闪存数据库系统,它巧妙地解决了小规模关键数据安全存储的问题,尤其适合那些对空间有着严苛要求的应用场景。 项目介绍 TinyFlashDB,正...

    gitblog_01196的博客 753

    光电振荡器(OEO):从原理到应用,解锁高频微波信号新纪元

    本文深入解析了光电振荡器(OEO)的核心原理与前沿应用。OEO通过巧妙的光-电-光转换机制,利用光学谐振腔产生高频、高纯度、低相位噪声的微波信号,有效突破了传统电子电路的频率瓶颈。文章详细拆解了其工作流程,并探讨了在雷达系统、高速光通信及精密测量等领域的硬核应用价值。

    weixin_29231027的博客 367

    FlashDB源码剖析:从数据结构到核心算法的完整解析

    FlashDB是一款支持KV数据和时序数据的超轻量级数据库,专为嵌入式系统设计。本文将深入剖析FlashDB的核心架构、数据结构设计及关键算法实现,帮助开发者理解其高效存储的底层原理。 ## 一、架构设计:轻量级数据库的分层模型 FlashDB采用分层架构设计,通过FAL(Flash抽象层)实现对底层存储设备的统一管理。FAL架构分为三个核心层次: [![FlashDB分层架构](https

    gitblog_01058的博客 517

    OpenCV安装配置教程VS2022(超级顺利)

    博主最开始没打算写这篇博客,只是想简单的在网上找一下最新版的OpenCV的安装配置教程,适用于VS2022的,但是我搜了一早上,也没搜到一个能让我成功安装配置的,看了很多很多文章,根本就没有几篇有用的。所以没办法了,只能自己研究了,于是就整理了这篇博客,希望能帮到和我一样的人,这就是博主一直信奉的利他精神!

    weixin_47367099的博客 5万+

    生存网络与mlr3proba

    通过结合生存网络和mlr3proba,可以使用生存网络模型来预测个体在给定时间点发生事件的概率,并使用mlr3proba提供的工具进行模型的训练、评估和选择最佳模型。iii)基本的机器学习(ML)方法,如重新排序和调整。在本文中,我们将只讨论前五种,因为它们在文献中得到了更好的建立,并且它们具有相同的接口,这简化了调优,我们将在下面看到。我们不会为模型指定自定义架构,而是使用默认架构,如果你熟悉PyTorch,那么你可以选择创建自己的架构,如果你愿意的话,通过将其传递给模型中的custom_net参数。

    weixin_46587777的博客 1364

    FLASHDB KV数据库源码解析2:fdb_kv_set_blob()

    FLASHDB KV数据库源码学习2:fdb_kv_set_blob()

    2301_81122825的博客 817

    研究生如何快速发CVPR

    研究生如何快速发CVPR,找到科研方向

    python_vb的博客 786

    1、FlashTsDB时序数据库介绍

      FlashTsDB时序数据库介绍 1、What is FlashTsDB 1.1 背景 随着互联网、物联网的不断发展,对于海量具有时序特征数据的存储需求日益增多,TSDB(时序数据库)开始受到更多的关注。传统的商业时序数据库(例如OSI-PI)价格昂贵;Influxdb作为目前开源排名最高的时序数据库,集群版已经闭源商业化,开源版仅支持单机模式;OpenTsDB集群方案成熟(Hbase),但实测压缩比不高,性能也是差强人意。 在这样的大环境下,当前市面上无论是开源时序库还是商业时序库都有各自的

    阿芒的博客 2046

    40.8K星爆火!Crawl4AI实战突破Cloudflare 5秒盾:AI反爬新范式,爬虫再也不被封

    Crawl4AI的爆火(40.8K星)不是偶然——它解决了爬虫工程师最头疼的反爬问题,让爬虫从“体力活”变成“脑力活”,不用再花费大量时间配置指纹、编写行为脚本。但要注意:爬虫必须遵守目标网站的robots.txt协议,不得用于非法爬取数据(比如用户隐私、商业机密)。合理使用技术,才能长久落地。如果你在使用Crawl4AI时遇到具体问题(比如绕过更严格的反爬、批量爬取配置),欢迎在评论区交流,我会第一时间分享解决方案!

    专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1604

    温度PID控制PLC程序

    温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

    探索FlashDB:高效、嵌入式的Go语言键值存储

    探索FlashDB:高效、嵌入式的Go语言键值存储 在当今的数据驱动世界中,选择一个高效、可靠且易于嵌入的数据库解决方案至关重要。FlashDB,一个用纯Go编写的简单内存键值存储,正是满足这些需求的理想选择。本文将深入介绍FlashDB的核心特性、技术架构、应用场景以及性能优势,帮助您了解为何FlashDB是您项目的不二之选。 项目介绍 FlashDB是一个轻量级的内存键值存储系统,采用纯Go语...

    gitblog_00587的博客 629

    迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

    迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

    推荐开源项目:FlashDB - 高效能嵌入式数据库系统

    是一款由 ARMINK 团队开发的高性能、轻量级嵌入式数据库系统,专为物联网设备和资源受限的微控制器设计。该项目旨在提供可靠的数据存储解决方案,即使在低功耗环境下也能保持高效运行。 ## 技术分析 FlashDB 基于键值对(Key-Value)数据模型,其核心特性包括: 1. **高效的内存管理**:FlashDB 使用紧凑的数据结构和智能内存分配策略,最大限度地减少内存占用,适应有限的内...

    gitblog_00068的博客 1328

    复分析 阿尔福斯(Ahlfors) 第三版答案 英文

    答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

    IDEA的使用指南

    IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

    FLASHDB实战详解 - 嵌入式KV/TSD数据库开发全攻略

    FlashDB是一款专为嵌入式系统设计的轻量级数据库,提供KV键值存储和时序数据(TSD)存储两种模式。它解决了嵌入式存储中的三大痛点:配置参数管理、日志存储和Flash坏块处理。FlashDB具有掉电安全、坏块管理、高效缓存等特性,支持FAL模式和文件系统模式。其架构分为应用层、数据库核心层和存储抽象层,核心功能包括KV管理和TSL管理。FlashDB采用模块化设计,提供丰富的API接口,适用于嵌入式系统中的配置参数存储和操作日志记录等场景,能有效简化嵌入式开发中的数据存储管理。

    一无所知 790

    STM32F103 HAL库移植FlashDB记录

    FAL库-C文件:fal.c、fal_partition.c、fal_flash.c、fal_flash_stm32f1_port.c。FlashBD-C文件:fdb.c、fdb_utils.c、fdb_tsdb.c、fdb_kvdb.c、fdb_file.c。FlashBD-头文件:flashdb.h、fdb_low_lvl.h、fdb_def.h、fdb_cfg.h。FAL库-头文件:fal.h、fal_def.h、fal_cfg.h。第一步:修改fal_flash_stm32f1_port.c。

    沉默小AI的博客 2028

    杰理之FlashDB【篇】

    FlashDB是一个超轻量级的嵌入式数据库,专注于为嵌入式产品提供数据存储解决方案。与传统的基于文件系统的数据库不同,FlashDB结合了Flash的特点,具有较强的性能和可靠性。并在保证极低资源占用的前提下,应尽可能延长Flash的使用寿命。 ...

    u013820168的博客 896

    STM32 FLASHdb

    FlashDB是一款超轻量级的嵌入式数据库,专注于为嵌入式产品提供数据存储方案。

    weixin_57010826的博客 1199

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

    GD32上FAL Flash分区驱动移植移植前提下载源码移植过程加入以下文件及文件夹到工程目录和工程将demo目录下的接口文件做下修改修改配置文件fal_cfg.h复制demo中文件修改内部flash驱动接口外部SPI Flash的接口配置测试代码必须的初始化读写擦除 移植前提 下载源码 移植过程 加入以下文件及文件夹到工程目录和工程 工程目录文件添加参考 将demo目录下的接口文件做下修改 修改配置文件fal_cfg.h #ifndef _FAL_CFG_H_ #define _FAL_CFG_H

    aron566博客 5827

    轻量级嵌入式数据库FlashDB的介绍与使用

    一、FlashDB的介绍 FlashDB 是一款超轻量级的嵌入式数据库,专注于提供嵌入式产品的数据存储方案。与传统的基于文件系统的数据库不同,FlashDB 结合了 Flash 的特性,具有较强的性能及可靠性。并在保证极低的资源占用前提下,尽可能延长 Flash 使用寿命。 FlashDB 提供两种数据库模式: 键值数据库 和 时序数据库。 二、移植 定义 flash 设备 在定义 Flash 设备表前,需要先定义 Flash 设备。可以是片内 flash, 也可以是片外基于 SFUD 的 spi fla

    本博客分享软硬件一体化开发实战。硬件涵盖 PCB 设计、STM32 等 MCU 底层开发;软件包含 C++、Rust,Qt/QML、PyQt、Slint、TouchGFX、LVGL 各类 GUI 框架。方便软硬件开发者查阅学习。欢迎关注! 1万+

    基本定时器(TIM6/TIM7)

    基本定时器最简单,就干一件事:到点了触发中断。定时器本质就是计数器,每个时钟脉冲加1,数到ARR就溢出、产生中断、清0重来。三个核心寄存器:PSC(预分频器):对输入时钟分频CNT(计数器):从0往上数ARR(自动重装载值):数到这个值就溢出,CNT清0,产生更新中断公式:  定时周期 = (PSC+1) × (ARR+1) / 定时器时钟  更新事件频率 = 定时器时钟 / ((PSC+1) × (ARR+1)) 例:TIM6时钟84MHz,要定时0.5秒(2

    2401_89890233的博客 260
    上一篇: 先辑 EtherCat 关节方案培训笔记【二】硬件设计技巧
    下一篇: YuanHub 源码分析【三】电流环的初始化、应用和 Simulink 建模
    崔佳宇_
    崔佳宇_ 优质创作者: 嵌入式与硬件开发技术领域 优质创作者: 嵌入式与硬件开发技术领域
    博客等级 码龄10年 1万+粉丝 173原创
    评论
    成就一亿技术人!
    拼手气红包6.0元
    还能输入1000个字符
     
     条评论被折叠 查看
    添加红包

    请填写红包祝福语或标题

    个

    红包个数最小为10个

    元

    红包金额最低5元

    当前余额3.43元 前往充值 >
    需支付:10.00元
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付元
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值