nrf52832 SDK 15.3.0 Flash 操作
debug中遇到的问题:
1,写入数据,读出来不对
2,看之前被人写的代码发现,读flash直接用的标准C库函数:memcpy,但是,写用的专门的flash写接口。所以,我这里两个疑问:
A,写flash的时候,为什么没有用memcpy,可不可以用?
B,用const 修饰的全局变量是存储在ROM空间的(也就是内置flash上),没有用const修饰的全局变量 和 局部变量是存储在RAM空间上的。
比如 有个全局const 变量 A,全局变量 B,那么,memcpy(B,A)为什么就能正确执行,他们两个都在不同的地址空间中?
flash相关的知识点:
1,从datasheet中 Memroy章节 图:Memory Layout(如下) 中可以看到,Flash分为很多page,每个page又分为8个block。每个page的大小为4KBytes。

代码实现:
#include "stdint.h" #define FLASH_PAGE_SIZE 4096
#define FLASH_BASE_ADDRESS 0x6D000
#define FLASH_SIZE ( FLASH_PAGE_SIZE<<1) enum {
WSYS_FLASH_OK = ,
WSYS_FLASH_INVALID_ADDRESS,
WSYS_FLASH_INVALID_LENGTH
}; /*******************************************************************
* Function Nume: flash_read_data
* Descriptions : read data from flash
* In Para : address: address to access(address must be word-aligned), length: length to be read(4 integer multiple)
* In-Out Para : none
* Out Para : data: data buffer to be read
* Return Value : FLASH_SUCCESS: success, FLASH_ERROR_INVALID_ADDRESS: address error
*******************************************************************/
uint8_t flash_write_data(uint32_t address, uint8_t *data, uint16_t length); /*******************************************************************
* Function Nume: flash_read_data
* Descriptions : read data from flash
* In Para : address: address to access(align=2), length: length to be read(4 integer multiple)
* In-Out Para : none
* Out Para : data: data buffer to be read
* Return Value : FLASH_SUCCESS: success, FLASH_ERROR_INVALID_ADDRESS: address error
*******************************************************************/
uint8_t flash_read_data(uint32_t address, uint32_t *data, uint16_t length); /*******************************************************************
* Function Nume: flash_erase_data
* Descriptions : erase flash data
* In Para : address: address to access(align=2), length: length to be erased(4 integer multiple)
* In-Out Para : none
* Out Para : none
* Return Value : FLASH_SUCCESS: success, FLASH_ERROR_INVALID_ADDRESS: address error
*******************************************************************/
uint8_t flash_erase_data(uint32_t address, uint16_t length);
static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt);
static uint32_t sg_flash_buffer[FLASH_PAGE_SIZE/] = {};
NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage) =
{
/* Set a handler for fstorage events. */
.evt_handler = fstorage_evt_handler,
/* These below are the boundaries of the flash space assigned to this instance of fstorage.
* You must set these manually, even at runtime, before nrf_fstorage_init() is called.
* The function nrf5_flash_end_addr_get() can be used to retrieve the last address on the
* last page of flash available to write data. */
.start_addr = FLASH_BASE_ADDRESS,
.end_addr = (FLASH_BASE_ADDRESS + FLASH_SIZE),
};
static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt)
{
if (p_evt->result != NRF_SUCCESS)
{
WLOG_I("--> Event received: ERROR while executing an fstorage operation.\r\n");
return;
}
switch (p_evt->id)
{
case NRF_FSTORAGE_EVT_WRITE_RESULT:
{
WLOG_I("--> Event received: write %d bytes at address 0x%x.\r\n",
p_evt->len, p_evt->addr);
} break;
case NRF_FSTORAGE_EVT_ERASE_RESULT:
{
WLOG_I("--> Event received: erased %d page from address 0x%x.\r\n",
p_evt->len, p_evt->addr);
} break;
default:
break;
}
}
static void wait_for_flash_ready(void)
{
/* While fstorage is busy, sleep and wait for an event. */
while (nrf_fstorage_is_busy(&fstorage))
{
;
}
}
static void flash_read(uint32_t dest_addr, uint32_t src_addr, uint16_t length)
{
memcpy((uint32_t*)dest_addr, (uint32_t*)src_addr, length);
//nrf_fstorage_read(&fstorage, (uint32_t)src, (void *)dest, (length / 4));
}
/*******************************************************************
* Function Nume: flash_write_check
* Descriptions : it is need write or not
* In Para : m_flash_handle: pointer of the pstorage, data: data to be writed, length: length of the data, offset: offset in flash
* In-Out Para : none
* Out Para : none
* Return Value : 1: need write, 0: do not need write
*******************************************************************/
static uint8_t flash_write_check(uint32_t address, const uint8_t *data, uint16_t length)
{
uint32_t data_read = ;
const uint32_t *p_src_data = (const uint32_t *)data;
length = length / ;
for (uint16_t i=; i<length; i++)
{
flash_read((uint32_t)&data_read, address + i* , );
//if (memcmp(&data_read, &p_src_data[i], 4) != 0)
if (data_read != p_src_data[i])
{
return ;
}
}
WLOG_I("flash_write_check no need write\r\n");
return ;
}
/*******************************************************************
* Function Nume: flash_erase_check
* Descriptions : it is need erase or not
* In Para : m_flash_handle: pointer of the pstorage, length: length of the data, offset: offset in flash
* In-Out Para : none
* Out Para : none
* Return Value : 1: need erase, 0: do not need erase
*******************************************************************/
static uint8_t flash_erase_check(uint32_t dest_addr, uint16_t length)
{
uint32_t data_read = ;
uint32_t data_default = 0xFFFFFFFF;
length = length / ;
for (uint16_t i=; i<length; i++)
{
flash_read((uint32_t)&data_read, dest_addr + i* , );
//if (memcmp(&data_read, &data_default, 4) != 0)
if (data_default != data_read)
{
return ;
}
}
WLOG_I("flash_erase_check no need erse\r\n");
return ;
}
static void flash_erase_one_page(uint32_t dest_addr, uint16_t length)
{
uint32_t result = ;
uint16_t offset = ;
uint16_t remain = ;
uint32_t page_start = dest_addr / FLASH_PAGE_SIZE * FLASH_PAGE_SIZE;
memcpy(sg_flash_buffer, (uint32_t *)page_start, FLASH_PAGE_SIZE);
if(!= flash_erase_check(dest_addr, dest_addr))
{
return;
}
result = nrf_fstorage_erase(&fstorage, page_start, , NULL);
wait_for_flash_ready();
WLOG_I("FE==%d\r\n",result);
offset = dest_addr - page_start;
//Write back the data not need and can not be erased
if (offset != )
{
nrf_fstorage_write(&fstorage, page_start, sg_flash_buffer, offset, NULL);
wait_for_flash_ready();
}
//Write back the data not need and can not be erased
remain = FLASH_PAGE_SIZE - offset - length;
if (remain != )
{
nrf_fstorage_write(&fstorage, (dest_addr + length), (uint32_t *)&sg_flash_buffer[(offset+length)/], remain, NULL);
wait_for_flash_ready();
}
}
static void flash_write(uint32_t address, uint8_t *src, uint16_t length)
{
uint32_t result = ;
if( != flash_write_check(address, src, length))
{
return;
}
flash_erase_one_page(address, length);
result = nrf_fstorage_write(&fstorage, address, (void const *)src,length/*, NULL);
wait_for_flash_ready();
WLOG_I("FW==%d,length==%d\r\n",result,length);
}
static uint8_t valid_check(uint32_t address, uint16_t length)
{
if(address< FLASH_BASE_ADDRESS)
{
WLOG_E("flash_write_data invalid flash address\r\n");
return WSYS_FLASH_INVALID_ADDRESS;
}
if((address - FLASH_BASE_ADDRESS + length) > FLASH_SIZE)
{
WLOG_E("flash_write_data invalid length\r\n");
return WSYS_FLASH_INVALID_LENGTH;
}
return WSYS_FLASH_OK;
}
/*******************************************************************
* Function Nume: flash_read_data
* Descriptions : read data from flash
* In Para : address: address to access(address must be word-aligned), length: length to be read(4 integer multiple)
* In-Out Para : none
* Out Para : data: data buffer to be read
* Return Value : FLASH_SUCCESS: success, FLASH_ERROR_INVALID_ADDRESS: address error
*******************************************************************/
uint8_t flash_write_data(uint32_t address, uint8_t *data, uint16_t length)
{
uint16_t length_temp = ;
uint16_t offset = address - FLASH_BASE_ADDRESS;
uint8_t result = ;
result = valid_check(address,length);
if(WSYS_FLASH_OK != result)
return result;
if ((offset + length) <= FLASH_PAGE_SIZE)//single page
{
flash_write(address, data, length);
}else { //Multiple page
length_temp = FLASH_PAGE_SIZE - offset;
flash_write(address, data, length_temp);
address += length_temp;
data += length_temp;
length_temp = length - length_temp;
flash_write(address, data, length_temp);
}
return WSYS_FLASH_OK;
}
/*******************************************************************
* Function Nume: flash_erase_data
* Descriptions : erase flash data
* In Para : address: address to access(align=2), length: length to be erased(4 integer multiple)
* In-Out Para : none
* Out Para : none
* Return Value : FLASH_SUCCESS: success, FLASH_ERROR_INVALID_ADDRESS: address error
*******************************************************************/
uint8_t flash_erase_data(uint32_t address, uint16_t length)
{
uint16_t length_temp = ;
uint16_t offset = address - FLASH_BASE_ADDRESS;
uint8_t result = ;
result = valid_check(address,length);
if(WSYS_FLASH_OK != result)
return result;
if ((offset + length) <= FLASH_PAGE_SIZE)//single page
{
flash_erase_one_page(address, length);
}else { //Multiple page
length_temp = FLASH_PAGE_SIZE - offset;
flash_erase_one_page(address, length_temp);
address += length_temp;
length_temp = length - length_temp;
while(length_temp > FLASH_PAGE_SIZE)
{
flash_erase_one_page(address, FLASH_PAGE_SIZE);
length_temp -= FLASH_PAGE_SIZE;
address += FLASH_PAGE_SIZE;
}
if(length_temp > )
{
flash_erase_one_page(address, length_temp);
}
}
return WSYS_FLASH_OK;
}
/*******************************************************************
* Function Nume: flash_read_data
* Descriptions : read data from flash
* In Para : address: address to access(align=2), length: length to be read(4 integer multiple)
* In-Out Para : none
* Out Para : data: data buffer to be read
* Return Value : FLASH_SUCCESS: success, FLASH_ERROR_INVALID_ADDRESS: address error
*******************************************************************/
uint8_t flash_read_data(uint32_t address, uint32_t *data, uint16_t length)
{
flash_read((uint32_t)data, address, length);
return WSYS_FLASH_OK;
}
#if 1
#define add_len 4
void flash_test(void)
{
WLOG_I("flash_test\r\n");
//uint8_t *data_write = {"123456789ABCDEF0"};
uint8_t *data_write = {"123456789ABCDEF03333"};
#if 1
flash_write_data(FLASH_BASE_ADDRESS, data_write, +add_len);
nrf_delay_ms();
#endif
uint8_t data_read[+add_len] = {};
flash_read_data(FLASH_BASE_ADDRESS, (uint32_t*)data_read, +add_len);
WLOG_I("FR: %s\r\n", data_read);
//flash_erase_data(FLASH_BASE_ADDRESS,16+add_len);
//flash_read_data(FLASH_BASE_ADDRESS, (uint32_t*)data_read, 16+add_len);
//WLOG_I("FR_EEEE: %s\r\n", data_read);
}
#endif
/*******************************************************************
* Function Nume: flash_init
* Descriptions : init internal flash
* In Para : none
* In-Out Para : none
* Out Para : none
* Return Value : state
*******************************************************************/
Status_Type flash_init(void)
{
nrf_fstorage_api_t * p_fs_api;
p_fs_api = &nrf_fstorage_sd;
nrf_fstorage_init(&fstorage,p_fs_api,NULL);
return STATUS_SUCCESS;
}
const struct file_operations flash_fops =
{
.module = FLASH_MODULE,
.init = flash_init,
};
sdk_config.h 中需要修改:#define NRF_FSTORAGE_ENABLED 1
问题解答:
问题2A:
Flash有一些特性,1,对flash的读操作是没有次数限制的,但是,对flash的擦除和写操作是有次数限制的,这个和具体的芯片相关。如下是原文:
The Flash can be read an unlimited number of times by the CPU, but it has restrictions on the number of
times it can be written and erased and also on how it can be written.
2,写入的时候只能写入32bit字长的数据到字对齐的flash地址上,而且,flash的每个bit位上只能写入0,不能写1。要写入1的话,只能通过擦除的方式,原文如下:
The NVMC is only able to write '0' to bits in the Flash that are erased, that is, set to '1'. It cannot write back a
bit to '1'.
3,flash擦除的时候 只能一个page一个page的擦除
nrf52832 SDK 15.3.0 Flash 操作的更多相关文章
- u-boot移植总结(三)(转)S3C2440对Nand Flash操作和电路原理(基于K9F2G08U0A)
S3C2440对Nand Flash操作和电路原理(基于K9F2G08U0A) 转载自:http://www.cnblogs.com/idle_man/archive/2010/12/23/19153 ...
- Eclipse中通过Android模拟器调用OpenGL ES2.0函数操作步骤
原文地址: Eclipse中通过Android模拟器调用OpenGL ES2.0函数操作步骤 - 网络资源是无限的 - 博客频道 - CSDN.NET http://blog.csdn.net/fen ...
- ThinkPHP5.0框架开发--第7章 TP5.0数据库操作
ThinkPHP5.0框架开发--第7章 TP5.0数据库操作 第7章 TP5.0数据库操作 ===================================================== ...
- License for package Android SDK Build-Tools 28.0.3 not accepted
License for package Android SDK Build-Tools 28.0.3 not accepted 用flutter进行编写时出现了标题的错误,不是配置的原因,而是需要接受 ...
- eclipse一直卡住,出现 “android sdk content loader 0%” 卡住的错误分析及解决方法
分析:这种问题之前没有遇到过,也不知道什么原因,直接去网上查询,打开www.stackoverflow.com,输入要查询问题的关键词,我们输入 “android sdk content loader ...
- Android sdk content loader 0%的解决方案
Eclipse在启动时,经常会碰到半天启动不起来的情况,罪魁祸首就是“Android sdk content loader 0%”,题主经常是受这玩意的百般折磨,大早上一来就被这扫了工作的激情,浪费了 ...
- Process 'command '/Users/lidaqiang/Library/Android/sdk/build-tools/27.0.3/aapt'' finished with non-zero exit value 1
Process 'command '/Users/lidaqiang/Library/Android/sdk/build-tools/27.0.3/aapt'' finished with non-z ...
- Android sdk content loader 0%
打开Eclipse以后,一直在Android sdk content loader 0%,等了很长时间都没有变,解决的方法是Project->Clean->Clean all projec ...
- npm WARN react-native-maps@0.14.0 requires a peer of react@>=15.4.0 but none was installed
install the react-native here comes a questions :: npm WARN react-native@0.41.2 requires a pe ...
随机推荐
- [转]IIS应用程序池经典模式转集成模式解决方案
经典模式和集成模式的区别: IIS7.0中的Web应用程序有两种配置形式:经典形式和集成形式. 经典形式是为了与之前的版本兼容,运用ISAPI扩展来调用ASP.NET运转库,原先运转于IIS6.0下的 ...
- 365. Water and Jug Problem量杯灌水问题
[抄题]: 简而言之:只能对 杯子中全部的水/容量-杯子中全部的水进行操作 You are given two jugs with capacities x and y litres. There i ...
- Math的方法;Date的方法;
Math的方法: (1)弧度的π Math.PI() (2)返回平方根 Math.sqrt() (3)返回x的绝对值 Mathabs(x) (4)返回x的上舍入 Math.ceil(x) (5)返回 ...
- 设置angular公共样式表
一.现象 新创建的项目,是直接显示在src目录下的,假如会用到其它第三方的全局样式时,不能统一放在一个地方统一来管理,就会感觉有点乱. 二.解决 1.移动样式表. 在assets文件夹(该文件夹一般都 ...
- Web常见安全漏洞-SQL注入
SQL注入攻击(SQL Injection),简称注入攻击,是Web开发中最常见的一种安全漏洞. 可以用它来从数据库获取敏感信息,或者利用数据库的特性执行添加用户,导出文件等一系列恶意操作, 甚至有可 ...
- 提交操作自动遮蔽实现之ajax
有时候,我们期望一些提交操作自动增加遮蔽效果,提交成功时自动去除遮蔽. 方案: 1. 提交前增加遮蔽逻辑,成功后增加去除遮蔽逻辑,但是不够智能 2.通过ajax拦截,实现自动添加\去除遮蔽效果 aja ...
- 【转】《深入理解C# 3.x的新特性》博文系列汇总
[转]<深入理解C# 3.x的新特性>博文系列汇总 较之C# 2.0, C# 3.x引入了一系列新的特性,为我们编程带来很大的便利,通过有效地利用这些新特性,我们可以编写出更加简洁.优雅的 ...
- C#语言不常用语法笔记
只看过3天C#语法书,了解个大概,与C++等不同之处,或者看开源遇到一些奇异用法,记录一下,脑子不够用的情况下,还是记笔记靠谱. ==================== 顺便吐槽下,这年头得会各种编 ...
- C++ MFC棋牌类小游戏day4
根据昨天的计划,今天开始做下面的内容. 1.鼠标点击事件 2.点击坐标进行处理.(坐标转换) 3.判断选中的位置是否有效. 4.确定选中的棋子,设置棋子的状态和棋子所在坐标的状态. 5.判断移动是否有 ...
- 08-jQuery的位置信息
Query的位置信息跟JS的client系列.offset系列.scroll系列封装好的一些简便api. 一.宽度和高度 获取宽度 .width() 描述:为匹配的元素集合中获取第一个元素的当前计算宽 ...