[经验分享] 【平头哥RVB2601创意应用开发】使用体验02 -- KV存储

sonicfirr   2022-3-31 17:19 楼主

对申报的RVB2601创意项目经过一段时间的分模块开发后,本人准备开始将模块整合为完整的系统,特将整合过程分篇记录下来,本篇记录KV组件。

1KV存储系统介绍

KV,即“Key-Value”,是YoCYun on Chip)中一个进行持久化存储的轻量级组件,主要用于Nor Flash。来自于SDKkv v7.4.3)的README.md中的API说明如下图所示。

 

image-20220331171621-1.png

2-1 KV接口说明

 

KV存储,必须建立在Flash分区的基础之上,所以必须要先建立分区,在“Hello World”案例中,分区初始化的代码是注释掉的,所以需要把注释去掉才可以——这里也算一个坑吧,当时困扰了许久(其实也是不细心)。

 

image-20220331171621-2.png

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”影响,代码中改为了流水灯功能,具体实现大家可以参考博主TL-LED的博文“【平头哥RVB2601开发板试用体验】 GPIO输出测试(https://bbs.eeworld.com.cn/thread-1197715-1-1.html)”。

 

#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);
}

 

image-20220331171621-3.png

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();
}

 

回复评论 (4)

存储若干配置参数,使得项目参数的KV持久化看来楼主做的很有借鉴意义

点赞  2022-4-1 07:28
感谢分享,三人行,都是我师傅。一切都是新知识!
点赞  2022-4-9 18:49

KV这块有可以独立使用的源代码吗?

默认摸鱼,再摸鱼。2022、9、28
点赞  2022-4-12 17:16
引用: freebsder 发表于 2022-4-12 17:16 KV这块有可以独立使用的源代码吗?

只是几个API呀,这里添加了控制台命令,也是为了编辑KV值方便而已。

点赞  2022-4-12 19:09
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复