flash.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. /**
  2. * @file flash.c
  3. * @author chipsea
  4. * @brief Contains all functions support for flash driver
  5. * @version 0.1
  6. * @date 2020-11-30
  7. * @copyright Copyright (c) 2020, CHIPSEA Co., Ltd.
  8. * @note
  9. */
  10. #include "sdk_config.h"
  11. #include "flash.h"
  12. #include "log.h"
  13. #include "types.h"
  14. #include "error.h"
  15. #include "pwrmgr.h"
  16. #include <string.h>
  17. #include "rom_sym_def.h"
  18. #define FLASH_LOCK_504K 0x04//0x00-0x7DFFF
  19. #define FLASH_LOCK_496K 0x08//0x00-0x7BFFF
  20. #define FLASH_LOCK_480K 0x0C//0x00-0x77FFF
  21. #define FLASH_LOCK_448K 0x10//0x00-0x6FFFF
  22. #define FLASH_LOCK_384K 0x14//0x00-0x5FFFF
  23. #define FLASH_LOCK_HALF 0x18//0x00-0x3FFFF
  24. #define FLASH_LOCK_ALL 0x1C//0x00-0x7FFFF
  25. #define FLASH_UNLOCK 0x00
  26. #define WRITE_ENABLE 0x6000001
  27. #define WRITE_PROTECT 0x1008001
  28. #define REG_FLASH_BP (*((volatile unsigned int *)(0x4000c8a8)))
  29. #define REG_FLASH_WRITE_CTRL (*((volatile unsigned int *)(0x4000c890)))
  30. #define SPIF_WAIT_IDLE_CYC (32)
  31. #define SPIF_STATUS_WAIT_IDLE(n) \
  32. do \
  33. { \
  34. while((AP_SPIF->fcmd &0x02)==0x02); \
  35. { \
  36. volatile int delay_cycle = n; \
  37. while (delay_cycle--){;} \
  38. } \
  39. while ((AP_SPIF->config & 0x80000000) == 0);\
  40. } while (0);
  41. #define HAL_CACHE_ENTER_BYPASS_SECTION() do{ \
  42. HAL_ENTER_CRITICAL_SECTION();\
  43. AP_CACHE->CTRL0 = 0x02; \
  44. AP_PCR->CACHE_RST = 0x02;\
  45. AP_PCR->CACHE_BYPASS = 1; \
  46. HAL_EXIT_CRITICAL_SECTION();\
  47. }while(0);
  48. #define HAL_CACHE_EXIT_BYPASS_SECTION() do{ \
  49. HAL_ENTER_CRITICAL_SECTION();\
  50. AP_CACHE->CTRL0 = 0x00;\
  51. AP_PCR->CACHE_RST = 0x03;\
  52. AP_PCR->CACHE_BYPASS = 0;\
  53. HAL_EXIT_CRITICAL_SECTION();\
  54. }while(0);
  55. #define spif_wait_nobusy(flg, tout_ns, return_val) {if(_spif_wait_nobusy_x(flg, tout_ns)){if(return_val){ return return_val;}}}
  56. typedef struct {
  57. sysclk_t spif_ref_clk;
  58. uint32_t rd_instr;
  59. }xflash_Ctx_t;
  60. static xflash_Ctx_t s_xflashCtx = {.spif_ref_clk=SYS_CLK_RC_32M,.rd_instr=XFRD_FCMD_READ_DUAL};
  61. extern int _spif_wait_nobusy(uint8_t flg, uint32_t tout_ns);
  62. extern int spif_write(uint32_t addr, uint8_t* data, uint32_t size);
  63. extern int spif_write_dma(uint32_t addr, uint8_t* data, uint32_t size);
  64. extern int spif_read(uint32_t addr, uint8_t* data, uint32_t size);
  65. extern int spif_read_dma(uint32_t addr, uint8_t* data, uint32_t size);
  66. extern int spif_erase_sector(unsigned int addr);
  67. extern int spif_erase_block64(unsigned int addr);
  68. extern int spif_erase_all(void);
  69. extern uint8_t spif_flash_status_reg_0(void);
  70. extern int spif_write_protect(bool en);
  71. extern void spif_cmd(uint8_t op, uint8_t addrlen, uint8_t rdlen, uint8_t wrlen, uint8_t mbit, uint8_t dummy);
  72. extern void spif_rddata(uint8_t* data, uint8_t len);
  73. extern int spif_config(sysclk_t ref_clk, uint8_t div, uint32_t rd_instr, uint8_t mode_bit, uint8_t QE);
  74. static inline uint32_t spif_lock()
  75. {
  76. HAL_ENTER_CRITICAL_SECTION();
  77. uint32_t vic_iser = NVIC->ISER[0];
  78. //mask all irq
  79. NVIC->ICER[0] = 0xFFFFFFFF;
  80. //enable ll irq and tim1 irq
  81. NVIC->ISER[0] = 0x100010;
  82. HAL_EXIT_CRITICAL_SECTION();
  83. return vic_iser;
  84. }
  85. static inline void spif_unlock(uint32_t vic_iser)
  86. {
  87. HAL_ENTER_CRITICAL_SECTION();
  88. NVIC->ISER[0] = vic_iser;
  89. HAL_EXIT_CRITICAL_SECTION();
  90. }
  91. static void hal_cache_tag_flush(void)
  92. {
  93. HAL_ENTER_CRITICAL_SECTION();
  94. uint32_t cb = AP_PCR->CACHE_BYPASS;
  95. volatile int dly = 8;
  96. if(cb==0)
  97. {
  98. AP_PCR->CACHE_BYPASS = 1;
  99. }
  100. AP_CACHE->CTRL0 = 0x02;
  101. while (dly--){;};
  102. AP_CACHE->CTRL0 = 0x03;
  103. dly = 8;while (dly--){;};
  104. AP_CACHE->CTRL0 = 0x00;
  105. if(cb==0)
  106. {
  107. AP_PCR->CACHE_BYPASS = 0;
  108. }
  109. HAL_EXIT_CRITICAL_SECTION();
  110. }
  111. static uint8_t _spif_read_status_reg_x(void)
  112. {
  113. uint8_t status;
  114. spif_cmd(FCMD_RDST, 0, 2, 0, 0, 0);
  115. SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
  116. spif_rddata(&status, 1);
  117. return status;
  118. }
  119. static int _spif_wait_nobusy_x(uint8_t flg, uint32_t tout_ns)
  120. {
  121. uint8_t status;
  122. volatile int tout = (int )(tout_ns);
  123. for(; tout ; tout --){
  124. status = _spif_read_status_reg_x();
  125. if((status & flg) == 0)
  126. return ERR_NONE;
  127. //insert polling interval
  128. //5*32us
  129. WaitRTCCount(5);
  130. }
  131. return ERR_BUSY;
  132. }
  133. static void hal_cache_init(void)
  134. {
  135. volatile int dly=100;
  136. //clock gate
  137. hal_clk_gate_enable(MOD_HCLK_CACHE);
  138. hal_clk_gate_enable(MOD_PCLK_CACHE);
  139. //cache rst ahp
  140. AP_PCR->CACHE_RST=0x02;
  141. while(dly--){};
  142. AP_PCR->CACHE_RST=0x03;
  143. hal_cache_tag_flush();
  144. //cache enable
  145. AP_PCR->CACHE_BYPASS = 0;
  146. }
  147. static void hw_spif_cache_config(void)
  148. {
  149. spif_config(s_xflashCtx.spif_ref_clk,/*div*/1,s_xflashCtx.rd_instr,0,0);
  150. AP_SPIF->wr_completion_ctrl=0xff010005;//set longest polling interval
  151. NVIC_DisableIRQ(SPIF_IRQn);
  152. NVIC_SetPriority((IRQn_Type)SPIF_IRQn, IRQ_PRIO_HAL);
  153. hal_cache_init();
  154. }
  155. int hal_flash_erase_all(void)
  156. {
  157. uint8_t retval;
  158. uint32_t cb = AP_PCR->CACHE_BYPASS;
  159. HAL_CACHE_ENTER_BYPASS_SECTION();
  160. SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
  161. spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, ERR_BUSY);
  162. retval = spif_erase_all();
  163. SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
  164. spif_wait_nobusy(SFLG_WELWIP, SPIF_TIMEOUT, ERR_BUSY);
  165. HAL_CACHE_EXIT_BYPASS_SECTION();
  166. if(cb == 0)
  167. {
  168. hal_cache_tag_flush();
  169. }
  170. return retval;
  171. }
  172. /**
  173. * @fn void HalFlashInit(void)
  174. * @brief flash Initialization function.
  175. * @param NONE.
  176. * @return NONE.
  177. */
  178. ErrCode_t HalFlashInit(void)
  179. {
  180. hw_spif_cache_config();
  181. hal_pwrmgr_register(MOD_SPIF, NULL, hw_spif_cache_config);
  182. return ERR_NONE;
  183. }
  184. /**
  185. * @fn void HalFlashRead(uint32_t offset, uint8_t *buf, uint32_t len)
  186. * @brief flash read function.
  187. * @param[offset] read address in flash.
  188. * @param[buf] receive data buffer.
  189. * @param[len] receive data length.
  190. * @return NONE.
  191. */
  192. void HalFlashRead(uint32_t addr, uint8_t *buf, uint32_t len)
  193. {
  194. volatile uint8_t *u8_spif_addr = (volatile uint8_t *)((addr & 0x7ffff) | FLASH_BASE_ADDR);
  195. uint32_t cb = AP_PCR->CACHE_BYPASS;
  196. uint32_t cs = spif_lock();
  197. #if(SPIF_FLASH_SIZE==FLASH_SIZE_1MB)
  198. uint32_t remap = addr & 0xf80000;
  199. if(remap)
  200. {
  201. AP_SPIF->remap = remap;
  202. AP_SPIF->config |= 0x10000;
  203. }
  204. #endif
  205. //read flash addr direct access
  206. //bypass cache
  207. if(cb == 0)
  208. {
  209. HAL_CACHE_ENTER_BYPASS_SECTION();
  210. }
  211. for(int i=0; i<len; i++)
  212. {
  213. buf[i]=u8_spif_addr[i];
  214. }
  215. //bypass cache
  216. if(cb == 0)
  217. {
  218. HAL_CACHE_EXIT_BYPASS_SECTION();
  219. }
  220. #if(SPIF_FLASH_SIZE==FLASH_SIZE_1MB)
  221. if(remap)
  222. {
  223. AP_SPIF->remap = 0;
  224. AP_SPIF->config &= ~0x10000ul;
  225. }
  226. #endif
  227. spif_unlock(cs);
  228. }
  229. /**
  230. * @fn ErrCode_t HalFlashWrite(uint32_t offset, uint8_t *buf, uint16_t len)
  231. * @brief flash write function.(offset + len) must be smaller than the current sector
  232. * @param offset: write address in flash.
  233. * @param buf: write data buffer.
  234. * @param len: write data length.
  235. * @return ErrCode_t:return ERR_INVALID_PARAM when the input parameter is incorrect;
  236. return ERR_NONE when the operation is complete;
  237. */
  238. ErrCode_t HalFlashWrite(uint32_t addr, uint8_t* buf, uint32_t len)
  239. {
  240. ErrCode_t retval;
  241. if((buf == NULL) || (len == 0))
  242. return ERR_INVALID_DATA;
  243. uint32_t cs = spif_lock();
  244. addr &= 0x00FFFFFF;
  245. if( (addr < 0x2000) || (addr > 0x7FFFF) || ((addr+len) > 0x80000) )
  246. {
  247. return ERR_INVALID_PARAM;
  248. }
  249. if(len > 4096)
  250. {
  251. return ERR_INVALID_LENGTH;
  252. }
  253. HAL_CACHE_ENTER_BYPASS_SECTION();
  254. SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
  255. spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, ERR_BUSY);
  256. retval = (ErrCode_t)spif_write(addr, buf, len);
  257. SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
  258. spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, ERR_BUSY);
  259. HAL_CACHE_EXIT_BYPASS_SECTION();
  260. spif_unlock(cs);
  261. return retval;
  262. }
  263. /**
  264. * @fn ErrCode_t HalFlashWrite(uint32_t offset, uint8_t *buf, uint16_t len)
  265. * @brief flash write function.(offset + len) must be smaller than the current sector
  266. * @param offset: write address in flash.
  267. * @param buf: write data buffer.
  268. * @param len: write data length.
  269. * @return ErrCode_t:return ERR_INVALID_PARAM when the input parameter is incorrect;
  270. return ERR_NONE when the operation is complete;
  271. */
  272. ErrCode_t HalFlashWriteByDma(uint32_t addr, uint8_t* buf, uint32_t len)
  273. {
  274. ErrCode_t retval;
  275. if(buf == NULL)
  276. {
  277. return ERR_INVALID_DATA;
  278. }
  279. if((len == 0) || (len > 4096))
  280. {
  281. return ERR_INVALID_LENGTH;
  282. }
  283. uint32_t cs = spif_lock();
  284. addr &= 0x00FFFFFF;
  285. if( (addr < 0x2000) || (addr > 0x7FFFF) || ((addr+len) > 0x80000) )
  286. {
  287. return ERR_INVALID_PARAM;
  288. }
  289. HAL_CACHE_ENTER_BYPASS_SECTION();
  290. SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
  291. spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, ERR_BUSY);
  292. retval = (ErrCode_t)spif_write_dma(addr, buf, len);
  293. SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
  294. spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, ERR_BUSY);
  295. HAL_CACHE_EXIT_BYPASS_SECTION();
  296. spif_unlock(cs);
  297. return retval;
  298. }
  299. /**
  300. * @fn ErrCode_t HalFlashWriteWord(uint32_t offset, uint32_t value)
  301. * @brief flash write function.(offset + len) must be smaller than the current sector
  302. * @param offset: write address in flash.
  303. * @param value: write data.
  304. * @return ErrCode_t:return ERR_INVALID_PARAM when the input parameter is incorrect;
  305. return ERR_NONE when the operation is complete;
  306. */
  307. ErrCode_t HalFlashWriteWord(uint32_t offset, uint32_t value)
  308. {
  309. offset &= 0x00FFFFFF;
  310. if( (offset < 0x2000) || (offset > 0x7FFFC) )
  311. {
  312. return ERR_INVALID_PARAM;
  313. }
  314. uint32_t temp = value;
  315. return (HalFlashWrite(offset, (uint8_t *) &temp, 4));
  316. }
  317. /**
  318. * @fn ErrCode_t HalFlashErase(uint32_t sectorNum)
  319. * @brief erase one sector(4K byte) from falsh.
  320. * @param[sectorNum] erase sector number.
  321. * @return ErrCode_t:return ERR_INVALID_PARAM when the input parameter is incorrect;
  322. return ERR_NONE when the operation is complete;
  323. */
  324. ErrCode_t HalFlashErase(uint32_t sectorNum)
  325. {
  326. sectorNum &= 0x00FFFFFF;
  327. if( (sectorNum < 2) || (sectorNum > 0x7F) )
  328. {
  329. return ERR_INVALID_PARAM;
  330. }
  331. uint8_t status = _spif_read_status_reg_x() & FLASH_LOCK_ALL;
  332. if(status)
  333. {
  334. switch(status)
  335. {
  336. case FLASH_LOCK_504K:
  337. if(sectorNum > 0x7D)
  338. {
  339. return ERR_INVALID_PARAM;
  340. }
  341. break;
  342. case FLASH_LOCK_496K:
  343. if(sectorNum > 0x7B)
  344. {
  345. return ERR_INVALID_PARAM;
  346. }
  347. break;
  348. case FLASH_LOCK_480K:
  349. if(sectorNum > 0x77)
  350. {
  351. return ERR_INVALID_PARAM;
  352. }
  353. break;
  354. case FLASH_LOCK_448K:
  355. if(sectorNum > 0x6F)
  356. {
  357. return ERR_INVALID_PARAM;
  358. }
  359. break;
  360. case FLASH_LOCK_384K:
  361. if(sectorNum > 0x5F)
  362. {
  363. return ERR_INVALID_PARAM;
  364. }
  365. break;
  366. case FLASH_LOCK_HALF:
  367. if(sectorNum > 0x3F)
  368. {
  369. return ERR_INVALID_PARAM;
  370. }
  371. break;
  372. case FLASH_LOCK_ALL:
  373. return ERR_INVALID_PARAM;
  374. }
  375. }
  376. ErrCode_t retval;
  377. uint32_t cs = spif_lock();
  378. uint32_t cb = AP_PCR->CACHE_BYPASS;
  379. HAL_CACHE_ENTER_BYPASS_SECTION();
  380. SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
  381. spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, ERR_BUSY);
  382. retval = (ErrCode_t)spif_erase_sector((sectorNum<<12));
  383. SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
  384. spif_wait_nobusy(SFLG_WELWIP, SPIF_TIMEOUT, ERR_BUSY);
  385. HAL_CACHE_EXIT_BYPASS_SECTION();
  386. if(cb == 0)
  387. {
  388. hal_cache_tag_flush();
  389. }
  390. spif_unlock(cs);
  391. return retval;
  392. }
  393. /**
  394. * @fn ErrCode_t HalFlashErase64K(uint32_t addr)
  395. * @brief erase (64 Kbyte) from falsh.
  396. * @param[addr] erase addr.
  397. * @return ErrCode_t:return ERR_INVALID_PARAM when the input parameter is incorrect;
  398. return ERR_NONE when the operation is complete;
  399. */
  400. ErrCode_t HalFlashErase64K(uint32_t addr)
  401. {
  402. addr &= 0x00FFFFFF;
  403. if( (addr < 0x10000) || (addr > 0x70000) )
  404. {
  405. return ERR_INVALID_PARAM;
  406. }
  407. ErrCode_t retval;
  408. uint32_t cs = spif_lock();
  409. uint32_t cb = AP_PCR->CACHE_BYPASS;
  410. HAL_CACHE_ENTER_BYPASS_SECTION();
  411. SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
  412. spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, ERR_BUSY);
  413. retval = (ErrCode_t)spif_erase_block64(addr);
  414. SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC);
  415. spif_wait_nobusy(SFLG_WELWIP, SPIF_TIMEOUT, ERR_BUSY);
  416. HAL_CACHE_EXIT_BYPASS_SECTION();
  417. if(cb == 0)
  418. {
  419. hal_cache_tag_flush();
  420. }
  421. spif_unlock(cs);
  422. return retval;
  423. }
  424. /**
  425. * @fn void HalFlashLock(flash_lock_t lock)
  426. * @brief flash lock.
  427. * @param none.
  428. * @return none
  429. */
  430. void HalFlashLock(flash_lock_t lock)
  431. {
  432. REG_FLASH_WRITE_CTRL = WRITE_ENABLE;
  433. REG_FLASH_BP = lock;
  434. REG_FLASH_WRITE_CTRL = WRITE_PROTECT;
  435. }
  436. /**
  437. * @fn void HalFlashUnlock(void)
  438. * @brief flash unlock.
  439. * @param none.
  440. * @return none
  441. */
  442. void HalFlashUnlock(void)
  443. {
  444. while( _spif_read_status_reg_x() )
  445. {
  446. REG_FLASH_WRITE_CTRL = WRITE_ENABLE;
  447. REG_FLASH_BP = FLASH_UNLOCK;
  448. REG_FLASH_WRITE_CTRL = WRITE_PROTECT;
  449. WaitUs(50);
  450. }
  451. }