core_flash.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. /*
  2. * Copyright (c) 2022 OpenLuat & AirM2M
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. * this software and associated documentation files (the "Software"), to deal in
  6. * the Software without restriction, including without limitation the rights to
  7. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  8. * the Software, and to permit persons to whom the Software is furnished to do so,
  9. * subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in all
  12. * copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  16. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  17. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  18. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. */
  21. #include "bl_inc.h"
  22. void __FUNC_IN_RAM__ CACHE_CleanAll(CACHE_TypeDef *Cache)
  23. {
  24. while (Cache->CACHE_CS & CACHE_IS_BUSY);
  25. Cache->CACHE_REF = CACHE_REFRESH_ALLTAG;
  26. Cache->CACHE_REF |= CACHE_REFRESH;
  27. while ((Cache->CACHE_REF & CACHE_REFRESH));
  28. }
  29. #if 0 //没什么用,没有ROM里的API好用
  30. typedef struct
  31. {
  32. uint8_t Instruction;
  33. QSPI_BusModeTypeDef BusMode;
  34. QSPI_CmdFormatTypeDef CmdFormat;
  35. uint32_t Address;
  36. uint32_t WrData;
  37. uint32_t RdData;
  38. }FLASH_CommandTypeDef;
  39. #define QSPI_FIFO_NUM 32
  40. #define __FLASH_DISABLE_IRQ__
  41. #define FLASH_QSPI_TIMEOUT_DEFAULT_CNT (19000) //18944
  42. #define FLASH_QSPI_ACCESS_REQ_ENABLE (0x00000001U)
  43. #define FLASH_QSPI_FLASH_READY_ENABLE (0x0000006BU)
  44. static int32_t __FUNC_IN_RAM__ prvQSPI_Command(FLASH_CommandTypeDef *cmd, int32_t timeout)
  45. {
  46. int32_t i;
  47. int32_t status = -ERROR_OPERATION_FAILED;
  48. QSPI->REG_WDATA = cmd->WrData;
  49. QSPI->ADDRES = (QSPI->ADDRES & ~QUADSPI_ADDRESS_ADR) | (cmd->Address << 8);
  50. QSPI->FCU_CMD = (QSPI->FCU_CMD & ~(QUADSPI_FCU_CMD_CODE | QUADSPI_FCU_CMD_BUS_MODE | QUADSPI_FCU_CMD_CMD_FORMAT | QUADSPI_FCU_CMD_ACCESS_REQ)) | ((cmd->Instruction << 24) |((uint32_t)( cmd->BusMode<< 8)) |((uint32_t)( cmd->CmdFormat << 4))| (FLASH_QSPI_ACCESS_REQ_ENABLE));
  51. //Wait For CMD done
  52. for (i = 0; i < timeout; i += 4)
  53. {
  54. if (QSPI->INT_RAWSTATUS & QUADSPI_INT_RAWSTATUS_DONE_IR)
  55. {
  56. QSPI->INT_CLEAR = QUADSPI_INT_CLEAR_DONE;
  57. status = ERROR_NONE;
  58. break;
  59. }
  60. }
  61. cmd->RdData = QSPI->REG_RDATA;
  62. return status;
  63. }
  64. static int32_t __FUNC_IN_RAM__ prvQSPI_WriteEnable(QSPI_BusModeTypeDef bus_mode)
  65. {
  66. FLASH_CommandTypeDef sCommand;
  67. sCommand.Instruction = SPIFLASH_CMD_WREN;
  68. sCommand.CmdFormat = QSPI_CMDFORMAT_CMD8;
  69. if (QSPI_BUSMODE_444 == bus_mode)
  70. {
  71. sCommand.BusMode = QSPI_BUSMODE_444;
  72. }
  73. else
  74. {
  75. sCommand.BusMode = QSPI_BUSMODE_111;
  76. }
  77. if (prvQSPI_Command(&sCommand, FLASH_QSPI_TIMEOUT_DEFAULT_CNT))
  78. {
  79. return -ERROR_OPERATION_FAILED;
  80. }
  81. return ERROR_NONE;
  82. }
  83. //PP,QPP,Sector Erase,Block Erase, Chip Erase, Write Status Reg, Erase Security Reg
  84. static int32_t __FUNC_IN_RAM__ prvQSPI_IsBusy(QSPI_BusModeTypeDef bus_mode)
  85. {
  86. FLASH_CommandTypeDef sCommand;
  87. sCommand.Instruction = SPIFLASH_CMD_RDSR;
  88. sCommand.CmdFormat = QSPI_CMDFORMAT_CMD8_RREG8;
  89. if (QSPI_BUSMODE_444 == bus_mode)
  90. {
  91. sCommand.BusMode = QSPI_BUSMODE_444;
  92. }
  93. else
  94. {
  95. sCommand.BusMode = QSPI_BUSMODE_111;
  96. }
  97. if (prvQSPI_Command(&sCommand, FLASH_QSPI_TIMEOUT_DEFAULT_CNT))
  98. {
  99. return -ERROR_OPERATION_FAILED;
  100. }
  101. if (sCommand.RdData & BIT0)
  102. {
  103. return -ERROR_DEVICE_BUSY;
  104. }
  105. return ERROR_NONE;
  106. }
  107. int32_t __FUNC_IN_RAM__ Flash_Erase(uint32_t Address, uint32_t Length)
  108. {
  109. FLASH_CommandTypeDef sCommand;
  110. uint32_t TotalLen = 0;
  111. uint32_t FlashAddress, DummyLen;
  112. Address &= (uint32_t)(0x00FFFFFF);
  113. while (CACHE->CACHE_CS & CACHE_IS_BUSY);
  114. sCommand.BusMode = QSPI_BUSMODE_111;
  115. sCommand.CmdFormat = QSPI_CMDFORMAT_CMD8_ADDR24;
  116. while (TotalLen < Length)
  117. {
  118. if (prvQSPI_WriteEnable(sCommand.BusMode) != 0)
  119. {
  120. return -ERROR_OPERATION_FAILED;
  121. }
  122. FlashAddress = Address + TotalLen;
  123. DummyLen = Length - TotalLen;
  124. if (!(FlashAddress & SPI_FLASH_BLOCK_MASK) && (DummyLen >= SPI_FLASH_BLOCK_SIZE))
  125. {
  126. sCommand.Instruction = SPIFLASH_CMD_BE;
  127. TotalLen += SPI_FLASH_BLOCK_SIZE;
  128. }
  129. else
  130. {
  131. sCommand.Instruction = SPIFLASH_CMD_SE;
  132. TotalLen += SPI_FLASH_SECTOR_SIZE;
  133. }
  134. sCommand.Address = FlashAddress;
  135. #if (defined __FLASH_DISABLE_IRQ__)
  136. __disable_irq();
  137. #endif
  138. if (prvQSPI_Command(&sCommand, FLASH_QSPI_TIMEOUT_DEFAULT_CNT))
  139. {
  140. #if (defined __FLASH_DISABLE_IRQ__)
  141. CACHE_CleanAll(CACHE);
  142. __enable_irq();
  143. #endif
  144. return -ERROR_OPERATION_FAILED;
  145. }
  146. while(prvQSPI_IsBusy(sCommand.BusMode));
  147. #if (defined __FLASH_DISABLE_IRQ__)
  148. __enable_irq();
  149. #endif
  150. }
  151. #if (defined __FLASH_DISABLE_IRQ__)
  152. CACHE_CleanAll(CACHE);
  153. #endif
  154. return ERROR_NONE;
  155. }
  156. int32_t __FUNC_IN_RAM__ Flash_Program(uint32_t Address, const uint8_t *pBuf, uint32_t Len)
  157. {
  158. FLASH_CommandTypeDef sCommand;
  159. uint32_t FinishLen = 0, DummyLen, ProgramLen, i;
  160. int32_t status;
  161. uint32_t PageData[64];
  162. /* Initialize the adress variables */
  163. sCommand.Instruction = QUAD_INPUT_PAGE_PROG_CMD;
  164. sCommand.BusMode = QSPI_BUSMODE_114;
  165. sCommand.CmdFormat = QSPI_CMDFORMAT_CMD8_ADDR24_PDAT;
  166. Address &= 0x00ffffff;
  167. while(FinishLen < Len)
  168. {
  169. if (prvQSPI_WriteEnable(QSPI_BUSMODE_111))
  170. {
  171. return -ERROR_OPERATION_FAILED;
  172. }
  173. #if (defined __FLASH_DISABLE_IRQ__)
  174. __disable_irq();
  175. ProgramLen = ((Len - FinishLen) > 4)?4:(Len - FinishLen);
  176. #else
  177. ProgramLen = ((Len - FinishLen) > QSPI_FIFO_NUM)?QSPI_FIFO_NUM:(Len - FinishLen);
  178. #endif
  179. for(i = 0; i < ProgramLen; i+=4)
  180. {
  181. PageData[i >> 2] = BytesGetLe32(pBuf + i);
  182. }
  183. QSPI->FIFO_CNTL |= QUADSPI_FIFO_CNTL_TFFH;
  184. QSPI->BYTE_NUM = (ProgramLen << 16);
  185. sCommand.Address = Address + FinishLen;
  186. DummyLen = 0;
  187. while((DummyLen < ProgramLen) && !(QSPI->FIFO_CNTL & QUADSPI_FIFO_CNTL_TFFL))
  188. {
  189. QSPI->WR_FIFO = PageData[DummyLen >> 2];
  190. DummyLen += 4;
  191. }
  192. QSPI->ADDRES = (QSPI->ADDRES & ~QUADSPI_ADDRESS_ADR) | (sCommand.Address << 8);
  193. QSPI->FCU_CMD = (QSPI->FCU_CMD & ~(QUADSPI_FCU_CMD_CODE | QUADSPI_FCU_CMD_BUS_MODE | QUADSPI_FCU_CMD_CMD_FORMAT | QUADSPI_FCU_CMD_ACCESS_REQ)) | ((sCommand.Instruction << 24) |((uint32_t)( sCommand.BusMode<< 8)) |((uint32_t)( sCommand.CmdFormat << 4))| (FLASH_QSPI_ACCESS_REQ_ENABLE));
  194. while(DummyLen < ProgramLen)
  195. {
  196. while(QSPI->FIFO_CNTL & QUADSPI_FIFO_CNTL_TFFL)
  197. {
  198. }
  199. QSPI->WR_FIFO = PageData[DummyLen >> 2];
  200. DummyLen += 4;
  201. }
  202. // DBG("%u", DummyLen);
  203. status = -ERROR_OPERATION_FAILED;
  204. for (i = 0; i < FLASH_QSPI_TIMEOUT_DEFAULT_CNT; i += 4)
  205. {
  206. if (QSPI->INT_RAWSTATUS & QUADSPI_INT_RAWSTATUS_DONE_IR)
  207. {
  208. QSPI->INT_CLEAR = QUADSPI_INT_CLEAR_DONE;
  209. status = ERROR_NONE;
  210. break;
  211. }
  212. }
  213. if (status)
  214. {
  215. #if (defined __FLASH_DISABLE_IRQ__)
  216. CACHE_CleanAll(CACHE);
  217. __enable_irq();
  218. #endif
  219. return status;
  220. }
  221. while (prvQSPI_IsBusy(QSPI_BUSMODE_111));
  222. #if (defined __FLASH_DISABLE_IRQ__)
  223. __enable_irq();
  224. #endif
  225. FinishLen += ProgramLen;
  226. }
  227. #if (defined __FLASH_DISABLE_IRQ__)
  228. CACHE_CleanAll(CACHE);
  229. #endif
  230. return ERROR_NONE;
  231. }
  232. #endif
  233. /**
  234. * @brief Flash Erase Sector.
  235. * @param sectorAddress: The sector address to be erased
  236. * @retval FLASH Status: The returned value can be: QSPI_STATUS_ERROR, QSPI_STATUS_OK
  237. */
  238. uint8_t FLASH_EraseSector(uint32_t sectorAddress)
  239. {
  240. uint8_t ret;
  241. __disable_irq();
  242. //__disable_fault_irq();
  243. ret = ROM_QSPI_EraseSector(NULL, sectorAddress);
  244. //__enable_fault_irq();
  245. __enable_irq();
  246. return ret;
  247. }
  248. /**
  249. * @brief Flash Program Interface.
  250. * @param addr: specifies the address to be programmed.
  251. * @param size: specifies the size to be programmed.
  252. * @param buffer: pointer to the data to be programmed, need word aligned
  253. * @retval FLASH Status: The returned value can be: QSPI_STATUS_ERROR, QSPI_STATUS_OK
  254. */
  255. uint8_t FLASH_ProgramPage(uint32_t addr, uint32_t size, uint8_t *buffer)
  256. {
  257. uint8_t ret;
  258. QSPI_CommandTypeDef cmdType;
  259. cmdType.Instruction = QUAD_INPUT_PAGE_PROG_CMD;
  260. cmdType.BusMode = QSPI_BUSMODE_114;
  261. cmdType.CmdFormat = QSPI_CMDFORMAT_CMD8_ADDR24_PDAT;
  262. __disable_irq();
  263. //__disable_fault_irq();
  264. ret = ROM_QSPI_ProgramPage(&cmdType, DMA_Channel_1, addr, size, buffer);
  265. //__enable_fault_irq();
  266. __enable_irq();
  267. return ret;
  268. }
  269. int32_t Flash_Erase(uint32_t Address, uint32_t Length)
  270. {
  271. uint32_t TotalLen = 0;
  272. QSPI_CommandTypeDef sCommand;
  273. sCommand.BusMode = QSPI_BUSMODE_111;
  274. sCommand.CmdFormat = QSPI_CMDFORMAT_CMD8_ADDR24;
  275. uint32_t FlashAddress, DummyLen;
  276. uint8_t ret;
  277. while (TotalLen < Length)
  278. {
  279. FlashAddress = Address + TotalLen;
  280. DummyLen = Length - TotalLen;
  281. if (!(FlashAddress & SPI_FLASH_BLOCK_MASK) && (DummyLen >= SPI_FLASH_BLOCK_SIZE))
  282. {
  283. sCommand.Instruction = SPIFLASH_CMD_BE;
  284. TotalLen += SPI_FLASH_BLOCK_SIZE;
  285. }
  286. else
  287. {
  288. sCommand.Instruction = SPIFLASH_CMD_SE;
  289. TotalLen += SPI_FLASH_SECTOR_SIZE;
  290. }
  291. __disable_irq();
  292. //__disable_fault_irq();
  293. ret = ROM_QSPI_EraseSector(&sCommand, FlashAddress);
  294. //__enable_fault_irq();
  295. __enable_irq();
  296. }
  297. CACHE_CleanAll(CACHE);
  298. return ERROR_NONE;
  299. }
  300. int32_t Flash_Program(uint32_t Address, const uint8_t *pBuf, uint32_t Len)
  301. {
  302. uint32_t size = (Len + (4 - 1)) & (~(4 - 1));
  303. uint32_t Pos = 0;
  304. uint8_t ret;
  305. QSPI_CommandTypeDef cmdType;
  306. cmdType.Instruction = QUAD_INPUT_PAGE_PROG_CMD;
  307. cmdType.BusMode = QSPI_BUSMODE_114;
  308. cmdType.CmdFormat = QSPI_CMDFORMAT_CMD8_ADDR24_PDAT;
  309. while(Pos < size)
  310. {
  311. if ((size - Pos) > __FLASH_PAGE_SIZE__)
  312. {
  313. __disable_irq();
  314. //__disable_fault_irq();
  315. ret = ROM_QSPI_ProgramPage(&cmdType, DMA_Channel_1, Address + Pos, __FLASH_PAGE_SIZE__, pBuf + Pos);
  316. //__enable_fault_irq();
  317. __enable_irq();
  318. Pos += __FLASH_PAGE_SIZE__;
  319. }
  320. else
  321. {
  322. __disable_irq();
  323. //__disable_fault_irq();
  324. ret = ROM_QSPI_ProgramPage(&cmdType, DMA_Channel_1, Address + Pos, (size - Pos), pBuf + Pos);
  325. //__enable_fault_irq();
  326. __enable_irq();
  327. Pos += (size - Pos);
  328. }
  329. }
  330. CACHE_CleanAll(CACHE);
  331. return ERROR_NONE;
  332. }
  333. int Flash_EraseSector(uint32_t address, uint8_t NeedCheck)
  334. {
  335. uint8_t buf[__FLASH_PAGE_SIZE__];
  336. uint32_t i;
  337. uint8_t retry = 1;
  338. void *res;
  339. memset(buf, 0xff, __FLASH_PAGE_SIZE__);
  340. BL_ERASESECTOR_AGAIN:
  341. FLASH_EraseSector(address);
  342. #if (defined __BUILD_OS__) || (defined __BUILD_APP__)
  343. CACHE_CleanAll(CACHE);
  344. #endif
  345. if (!NeedCheck) return ERROR_NONE;
  346. for(i = 0; i < 4096; i+=__FLASH_PAGE_SIZE__)
  347. {
  348. res = memcmp(address + i, buf, __FLASH_PAGE_SIZE__);
  349. if (res)
  350. {
  351. DBG_INFO("%x", res);
  352. if (retry)
  353. {
  354. retry = 0;
  355. goto BL_ERASESECTOR_AGAIN;
  356. }
  357. else
  358. {
  359. return -1;
  360. }
  361. }
  362. }
  363. return 0;
  364. }
  365. int Flash_ProgramData(uint32_t address, uint32_t *Data, uint32_t Len, uint8_t NeedCheck)
  366. {
  367. void *res;
  368. uint32_t size = (Len + (4 - 1)) & (~(4 - 1));
  369. FLASH_ProgramPage(address, size, Data);
  370. #if (defined __BUILD_OS__) || (defined __BUILD_APP__)
  371. CACHE_CleanAll(CACHE);
  372. #endif
  373. if (!NeedCheck) return ERROR_NONE;
  374. res = memcmp(address, Data, Len);
  375. if (res)
  376. {
  377. DBG_INFO("%x", res);
  378. FLASH_ProgramPage(address, size, Data);
  379. #if (defined __BUILD_OS__) || (defined __BUILD_APP__)
  380. CACHE_CleanAll(CACHE);
  381. #endif
  382. res = memcmp(address, Data, size);
  383. if (res)
  384. {
  385. DBG_INFO("%x", res);
  386. return -1;
  387. }
  388. }
  389. return 0;
  390. }