gd32f3x0_fmc.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. /*!
  2. \file gd32f3x0_fmc.c
  3. \brief FMC driver
  4. */
  5. /*
  6. Copyright (C) 2017 GigaDevice
  7. 2017-06-06, V1.0.0, firmware for GD32F3x0
  8. */
  9. #include "gd32f3x0_fmc.h"
  10. /* FMC main memory programming functions */
  11. /*!
  12. \brief unlock the main FMC operation
  13. it is better to used in pairs with fmc_lock
  14. \param[in] none
  15. \param[out] none
  16. \retval none
  17. */
  18. void fmc_unlock(void)
  19. {
  20. if((RESET != (FMC_CTL & FMC_CTL_LK))){
  21. /* write the FMC key */
  22. FMC_KEY = UNLOCK_KEY0;
  23. FMC_KEY = UNLOCK_KEY1;
  24. }
  25. }
  26. /*!
  27. \brief lock the main FMC operation
  28. it is better to used in pairs with fmc_unlock after an operation
  29. \param[in] none
  30. \param[out] none
  31. \retval none
  32. */
  33. void fmc_lock(void)
  34. {
  35. /* set the LK bit*/
  36. FMC_CTL |= FMC_CTL_LK;
  37. }
  38. /*!
  39. \brief set the wait state counter value
  40. \param[in] wscnt: wait state counter value
  41. \arg WS_WSCNT_0: 0 wait state added
  42. \arg WS_WSCNT_1: 1 wait state added
  43. \arg WS_WSCNT_2: 2 wait state added
  44. \param[out] none
  45. \retval none
  46. */
  47. void fmc_wscnt_set(uint8_t wscnt)
  48. {
  49. uint32_t reg;
  50. reg = FMC_WS;
  51. /* set the wait state counter value */
  52. reg &= ~FMC_WS_WSCNT;
  53. FMC_WS = (reg | wscnt);
  54. }
  55. /*!
  56. \brief fmc wait state enable
  57. \param[in] none
  58. \param[out] none
  59. \retval none
  60. */
  61. void fmc_wait_state_enable(void)
  62. {
  63. /* unlock the main flash */
  64. fmc_unlock();
  65. /* set the WSEN bit in register FMC_WSEN */
  66. FMC_WSEN |= FMC_WSEN_WSEN;
  67. /* lock the main flash after operation */
  68. fmc_lock();
  69. }
  70. /*!
  71. \brief fmc wait state disable
  72. \param[in] none
  73. \param[out] none
  74. \retval none
  75. */
  76. void fmc_wait_state_disable(void)
  77. {
  78. /* unlock the main flash */
  79. fmc_unlock();
  80. /* reset the WSEN bit in register FMC_WSEN */
  81. FMC_WSEN &= ~FMC_WSEN_WSEN;
  82. /* lock the main flash after operation */
  83. fmc_lock();
  84. }
  85. /*!
  86. \brief erase page
  87. \param[in] page_address: target page start address
  88. \param[out] none
  89. \retval fmc_state
  90. */
  91. fmc_state_enum fmc_page_erase(uint32_t page_address)
  92. {
  93. fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  94. if(FMC_READY == fmc_state){
  95. /* start page erase */
  96. FMC_CTL |= FMC_CTL_PER;
  97. FMC_ADDR = page_address;
  98. FMC_CTL |= FMC_CTL_START;
  99. /* wait for the FMC ready */
  100. fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  101. /* reset the PER bit */
  102. FMC_CTL &= ~FMC_CTL_PER;
  103. }
  104. /* return the FMC state */
  105. return fmc_state;
  106. }
  107. /*!
  108. \brief erase whole chip
  109. \param[in] none
  110. \param[out] none
  111. \retval fmc_state
  112. */
  113. fmc_state_enum fmc_mass_erase(void)
  114. {
  115. fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  116. if(FMC_READY == fmc_state){
  117. /* start chip erase */
  118. FMC_CTL |= FMC_CTL_MER;
  119. FMC_CTL |= FMC_CTL_START;
  120. /* wait for the FMC ready */
  121. fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  122. /* reset the MER bit */
  123. FMC_CTL &= ~FMC_CTL_MER;
  124. }
  125. /* return the fmc state */
  126. return fmc_state;
  127. }
  128. /*!
  129. \brief program a word at the corresponding address
  130. \param[in] address: address to program
  131. \param[in] data: word to program
  132. \param[out] none
  133. \retval fmc_state
  134. */
  135. fmc_state_enum fmc_word_program(uint32_t address, uint32_t data)
  136. {
  137. fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  138. if(FMC_READY == fmc_state){
  139. /* set the PG bit to start program */
  140. FMC_CTL |= FMC_CTL_PG;
  141. REG32(address) = data;
  142. /* wait for the FMC ready */
  143. fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  144. /* reset the PG bit */
  145. FMC_CTL &= ~FMC_CTL_PG;
  146. }
  147. /* return the FMC state */
  148. return fmc_state;
  149. }
  150. /*!
  151. \brief program a half word at the corresponding address
  152. \param[in] address: address to program
  153. \param[in] data: word to program
  154. \param[out] none
  155. \retval fmc_state
  156. */
  157. fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data)
  158. {
  159. fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  160. if(FMC_READY == fmc_state){
  161. /* set the PG bit to start program */
  162. FMC_CTL |= FMC_CTL_PG;
  163. REG16(address) = data;
  164. /* wait for the FMC ready */
  165. fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  166. /* reset the PG bit */
  167. FMC_CTL &= ~FMC_CTL_PG;
  168. }
  169. /* return the FMC state */
  170. return fmc_state;
  171. }
  172. /*!
  173. \brief program a word at the corresponding address without erasing
  174. \param[in] address: address to program
  175. \param[in] data: word to program
  176. \param[out] none
  177. \retval fmc_state
  178. */
  179. fmc_state_enum fmc_word_reprogram(uint32_t address, uint32_t data)
  180. {
  181. fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  182. FMC_WSEN |= FMC_WSEN_BPEN;
  183. if(FMC_READY == fmc_state){
  184. /* set the PG bit to start program */
  185. FMC_CTL |= FMC_CTL_PG;
  186. REG32(address) = data;
  187. /* wait for the FMC ready */
  188. fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  189. /* reset the PG bit */
  190. FMC_CTL &= ~FMC_CTL_PG;
  191. }
  192. /* return the FMC state */
  193. return fmc_state;
  194. }
  195. /* FMC option bytes programming functions */
  196. /*!
  197. \brief unlock the option byte operation
  198. it is better to used in pairs with ob_lock
  199. \param[in] none
  200. \param[out] none
  201. \retval none
  202. */
  203. void ob_unlock(void)
  204. {
  205. if(RESET == (FMC_CTL & FMC_CTL_OBWEN)){
  206. /* write the FMC key */
  207. FMC_OBKEY = UNLOCK_KEY0;
  208. FMC_OBKEY = UNLOCK_KEY1;
  209. }
  210. }
  211. /*!
  212. \brief lock the option byte operation
  213. it is better to used in pairs with ob_unlock after an operation
  214. \param[in] none
  215. \param[out] none
  216. \retval none
  217. */
  218. void ob_lock(void)
  219. {
  220. /* reset the OBWE bit */
  221. FMC_CTL &= ~FMC_CTL_OBWEN;
  222. }
  223. /*!
  224. \brief reload the option byte and generate a system reset
  225. \param[in] none
  226. \param[out] none
  227. \retval none
  228. */
  229. void ob_reset(void)
  230. {
  231. /* set the OBRLD bit */
  232. FMC_CTL |= FMC_CTL_OBRLD;
  233. }
  234. /*!
  235. \brief erase the option byte
  236. programmer must ensure FMC & option byte are both unlocked before calling this function
  237. \param[in] none
  238. \param[out] none
  239. \retval fmc_state
  240. */
  241. fmc_state_enum ob_erase(void)
  242. {
  243. uint16_t fmc_spc;
  244. uint32_t fmc_plevel = ob_obstat_plevel_get();
  245. fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  246. /* get the original option byte security protection code */
  247. if(OB_OBSTAT_PLEVEL_NO == fmc_plevel){
  248. fmc_spc = FMC_NSPC;
  249. }else if(OB_OBSTAT_PLEVEL_LOW == fmc_plevel){
  250. fmc_spc = FMC_LSPC;
  251. }else{
  252. fmc_spc = FMC_HSPC;
  253. fmc_state = FMC_OB_HSPC;
  254. }
  255. if(FMC_READY == fmc_state){
  256. /* start erase the option byte */
  257. FMC_CTL |= FMC_CTL_OBER;
  258. FMC_CTL |= FMC_CTL_START;
  259. /* wait for the FMC ready */
  260. fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  261. if(FMC_READY == fmc_state){
  262. /* reset the OBER bit */
  263. FMC_CTL &= ~FMC_CTL_OBER;
  264. /* set the OBPG bit */
  265. FMC_CTL |= FMC_CTL_OBPG;
  266. /* restore the last get option byte security protection code */
  267. OB_SPC = fmc_spc;
  268. /* wait for the FMC ready */
  269. fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  270. if(FMC_TOERR != fmc_state){
  271. /* reset the OBPG bit */
  272. FMC_CTL &= ~FMC_CTL_OBPG;
  273. }
  274. }else{
  275. if(FMC_TOERR != fmc_state){
  276. /* reset the OBPG bit */
  277. FMC_CTL &= ~FMC_CTL_OBPG;
  278. }
  279. }
  280. }
  281. /* return the FMC state */
  282. return fmc_state;
  283. }
  284. /*!
  285. \brief enable option byte write protection (OB_WP)
  286. \param[in] ob_wp: write protection configuration data
  287. \param[out] none
  288. \retval fmc_state
  289. */
  290. fmc_state_enum ob_write_protection_enable(uint32_t ob_wp)
  291. {
  292. uint16_t ob_wrp0, ob_wrp1;
  293. fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  294. ob_wp = (uint32_t)(~ob_wp);
  295. ob_wrp0 = (uint16_t)(ob_wp & OB_LWP);
  296. ob_wrp1 = (uint16_t)((ob_wp & OB_HWP) >> 8);
  297. if(FMC_READY == fmc_state){
  298. /* set the OBPG bit*/
  299. FMC_CTL |= FMC_CTL_OBPG;
  300. if(0xFFU != ob_wrp0){
  301. OB_WP0 = ob_wrp0;
  302. /* wait for the FMC ready */
  303. fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  304. }
  305. if((FMC_READY == fmc_state) && (0xFFU != ob_wrp1)){
  306. OB_WP1 = ob_wrp1;
  307. /* wait for the FMC ready */
  308. fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  309. }
  310. if(FMC_TOERR != fmc_state){
  311. /* reset the OBPG bit */
  312. FMC_CTL &= ~FMC_CTL_OBPG;
  313. }
  314. }
  315. /* return the FMC state */
  316. return fmc_state;
  317. }
  318. /*!
  319. \brief configure security protection
  320. \param[in] ob_spc: specify security protection code
  321. \arg FMC_NSPC: no security protection
  322. \arg FMC_LSPC: low security protection
  323. \arg FMC_HSPC: high security protection
  324. \param[out] none
  325. \retval fmc_state
  326. */
  327. fmc_state_enum ob_security_protection_config(uint8_t ob_spc)
  328. {
  329. fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  330. /* the OB_SPC byte cannot be reprogrammed if protection level is high */
  331. if(OB_OBSTAT_PLEVEL_HIGH == ob_obstat_plevel_get()){
  332. fmc_state = FMC_OB_HSPC;
  333. }
  334. if(FMC_READY == fmc_state){
  335. /* start erase the option byte */
  336. FMC_CTL |= FMC_CTL_OBER;
  337. FMC_CTL |= FMC_CTL_START;
  338. /* wait for the FMC ready */
  339. fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  340. if(FMC_READY == fmc_state){
  341. /* reset the OBER bit */
  342. FMC_CTL &= ~FMC_CTL_OBER;
  343. /* enable the option bytes programming */
  344. FMC_CTL |= FMC_CTL_OBPG;
  345. OB_SPC = ob_spc;
  346. /* wait for the FMC ready */
  347. fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  348. if(FMC_TOERR != fmc_state){
  349. /* reset the OBPG bit */
  350. FMC_CTL &= ~FMC_CTL_OBPG;
  351. }
  352. }else{
  353. if(FMC_TOERR != fmc_state){
  354. /* reset the OBER bit */
  355. FMC_CTL &= ~FMC_CTL_OBER;
  356. }
  357. }
  358. }
  359. /* return the FMC state */
  360. return fmc_state;
  361. }
  362. /*!
  363. \brief program the FMC user option byte
  364. \param[in] ob_user: user option byte
  365. \arg OB_FWDGT_SW: software free watchdog timer
  366. \arg OB_FWDGT_HW: hardware free watchdog timer
  367. \arg OB_DEEPSLEEP_NRST: generate a reset instead of entering deepsleep mode
  368. \arg OB_DEEPSLEEP_RST: no reset when entering deepsleep mode
  369. \arg OB_STDBY_NRST: generate a reset instead of entering standby mode
  370. \arg OB_STDBY_RST: no reset when entering deepsleep mode
  371. \arg OB_BOOT1_SET_1: BOOT1 bit is 1
  372. \arg OB_BOOT1_SET_0: BOOT1 bit is 0
  373. \arg OB_VDDA_DISABLE: disable VDDA monitor
  374. \arg OB_VDDA_ENABLE: enable VDDA monitor
  375. \arg OB_SRAM_PARITY_DISABLE: disable sram parity check
  376. \arg OB_SRAM_PARITY_ENABLE: enable sram parity check
  377. \param[out] none
  378. \retval fmc_state
  379. */
  380. fmc_state_enum ob_user_write(uint8_t ob_user)
  381. {
  382. fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  383. if(FMC_READY == fmc_state){
  384. /* set the OBPG bit */
  385. FMC_CTL |= FMC_CTL_OBPG;
  386. OB_USER = (uint8_t)(ob_user | OB_USER_MASK);
  387. /* wait for the FMC ready */
  388. fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  389. if(FMC_TOERR != fmc_state){
  390. /* reset the OBPG bit */
  391. FMC_CTL &= ~FMC_CTL_OBPG;
  392. }
  393. }
  394. /* return the FMC state */
  395. return fmc_state;
  396. }
  397. /*!
  398. \brief program the FMC data option byte
  399. \param[in] address: OB_DATA_ADDR0 or OB_DATA_ADDR1
  400. \arg OB_DATA_ADDR0: option byte data address 0
  401. \arg OB_DATA_ADDR1: option byte data address 1
  402. \param[in] data: the byte to be programmed
  403. \param[out] none
  404. \retval fmc_state
  405. */
  406. fmc_state_enum ob_data_program(uint32_t address, uint8_t data)
  407. {
  408. fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  409. if(FMC_READY == fmc_state){
  410. /* set the OBPG bit */
  411. FMC_CTL |= FMC_CTL_OBPG;
  412. REG16(address) = data;
  413. /* wait for the FMC ready */
  414. fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
  415. if(FMC_TOERR != fmc_state){
  416. /* reset the OBPG bit */
  417. FMC_CTL &= ~FMC_CTL_OBPG;
  418. }
  419. }
  420. /* return the FMC state */
  421. return fmc_state;
  422. }
  423. /*!
  424. \brief get OB_USER in register FMC_OBSTAT
  425. \param[in] none
  426. \param[out] none
  427. \retval ob_user
  428. */
  429. uint8_t ob_user_get(void)
  430. {
  431. return (uint8_t)(FMC_OBSTAT >> 8);
  432. }
  433. /*!
  434. \brief get OB_DATA in register FMC_OBSTAT
  435. \param[in] none
  436. \param[out] none
  437. \retval ob_data
  438. */
  439. uint16_t ob_data_get(void)
  440. {
  441. return (uint16_t)(FMC_OBSTAT >> 16);
  442. }
  443. /*!
  444. \brief get the FMC option byte write protection (OB_WP) in register FMC_WP
  445. \param[in] none
  446. \param[out] none
  447. \retval OB_WP
  448. */
  449. uint16_t ob_write_protection_get(void)
  450. {
  451. return (uint16_t)(FMC_WP);
  452. }
  453. /*!
  454. \brief get the value of FMC option byte security protection level (PLEVEL) in FMC_OBSTAT register
  455. \param[in] none
  456. \param[out] none
  457. \retval the value of PLEVEL
  458. */
  459. uint32_t ob_obstat_plevel_get(void)
  460. {
  461. return (FMC_OBSTAT & (FMC_OBSTAT_PLVL_BIT0 | FMC_OBSTAT_PLVL_BIT1));
  462. }
  463. /* FMC interrupts and flags management functions */
  464. /*!
  465. \brief enable FMC interrupt
  466. \param[in] interrupt: the FMC interrupt source
  467. \arg FMC_INTEN_END: FMC end of operation interrupt
  468. \arg FMC_INTEN_ERR: FMC error interrupt
  469. \param[out] none
  470. \retval none
  471. */
  472. void fmc_interrupt_enable(uint32_t interrupt)
  473. {
  474. FMC_CTL |= interrupt;
  475. }
  476. /*!
  477. \brief disable FMC interrupt
  478. \param[in] interrupt: the FMC interrupt source
  479. \arg FMC_INTEN_END: FMC end of operation interrupt
  480. \arg FMC_INTEN_ERR: FMC error interrupt
  481. \param[out] none
  482. \retval none
  483. */
  484. void fmc_interrupt_disable(uint32_t interrupt)
  485. {
  486. FMC_CTL &= ~(uint32_t)interrupt;
  487. }
  488. /*!
  489. \brief get flag set or reset
  490. \param[in] flag: check FMC flag
  491. \arg FMC_FLAG_BUSY: FMC busy flag
  492. \arg FMC_FLAG_PGERR: FMC programming error flag
  493. \arg FMC_FLAG_WPERR: FMC write protection error flag
  494. \arg FMC_FLAG_END: FMC end of programming flag
  495. \param[out] none
  496. \retval FlagStatus: SET or RESET
  497. */
  498. FlagStatus fmc_flag_get(uint32_t flag)
  499. {
  500. FlagStatus status = RESET;
  501. if(FMC_STAT & flag){
  502. status = SET;
  503. }
  504. /* return the state of corresponding FMC flag */
  505. return status;
  506. }
  507. /*!
  508. \brief clear the FMC pending flag by writing 1
  509. \param[in] flag: clear FMC flag
  510. \arg FMC_FLAG_PGERR: FMC programming error flag
  511. \arg FMC_FLAG_WPERR: FMC write protection error flag
  512. \arg FMC_FLAG_END: fmc end of programming flag
  513. \param[out] none
  514. \retval none
  515. */
  516. void fmc_flag_clear(uint32_t flag)
  517. {
  518. /* clear the flags */
  519. FMC_STAT = flag;
  520. }
  521. /*!
  522. \brief get the FMC state
  523. \param[in] none
  524. \param[out] none
  525. \retval fmc_state
  526. */
  527. fmc_state_enum fmc_state_get(void)
  528. {
  529. fmc_state_enum fmc_state = FMC_READY;
  530. if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_BUSY)){
  531. fmc_state = FMC_BUSY;
  532. }else{
  533. if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_WPERR)){
  534. fmc_state = FMC_WPERR;
  535. }else{
  536. if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_PGERR)){
  537. fmc_state = FMC_PGERR;
  538. }
  539. }
  540. }
  541. /* return the FMC state */
  542. return fmc_state;
  543. }
  544. /*!
  545. \brief check whether FMC is ready or not
  546. \param[in] timeout: timeout count
  547. \param[out] none
  548. \retval fmc_state
  549. */
  550. fmc_state_enum fmc_ready_wait(uint32_t timeout)
  551. {
  552. fmc_state_enum fmc_state = FMC_BUSY;
  553. /* wait for FMC ready */
  554. do{
  555. /* get FMC state */
  556. fmc_state = fmc_state_get();
  557. timeout--;
  558. }while((FMC_BUSY == fmc_state) && (0U != timeout));
  559. if(FMC_BUSY == fmc_state){
  560. fmc_state = FMC_TOERR;
  561. }
  562. /* return the FMC state */
  563. return fmc_state;
  564. }