nrf51822 SDK12.3.0的flash读写

来源:互联网 发布:win10好多软件打不开 编辑:程序博客网 时间:2024/05/29 08:14
一、前言
因为sdk12使用fstorage代替了pstorage,网上能搜到的资料都用不了了,于是只能去nordic的官方论坛里面找。在论坛里面蹲了两天,终于实现了flash的存储。

二、实验平台
协议栈版本:nRF5_SDK_12.3.0_d7731ad
例程为ble_app_uart

三、实验流程
1、结构体与全局变量声明
#define DATA_SIZE  8uint32_t m_datas[DATA_SIZE]={0,1,2,3,88,5,6,7};uint8_t  erase_flag=0;uint8_t  store_flag=0;FS_REGISTER_CFG(fs_config_t fs_config) ={.callback  = fs_evt_handler,// Function for event callbacks..num_pages = 1,             // Number of physical flash pages required..priority  = 0xFE           // Priority for flash usage.};


2、flash操作回调函数
static void fs_evt_handler(fs_evt_t const * const evt, fs_ret_t result){     if( (evt->id == FS_EVT_STORE) && (result == FS_SUCCESS) )     {          store_flag = 0;  printf("store_flag: %d  \r\n", store_flag);         // NRF_LOG_RAW_INFO("store_flag: %d  \r\n", store_flag);     }     else if( (evt->id == FS_EVT_ERASE) && (result == FS_SUCCESS) )     {          erase_flag = 0;          //NRF_LOG_RAW_INFO("erase_flag: %d  \r\n", erase_flag);  printf("erase_flag: %d  \r\n", erase_flag);     }     else if (result != NRF_SUCCESS)      {  printf("fstorage error and code: %d  \r\n", result);        // NRF_LOG_RAW_INFO("fstorage error and code: %d  \r\n", result);     }}


3、flash功能初始(main函数中)
fs_ret_t ret = fs_init();if( ret == FS_SUCCESS ){ printf("fs init successful\r\n");}else{  printf("fs init failed\r\n");  printf("err_code is:%d\r\n",ret);  m_flash_erase();}       

4、flash操作相关函数
uint32_t const * address_of_page(uint16_t page_num){    return fs_config.p_start_addr + (page_num * DATA_SIZE);}void m_flash_read(const uint32_t* address){    uint32_t* m_addr = (uint32_t*)address;    uint32_t buff[DATA_SIZE];    for(int i=0; i<DATA_SIZE; i++ )    {          buff[i] = *m_addr;        //NRF_LOG_INFO("Data: %d\r\n",m_tbd_obj.flash_test[i]);         m_addr++;     }    for(int i = 0; i< DATA_SIZE; i++)    {      printf("%d ",buff[i]);    }    printf("\r\n"); }void m_flash_write(void){      fs_ret_t ret;      erase_flag=1;      // Erase one page (page 0).      ret = fs_erase(&fs_config, address_of_page(0), 1,NULL);      if (ret != FS_SUCCESS)      {// NRF_LOG_INFO("fs_erase error\r\n"); printf("fs_erase error\r\n"); printf("err_code is:%d\r\n",ret);      }      else      {printf("fs_erase FS_SUCCESS\r\n");//NRF_LOG_INFO("fs_erase FS_SUCCESS\r\n");       }        while(erase_flag == 1) { power_manage(); }        store_flag=1;ret = fs_store(&fs_config, fs_config.p_start_addr, m_datas, DATA_SIZE,NULL);if (ret != FS_SUCCESS){//  NRF_LOG_INFO("fs_store error\r\n"); printf("fs_store error\r\n"); printf("err_code is:%d\r\n",ret);}else{//NRF_LOG_INFO("fs_store FS_SUCCESS\r\n");   printf("fs_store FS_SUCCESS\r\n");   }while(store_flag == 1) { power_manage(); }}void m_flash_erase(void){    erase_flag=1;      // Erase one page (page 0).    fs_ret_t ret = fs_erase(&fs_config, address_of_page(0), 1, NULL);    if( ret != FS_SUCCESS )    {       // NRF_LOG_INFO("fs_erase error\r\n");       printf("fs_erase error\r\n");       printf("err_code is:%d\r\n",ret);    }   else   {    //     NRF_LOG_INFO("fs_erase FS_SUCCESS\r\n");    printf("fs_erase FS_SUCCESS\r\n");   }   while(erase_flag == 1) { power_manage(); }}



5、在ble_stack_init中添加sys_evt_dispatch
因为fstorage的实现是基于状态机,协议栈会分步进行flash操作。在我们erase/write的操作函数中有一个等待标志位清零的循环,这个标志位就是在flahs回调函数中进行清零的。
在main.c中添加
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){     ble_advertising_on_sys_evt(sys_evt);    //这函数在fstorage.c中实现    fs_sys_event_handler(sys_evt);}
当有系统事件时,会执行fs_sys_event_handler(sys_evt)函数
void fs_sys_event_handler(uint32_t sys_evt){    fs_op_t * const p_op = &m_queue.op[m_queue.rp];    if (m_flags & FS_FLAG_PROCESSING)    {        // A flash operation was initiated by this module. Handle the result.        switch (sys_evt)        {            case NRF_EVT_FLASH_OPERATION_SUCCESS:                on_operation_success(p_op); //当flash操作成功时                break;            case NRF_EVT_FLASH_OPERATION_ERROR:                on_operation_failure(p_op); //当flash操作失败时                break;        }    }    else if ((m_flags & FS_FLAG_FLASH_REQ_PENDING))    {        // A flash operation was initiated outside this module.        // A callback which indicates that it has finished was received.        m_flags &= ~FS_FLAG_FLASH_REQ_PENDING;        // If there are any elements left in the queue, set FS_FLAG_PROCESSING.        if (m_queue.count > 0)        {           m_flags |= FS_FLAG_PROCESSING;        }    }    // Resume processing the queue, if necessary.    queue_process();}
我们进入flash操作成功的分支,进入on_operation_success(fs_op_t * const p_op)
static void on_operation_success(fs_op_t * const p_op){    m_retry_count = 0;    switch (p_op->op_code)    {        case FS_OP_STORE:        {            uint16_t chunk_len;            if ((p_op->store.length_words - p_op->store.offset) < FS_MAX_WRITE_SIZE_WORDS)            {                chunk_len = p_op->store.length_words - p_op->store.offset;            }            else            {                chunk_len = FS_MAX_WRITE_SIZE_WORDS;            }            p_op->store.offset += chunk_len;            if (p_op->store.offset == p_op->store.length_words)            {                // The operation has finished.                send_event(p_op, FS_SUCCESS); //flash操作完成之后执行                queue_advance();            }        }        break;        case FS_OP_ERASE:        {            p_op->erase.page++;            p_op->erase.pages_erased++;            if (p_op->erase.pages_erased == p_op->erase.pages_to_erase)            {                send_event(p_op, FS_SUCCESS);                queue_advance();            }        }        break;        default:            // Should not happen.            break;    }}
进入send_event(p_op, FS_SUCCESS)
static void send_event(fs_op_t const * const p_op, fs_ret_t result){    fs_evt_t evt;    memset(&evt, 0x00, sizeof(fs_evt_t));    switch (p_op->op_code)    {        case FS_OP_STORE:            evt.id                 = FS_EVT_STORE;            evt.store.p_data       = p_op->store.p_dest;            evt.store.length_words = p_op->store.length_words;            break;        case FS_OP_ERASE:            evt.id               = FS_EVT_ERASE;            evt.erase.first_page = p_op->erase.page - p_op->erase.pages_erased;            evt.erase.last_page  = p_op->erase.page;            break;        default:            // Should not happen.            break;    }    evt.p_context = p_op->p_context;    p_op->p_config->callback(&evt, result);  //这里就调用了之前注册的回调函数}




四、实验结果
上电初始化之后,串口输出
fs init successful
调用m_flash_write()之后,串口输出

m_flash_write..fs_erase FS_SUCCESSerase_flag: 0  fs_store FS_SUCCESSstore_flag: 0  
这样代表了已经存储成功

调用m_flash_read(),输出

m_flash_read..0 1 2 3 88 5 6 7

如有错误,请留言。
原创粉丝点击