pstorage

Persistent Storage

52擦写次数:endurance 



特别注意,用户如果要使用 pstorage ,那么必须要更改  #include "pstorage_platform.h"  下的 #define PSTORAGE_NUM_OF_PAGES  (默认是1)加一页。

带协议栈的BLE工程中使用 flash 操作(有bootloader需要page加1页)


NordicSDKflash操作封装成了一个pstorage模块。模块提供了很好用的flash操作接口。基本操作步骤如下:

使用flash前需要调用 pstorage_init函数来初始化pstorage模块。  uint32_t pstorage_init(void)

然后就可以调用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,buff);

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


正确的方式:

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

    Pstorage_update(dest1,buff);

    等待上面操作完成。

    修改buff数据。

    Pstorage_updata(dest2,buff);

或者:

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

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

    Pstorage_update(dest1,buff1);

    Pstorage_updata(dest2,buff2);





添加工程文件

  


函数分析:

#include "pstorage_platform.h"

1、Size of one flash page = 4096 bytes



2、pstorage_flash_page_end 可用的页数 : 0X7A000/0X1000= 0X7A  或0X80  ,地址分配是 由上到下,即由大到小。pstorage_flash_page_end = 0x80时,page为1,存在0x7E000;page为2,存在0x7D000。


PSTORAGE_NUM_OF_PAGES:分配 用于PSTORAGE 的页数,修改大小会影响起始地址(看上)。如果应用程序支持DFU(bootloader)且用了PSTORAGE ,那么需要添加一页给bootloader 。

PSTORAGE_MIN_BLOCK_SIZE :定义了BLOCK 最小单位(16字节)。



3、pstorage_init();//only call this function once


4、pstorage_register(&test_module_param, &test_block_id);//only call this function once


初始化模块参数注意: block_size最小是 16,且是4的倍数。如果有bootloaderPSTORAGE_NUM_OF_PAGES多加1




5、pstorage_block_identifier_get(p_base_id,block_num,p_block_id); //only call this functiononce

用于block_count 大于 1的情况,为每一个block申请一个ID,然后就可以单独操作每一小块。



6、pstorage_store (p_dest,p_src,size,offset); 

//only write data to a single block,and need waiting。只能操作多块中的一小块,且等待操作完成



NOTE :

1__attribute__((aligned(4))) 数据没有4字节对对齐,出现存储地址错误



2p_src must be word aligned,即必须是4的倍数。If  5only 4so 8



3p_src参数是常驻内存的,不能为局部变量,因为该函数执行需要时间。


7、pstorage_load  (p_dest,p_src,size,offset);  

//only read data from a single block,and do not needwaiting。只能操作多块中的一小块,不需要等待


注意的是与pstorage_store 的参数p_dest 和p_src 的区别,是反过来的。

err_code = pstorage_store(&test_block_0_id,src_tab0,8,0);

err_code = pstorage_load(src_load0,&test_block_0_id,8,0);

8、pstorage_update(p_dest,p_src,size,offset) ;用法和store一样,只是不用clear。  



9、pstorage_clear(p_base_id,size) ;




10、非常指的注意的问题 , 如果没添加这些读是可以进入回调的,但擦除和写都不能




函数应用过程中 遇到的问题:

1、block_size 的设定 ,大于16且是4的倍数。因为要字对齐(4字节对齐)。__attribute__((aligned(4)))

2、申请的pstorage 大小 = module_param.block_count * module_param.block_size (字节)。如果module_param.block_count 大于1,可以通过pstorage_block_identifier_get()为每一小块注册一个ID,然后你就可以单独操作每一小块。(4字节对齐)。

3、pstorage_store(pstorage_handle_t * p_dest, uint8_t * p_src, pstorage_size_tsize, pstorage_size_t  offset) 函数中的形参size是4的倍数,因为要字对齐(4字节对齐)。例如你需要存5字节的数组,那你size的大小为8。若是5,你只能存了4字节的数据。另外特别注意:p_src要是常驻内存变量,不能为局部变量,因为store需要时间处理。

4、pstorage_update()同上,The applicationcannot free or reuse the memory that is the sourceof data until this operation is complete.

5、pstorage_store()和pstorage_load()的形参看起来一样,其实p_dest 和p_src 对调的。

6、pstorage_clear()、pstorage_store()操作需要时间 ,需要等待这些操作完成才能做其他操作。利用module_param.cb回调函数判断是否处理完成。

7、在初始化里调用flah操作函数,module_param.cb可以被调用,但在按键触发方式和定时器里module_param.cb就不被调用了???

初始化里可以用下面的while()等待方式判断操作完成,但被正式调用的时候这种方式就不行了,module_param.cb一直不能被调用,程序

一直死在while()里。

错误的做法!!!!!!

8、pstorage_store()和pstorage_update()的区别:


疑问:复位,或重新上电,直接再读出的数据还是正常的,相当于存储在固定地址???????


程序实例:

#include "user_pstorage.h"
#include "app_uart.h"
#include "nrf_delay.h"
//要写的数据是要常驻内存的,写有延时性,临时变量可能写一半就释放了。
uint8_t src_tab0[16]={0x01,0x02,0x03,0x04,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t src_tab1[16]={0x11,0x12,0x13,0x14,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t src_tab2[16]={0x21,0x22,0x23,0x24,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};



ePstorageState egPstorageState; //操作状态

pstorage_handle_t test_block_id;//define a global struct variable,Flash storage address index
pstorage_handle_t test_block_0_id;//block_count = 3
pstorage_handle_t test_block_1_id;//block_count = 3
pstorage_handle_t test_block_2_id;//block_count = 3

pstorage_module_param_t test_module_param;//define a Module parameter Struct

//Persistent storage operation completion callback function Events.
static void test_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_CLEAR_OP_CODE:
 if (result == NRF_SUCCESS)
{
egPstorageState = PSTORAGE_CLEAR_OP_SUCCESS;// Clear operation successful.
 }
else
 {
// Clear operation failed.
 }
 break;
case PSTORAGE_STORE_OP_CODE:
if (result == NRF_SUCCESS)
{
egPstorageState = PSTORAGE_STORE_OP_SUCCESS;
 }
else
 {
// store operation failed.
 }
 break;  
case PSTORAGE_UPDATE_OP_CODE:
           if (result == NRF_SUCCESS)
           {
               egPstorageState = PSTORAGE_UPDATE_OP_SUCCESS; //flash operation is completed,you can load flash data.
           }
           else
           {
              // Update operation failed.
           }
           break;
case PSTORAGE_LOAD_OP_CODE:
   if (result == NRF_SUCCESS)
   {
egPstorageState = PSTORAGE_LOAD_OP_SUCCESS;
   }
   else
   {
// Store operation failed.
    }
   break;
    }
}


uint32_t test_pstorage_init(void)
{
uint32_t err_code;

test_module_param.block_count = 4;//Select 4 blocks, total of 64 bytes
test_module_param.block_size = 16;//Select block size of 16 bytes.
test_module_param.cb = test_cb;//Set the pstorage callback handler

err_code = pstorage_init();//only call this function once
if(err_code == NRF_SUCCESS)
{
//printf("\r\nPstorage init success");
}
else
{
//printf("\r\nPstorage init failed");
}

    err_code = pstorage_register(&test_module_param, &test_block_id);//only call this function once
    if(err_code == NRF_SUCCESS)
{
        //printf("\r\nPstorage regis success");
}
    else
{
        //printf("\r\nPstorage regis failed");
}


err_code = pstorage_block_identifier_get(&test_block_id,0,&test_block_0_id);//get the first block ID
APP_ERROR_CHECK(err_code);
err_code = pstorage_block_identifier_get(&test_block_id,1,&test_block_1_id);//get the second block ID
APP_ERROR_CHECK(err_code);
err_code = pstorage_block_identifier_get(&test_block_id,2,&test_block_2_id);//get the third block ID
APP_ERROR_CHECK(err_code);
return err_code;
}


void test_pstorage_clear(void)
{
uint32_t err_code;
err_code = pstorage_clear(&test_block_id, 4*16);//clear all
APP_ERROR_CHECK(err_code);
}
void test_pstorage_clear1(void)
{
uint32_t err_code;
err_code = pstorage_clear(&test_block_1_id, 1*16);//clear test_block_1_id
APP_ERROR_CHECK(err_code);
}
void test_pstorage_store(void)
{
 uint32_t err_code;

    err_code = pstorage_store(&test_block_0_id,src_tab0,8,0);
APP_ERROR_CHECK(err_code);
    err_code = pstorage_store(&test_block_1_id,src_tab1,8,0);
APP_ERROR_CHECK(err_code);
    err_code = pstorage_store(&test_block_2_id,src_tab2,8,0);
APP_ERROR_CHECK(err_code);
}
void test_pstorage_update(void)
{
uint32_t err_code;
err_code = pstorage_update(&test_block_0_id,src_tab1,8,0);
APP_ERROR_CHECK(err_code);
}

void test_pstorage_load(void)
{
uint32_t err_code;
uint8_t i=0;
uint8_t src_load0[16];
uint8_t src_load1[16];
uint8_t src_load2[16];

err_code = pstorage_load(src_load0,&test_block_0_id,12,0);
APP_ERROR_CHECK(err_code);

err_code = pstorage_load(src_load1,&test_block_1_id,12,0);
APP_ERROR_CHECK(err_code);

err_code = pstorage_load(src_load2,&test_block_2_id,12,0);
APP_ERROR_CHECK(err_code);

for(i=0;i<12;i++)
{
printf("load0[%d]=%x \r\n",i,src_load0[i]);
}
for(i=0;i<12;i++)
{
printf("load1[%d]=%x \r\n",i,src_load1[i]);
}
for(i=0;i<12;i++)
{
printf("load2[%d]=%x \r\n",i,src_load2[i]);
}
}

//
void test_pstorage(void)
{
uint32_t err_code;
uint8_t  src_tab0[8]={0x01,0x02,0x03,0x04,0x05};
uint8_t src_load0[12];
uint8_t i=0;

 egPstorageState = PSTORAGE_CLEAR_OP;
err_code = pstorage_clear(&test_block_0_id, 4*16);//clear all
APP_ERROR_CHECK(err_code);
while(egPstorageState == PSTORAGE_CLEAR_OP);

egPstorageState = PSTORAGE_STORE_OP;
    err_code = pstorage_store(&test_block_0_id,src_tab0,8,0);
APP_ERROR_CHECK(err_code);
while(egPstorageState == PSTORAGE_STORE_OP);

egPstorageState = PSTORAGE_LOAD_OP;
err_code = pstorage_load(src_load0,&test_block_0_id,12,0);
APP_ERROR_CHECK(err_code);
while(egPstorageState == PSTORAGE_LOAD_OP);

for(i=0;i<12;i++)
{
printf("load0[%d]=%x \r\n",i,src_load0[i]);
}
}


系统调用函数
static void sys_evt_dispatch(uint32_t sys_evt)
{
    pstorage_sys_event_handler(sys_evt);
}
协议栈添加:
    err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
    APP_ERROR_CHECK(err_code);








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值