作者 | firr
对申报的RVB2601创意项目经过一段时间的分模块开发后,本人准备开始将模块整合为完整的系统,特将整合过程分篇记录下来,本篇记录KV组件。
1、KV存储系统介绍
KV,即“Key-Value”,是YoC(Yun on Chip)中一个进行持久化存储的轻量级组件,主要用于Nor Flash。来自于SDK(kv v7.4.3)的README.md中的API说明如下图所示。
图2-1 KV接口说明
KV存储,必须建立在Flash分区的基础之上,所以必须要先建立分区,在“Hello World”案例中,分区初始化的代码是注释掉的,所以需要把注释去掉才可以——这里也算一个坑吧,当时困扰了许久(其实也是不细心)。
图2-2 分区初始化默认被注释了
2、项目参数的KV持久化
本人的项目中需要存储若干配置参数,为了这些参数搞个文件系统,实在没有必要,而KV组件正好可以满足需求。
这里导入的是“Hello World Demo”,并在“app/src/init.c”中添加KV初始化的代码。
#include <stdbool.h> #include <aos/aos.h> #include <yoc/yoc.h> #include <yoc/partition.h> #include <devices/devicelist.h> #include "board.h" #include "app_init.h" #include "drv/pin.h" const char *TAG = "INIT"; #ifndef CONSOLE_UART_IDX #define CONSOLE_UART_IDX 0 #endif /* --------------------by AITA Mr.Fei, global variables--------------------- */ #define ENDIAN_LIMIT 32 //endian counts limit char GID[9]; //gateway id char EID[ENDIAN_LIMIT][9];//endians' id int endian_count = 1; //actually endian counts int period = 10; //polling period -- minutes int timeout = 15; //timeout of waiting USR220 resp -- seconds int repeat = 3; //repeat times when timeout int aita_InitKV(void) { char buf[10] = {0}; int ret = -1; ret = partition_init(); if (ret > 0) { LOGI(TAG, "find %d partitions\n", ret); } else { LOGE(TAG, "partition init failed\n"); return ret; } ret = aos_kv_init("kv"); if(ret == 0) { LOGE(TAG, "kv init done\n"); } else { LOGE(TAG, "kv init failed\n"); return -1; } ret = aos_kv_getstring("endian_count", &buf, 10); if(ret > 0) { endian_count = atoi(buf); endian_count = (endian_count<ENDIAN_LIMIT) ? endian_count : ENDIAN_LIMIT; printf("endian_count: %d\n", endian_count); char eid[5] = "EIDx"; for(int i=0; i<endian_count; i++) { eid[3] = i+0x30; aos_kv_getstring(eid, EID[i], 9); printf("EID No.%d : %s\n", i, EID[i]); } } else { LOGE(TAG, "Endian Count load failed\n"); return ret; } ret = aos_kv_getstring("period", &buf, 10); if(ret > 0) { period = atoi(buf); printf("period: %d\n", period); } else { LOGE(TAG, "period load failed\n"); return ret; } ret = aos_kv_getstring("timeout", &buf, 10); if(ret > 0) { timeout = atoi(buf); printf("timeout: %d\n", timeout); } else { LOGE(TAG, "timeout load failed\n"); return ret; } ret = aos_kv_getstring("repeat", &buf, 10); if(ret > 0) { repeat = atoi(buf); printf("repeat: %d\n", repeat); } else { LOGE(TAG, "repeat load failed\n"); return ret; } return 0; } void board_yoc_init() { board_init(); // uart_csky_register(CONSOLE_UART_IDX); console_init(CONSOLE_UART_IDX, 115200, 128); ulog_init(); aos_set_log_level(AOS_LL_DEBUG); LOGI(TAG, "Build:%s,%s",__DATE__, __TIME__); aita_InitKV(); board_cli_init(); }
main.c则先对KV组件进行测试,系统启动时在控制台输出KV值。为了不受定时输出的“Hello World”影响,代码中改为了流水灯功能,具体实现大家可以参考博主anni_zzg的博文“【平头哥RVB2601创意应用开发】二 搞定GPIO口”。
#include <stdlib.h> #include <string.h> #include <aos/aos.h> #include "aos/cli.h" #include "main.h" #include "app_init.h" #include "oled.h" #define TAG "app" int main(void) { board_yoc_init(); LOGD(TAG, "%s\n", aos_get_app_version()); aita_InitBSP(); while (1) { aita_FlashLED(); } return 0; } void aita_InitBSP(void) { oled_init(); aita_InitLED(); }
给出我自己的LED GPIO初始化和流水灯实现的代码。
#include <aos/aos.h> #include <drv/pin.h> #include <drv/gpio_pin.h> csi_gpio_pin_t aita_led_red_pin; csi_gpio_pin_t aita_led_green_pin; csi_gpio_pin_t aita_led_blue_pin; void aita_InitLED(void) { //set pin gpio function csi_pin_set_mux(PA7, PIN_FUNC_GPIO); csi_pin_set_mux(PA25, PIN_FUNC_GPIO); csi_pin_set_mux(PA4, PIN_FUNC_GPIO); //init pin device & set direction csi_gpio_pin_init(&aita_led_red_pin, PA7); csi_gpio_pin_dir(&aita_led_red_pin, GPIO_DIRECTION_OUTPUT); csi_gpio_pin_init(&aita_led_green_pin, PA25); csi_gpio_pin_dir(&aita_led_green_pin, GPIO_DIRECTION_OUTPUT); csi_gpio_pin_init(&aita_led_blue_pin, PA4); csi_gpio_pin_dir(&aita_led_blue_pin, GPIO_DIRECTION_OUTPUT); //set leds' state at startup csi_gpio_pin_write(&aita_led_red_pin, GPIO_PIN_HIGH); csi_gpio_pin_write(&aita_led_green_pin, GPIO_PIN_HIGH); csi_gpio_pin_write(&aita_led_blue_pin, GPIO_PIN_HIGH); } void aita_FlashLED(void) { csi_gpio_pin_write(&aita_led_red_pin, GPIO_PIN_LOW); csi_gpio_pin_write(&aita_led_green_pin, GPIO_PIN_HIGH); csi_gpio_pin_write(&aita_led_blue_pin, GPIO_PIN_HIGH); aos_msleep(1000); csi_gpio_pin_write(&aita_led_red_pin, GPIO_PIN_HIGH); csi_gpio_pin_write(&aita_led_green_pin, GPIO_PIN_LOW); csi_gpio_pin_write(&aita_led_blue_pin, GPIO_PIN_HIGH); aos_msleep(1000); csi_gpio_pin_write(&aita_led_red_pin, GPIO_PIN_HIGH); csi_gpio_pin_write(&aita_led_green_pin, GPIO_PIN_HIGH); csi_gpio_pin_write(&aita_led_blue_pin, GPIO_PIN_LOW); aos_msleep(1000); csi_gpio_pin_write(&aita_led_red_pin, GPIO_PIN_HIGH); csi_gpio_pin_write(&aita_led_green_pin, GPIO_PIN_HIGH); csi_gpio_pin_write(&aita_led_blue_pin, GPIO_PIN_HIGH); aos_msleep(1000); }
图2-3 启动时控制台输出KV存储值
当然,这些KV值都是提前写入的。项目开启了KV的控制台命令,这样可以随时修改项目参数。考虑到实际应用时,现场也可以接入串口进行调试,因此,控制台作为配置参数的方式。开启控制台KV命令,只需调用api即可,本例写在board_cli_init()函数中。
#include <aos/debug.h> #include <aos/cli.h> void board_cli_init() { aos_cli_init(); extern void cli_reg_cmd_ps(void); cli_reg_cmd_ps(); extern void cli_reg_cmd_free(void); cli_reg_cmd_free(); //cli command of kv func extern void cli_reg_cmd_kvtool(void); cli_reg_cmd_kvtool(); }
本文源自:平头哥芯片开放社区
欢迎关注公众号:芯片开放社区(ID:OCC_THEAD),查看更多应用实战文章。