资源和软件环境:
1. softdevice 7.1.0
2. SDK 6.0.0
一、 写flash
在启动SOFTDEVICE 后,使用uint32_t sd_flash_write(uint32_t * const p_dst, uint32_t const * const p_src, uint32_t size) 进行flash的写操作,当然在该区域如果已经有数据存在,需要把该页的其他数据拷贝出来,然后使用uint32_t sd_flash_page_erase(uint32_t page_number)擦除该页,再进行写操作。
该例子,该页只有这个数据,所以写前没有拷贝其他数据出来。
void start_dfu_event_process(void)
{
uint32_t retval;
uint8_t flag[8] = “sdfustr”;
uint32_t sdfu_flag_addr_page = SDFU_FLAG_ADDR_PAGE;
uint32_t sdfu_flag_addr = SDFU_FLAG_ADDR_PAGE*FLASH_PAGE_SIZE;
uint8_t * p_data_addr = (uint8_t *)flag;
retval = sd_flash_page_erase(sdfu_flag_addr_page);
if(retval == NRF_SUCCESS)
{
retval = sd_flash_write(((uint32_t *)sdfu_flag_addr),
(uint32_t *)p_data_addr,
CEIL_DIV(7,sizeof(uint32_t)));
}
}
二、读flash
读flash使用直接地址访问的方式读取。
uint32_t ble_ccs_data_load(curtain_control_t *ccs_data)
{
uint32_t ccs_data_addr;
uint8_t * p_data_addr = (uint8_t*)ccs_data;
ccs_data_addr = FLASH_LAST_PAGE*FLASH_PAGE_SIZE;
memcpy((uint32_t *)p_data_addr,(uint32_t *)ccs_data_addr,
sizeof(curtain_control_t));
return NRF_SUCCESS;
}
还可以这样读取
uint8_t flag[4];
uint32_t sdfu_flag_addr = SDFU_FLAG_ADDR_PAGE*FLASH_PAGE_SIZE;
// Get the flag of sdfu from the flash
flag[0] = *(uint8_t *)(sdfu_flag_addr+0);
flag[1] = *(uint8_t *)(sdfu_flag_addr+1);
flag[2] = *(uint8_t *)(sdfu_flag_addr+2);
flag[3] = *(uint8_t *)(sdfu_flag_addr+3);
但是在刚连接的时候,如果写Flash,会出现失败。
通过测试发现,在系统收到BLE_GAP_EVT_CONNECTED(0x10)和BLE_GAP_EVT_CONN_PARAM_UPDATE(0x12)事件之间写Flash,就会出现失败(sd_flash_write 返回NRF_ERROR_INVALID_DATA(0x11)),具体原因不是很清楚,应该是在这个时间段里,Flash被写保护了。
缩短BLE_GAP_EVT_CONNECTED(0x10)和BLE_GAP_EVT_CONN_PARAM_UPDATE(0x12)事件之间时间,可以通过修改FIRST_CONN_PARAMS_UPDATE_DELAY 目前我修改到0.2 秒