core_flash.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  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. #ifdef __RUN_IN_RAM__
  23. #define __disable_irq()
  24. #define __disable_fault_irq()
  25. #define __enable_fault_irq()
  26. #define __enable_irq()
  27. #endif
  28. void __FUNC_IN_RAM__ CACHE_CleanAll(CACHE_TypeDef *Cache)
  29. {
  30. while (Cache->CACHE_CS & CACHE_IS_BUSY);
  31. Cache->CACHE_REF = CACHE_REFRESH_ALLTAG;
  32. Cache->CACHE_REF |= CACHE_REFRESH;
  33. while ((Cache->CACHE_REF & CACHE_REFRESH));
  34. }
  35. #ifdef __RUN_IN_RAM__
  36. typedef struct
  37. {
  38. uint8_t Instruction;
  39. QSPI_BusModeTypeDef BusMode;
  40. QSPI_CmdFormatTypeDef CmdFormat;
  41. uint32_t Address;
  42. uint32_t WrData;
  43. uint32_t RdData;
  44. }FLASH_CommandTypeDef;
  45. #define QSPI_FIFO_NUM 32
  46. #define FLASH_QSPI_TIMEOUT_DEFAULT_CNT (19000) //18944
  47. #define FLASH_QSPI_ACCESS_REQ_ENABLE (0x00000001U)
  48. #define FLASH_QSPI_FLASH_READY_ENABLE (0x0000006BU)
  49. static int32_t prvQSPI_Command(FLASH_CommandTypeDef *cmd, int32_t timeout)
  50. {
  51. int32_t i;
  52. int32_t status = -ERROR_OPERATION_FAILED;
  53. QSPI->REG_WDATA = cmd->WrData;
  54. QSPI->ADDRES = (QSPI->ADDRES & ~QUADSPI_ADDRESS_ADR) | (cmd->Address << 8);
  55. 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));
  56. //Wait For CMD done
  57. for (i = 0; i < timeout; i += 4)
  58. {
  59. if (QSPI->INT_RAWSTATUS & QUADSPI_INT_RAWSTATUS_DONE_IR)
  60. {
  61. QSPI->INT_CLEAR = QUADSPI_INT_CLEAR_DONE;
  62. status = ERROR_NONE;
  63. break;
  64. }
  65. }
  66. cmd->RdData = QSPI->REG_RDATA;
  67. return status;
  68. }
  69. static int32_t prvQSPI_WriteEnable(QSPI_BusModeTypeDef bus_mode)
  70. {
  71. FLASH_CommandTypeDef sCommand;
  72. sCommand.Instruction = SPIFLASH_CMD_WREN;
  73. sCommand.CmdFormat = QSPI_CMDFORMAT_CMD8;
  74. if (QSPI_BUSMODE_444 == bus_mode)
  75. {
  76. sCommand.BusMode = QSPI_BUSMODE_444;
  77. }
  78. else
  79. {
  80. sCommand.BusMode = QSPI_BUSMODE_111;
  81. }
  82. if (prvQSPI_Command(&sCommand, FLASH_QSPI_TIMEOUT_DEFAULT_CNT))
  83. {
  84. return -ERROR_OPERATION_FAILED;
  85. }
  86. return ERROR_NONE;
  87. }
  88. //PP,QPP,Sector Erase,Block Erase, Chip Erase, Write Status Reg, Erase Security Reg
  89. int32_t prvQSPI_IsBusy(QSPI_BusModeTypeDef bus_mode)
  90. {
  91. FLASH_CommandTypeDef sCommand;
  92. sCommand.Instruction = SPIFLASH_CMD_RDSR;
  93. sCommand.CmdFormat = QSPI_CMDFORMAT_CMD8_RREG8;
  94. if (QSPI_BUSMODE_444 == bus_mode)
  95. {
  96. sCommand.BusMode = QSPI_BUSMODE_444;
  97. }
  98. else
  99. {
  100. sCommand.BusMode = QSPI_BUSMODE_111;
  101. }
  102. if (prvQSPI_Command(&sCommand, FLASH_QSPI_TIMEOUT_DEFAULT_CNT))
  103. {
  104. return -ERROR_OPERATION_FAILED;
  105. }
  106. if (sCommand.RdData & BIT0)
  107. {
  108. return -ERROR_DEVICE_BUSY;
  109. }
  110. return ERROR_NONE;
  111. }
  112. int32_t Flash_EraseStart(uint32_t Address, uint8_t IsBlock)
  113. {
  114. FLASH_CommandTypeDef sCommand;
  115. Address &= (uint32_t)(0x00FFFFFF);
  116. while (CACHE->CACHE_CS & CACHE_IS_BUSY);
  117. sCommand.BusMode = QSPI_BUSMODE_111;
  118. sCommand.CmdFormat = QSPI_CMDFORMAT_CMD8_ADDR24;
  119. if (prvQSPI_WriteEnable(sCommand.BusMode) != 0)
  120. {
  121. return -ERROR_OPERATION_FAILED;
  122. }
  123. if (IsBlock)
  124. {
  125. sCommand.Instruction = SPIFLASH_CMD_BE;
  126. }
  127. else
  128. {
  129. sCommand.Instruction = SPIFLASH_CMD_SE;
  130. }
  131. sCommand.Address = Address;
  132. if (prvQSPI_Command(&sCommand, FLASH_QSPI_TIMEOUT_DEFAULT_CNT))
  133. {
  134. return -ERROR_OPERATION_FAILED;
  135. }
  136. return ERROR_NONE;
  137. }
  138. int32_t Flash_CheckBusy(void)
  139. {
  140. return prvQSPI_IsBusy(QSPI_BUSMODE_111);
  141. }
  142. #endif
  143. #if 0
  144. int32_t __FUNC_IN_RAM__ Flash_Program(uint32_t Address, const uint8_t *pBuf, uint32_t Len)
  145. {
  146. FLASH_CommandTypeDef sCommand;
  147. uint32_t FinishLen = 0, DummyLen, ProgramLen, i;
  148. int32_t status;
  149. uint32_t PageData[64];
  150. /* Initialize the adress variables */
  151. sCommand.Instruction = QUAD_INPUT_PAGE_PROG_CMD;
  152. sCommand.BusMode = QSPI_BUSMODE_114;
  153. sCommand.CmdFormat = QSPI_CMDFORMAT_CMD8_ADDR24_PDAT;
  154. Address &= 0x00ffffff;
  155. while(FinishLen < Len)
  156. {
  157. if (prvQSPI_WriteEnable(QSPI_BUSMODE_111))
  158. {
  159. return -ERROR_OPERATION_FAILED;
  160. }
  161. #if (defined __FLASH_DISABLE_IRQ__)
  162. __disable_irq();
  163. ProgramLen = ((Len - FinishLen) > 4)?4:(Len - FinishLen);
  164. #else
  165. ProgramLen = ((Len - FinishLen) > QSPI_FIFO_NUM)?QSPI_FIFO_NUM:(Len - FinishLen);
  166. #endif
  167. for(i = 0; i < ProgramLen; i+=4)
  168. {
  169. PageData[i >> 2] = BytesGetLe32(pBuf + i);
  170. }
  171. QSPI->FIFO_CNTL |= QUADSPI_FIFO_CNTL_TFFH;
  172. QSPI->BYTE_NUM = (ProgramLen << 16);
  173. sCommand.Address = Address + FinishLen;
  174. DummyLen = 0;
  175. while((DummyLen < ProgramLen) && !(QSPI->FIFO_CNTL & QUADSPI_FIFO_CNTL_TFFL))
  176. {
  177. QSPI->WR_FIFO = PageData[DummyLen >> 2];
  178. DummyLen += 4;
  179. }
  180. QSPI->ADDRES = (QSPI->ADDRES & ~QUADSPI_ADDRESS_ADR) | (sCommand.Address << 8);
  181. 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));
  182. while(DummyLen < ProgramLen)
  183. {
  184. while(QSPI->FIFO_CNTL & QUADSPI_FIFO_CNTL_TFFL)
  185. {
  186. }
  187. QSPI->WR_FIFO = PageData[DummyLen >> 2];
  188. DummyLen += 4;
  189. }
  190. // DBG("%u", DummyLen);
  191. status = -ERROR_OPERATION_FAILED;
  192. for (i = 0; i < FLASH_QSPI_TIMEOUT_DEFAULT_CNT; i += 4)
  193. {
  194. if (QSPI->INT_RAWSTATUS & QUADSPI_INT_RAWSTATUS_DONE_IR)
  195. {
  196. QSPI->INT_CLEAR = QUADSPI_INT_CLEAR_DONE;
  197. status = ERROR_NONE;
  198. break;
  199. }
  200. }
  201. if (status)
  202. {
  203. #if (defined __FLASH_DISABLE_IRQ__)
  204. CACHE_CleanAll(CACHE);
  205. __enable_irq();
  206. #endif
  207. return status;
  208. }
  209. while (prvQSPI_IsBusy(QSPI_BUSMODE_111));
  210. #if (defined __FLASH_DISABLE_IRQ__)
  211. __enable_irq();
  212. #endif
  213. FinishLen += ProgramLen;
  214. }
  215. #if (defined __FLASH_DISABLE_IRQ__)
  216. CACHE_CleanAll(CACHE);
  217. #endif
  218. return ERROR_NONE;
  219. }
  220. #endif
  221. /**
  222. * @brief Flash Erase Sector.
  223. * @param sectorAddress: The sector address to be erased
  224. * @retval FLASH Status: The returned value can be: QSPI_STATUS_ERROR, QSPI_STATUS_OK
  225. */
  226. uint8_t FLASH_EraseSector(uint32_t sectorAddress)
  227. {
  228. uint8_t ret;
  229. __disable_irq();
  230. //__disable_fault_irq();
  231. ret = ROM_QSPI_EraseSector(NULL, sectorAddress);
  232. //__enable_fault_irq();
  233. __enable_irq();
  234. return ret;
  235. }
  236. /**
  237. * @brief Flash Program Interface.
  238. * @param addr: specifies the address to be programmed.
  239. * @param size: specifies the size to be programmed.
  240. * @param buffer: pointer to the data to be programmed, need word aligned
  241. * @retval FLASH Status: The returned value can be: QSPI_STATUS_ERROR, QSPI_STATUS_OK
  242. */
  243. uint8_t FLASH_ProgramPage(uint32_t addr, uint32_t size, uint8_t *buffer)
  244. {
  245. uint8_t ret;
  246. QSPI_CommandTypeDef cmdType;
  247. cmdType.Instruction = QUAD_INPUT_PAGE_PROG_CMD;
  248. cmdType.BusMode = QSPI_BUSMODE_114;
  249. cmdType.CmdFormat = QSPI_CMDFORMAT_CMD8_ADDR24_PDAT;
  250. __disable_irq();
  251. //__disable_fault_irq();
  252. ret = ROM_QSPI_ProgramPage(&cmdType, DMA_Channel_1, addr, size, buffer);
  253. //__enable_fault_irq();
  254. __enable_irq();
  255. return ret;
  256. }
  257. int32_t Flash_Erase(uint32_t Address, uint32_t Length)
  258. {
  259. uint32_t TotalLen = 0;
  260. QSPI_CommandTypeDef sCommand;
  261. sCommand.BusMode = QSPI_BUSMODE_111;
  262. sCommand.CmdFormat = QSPI_CMDFORMAT_CMD8_ADDR24;
  263. uint32_t FlashAddress, DummyLen;
  264. uint8_t ret;
  265. while (TotalLen < Length)
  266. {
  267. FlashAddress = Address + TotalLen;
  268. DummyLen = Length - TotalLen;
  269. if (!(FlashAddress & SPI_FLASH_BLOCK_MASK) && (DummyLen >= SPI_FLASH_BLOCK_SIZE))
  270. {
  271. sCommand.Instruction = SPIFLASH_CMD_BE;
  272. TotalLen += SPI_FLASH_BLOCK_SIZE;
  273. }
  274. else
  275. {
  276. sCommand.Instruction = SPIFLASH_CMD_SE;
  277. TotalLen += SPI_FLASH_SECTOR_SIZE;
  278. }
  279. __disable_irq();
  280. //__disable_fault_irq();
  281. ret = ROM_QSPI_EraseSector(&sCommand, FlashAddress);
  282. //__enable_fault_irq();
  283. __enable_irq();
  284. }
  285. CACHE_CleanAll(CACHE);
  286. return ERROR_NONE;
  287. }
  288. int32_t Flash_Program(uint32_t Address, const uint8_t *pBuf, uint32_t Len)
  289. {
  290. uint32_t size = (Len + (4 - 1)) & (~(4 - 1));
  291. uint32_t Pos = 0;
  292. uint8_t ret;
  293. QSPI_CommandTypeDef cmdType;
  294. cmdType.Instruction = QUAD_INPUT_PAGE_PROG_CMD;
  295. cmdType.BusMode = QSPI_BUSMODE_114;
  296. cmdType.CmdFormat = QSPI_CMDFORMAT_CMD8_ADDR24_PDAT;
  297. while(Pos < size)
  298. {
  299. if ((size - Pos) > __FLASH_PAGE_SIZE__)
  300. {
  301. __disable_irq();
  302. //__disable_fault_irq();
  303. ret = ROM_QSPI_ProgramPage(&cmdType, DMA_Channel_1, Address + Pos, __FLASH_PAGE_SIZE__, pBuf + Pos);
  304. //__enable_fault_irq();
  305. __enable_irq();
  306. Pos += __FLASH_PAGE_SIZE__;
  307. }
  308. else
  309. {
  310. __disable_irq();
  311. //__disable_fault_irq();
  312. ret = ROM_QSPI_ProgramPage(&cmdType, DMA_Channel_1, Address + Pos, (size - Pos), pBuf + Pos);
  313. //__enable_fault_irq();
  314. __enable_irq();
  315. Pos += (size - Pos);
  316. }
  317. }
  318. CACHE_CleanAll(CACHE);
  319. return ERROR_NONE;
  320. }
  321. int Flash_EraseSector(uint32_t address, uint8_t NeedCheck)
  322. {
  323. uint8_t buf[__FLASH_PAGE_SIZE__];
  324. uint32_t i;
  325. uint8_t retry = 1;
  326. void *res;
  327. memset(buf, 0xff, __FLASH_PAGE_SIZE__);
  328. BL_ERASESECTOR_AGAIN:
  329. FLASH_EraseSector(address);
  330. #if (defined __BUILD_OS__) || (defined __BUILD_APP__)
  331. CACHE_CleanAll(CACHE);
  332. #endif
  333. if (!NeedCheck) return ERROR_NONE;
  334. for(i = 0; i < 4096; i+=__FLASH_PAGE_SIZE__)
  335. {
  336. res = memcmp(address + i, buf, __FLASH_PAGE_SIZE__);
  337. if (res)
  338. {
  339. DBG_INFO("%x", res);
  340. if (retry)
  341. {
  342. retry = 0;
  343. goto BL_ERASESECTOR_AGAIN;
  344. }
  345. else
  346. {
  347. return -1;
  348. }
  349. }
  350. }
  351. return 0;
  352. }
  353. int Flash_ProgramData(uint32_t address, uint32_t *Data, uint32_t Len, uint8_t NeedCheck)
  354. {
  355. void *res;
  356. uint32_t size = (Len + (4 - 1)) & (~(4 - 1));
  357. FLASH_ProgramPage(address, size, Data);
  358. #if (defined __BUILD_OS__) || (defined __BUILD_APP__)
  359. CACHE_CleanAll(CACHE);
  360. #endif
  361. if (!NeedCheck) return ERROR_NONE;
  362. res = memcmp(address, Data, Len);
  363. if (res)
  364. {
  365. DBG_INFO("%x", res);
  366. FLASH_ProgramPage(address, size, Data);
  367. #if (defined __BUILD_OS__) || (defined __BUILD_APP__)
  368. CACHE_CleanAll(CACHE);
  369. #endif
  370. res = memcmp(address, Data, size);
  371. if (res)
  372. {
  373. DBG_INFO("%x", res);
  374. return -1;
  375. }
  376. }
  377. return 0;
  378. }