STM32 利用FlashDB库实现在线扇区数据管理不丢失

04-27 1973阅读 0评论

STM32 利用FlashDB库实现在线扇区数据管理不丢失


  • 📍FalshDB地址:https://gitee.com/Armink/FlashDB
    • ✨STM32没有片内EEPROM这样的存储区,虽然有备份寄存器,仅可以实现对少量数据的频繁存储,但是依赖备份电源(BAT引脚)为芯片维持供电,才能保持数据的不丢失。FlashDB库利用在线对片内或片外存储扇区进行管理,可以有效的保存数据,掉电不丢失。在不增加像EEPROM外设的情况下,有效利用内部空余的flash空间,进行数据存储,也可以对片外spi flash存储芯片进行数据管理。类似esp32的NVS空间,也有使用键值对,进行数据存储和管理。
      • 🌿FlashDB库,目前包含STM32F1、F4的相关Keil MDK demo现成的工程例程,可以直接测试使用,可以移植到STM32其他型号单片机上使用。目前是支持STM32和esp8266的。
      • 🧨FlashDB移植指南:https://armink.gitee.io/flashdb/#/zh-cn/porting
        • 🥕类似轻量级的还有EasyFlash(同作者FlashDB) 、 tinyFlash.
        • 🎉如果觉得使用库移植比较麻烦,轻度使用操作内部flash,读写实现代码,可以参考:https://juejin.cn/post/7203569814182019132
          • 🔖个人使用的是STM32F427进行demo测试,测试结果和说明文档内容相符。

            STM32 利用FlashDB库实现在线扇区数据管理不丢失

            • 🥕以下内容是该项目作者的对其的相关内容的介绍:

              📘FlashDB使用场景介绍

              • 🎉如今,物联网产品种类越来越多,运行时产生的数据种类及总量及也在不断变大。FlashDB 提供了多样化的数据存储方案,不仅资源占用小,并且存储容量大,非常适合用于物联网产品。下面是主要应用场景:
                • 键值数据库 :
                  • 产品参数存储
                    • 用户配置信息存储
                      • 小文件管理
                      • 时序数据库 :

                        存储动态产生的结构化数据:如 温湿度传感器采集的环境监测信息,智能手环实时记录的人体健康信息等

                        记录运行日志:存储产品历史的运行日志,异常告警的记录等

                        KVDB 键值数据库介绍

                        • 🌿KVDB 的基础功能的使用:

                          记录开机次数:

                          void kvdb_basic_sample(fdb_kvdb_t kvdb)
                          {
                              struct fdb_blob blob;
                              int boot_count = 0;
                              FDB_INFO("==================== 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) {
                                      FDB_INFO("get the 'boot_count' value is %d\n", boot_count);
                                  } else {
                                      FDB_INFO("get the 'boot_count' failed\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\n", boot_count);
                              }
                              FDB_INFO("===========================================================\n");
                          }
                          
                          • 🌿字符串类型 KV

                            字符串 KV 的相关功能,字符串 KV 作为一个特殊的 KV 类型,其 Key 与 Value 均为字符串,常被用于参数存储、命令存储等可读性要求较高的场景。

                            void kvdb_type_string_sample(fdb_kvdb_t kvdb)
                            {
                                FDB_INFO("==================== kvdb_type_string_sample ====================\n");
                                { /* 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\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\n", temp_data);
                                    }
                                }
                                { /* CHANGE the KV value */
                                    char temp_data[10] = "38C";
                                    /* change the "temp" KV's value to "38C" */
                                    fdb_kv_set(kvdb, "temp", temp_data);
                                    FDB_INFO("set 'temp' value to %s\n", temp_data);
                                }
                                { /* DELETE the KV by name */
                                    fdb_kv_del(kvdb, "temp");
                                    FDB_INFO("delete the 'temp' finish\n");
                                }
                                FDB_INFO("===========================================================\n");
                            }
                            
                            • 遍历所有 KV

                              遍历 KVDB 中的所有 KV ,用户可以在遍历 KV 时增加自己的处理动作。

                              • 首先初始化了 KVDB 的迭代器,然后使用迭代器 API ,将 KVDB 的所有 KV 逐一遍历出来。

                                遍历出来的 KV 对象含有 KV 的一些属性,包括:key name, value saved addr, value length 等,用户通过 fdb_blob_read 配合 fdb_kv_to_blob 读取出来,做一些自己的业务处理。

                                void kvdb_tarversal_sample(fdb_kvdb_t kvdb)
                                {
                                    struct fdb_kv_iterator iterator;
                                    fdb_kv_t cur_kv;
                                    struct fdb_blob blob;
                                    size_t data_size;
                                    uint8_t *data_buf;
                                    fdb_kv_iterator_init(kvdb, &iterator);
                                    while (fdb_kv_iterate(kvdb, &iterator)) {
                                        cur_kv = &(iterator.curr_kv);
                                        data_size = (size_t) cur_kv->value_len;
                                        data_buf = (uint8_t *) malloc(data_size);
                                        if (data_buf == NULL) {
                                            FDB_INFO("Error: malloc failed.\n");
                                            break;
                                        }
                                        fdb_blob_read((fdb_db_t) kvdb, fdb_kv_to_blob(cur_kv, fdb_blob_make(&blob, data_buf, data_size)));
                                        /*
                                         * balabala do what ever you like with blob...
                                         */
                                        free(data_buf);
                                    }
                                }
                                

                                STM32 利用FlashDB库实现在线扇区数据管理不丢失

                                • 二进制大对象 (BLOB)

                                  时序数据库

                                  • TSDB 基础示例,具体介绍:https://armink.gitee.io/flashdb/#/zh-cn/sample-tsdb-basic
                                  • 该示例主要演示了 TSDB 的基础功能,包括 TSL(时序记录)的追加、查询及状态修改功能。

                                    samples/tsdb_sample.c ,包含追加、查询及状态修改这几个过程,大致代码如下:

                                    void tsdb_sample(fdb_tsdb_t tsdb)
                                    {
                                        struct fdb_blob blob;
                                        FDB_INFO("==================== tsdb_sample ====================\n");
                                        { /* 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)\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)\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_by_time_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\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 orderC.
                                             *       like: FDB_TSL_WRITE -> FDB_TSL_USER_STATUS1 -> FDB_TSL_DELETED -> FDB_TSL_USER_STATUS2
                                             *       The intermediate states can also be ignored.
                                             *       such as: FDB_TSL_WRITE -> FDB_TSL_DELETED
                                             */
                                            fdb_tsl_iter(tsdb, set_status_cb, tsdb);
                                        }
                                        FDB_INFO("===========================================================\n");
                                    }
                                    

                                    STM32 利用FlashDB库实现在线扇区数据管理不丢失


免责声明
本网站所收集的部分公开资料来源于AI生成和互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,1973人围观)

还没有评论,来说两句吧...

目录[+]