nrf51822 SDK12.3.0的flash读写

一、前言

因为sdk12使用fstorage代替了pstorage,网上能搜到的资料都用不了了,于是只能去nordic的官方论坛里面找。在论坛里面蹲了两天,终于实现了flash的存储。

 

二、实验平台

协议栈版本:nRF5_SDK_12.3.0_d7731ad

例程为ble_app_uart

 

三、实验流程

1、结构体与全局变量声明

#define DATA_SIZE  256
uint32_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_SUCCESS
erase_flag: 0  
fs_store FS_SUCCESS
store_flag: 0  

这样代表了已经存储成功

 

调用m_flash_read(),输出

 

m_flash_read..0 1 2 3 88 5 6 7

 

如有错误,请留言。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值