Nordic的SDK将flash操纵封装成一个pstorage模块,模块提供了很好的flash操作接口。
使用flash前需要调用pstorage_init函数来初始化pstorage模块,
然后就可以调用pstorage_register函数来注册自己要使用的block数量和block_size之后就可以使用pstorage_block_identifier_get函数或得到你要的操作
block_num的地址,然后在使用获得的地址调用pstorage_load,pstorage_store等操作,这里要注意的是涉及存储的操作,比如store和update因为模块内部
处理都需要时间,而这些函数内部不会复制你传进来的buff,如果你只用了一个buff的话,连续调用两个updata是会出错的,你需要等待上传操作完成才能使用这个
buff.
错误方式:
buff:里面放的是要存储的数据
Pstorage_update(dest1,buff);
修改buff数据。
Pstorage_updata(dest2,buff);
看过内部源码的都知道updata的分两次操作,首先赋值原来的flash数据到swap区,然后擦除之前放的数据的page,之后再将原来的数据修改后写,所以这个过程需要时间
在上次操作完成又使用了buff,会导致前面一次的flash操作出问题。
正确的方式:
Buff:里面放的是要存储的数据
Pstorage_update(dest1,buff);
等待上面操作完成。
修改buff数据
Pstorage_updata(dest2,buff);
Buff1:里面放的是存储到dest1的数据
Buff2:里面放的是存储到dest2的数据
Pstorage_update(dest1,buff);
Pstorage_update(dest2,buff);
我们在uart上来实验flash的使用,
我们通过手机向设备发送八个字节的数据,设备收到后先存储在flash中然后在flash的回调函数中判断是否存储完成,如果完成就设置标志,最后在主函数中判断这个标志,
如果标志被置位代表存储操作完成,我们就可以调用读操作读出来flash中的数据了
首先在main中添加 #include"pstorage.h"
然后我们要初始化,在注册自己要使用的flash大小。
添加flash相关的代码和变量
pstorage_handle_t block_id ;//定义全局变量,flash存储的地址
uint8_t my_flash=0;
uint8_t my_buff[8]={0};
flash中定义flash操作完成后的回调函数
//在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
module_param.cb=my_cb;
pstorage_init();//初始化
pstorage_register(&module_param,&block_id);
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中做的,我们
在这个函数中添加自己的代码,红色部分为添加的代码
之后就是main函数中判断标准然后读flash在打印出来的代码部分如下
最后最重要的一点是对sys_evt事件的处理,当flash操作完成后,sd会上抛给APP相应sys_evt事件。
因为pstorage的实现是基于状态的,比如我们上面使用的update,它的实现是分步做的,先擦除交换区,
然后将数据写到交换区,然后修改在写回,每个时刻下一步要做的时都由当前的操作返回的状态机决定,
所以pstorage需要获得sys_evt然后进行下一步的处理,至于这些处理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_sys_evt_handler(sys_evt);
}
最后编译工程就可以操作,手机连上设备后,找到tx特征值,然后写8个数据过去
以上代码都经过本人验证