BLE-NRF51822教程7-带协议栈工程中使用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大小。
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个数据过去 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |