加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

BLE-NRF51822教程7-带协议栈工程中使用flash

发布时间:2020-12-15 19:51:26 所属栏目:百科 来源:网络整理
导读:文章来源:http://blog.chinaunix.net/uid-28852942-id-5576719.html 本教程说明 如何在带协议栈的BLE工程中使用flash操作。 教程基于sdk9.0的?uart工程 xxxNordicSemiconductornRF_Examples9.0.0ble_peripheralble_app_uart Nordic的SDK将flash操作封

文章来源:http://blog.chinaunix.net/uid-28852942-id-5576719.html


本教程说明 如何在带协议栈的BLE工程中使用flash操作。

教程基于sdk9.0的?uart工程

xxxNordicSemiconductornRF_Examples9.0.0ble_peripheralble_app_uart

Nordic的SDK将flash操作封装成了一个pstorage模块。 模块提供了很好用的flash操作接口。


使用flash前需要调用?pstorage_init函数来初始化pstorage模块。

然后就可以调用pstorage_register函数来注册自己要使用的block数量和block_size(最好四字节对齐)

之后就可以使用pstorage_block_identifier_get??函数来或得你要操作的block_num (0-申请的block数量)?的地址。然后在使用获得的地址调用pstorage_load?,pstorage_store??等操作

这里需要注意的是 涉及到存储的操作,比如store?和updata因为模块内部处理都需要时间,而这些函数内部又不会复制你传进来的buff所以,如果你只用了一个buff的话,连续调用两个updata是会出错的。你需要等待上次的操作完成才能再使用这个buff。

用代码来解释下。

错误的使用方式:

?Buff:里面放的是要存储的数据

????Pstorage_update(dest1,buff);

????修改buff数据。

????Pstorage_updata(dest2,102)">?看过内部源码的都知道updata的是分两次操作的,首先赋值原来的flash数据到swap区然后,然后擦除之前放数据的page,之后再将原来的数据修改后写会。所以这个过程需要时间。未在上次操作完成就又使用了buff,会导致前面一次的flash写操作出问题。


正确的方式:

Buff:里面放的是要存储的数据

????等待上面操作完成。

或者:

Buff1:里面放的是要存储到dest1的数据

Buff2:里面放的是要存储到dest2的数据

我们在uart的demo上来实验flash的使用。

我们通过手机向设备发送八个字节的数据,设备受到后先存储在flash中然后在flash的回调函数中判断是否存储完成,如果完成就设置标志。 最后在主函数中判断这个标志,如果标志被置位代表存储操作完成,我们就可以调用读操作来读出flash中的数据了


下面介绍代码的编写:

PS:UART例子中要先关流控

首先在main.c#include”pstorage.h”

然后我们要 初始化,再注册自己要使用的flash大小。


添加flash相关的代码和变量。

pstorage_handle_t block_id;//定义全局变量,flash存储的地址索引

uint8_t my_flag = 0;//定义标志标量。Main函数中会根据标志来??????????????? ????? //读flash

uint8_t my_buff[8]={0};? //全局数组用来存放手机发过来的数据,???????????? ??????? //然后写到flash中

//定义flash操作完成后的回调函数,

static void my_cb(pstorage_handle_t? * handle,uint8_t op_code,uint32_t result,

?????????????????? uint8_t? * p_data,uint32_t?? data_len)

{

??? switch(op_code)

??? {??????

?????? case PSTORAGE_UPDATE_OP_CODE:

?????????? if (result == NRF_SUCCESS)

?????????? {

?????????????? my_flag = 1; //当flash update完成后置位标志。?Main函数中便可以读flash数据了

?????????? }

?????????? else

?????????????? // Update operation failed.

?????????? break;

??? }

}

//main中添加flash的初始化和注册代码

int main(void)

??? uint32_t err_code;

??? bool erase_bonds;

??? uint8_t? start_string[] = START_STRING;

?? pstorage_module_param_t module_param;

?? module_param.block_count = 1; // 申请了一个块

?? module_param.block_size = 16;? //块大小为16(最小要求是16,但是后面的处理我们都只处理手机发过来的前8字节)

?? module_param.cb = my_cb;

?? pstorage_init();????? //初始化

?? pstorage_register(&module_param,&g_block_id);//注册申请

??? // Initialize.

??? APP_TIMER_INIT(APP_TIMER_PRESCALER,APP_TIMER_MAX_TIMERS,APP_TIMER_OP_QUEUE_SIZE,false);

??? uart_init();

??? buttons_leds_init(&erase_bonds);

?? ………..

?? ……….

}.

然后我们需要在手机发送数据过来的时候将数据更新到flash中。

在?ble_nus.c中的ble_nus_on_ble_evt函数中有对手机写事件的处理。处理是在函数on_write中做的,我们在这个函数中添加自己的代码,红色部分为添加的代码

static void on_write(ble_nus_t * p_nus,ble_evt_t * p_ble_evt)

??? ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;

??? if ( (p_evt_write->handle == p_nus->rx_handles.cccd_handle)&& (p_evt_write->len == 2))

??? {

?????? ? ………………………….

??? else if ( (p_evt_write->handle == p_nus->tx_handles.value_handle)&& (p_nus->data_handler != NULL))

??? {??? //屏蔽掉之前的处理函数,添加flash?更新数据操作。

??????? //p_nus->data_handler(p_nus,p_evt_write->data,p_evt_write->len);

? ? ? ???pstorage_handle_t? ??? dest_block_id;

?????????uint8_t len = p_evt_write->len>8?8:p_evt_write->len;

???????? memcpy(my_buff,len);

???????? pstorage_block_identifier_get(&g_block_id,&dest_block_id);?? //因为只注册了一个flash块,所以其实这个函数可以不调用的。

???????? pstorage_update(&dest_block_id,my_buff,8,0);

???? }

??? else

??????? // Do Nothing. This event is not relevant for this service.

之后就是main函数中判断标志然后读flash再打印出来的代码

部分代码如下:

?Main(){

?????? …………….

??? // Enter main loop.

??? for (;;)

??????? power_manage();

?????? if ( my_flag == 1 ){

?????????? printf("rnread flash: ");

?????????? my_flag = 0;

?????????? pstorage_handle_t? ? dest_block_id;

?????????? uint8_t buff[8];

?????? //因为只注册了一个flash块,所以其实这个函数可以不调用的。? ?????? ? pstorage_block_identifier_get(&g_block_id,&dest_block_id);

?????????? pstorage_load(buff,&dest_block_id,0);

?????????? for(int i = 0; i< 8; i++){

????????????? printf("%d ",buff[i]);

?????????? printf("rn");

?????? }

最后最重要的一点是 对?sys_evt事件的处理,当flash操作完成后,sd会上抛给app?相应的sys_evt事件。(类似sd会上抛给APP BLE的事件)

因为pstorage的实现是基于状态机的。比如我们上面使用的update,它的实现是分步做的,先擦除交换区,然后将就数据写到交换区,然后修改再写回。每个时刻下一步要做的事都由当前的操作返回后的状态机决定。 所以pstorage需要获得sys_evt(flash的操作返回)然后进行下一步的处理。至于这些处理pstorage内部都是做好的。我们只要将事件处理函数添加到代码中就可以了。

首先要注册?sys_evt?的事件派发函数

在main.c中的?ble_stack_init函数最后添加注册代码

static void ble_stack_init(void)

{??

??? …………………

??? …………………???

??? err_code=softdevice_sys_evt_handler_set(sys_evt_dispatch);

??? APP_ERROR_CHECK(err_code);

然后在定义这个函数

static void sys_evt_dispatch(uint32_t sys_evt)

????//这个函数时在pstorage模块中实现的

??? pstorage_sys_event_handler(sys_evt);

?最后编译工程就可以操作了,手机连上设备后,找到tx特征值(可以写的那个),然后写8个数据过去

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读