bsp_flash.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. //flash 1.0V
  2. /*********************************************************************
  3. * INCLUDES
  4. */
  5. #include "bsp_flash.h"
  6. #include "exception.h"
  7. #include "system.h"
  8. /*********************************************************************
  9. * LOCAL FUNCTIONS DEF
  10. */
  11. static void fstorageCallbackFunc(nrf_fstorage_evt_t *pFstorageEvent);
  12. static uint32_t getflashEndAddress(void);
  13. static void waitForFlashReady(nrf_fstorage_t const *pFstorageHandle);
  14. /*********************************************************************
  15. * LOCAL VARIABLES
  16. */
  17. NRF_FSTORAGE_DEF(nrf_fstorage_t s_fstorageHandle) =
  18. {
  19. /* Set a handler for fstorage events. */
  20. .evt_handler = fstorageCallbackFunc,
  21. /* These below are the boundaries of the flash space assigned to this instance of fstorage.
  22. * You must set these manually, even at runtime, before nrf_fstorage_init() is called.
  23. * The function nrf5_flash_end_addr_get() can be used to retrieve the last address on the
  24. * last page of flash available to write data. */
  25. .start_addr = START_FSTORAGE_ADDR,
  26. .end_addr = END_FSTORAGE_ADDR,
  27. };
  28. /*********************************************************************
  29. * LOCAL FUNCTIONS
  30. */
  31. /**
  32. @brief Fstorage读写内存操作
  33. @param flashAddr -[in] 闪存地址
  34. @param readWriteFlag -[in] 读写操作标志
  35. @param pData -[in&out] 指向需要操作的数据
  36. @param dataLen -[in] 数据长度
  37. @return 错误代码
  38. */
  39. static uint32_t Fstorage_FlashRW(uint32_t flashAddr, uint8_t readWriteFlag, uint32_t *pData, uint32_t dataLen)
  40. {
  41. ret_code_t errCode;
  42. if(flashAddr%4 != 0 || flashAddr == 0)return FLASH_ERROR_ADDRALIGN;
  43. if((flashAddr + dataLen) > END_FSTORAGE_ADDR){
  44. return FLASH_ERROR_ADDROVERBOUNDS; //是否越界
  45. }
  46. if(readWriteFlag == FSTORAGE_READ) // 读取数据
  47. {
  48. errCode = nrf_fstorage_read(&s_fstorageHandle, flashAddr, pData, dataLen);
  49. if(errCode != NRF_SUCCESS)return FLASH_ERROR_READ;
  50. }
  51. else // 写入数据
  52. {
  53. if(dataLen %4 != 0 || dataLen == 0)return FLASH_ERROR_DATAALIGN;
  54. if( FLASH_ZONEADDR_CHECK(flashAddr) )return FLASH_ERROR_ZONEADDR;
  55. errCode = nrf_fstorage_erase(&s_fstorageHandle, flashAddr, 1, NULL); // 只能写入位值1,不能写入位值0,所以先擦后写
  56. if(errCode != NRF_SUCCESS)return FLASH_ERROR_ERASE;
  57. errCode = nrf_fstorage_write(&s_fstorageHandle, flashAddr, pData, dataLen, NULL);
  58. if(errCode != NRF_SUCCESS)return FLASH_ERROR_WRITE;
  59. waitForFlashReady(&s_fstorageHandle); // 等待写完
  60. }
  61. return FLASH_OP_SUCCESS;
  62. }
  63. /**
  64. @brief Fstorage写内存操作,调用前FLASH预先已擦除
  65. @param flashAddr -[in] 闪存地址
  66. @param pData -[in&out] 指向需要操作的数据
  67. @param dataLen -[in] 数据长度
  68. @param is_check - [in] 是否检测数据存不存在
  69. @return 0:写入成功 1:4字节不对齐 2:已有数据存在 3:访问越界
  70. */
  71. static uint32_t Fstorage_FlashOnlyWrite(uint32_t flashAddr, uint32_t *pData, uint32_t dataLen, bool is_check)
  72. {
  73. ret_code_t errCode;
  74. uint32_t check,i,len;
  75. if(flashAddr%4 != 0 || flashAddr == 0)return FLASH_ERROR_ADDRALIGN;
  76. if(dataLen %4 != 0 || dataLen == 0)return FLASH_ERROR_DATAALIGN;
  77. if((flashAddr + dataLen) > END_FSTORAGE_ADDR){
  78. return FLASH_ERROR_ADDROVERBOUNDS;
  79. }
  80. if(is_check)
  81. {
  82. len = dataLen / 4;
  83. for(i=0;i<len;i++)
  84. {
  85. memcpy(&check, (uint32_t*)flashAddr + i, 4);
  86. if(check != 0xFFFFFFFF)return FLASH_ERROR_DATAEXIST;
  87. }
  88. }
  89. errCode = nrf_fstorage_write(&s_fstorageHandle, flashAddr, pData, dataLen, NULL);
  90. if(errCode != NRF_SUCCESS)return FLASH_ERROR_WRITE;
  91. waitForFlashReady(&s_fstorageHandle); // 等待写完
  92. return FLASH_OP_SUCCESS;
  93. }
  94. /**
  95. @brief Fstorage擦除一整页
  96. @param 要擦除的页的首地址
  97. @return 错误代码
  98. */
  99. static uint32_t Fstorage_FlashOnlyErasePage(uint32_t zone_addr)
  100. {
  101. ret_code_t errCode;
  102. if(zone_addr%4 != 0 || zone_addr == 0)return FLASH_ERROR_ADDRALIGN;
  103. if( FLASH_ZONEADDR_CHECK(zone_addr) )return FLASH_ERROR_ZONEADDR;
  104. errCode = nrf_fstorage_erase(&s_fstorageHandle, zone_addr, 1, NULL); // 只能写入位值1,不能写入位值0,所以先擦后写
  105. if(errCode != NRF_SUCCESS)return FLASH_ERROR_ERASE;
  106. waitForFlashReady(&s_fstorageHandle);
  107. return FLASH_OP_SUCCESS;
  108. }
  109. /*********************************************************************
  110. * LOCAL FUNCTIONS
  111. */
  112. /**
  113. @brief Fstorage事件回调函数
  114. @param pFstorageEvent -[in] Fstorage事件
  115. @return 无
  116. */
  117. static void fstorageCallbackFunc(nrf_fstorage_evt_t *pFstorageEvent)
  118. {
  119. if(pFstorageEvent->result != NRF_SUCCESS)
  120. {
  121. DEBUG_LOG("--> Event received: ERROR while executing an fstorage operation.\n");
  122. return ;
  123. }
  124. switch(pFstorageEvent->id)
  125. {
  126. case NRF_FSTORAGE_EVT_WRITE_RESULT:
  127. //DEBUG_LOG("--> Event received: wrote %d bytes at address 0x%x.\n", pFstorageEvent->len, pFstorageEvent->addr);
  128. break;
  129. case NRF_FSTORAGE_EVT_ERASE_RESULT:
  130. //DEBUG_LOG("--> Event received: erased %d page from address 0x%x.\n", pFstorageEvent->len, pFstorageEvent->addr);
  131. break;
  132. default:
  133. break;
  134. }
  135. }
  136. /**
  137. @brief 检索Flash上可用于写入数据的地址
  138. @param 无
  139. @return 无
  140. */
  141. static uint32_t getflashEndAddress(void)
  142. {
  143. uint32_t const bootloaderAddr = NRF_UICR->NRFFW[0];
  144. uint32_t const pageSz = NRF_FICR->CODEPAGESIZE;
  145. uint32_t const codeSz = NRF_FICR->CODESIZE;
  146. return (bootloaderAddr != 0xFFFFFFFF ? bootloaderAddr : (codeSz * pageSz));
  147. }
  148. /**
  149. @brief 等待写入完成
  150. @param pFstorageHandle -[in] Fstorage句柄
  151. @return 无
  152. */
  153. static void waitForFlashReady(nrf_fstorage_t const *pFstorageHandle)
  154. {
  155. while(nrf_fstorage_is_busy(pFstorageHandle)) // While fstorage is busy, sleep and wait for an event.
  156. {
  157. nrf_pwr_mgmt_run();
  158. }
  159. }
  160. /**
  161. @brief 从flash中连续读取N个4字节数据
  162. @param addr-[in] 读取的首地址
  163. @param pData -[in&out] 指向需要操作的数据
  164. @param dataLen -[in] 数据长度
  165. @return 错误代码
  166. */
  167. static uint32_t Read_N_4Byte_flash(uint32_t addr , uint32_t *pData, uint32_t dataLen)
  168. {
  169. return Fstorage_FlashRW(addr, FSTORAGE_READ, pData, dataLen);
  170. }
  171. /**
  172. @brief 获取页号所在的首地址
  173. @param PageNum-[in] 需要查找的页号
  174. @param PageAddr-[in/out] 返回的页号首地址
  175. @return 错误代码
  176. */
  177. static uint32_t GetPageAddr(uint16_t PageNum, uint32_t *PageAddr)
  178. {
  179. if(PageNum >= FLASH_PAGE_NUM)return FLASH_ERROR_PAGENUM;
  180. *PageAddr = FLASH_ZONE_ADDR_1 + PageNum * FLASH_PAGE_SIZE;
  181. return FLASH_OP_SUCCESS;
  182. }
  183. /**
  184. @brief 获取页号所在的尾地址(该页号下一页的首地址)
  185. @param PageNum-[in] 需要查找的页号
  186. @param PageAddr-[in/out] 返回的页号首地址
  187. @return 错误代码
  188. */
  189. static uint32_t GetPageEndAddr(uint16_t PageNum, uint32_t *PageAddr)
  190. {
  191. if(PageNum >= FLASH_PAGE_NUM)return FLASH_ERROR_PAGENUM;
  192. *PageAddr = FLASH_ZONE_ADDR_1 + (PageNum+1) * FLASH_PAGE_SIZE;
  193. return FLASH_OP_SUCCESS;
  194. }
  195. /**
  196. @brief 获取地址距离所在页的偏移量
  197. @param addr-[in] 需要查找的flash地址
  198. @param _offset-[in/out] 返回的偏移量
  199. @return 错误代码
  200. */
  201. static uint32_t GetDistanceFromPage(uint32_t addr, uint32_t *_offset)
  202. {
  203. if(addr %4 != 0 || addr == 0)return FLASH_ERROR_ADDRALIGN;
  204. if(addr > END_FSTORAGE_ADDR || addr < START_FSTORAGE_ADDR){
  205. return FLASH_ERROR_ADDROVERBOUNDS; //是否越界
  206. }
  207. //获取偏移量
  208. *_offset = ((addr - START_FSTORAGE_ADDR)%FLASH_PAGE_SIZE)/4;
  209. return FLASH_OP_SUCCESS;
  210. }
  211. /**
  212. @brief 判断是否需要擦除
  213. @param start_addr-[in] flash首地址
  214. @param len -[in] 长度
  215. @param is_erase-[in/out] 1:需要擦除,0:不需要擦除
  216. @return 错误代码
  217. */
  218. static uint32_t __NeedErase(uint32_t start_addr , uint32_t len , uint8_t *is_erase)
  219. {
  220. uint32_t err_code;
  221. uint32_t i = 0, data;
  222. if((start_addr + len) > END_FSTORAGE_ADDR)return FLASH_ERROR_ADDROVERBOUNDS;
  223. if(start_addr%4 != 0 || start_addr == 0)return FLASH_ERROR_ADDRALIGN;
  224. if(len %4 != 0 || len == 0)return FLASH_ERROR_DATAALIGN;
  225. len /=4;
  226. for(;i<len;i++)
  227. {
  228. err_code = Fstorage_FlashRW(start_addr, FSTORAGE_READ, &data, 4);
  229. if(err_code != FLASH_OP_SUCCESS)return err_code;
  230. if(data != 0xFFFFFFFF)break;
  231. start_addr += 4;
  232. }
  233. *is_erase = (i==len)?0:1;
  234. return FLASH_OP_SUCCESS;
  235. }
  236. static void bsp_flash_init_process(void)
  237. {
  238. if(Except_TxError(EXCEPT_FLASH_INIT,"bsp_flash_init_error\r\n") == 0)
  239. {
  240. Process_Stop(bsp_flash_init_process);
  241. }
  242. }
  243. /****************************************************接口****************************************************/
  244. /**
  245. @brief Fstorage读写内存初始化
  246. @param 无
  247. @return 无
  248. */
  249. void Fstorage_FlashInit(void)
  250. {
  251. int ret = 0;
  252. ret_code_t errCode;
  253. nrf_fstorage_api_t *pFstorageApi;
  254. pFstorageApi = &nrf_fstorage_sd;
  255. errCode = nrf_fstorage_init(&s_fstorageHandle, pFstorageApi, NULL); // Flash处理的开始地址和结束地址初始化
  256. if(errCode != NRF_SUCCESS)ret = -1;
  257. (void)getflashEndAddress(); // 获取地址,判断为可写地址大小
  258. if(ret == -1)
  259. {
  260. Process_Start(0,"bsp_flash_init_process",bsp_flash_init_process);
  261. }
  262. }
  263. /**
  264. @brief 从flash中连续读取N个字节数据
  265. @param addr-[in] 读取的首地址
  266. @param pData -[in&out] 指向需要操作的数据
  267. @param dataLen -[in] 数据长度
  268. @return 错误代码
  269. */
  270. uint32_t Read_N_Byte_flash(uint32_t addr , uint32_t *pData, uint32_t dataLen)
  271. {
  272. if(addr > END_FSTORAGE_ADDR || addr < START_FSTORAGE_ADDR){
  273. return FLASH_ERROR_ADDROVERBOUNDS; //是否越界
  274. }
  275. memcpy(pData, (uint32_t*)addr, dataLen);
  276. return FLASH_OP_SUCCESS;
  277. }
  278. /**
  279. @brief 获取flash地址所在的页号
  280. @param addr-[in] 需要查找的flash地址
  281. @param page_num-[in/out] 返回的页号
  282. @return 错误代码
  283. */
  284. uint32_t GetPageNum(uint32_t addr, uint16_t *PageNum)
  285. {
  286. uint16_t page_num = 0;
  287. if(addr > END_FSTORAGE_ADDR || addr < START_FSTORAGE_ADDR){
  288. return FLASH_ERROR_ADDROVERBOUNDS; //是否越界
  289. }
  290. // if(addr %4 != 0 || addr == 0)return FLASH_ERROR_ADDRALIGN;
  291. page_num = (addr - START_FSTORAGE_ADDR)/FLASH_PAGE_SIZE;
  292. if(page_num >= FLASH_PAGE_NUM)return FLASH_ERROR_PAGENUM;
  293. *PageNum = page_num;
  294. return FLASH_OP_SUCCESS;
  295. }
  296. /**
  297. @brief 擦除1页
  298. @param PageNum-[in] 页号
  299. @return 错误代码
  300. */
  301. uint32_t Erase_OnePage(uint16_t PageNum)
  302. {
  303. uint32_t PageAddr;
  304. uint32_t err_code;
  305. err_code = GetPageAddr(PageNum, &PageAddr);
  306. if(err_code != FLASH_OP_SUCCESS)return err_code;
  307. return Fstorage_FlashOnlyErasePage(PageAddr);
  308. }
  309. /**
  310. @brief 写N个字到flash中
  311. @param addr-[in] 写入的flash首地址
  312. @param pdata-[in] 需要写入的数据
  313. @param len-[in] 数据长度
  314. @return 错误代码
  315. */
  316. uint32_t Write_N_4Byte_flash(uint32_t addr , uint32_t *pdata, uint32_t len)
  317. {
  318. uint8_t is_erase; //判断是否要擦除
  319. uint16_t start_page = 0; //起始页号
  320. uint32_t page_size = 0; //需要操作页的大小
  321. uint32_t _offset = 0; //页操作页码的起始地址
  322. uint32_t page_offset = 0; //页偏移
  323. uint32_t data_offset = 0; //数据偏移
  324. uint32_t remain_size = 0; //本次操作页可以使用的剩余大小
  325. uint32_t base_addr = 0; //本次操作页的基地址
  326. uint32_t surplus = 0; //总的剩余的字节
  327. uint32_t err_code; //错误代码
  328. uint32_t flash_PageBuff[PAGE_INT_SIZE]; //页缓冲区
  329. //是否越界
  330. if((addr + len) > END_FSTORAGE_ADDR){
  331. return FLASH_ERROR_ADDROVERBOUNDS;
  332. }
  333. //获取起始页号
  334. err_code = GetPageNum(addr, &start_page);
  335. if(err_code != FLASH_OP_SUCCESS)return err_code;
  336. //获取偏移量
  337. err_code = GetDistanceFromPage(addr,&_offset);
  338. if(err_code != FLASH_OP_SUCCESS)return err_code;
  339. //计算需要写入的页数
  340. if(((PAGE_INT_SIZE - _offset)*4) >= len)
  341. {
  342. page_size = 1;
  343. surplus = 0;
  344. }
  345. else
  346. {
  347. page_size = 1;
  348. surplus = len - ((PAGE_INT_SIZE - _offset)*4);
  349. page_size += ((surplus/FLASH_PAGE_SIZE) + (surplus%FLASH_PAGE_SIZE>0?1:0));
  350. }
  351. //每页写入
  352. surplus = len;
  353. for(page_offset = 0; page_offset < page_size; page_offset++)
  354. {
  355. //获取页首地址
  356. err_code = GetPageAddr(start_page + page_offset, &base_addr);
  357. if(err_code != FLASH_OP_SUCCESS)return err_code;
  358. if(page_offset == 0)
  359. {
  360. //第一次偏移根据目的地址来确定
  361. remain_size = (PAGE_INT_SIZE - _offset)*4<surplus ? (PAGE_INT_SIZE - _offset)*4:surplus;
  362. surplus = len - remain_size;
  363. }
  364. else
  365. {
  366. //后面操作的偏移都是从首地址开始
  367. _offset = 0;
  368. remain_size = surplus > FLASH_PAGE_SIZE ? FLASH_PAGE_SIZE : surplus;
  369. surplus = surplus - remain_size;
  370. }
  371. //判断是否要擦除
  372. err_code = __NeedErase(base_addr + _offset*4 , remain_size, &is_erase);
  373. if(err_code != FLASH_OP_SUCCESS)return err_code;
  374. //先擦除后写
  375. if(is_erase)
  376. {
  377. //读取
  378. err_code = Read_N_4Byte_flash(base_addr , flash_PageBuff, FLASH_PAGE_SIZE);
  379. if(err_code != FLASH_OP_SUCCESS)return err_code;
  380. //修改
  381. memcpy(&flash_PageBuff[_offset], pdata + data_offset, remain_size);
  382. //写回
  383. err_code = Fstorage_FlashRW(base_addr, FSTORAGE_WRITE, flash_PageBuff, FLASH_PAGE_SIZE);
  384. if(err_code != FLASH_OP_SUCCESS)return err_code;
  385. }
  386. else
  387. {
  388. //不需要擦除,直接写
  389. err_code = Fstorage_FlashOnlyWrite(base_addr + _offset*4, pdata + data_offset, remain_size, false); //直接写
  390. if(err_code != FLASH_OP_SUCCESS)return err_code;
  391. }
  392. data_offset += remain_size/4; //除以4是因为pData指针+1是移动4个字节
  393. }
  394. return FLASH_OP_SUCCESS;
  395. }
  396. /**
  397. @brief 只写N个字到flash中,调用前FLASH预先已擦除
  398. @param addr-[in] 写入的flash首地址
  399. @param pdata-[in] 需要写入的数据
  400. @param len-[in] 数据长度
  401. @return 错误代码
  402. */
  403. uint32_t Only_Write_N_4Byte_flash(uint32_t addr , uint32_t *pdata, uint32_t len, bool is_check)
  404. {
  405. return Fstorage_FlashOnlyWrite(addr, pdata, len, is_check);
  406. }
  407. /**
  408. @brief 查找一页中可写的空间(0xFF)
  409. @param PageNum-[in] 输入的页号
  410. @param start_addr-[in/out] 返回的空闲空间的起始地址
  411. @param len-[in/out] 返回的空间的长度
  412. @return 错误代码
  413. */
  414. uint32_t Find_FreeSpace_In_Page(uint16_t PageNum, uint32_t *start_addr, uint32_t *len)
  415. {
  416. uint32_t PageEndAddr, RetrieveAddr, i;
  417. uint32_t flash_data;
  418. if(PageNum >= FLASH_PAGE_NUM)return FLASH_ERROR_PAGENUM;
  419. //获取该页的结尾地址
  420. GetPageEndAddr(PageNum, &PageEndAddr);
  421. //从页尾开始检索空闲空间
  422. RetrieveAddr = PageEndAddr;
  423. for(i = 0;i<PAGE_INT_SIZE;i++)
  424. {
  425. RetrieveAddr -= 4;
  426. Read_N_4Byte_flash(RetrieveAddr , &flash_data, 4);
  427. if(flash_data != 0xFFFFFFFF)break;
  428. }
  429. *start_addr = PageEndAddr - i *4;
  430. *len = i*4;
  431. return FLASH_OP_SUCCESS;
  432. }
  433. /****************************************************END OF FILE****************************************************/