nRF52 Flash read and write data (different ways with or without protocol stack)

foreword

Recently developed nrf52833, need to read and write data in Flash, found that after the Bluetooth protocol stack is turned on, the original method of operating the register will cause the program to report errors. function, here are the different reading and writing methods with or without the protocol stack.
In addition, I turned on Bluetooth sniffing in my development, and reading and writing failed even if I used the read and write functions provided by the protocol stack. Finally, I found that I had to turn off sniffing to write normally. I guess it’s not just sniffing. It’s estimated that when broadcasting, To read and write Flash, you must first turn off the broadcast.

1. Reading and writing without protocol stack

1. Data writing

//按字节,连续写FLASH
//注意Addr得是每一页的起始地址
void NRF_Flash_Write(uint32_t Addr,uint8_t* Data,uint32_t Lenth)
{
    
    
	//擦除页
	nrf_nvmc_page_erase(Addr);
	nrf_delay_ms(100);
	//写数据
	nrf_nvmc_write_bytes(Addr,Data,Lenth);
}

2. Data readout

//按字节,连续读取FLASH
//每次读取一个字,然后转成字节
void NRF_Flash_Read(uint32_t Addr,uint8_t* Data,uint32_t Lenth)
{
    
    
	uint32_t *pData,i,j,idx=0;
	
	//要读的字个数
	j=Lenth/4;
	j=((Lenth%4)!=0)?j+1:j;

	for(i=0;i<j;i++)
	{
    
    
		pData=(uint32_t*)Addr;
		Data[idx++] = *pData;
		Data[idx++] = (*pData)>>8;
		Data[idx++] = (*pData)>>16;
		Data[idx++] = (*pData)>>24;
		Addr += 4;
	}
}

2. Data reading and writing when there is a protocol stack

Using the fstorage method, the function encapsulated here, and the reading and writing method when there is no protocol stack, the reading and writing results are the same, for example, writing {0x01, 0x02, 0x03, 0x04}, the reading and writing results will be {0x01, 0x02 ,0x03,0x04}, because the big and small endian issues are considered

1. Initialization

//头文件,对应的C文件也要添工程中
#include "nrf_fstorage.h"
#include "nrf_fstorage_sd.h"
//Flash读写回调
void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt);
static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt)
{
    
    
	if(p_evt->result != NRF_SUCCESS)
	{
    
    
		//printf("--> Event received: ERROR while executing an fstorage operation.");
		return;
	}

	switch (p_evt->id)
	{
    
    
		case NRF_FSTORAGE_EVT_WRITE_RESULT:
		{
    
    
			//printf("--> Event received: wrote %d bytes at address 0x%x.",p_evt->len, p_evt->addr);
		} break;

		case NRF_FSTORAGE_EVT_ERASE_RESULT:
		{
    
    
			// printf("--> Event received: erased %d page from address 0x%x.",p_evt->len, p_evt->addr);
		} break;

		default:break;
	}
}

//定义可操作的Flash空间
NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage) =
{
    
    
    .evt_handler = fstorage_evt_handler,	//回调
    .start_addr  = Sys_Info_Addr,			//操作的起始地址
    .end_addr    = Sys_Info_Addr+0xFFF, 	//操作的结束地址
};

//协议栈下读写Flash初始化
void ble_fstorage_init()
{
    
    
	ret_code_t err;
	nrf_fstorage_api_t * p_fs_api;
	p_fs_api = &nrf_fstorage_sd;	//处理操作类型设置
	
	err = nrf_fstorage_init(&fstorage, p_fs_api, NULL);//flash处理的开始地址和结束地址初始化
	APP_ERROR_CHECK(err);	
}

//协议栈下读写Flash反初始化
void ble_fstorage_deinit()
{
    
    
	nrf_fstorage_uninit(&fstorage,NULL);
}

2. Data writing

Pay attention to turn off Bluetooth sniffing and broadcasting first

//协议栈下,Flash写入,Addr需要是页地址的开头
void ble_fstorage_write(uint32_t Addr,uint8_t* Data,uint32_t Lenth)
{
    
    
	uint32_t err;

	//先擦除页
	err=nrf_fstorage_erase(&fstorage,Addr,1,NULL);
	APP_ERROR_CHECK(err);
	nrf_delay_ms(10);
	
	//写入数据,按字节
	err = nrf_fstorage_write(&fstorage,Addr,Data,Lenth,NULL);
	APP_ERROR_CHECK(err);
	nrf_delay_ms(10);
}

3. Data readout

//协议栈下数据读出
void ble_fstorage_read(uint32_t Addr,uint8_t* Data,uint32_t Lenth)
{
    
    
	uint32_t err;
	
	err = nrf_fstorage_read(&fstorage,Addr,Data,Lenth);
	APP_ERROR_CHECK(err);
}

4. Actual use

//协议栈初始化
void ble_init()
{
    
    
	/* code begin*/

	ble_fstorage_init();

	/* code end*/
}

	//调用协议栈提供的Flash读写函数前,要先停止广播或嗅探
	ble_scan_stop();
	
	//开启蓝牙协议栈后,要用协议栈提供的Flash读写函数
	ble_fstorage_write(Sys_Info_Addr,(uint8_t *)&Sys_Info,sizeof(Sys_Info));
	
	//读数据
	ble_fstorage_read(Sys_Info_Addr,(uint8_t *)&Sys_Info,sizeof(Sys_Info));

	//恢复嗅探
	ble_scan_start();

3. Summary

1、开启协议栈后,要用协议栈的专用读写函数
2、读写前,关闭嗅探,或广播

Guess you like

Origin blog.csdn.net/qq_36365231/article/details/127276702