gd32f4xx_fmc.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. /*!
  2. \file gd32f4xx_fmc.c
  3. \brief FMC driver
  4. \version 2016-08-15, V1.0.0, firmware for GD32F4xx
  5. \version 2018-12-12, V2.0.0, firmware for GD32F4xx
  6. \version 2020-09-30, V2.1.0, firmware for GD32F4xx
  7. */
  8. /*
  9. Copyright (c) 2020, GigaDevice Semiconductor Inc.
  10. Redistribution and use in source and binary forms, with or without modification,
  11. are permitted provided that the following conditions are met:
  12. 1. Redistributions of source code must retain the above copyright notice, this
  13. list of conditions and the following disclaimer.
  14. 2. Redistributions in binary form must reproduce the above copyright notice,
  15. this list of conditions and the following disclaimer in the documentation
  16. and/or other materials provided with the distribution.
  17. 3. Neither the name of the copyright holder nor the names of its contributors
  18. may be used to endorse or promote products derived from this software without
  19. specific prior written permission.
  20. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  22. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  23. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  24. INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  27. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  29. OF SUCH DAMAGE.
  30. */
  31. #include "gd32f4xx_fmc.h"
  32. /*!
  33. \brief set the wait state counter value
  34. \param[in] wscnt: wait state counter value
  35. only one parameter can be selected which is shown as below:
  36. \arg WS_WSCNT_0: FMC 0 wait
  37. \arg WS_WSCNT_1: FMC 1 wait
  38. \arg WS_WSCNT_2: FMC 2 wait
  39. \arg WS_WSCNT_3: FMC 3 wait
  40. \arg WS_WSCNT_4: FMC 4 wait
  41. \arg WS_WSCNT_5: FMC 5 wait
  42. \arg WS_WSCNT_6: FMC 6 wait
  43. \arg WS_WSCNT_7: FMC 7 wait
  44. \arg WS_WSCNT_8: FMC 8 wait
  45. \arg WS_WSCNT_9: FMC 9 wait
  46. \arg WS_WSCNT_10: FMC 10 wait
  47. \arg WS_WSCNT_11: FMC 11 wait
  48. \arg WS_WSCNT_12: FMC 12 wait
  49. \arg WS_WSCNT_13: FMC 13 wait
  50. \arg WS_WSCNT_14: FMC 14 wait
  51. \arg WS_WSCNT_15: FMC 15 wait
  52. \param[out] none
  53. \retval none
  54. */
  55. void fmc_wscnt_set(uint32_t wscnt)
  56. {
  57. uint32_t reg;
  58. reg = FMC_WS;
  59. /* set the wait state counter value */
  60. reg &= ~FMC_WC_WSCNT;
  61. FMC_WS = (reg | wscnt);
  62. }
  63. /*!
  64. \brief unlock the main FMC operation
  65. \param[in] none
  66. \param[out] none
  67. \retval none
  68. */
  69. void fmc_unlock(void)
  70. {
  71. if((RESET != (FMC_CTL & FMC_CTL_LK))){
  72. /* write the FMC key */
  73. FMC_KEY = UNLOCK_KEY0;
  74. FMC_KEY = UNLOCK_KEY1;
  75. }
  76. }
  77. /*!
  78. \brief lock the main FMC operation
  79. \param[in] none
  80. \param[out] none
  81. \retval none
  82. */
  83. void fmc_lock(void)
  84. {
  85. /* set the LK bit*/
  86. FMC_CTL |= FMC_CTL_LK;
  87. }
  88. /*!
  89. \brief erase sector
  90. \param[in] fmc_sector: select the sector to erase
  91. only one parameter can be selected which is shown as below:
  92. \arg CTL_SECTOR_NUMBER_0: sector 0
  93. \arg CTL_SECTOR_NUMBER_1: sector 1
  94. \arg CTL_SECTOR_NUMBER_2: sector 2
  95. \arg CTL_SECTOR_NUMBER_3: sector 3
  96. \arg CTL_SECTOR_NUMBER_4: sector 4
  97. \arg CTL_SECTOR_NUMBER_5: sector 5
  98. \arg CTL_SECTOR_NUMBER_6: sector 6
  99. \arg CTL_SECTOR_NUMBER_7: sector 7
  100. \arg CTL_SECTOR_NUMBER_8: sector 8
  101. \arg CTL_SECTOR_NUMBER_9: sector 9
  102. \arg CTL_SECTOR_NUMBER_10: sector 10
  103. \arg CTL_SECTOR_NUMBER_11: sector 11
  104. \arg CTL_SECTOR_NUMBER_12: sector 12
  105. \arg CTL_SECTOR_NUMBER_13: sector 13
  106. \arg CTL_SECTOR_NUMBER_14: sector 14
  107. \arg CTL_SECTOR_NUMBER_15: sector 15
  108. \arg CTL_SECTOR_NUMBER_16: sector 16
  109. \arg CTL_SECTOR_NUMBER_17: sector 17
  110. \arg CTL_SECTOR_NUMBER_18: sector 18
  111. \arg CTL_SECTOR_NUMBER_19: sector 19
  112. \arg CTL_SECTOR_NUMBER_20: sector 20
  113. \arg CTL_SECTOR_NUMBER_21: sector 21
  114. \arg CTL_SECTOR_NUMBER_22: sector 22
  115. \arg CTL_SECTOR_NUMBER_23: sector 23
  116. \arg CTL_SECTOR_NUMBER_24: sector 24
  117. \arg CTL_SECTOR_NUMBER_25: sector 25
  118. \arg CTL_SECTOR_NUMBER_26: sector 26
  119. \arg CTL_SECTOR_NUMBER_27: sector 27
  120. \param[out] none
  121. \retval state of FMC
  122. \arg FMC_READY: the operation has been completed
  123. \arg FMC_BUSY: the operation is in progress
  124. \arg FMC_RDDERR: read D-bus protection error
  125. \arg FMC_PGSERR: program sequence error
  126. \arg FMC_PGMERR: program size not match error
  127. \arg FMC_WPERR: erase/program protection error
  128. \arg FMC_OPERR: operation error
  129. \arg FMC_PGERR: program error
  130. */
  131. fmc_state_enum fmc_sector_erase(uint32_t fmc_sector)
  132. {
  133. fmc_state_enum fmc_state = FMC_READY;
  134. /* wait for the FMC ready */
  135. fmc_state = fmc_ready_wait();
  136. if(FMC_READY == fmc_state){
  137. /* start sector erase */
  138. FMC_CTL &= ~FMC_CTL_SN;
  139. FMC_CTL |= (FMC_CTL_SER | fmc_sector);
  140. FMC_CTL |= FMC_CTL_START;
  141. /* wait for the FMC ready */
  142. fmc_state = fmc_ready_wait();
  143. /* reset the SER bit */
  144. FMC_CTL &= (~FMC_CTL_SER);
  145. FMC_CTL &= ~FMC_CTL_SN;
  146. }
  147. /* return the FMC state */
  148. return fmc_state;
  149. }
  150. /*!
  151. \brief erase whole chip
  152. \param[in] none
  153. \param[out] none
  154. \retval state of FMC
  155. \arg FMC_READY: the operation has been completed
  156. \arg FMC_BUSY: the operation is in progress
  157. \arg FMC_RDDERR: read D-bus protection error
  158. \arg FMC_PGSERR: program sequence error
  159. \arg FMC_PGMERR: program size not match error
  160. \arg FMC_WPERR: erase/program protection error
  161. \arg FMC_OPERR: operation error
  162. \arg FMC_PGERR: program error
  163. */
  164. fmc_state_enum fmc_mass_erase(void)
  165. {
  166. fmc_state_enum fmc_state = FMC_READY;
  167. /* wait for the FMC ready */
  168. fmc_state = fmc_ready_wait();
  169. if(FMC_READY == fmc_state){
  170. /* start whole chip erase */
  171. FMC_CTL |= (FMC_CTL_MER0 | FMC_CTL_MER1);
  172. FMC_CTL |= FMC_CTL_START;
  173. /* wait for the FMC ready */
  174. fmc_state = fmc_ready_wait();
  175. /* reset the MER bits */
  176. FMC_CTL &= ~(FMC_CTL_MER0 | FMC_CTL_MER1);
  177. }
  178. /* return the fmc state */
  179. return fmc_state;
  180. }
  181. /*!
  182. \brief erase all FMC sectors in bank0
  183. \param[in] none
  184. \param[out] none
  185. \retval state of FMC
  186. \arg FMC_READY: the operation has been completed
  187. \arg FMC_BUSY: the operation is in progress
  188. \arg FMC_RDDERR: read D-bus protection error
  189. \arg FMC_PGSERR: program sequence error
  190. \arg FMC_PGMERR: program size not match error
  191. \arg FMC_WPERR: erase/program protection error
  192. \arg FMC_OPERR: operation error
  193. \arg FMC_PGERR: program error
  194. */
  195. fmc_state_enum fmc_bank0_erase(void)
  196. {
  197. fmc_state_enum fmc_state = FMC_READY;
  198. /* wait for the FMC ready */
  199. fmc_state = fmc_ready_wait();
  200. if(FMC_READY == fmc_state){
  201. /* start FMC bank0 erase */
  202. FMC_CTL |= FMC_CTL_MER0;
  203. FMC_CTL |= FMC_CTL_START;
  204. /* wait for the FMC ready */
  205. fmc_state = fmc_ready_wait();
  206. /* reset the MER0 bit */
  207. FMC_CTL &= (~FMC_CTL_MER0);
  208. }
  209. /* return the fmc state */
  210. return fmc_state;
  211. }
  212. /*!
  213. \brief erase all FMC sectors in bank1
  214. \param[in] none
  215. \param[out] none
  216. \retval state of FMC
  217. \arg FMC_READY: the operation has been completed
  218. \arg FMC_BUSY: the operation is in progress
  219. \arg FMC_RDDERR: read D-bus protection error
  220. \arg FMC_PGSERR: program sequence error
  221. \arg FMC_PGMERR: program size not match error
  222. \arg FMC_WPERR: erase/program protection error
  223. \arg FMC_OPERR: operation error
  224. \arg FMC_PGERR: program error
  225. */
  226. fmc_state_enum fmc_bank1_erase(void)
  227. {
  228. fmc_state_enum fmc_state = FMC_READY;
  229. /* wait for the FMC ready */
  230. fmc_state = fmc_ready_wait();
  231. if(FMC_READY == fmc_state){
  232. /* start FMC bank1 erase */
  233. FMC_CTL |= FMC_CTL_MER1;
  234. FMC_CTL |= FMC_CTL_START;
  235. /* wait for the FMC ready */
  236. fmc_state = fmc_ready_wait();
  237. /* reset the MER1 bit */
  238. FMC_CTL &= (~FMC_CTL_MER1);
  239. }
  240. /* return the fmc state */
  241. return fmc_state;
  242. }
  243. /*!
  244. \brief program a word at the corresponding address
  245. \param[in] address: address to program
  246. \param[in] data: word to program(0x00000000 - 0xFFFFFFFF)
  247. \param[out] none
  248. \retval state of FMC
  249. \arg FMC_READY: the operation has been completed
  250. \arg FMC_BUSY: the operation is in progress
  251. \arg FMC_RDDERR: read D-bus protection error
  252. \arg FMC_PGSERR: program sequence error
  253. \arg FMC_PGMERR: program size not match error
  254. \arg FMC_WPERR: erase/program protection error
  255. \arg FMC_OPERR: operation error
  256. \arg FMC_PGERR: program error
  257. */
  258. fmc_state_enum fmc_word_program(uint32_t address, uint32_t data)
  259. {
  260. fmc_state_enum fmc_state = FMC_READY;
  261. /* wait for the FMC ready */
  262. fmc_state = fmc_ready_wait();
  263. if(FMC_READY == fmc_state){
  264. /* set the PG bit to start program */
  265. FMC_CTL &= ~FMC_CTL_PSZ;
  266. FMC_CTL |= CTL_PSZ_WORD;
  267. FMC_CTL |= FMC_CTL_PG;
  268. REG32(address) = data;
  269. /* wait for the FMC ready */
  270. fmc_state = fmc_ready_wait();
  271. /* reset the PG bit */
  272. FMC_CTL &= ~FMC_CTL_PG;
  273. }
  274. /* return the FMC state */
  275. return fmc_state;
  276. }
  277. /*!
  278. \brief program a half word at the corresponding address
  279. \param[in] address: address to program
  280. \param[in] data: halfword to program(0x0000 - 0xFFFF)
  281. \param[out] none
  282. \retval state of FMC
  283. \arg FMC_READY: the operation has been completed
  284. \arg FMC_BUSY: the operation is in progress
  285. \arg FMC_RDDERR: read D-bus protection error
  286. \arg FMC_PGSERR: program sequence error
  287. \arg FMC_PGMERR: program size not match error
  288. \arg FMC_WPERR: erase/program protection error
  289. \arg FMC_OPERR: operation error
  290. \arg FMC_PGERR: program error
  291. */
  292. fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data)
  293. {
  294. fmc_state_enum fmc_state = FMC_READY;
  295. /* wait for the FMC ready */
  296. fmc_state = fmc_ready_wait();
  297. if(FMC_READY == fmc_state){
  298. /* set the PG bit to start program */
  299. FMC_CTL &= ~FMC_CTL_PSZ;
  300. FMC_CTL |= CTL_PSZ_HALF_WORD;
  301. FMC_CTL |= FMC_CTL_PG;
  302. REG16(address) = data;
  303. /* wait for the FMC ready */
  304. fmc_state = fmc_ready_wait();
  305. /* reset the PG bit */
  306. FMC_CTL &= ~FMC_CTL_PG;
  307. }
  308. /* return the FMC state */
  309. return fmc_state;
  310. }
  311. /*!
  312. \brief program a byte at the corresponding address
  313. \param[in] address: address to program
  314. \param[in] data: byte to program(0x00 - 0xFF)
  315. \param[out] none
  316. \retval state of FMC
  317. \arg FMC_READY: the operation has been completed
  318. \arg FMC_BUSY: the operation is in progress
  319. \arg FMC_RDDERR: read D-bus protection error
  320. \arg FMC_PGSERR: program sequence error
  321. \arg FMC_PGMERR: program size not match error
  322. \arg FMC_WPERR: erase/program protection error
  323. \arg FMC_OPERR: operation error
  324. \arg FMC_PGERR: program error
  325. */
  326. fmc_state_enum fmc_byte_program(uint32_t address, uint8_t data)
  327. {
  328. fmc_state_enum fmc_state = FMC_READY;
  329. /* wait for the FMC ready */
  330. fmc_state = fmc_ready_wait();
  331. if(FMC_READY == fmc_state){
  332. /* set the PG bit to start program */
  333. FMC_CTL &= ~FMC_CTL_PSZ;
  334. FMC_CTL |= CTL_PSZ_BYTE;
  335. FMC_CTL |= FMC_CTL_PG;
  336. REG8(address) = data;
  337. /* wait for the FMC ready */
  338. fmc_state = fmc_ready_wait();
  339. /* reset the PG bit */
  340. FMC_CTL &= ~FMC_CTL_PG;
  341. }
  342. /* return the FMC state */
  343. return fmc_state;
  344. }
  345. /*!
  346. \brief unlock the option byte operation
  347. \param[in] none
  348. \param[out] none
  349. \retval none
  350. */
  351. void ob_unlock(void)
  352. {
  353. if(RESET != (FMC_OBCTL0 & FMC_OBCTL0_OB_LK)){
  354. /* write the FMC key */
  355. FMC_OBKEY = OB_UNLOCK_KEY0;
  356. FMC_OBKEY = OB_UNLOCK_KEY1;
  357. }
  358. }
  359. /*!
  360. \brief lock the option byte operation
  361. \param[in] none
  362. \param[out] none
  363. \retval none
  364. */
  365. void ob_lock(void)
  366. {
  367. /* reset the OB_LK bit */
  368. FMC_OBCTL0 |= FMC_OBCTL0_OB_LK;
  369. }
  370. /*!
  371. \brief send option byte change command
  372. \param[in] none
  373. \param[out] none
  374. \retval none
  375. */
  376. void ob_start(void)
  377. {
  378. fmc_state_enum fmc_state = FMC_READY;
  379. /* set the OB_START bit in OBCTL0 register */
  380. FMC_OBCTL0 |= FMC_OBCTL0_OB_START;
  381. fmc_state = fmc_ready_wait();
  382. if(FMC_READY != fmc_state){
  383. while(1){
  384. }
  385. }
  386. }
  387. /*!
  388. \brief erase option byte
  389. \param[in] none
  390. \param[out] none
  391. \retval none
  392. */
  393. void ob_erase(void)
  394. {
  395. uint32_t reg, reg1;
  396. fmc_state_enum fmc_state = FMC_READY;
  397. /* wait for the FMC ready */
  398. fmc_state = fmc_ready_wait();
  399. if(FMC_READY == fmc_state){
  400. reg = FMC_OBCTL0;
  401. reg1 = FMC_OBCTL1;
  402. /* reset the OB_FWDGT, OB_DEEPSLEEP and OB_STDBY, set according to ob_fwdgt ,ob_deepsleep and ob_stdby */
  403. reg |= (FMC_OBCTL0_NWDG_HW | FMC_OBCTL0_NRST_DPSLP | FMC_OBCTL0_NRST_STDBY);
  404. /* reset the BOR level */
  405. reg |= FMC_OBCTL0_BOR_TH;
  406. /* reset option byte boot bank value */
  407. reg &= ~FMC_OBCTL0_BB;
  408. /* reset option byte dbs value */
  409. reg &= ~FMC_OBCTL0_DBS;
  410. /* reset drp and wp value */
  411. reg |= FMC_OBCTL0_WP0;
  412. reg &= (~FMC_OBCTL0_DRP);
  413. FMC_OBCTL0 = reg;
  414. reg1 |= FMC_OBCTL1_WP1;
  415. FMC_OBCTL1 = reg1;
  416. FMC_OBCTL0 = reg;
  417. }
  418. }
  419. /*!
  420. \brief enable write protection
  421. \param[in] ob_wp: specify sector to be write protected
  422. one or more parameters can be selected which are shown as below:
  423. \arg OB_WP_x(x=0..22):sector x(x = 0,1,2...22)
  424. \arg OB_WP_23_27: sector23~27
  425. \arg OB_WP_ALL: all sector
  426. \param[out] none
  427. \retval none
  428. */
  429. void ob_write_protection_enable(uint32_t ob_wp)
  430. {
  431. uint32_t reg0 = FMC_OBCTL0;
  432. uint32_t reg1 = FMC_OBCTL1;
  433. fmc_state_enum fmc_state = FMC_READY;
  434. if(RESET != (FMC_OBCTL0 & FMC_OBCTL0_DRP)){
  435. while(1){
  436. }
  437. }
  438. /* wait for the FMC ready */
  439. fmc_state = fmc_ready_wait();
  440. if(FMC_READY == fmc_state){
  441. reg0 &= (~((uint32_t)ob_wp << 16));
  442. reg1 &= (~(ob_wp & 0xFFFF0000U));
  443. FMC_OBCTL0 = reg0;
  444. FMC_OBCTL1 = reg1;
  445. }
  446. }
  447. /*!
  448. \brief disable write protection
  449. \param[in] ob_wp: specify sector to be write protected
  450. one or more parameters can be selected which are shown as below:
  451. \arg OB_WP_x(x=0..22):sector x(x = 0,1,2...22)
  452. \arg OB_WP_23_27: sector23~27
  453. \arg OB_WP_ALL: all sector
  454. \param[out] none
  455. \retval none
  456. */
  457. void ob_write_protection_disable(uint32_t ob_wp)
  458. {
  459. uint32_t reg0 = FMC_OBCTL0;
  460. uint32_t reg1 = FMC_OBCTL1;
  461. fmc_state_enum fmc_state = FMC_READY;
  462. if(RESET != (FMC_OBCTL0 & FMC_OBCTL0_DRP)){
  463. while(1){
  464. }
  465. }
  466. /* wait for the FMC ready */
  467. fmc_state = fmc_ready_wait();
  468. if(FMC_READY == fmc_state){
  469. reg0 |= ((uint32_t)ob_wp << 16);
  470. reg1 |= (ob_wp & 0xFFFF0000U);
  471. FMC_OBCTL0 = reg0;
  472. FMC_OBCTL1 = reg1;
  473. }
  474. }
  475. /*!
  476. \brief enable erase/program protection and D-bus read protection
  477. \param[in] ob_drp: enable the WPx bits used as erase/program protection and D-bus read protection of each sector
  478. one or more parameters can be selected which are shown as below:
  479. \arg OB_DRP_x(x=0..22): sector x(x = 0,1,2...22)
  480. \arg OB_DRP_23_27: sector23~27
  481. \arg OB_DRP_ALL: all sector
  482. \param[out] none
  483. \retval none
  484. */
  485. void ob_drp_enable(uint32_t ob_drp)
  486. {
  487. uint32_t reg0 = FMC_OBCTL0;
  488. uint32_t reg1 = FMC_OBCTL1;
  489. fmc_state_enum fmc_state = FMC_READY;
  490. uint32_t drp_state = FMC_OBCTL0 & FMC_OBCTL0_DRP;
  491. uint32_t wp0_state = FMC_OBCTL0 & FMC_OBCTL0_WP0;
  492. uint32_t wp1_state = FMC_OBCTL1 & FMC_OBCTL1_WP1;
  493. /*disable write protection before enable D-bus read protection*/
  494. if((RESET != drp_state) && ((FMC_OBCTL0_WP0 != wp0_state) && (FMC_OBCTL1_WP1 != wp1_state))){
  495. while(1){
  496. }
  497. }
  498. /* wait for the FMC ready */
  499. fmc_state = fmc_ready_wait();
  500. if(FMC_READY == fmc_state){
  501. reg0 &= ~FMC_OBCTL0_WP0;
  502. reg1 &= ~FMC_OBCTL1_WP1;
  503. reg0 |= ((uint32_t)ob_drp << 16);
  504. reg1 |= ((uint32_t)ob_drp & 0xFFFF0000U);
  505. FMC_OBCTL0 = reg0;
  506. FMC_OBCTL1 = reg1;
  507. FMC_OBCTL0 |= FMC_OBCTL0_DRP;
  508. }
  509. }
  510. /*!
  511. \brief disable erase/program protection and D-bus read protection
  512. \param[in] ob_drp: disable the WPx bits used as erase/program protection and D-bus read protection of each sector
  513. one or more parameters can be selected which are shown as below:
  514. \arg OB_DRP_x(x=0..22): sector x(x = 0,1,2...22)
  515. \arg OB_DRP_23_27: sector23~27
  516. \arg OB_DRP_ALL: all sector
  517. \param[out] none
  518. \retval none
  519. */
  520. void ob_drp_disable(uint32_t ob_drp)
  521. {
  522. uint32_t reg0 = FMC_OBCTL0;
  523. uint32_t reg1 = FMC_OBCTL1;
  524. fmc_state_enum fmc_state = FMC_READY;
  525. /* wait for the FMC ready */
  526. fmc_state = fmc_ready_wait();
  527. if(FMC_READY == fmc_state){
  528. reg0 |= FMC_OBCTL0_WP0;
  529. reg0 &= (~FMC_OBCTL0_DRP);
  530. FMC_OBCTL0 = reg0;
  531. reg1 |= FMC_OBCTL1_WP1;
  532. FMC_OBCTL1 = reg1;
  533. }
  534. }
  535. /*!
  536. \brief configure security protection level
  537. \param[in] ob_spc: specify security protection level
  538. only one parameter can be selected which is shown as below:
  539. \arg FMC_NSPC: no security protection
  540. \arg FMC_LSPC: low security protection
  541. \arg FMC_HSPC: high security protection
  542. \param[out] none
  543. \retval none
  544. */
  545. void ob_security_protection_config(uint8_t ob_spc)
  546. {
  547. fmc_state_enum fmc_state = FMC_READY;
  548. /* wait for the FMC ready */
  549. fmc_state = fmc_ready_wait();
  550. if(FMC_READY == fmc_state){
  551. uint32_t reg;
  552. reg = FMC_OBCTL0;
  553. /* reset the OBCTL0_SPC, set according to ob_spc */
  554. reg &= ~FMC_OBCTL0_SPC;
  555. reg |= ((uint32_t)ob_spc << 8);
  556. FMC_OBCTL0 = reg;
  557. }
  558. }
  559. /*!
  560. \brief program the FMC user option byte
  561. \param[in] ob_fwdgt: option byte watchdog value
  562. only one parameter can be selected which is shown as below:
  563. \arg OB_FWDGT_SW: software free watchdog
  564. \arg OB_FWDGT_HW: hardware free watchdog
  565. \param[in] ob_deepsleep: option byte deepsleep reset value
  566. only one parameter can be selected which is shown as below:
  567. \arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode
  568. \arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode
  569. \param[in] ob_stdby:option byte standby reset value
  570. only one parameter can be selected which is shown as below:
  571. \arg OB_STDBY_NRST: no reset when entering standby mode
  572. \arg OB_STDBY_RST: generate a reset instead of entering standby mode
  573. \param[out] none
  574. \retval none
  575. */
  576. void ob_user_write(uint32_t ob_fwdgt, uint32_t ob_deepsleep, uint32_t ob_stdby)
  577. {
  578. fmc_state_enum fmc_state = FMC_READY;
  579. /* wait for the FMC ready */
  580. fmc_state = fmc_ready_wait();
  581. if(FMC_READY == fmc_state){
  582. uint32_t reg;
  583. reg = FMC_OBCTL0;
  584. /* reset the OB_FWDGT, OB_DEEPSLEEP and OB_STDBY, set according to ob_fwdgt ,ob_deepsleep and ob_stdby */
  585. reg &= ~(FMC_OBCTL0_NWDG_HW | FMC_OBCTL0_NRST_DPSLP | FMC_OBCTL0_NRST_STDBY);
  586. FMC_OBCTL0 = (reg | ob_fwdgt | ob_deepsleep | ob_stdby);
  587. }
  588. }
  589. /*!
  590. \brief program the option byte BOR threshold value
  591. \param[in] ob_bor_th: user option byte
  592. only one parameter can be selected which is shown as below:
  593. \arg OB_BOR_TH_VALUE3: BOR threshold value 3
  594. \arg OB_BOR_TH_VALUE2: BOR threshold value 2
  595. \arg OB_BOR_TH_VALUE1: BOR threshold value 1
  596. \arg OB_BOR_TH_OFF: no BOR function
  597. \param[out] none
  598. \retval none
  599. */
  600. void ob_user_bor_threshold(uint32_t ob_bor_th)
  601. {
  602. uint32_t reg;
  603. reg = FMC_OBCTL0;
  604. /* set the BOR level */
  605. reg &= ~FMC_OBCTL0_BOR_TH;
  606. FMC_OBCTL0 = (reg | ob_bor_th);
  607. }
  608. /*!
  609. \brief configure the option byte boot bank value
  610. \param[in] boot_mode: specifies the option byte boot bank value
  611. only one parameter can be selected which is shown as below:
  612. \arg OB_BB_DISABLE: boot from bank0
  613. \arg OB_BB_ENABLE: boot from bank1 or bank0 if bank1 is void
  614. \param[out] none
  615. \retval none
  616. */
  617. void ob_boot_mode_config(uint32_t boot_mode)
  618. {
  619. uint32_t reg;
  620. reg = FMC_OBCTL0;
  621. /* set option byte boot bank value */
  622. reg &= ~FMC_OBCTL0_BB;
  623. FMC_OBCTL0 = (reg | boot_mode);
  624. }
  625. /*!
  626. \brief get the FMC user option byte
  627. \param[in] none
  628. \param[out] none
  629. \retval the FMC user option byte values: ob_fwdgt(Bit0), ob_deepsleep(Bit1), ob_stdby(Bit2)
  630. */
  631. uint8_t ob_user_get(void)
  632. {
  633. return (uint8_t)((uint8_t)(FMC_OBCTL0 >> 5) & (uint8_t)0x07);
  634. }
  635. /*!
  636. \brief get the FMC option byte write protection
  637. \param[in] none
  638. \param[out] none
  639. \retval the FMC write protection option byte value
  640. */
  641. uint16_t ob_write_protection0_get(void)
  642. {
  643. /* return the FMC write protection option byte value */
  644. return (uint16_t)(((uint16_t)(FMC_OBCTL0 >> 16)) & (uint16_t)0x0FFF);
  645. }
  646. /*!
  647. \brief get the FMC option byte write protection
  648. \param[in] none
  649. \param[out] none
  650. \retval the FMC write protection option byte value
  651. */
  652. uint16_t ob_write_protection1_get(void)
  653. {
  654. /* return the the FMC write protection option byte value */
  655. return (uint16_t)(((uint16_t)(FMC_OBCTL1 >> 16)) & (uint16_t)0x0FFF);
  656. }
  657. /*!
  658. \brief get the FMC D-bus read protection protection
  659. \param[in] none
  660. \param[out] none
  661. \retval the FMC erase/program protection and D-bus read protection option bytes value
  662. */
  663. uint16_t ob_drp0_get(void)
  664. {
  665. /* return the FMC erase/program protection and D-bus read protection option bytes value */
  666. return (uint16_t)(((uint16_t)(FMC_OBCTL0 >> 16)) & (uint16_t)0x0FFF);
  667. }
  668. /*!
  669. \brief get the FMC D-bus read protection protection
  670. \param[in] none
  671. \param[out] none
  672. \retval the FMC erase/program protection and D-bus read protection option bytes value
  673. */
  674. uint16_t ob_drp1_get(void)
  675. {
  676. /* return the FMC erase/program protection and D-bus read protection option bytes value */
  677. return (uint16_t)(((uint16_t)(FMC_OBCTL1 >> 16)) & (uint16_t)0x0FFF);
  678. }
  679. /*!
  680. \brief get the FMC option byte security protection
  681. \param[in] none
  682. \param[out] none
  683. \retval FlagStatus: SET or RESET
  684. */
  685. FlagStatus ob_spc_get(void)
  686. {
  687. FlagStatus spc_state = RESET;
  688. if (((uint8_t)(FMC_OBCTL0 >> 8)) != (uint8_t)FMC_NSPC){
  689. spc_state = SET;
  690. }else{
  691. spc_state = RESET;
  692. }
  693. return spc_state;
  694. }
  695. /*!
  696. \brief get the FMC option byte BOR threshold value
  697. \param[in] none
  698. \param[out] none
  699. \retval the FMC BOR threshold value:OB_BOR_TH_OFF,OB_BOR_TH_VALUE1,OB_BOR_TH_VALUE2,OB_BOR_TH_VALUE3
  700. */
  701. uint8_t ob_user_bor_threshold_get(void)
  702. {
  703. /* return the FMC BOR threshold value */
  704. return (uint8_t)((uint8_t)FMC_OBCTL0 & (uint8_t)0x0C);
  705. }
  706. /*!
  707. \brief enable FMC interrupt
  708. \param[in] fmc_int: the FMC interrupt source
  709. only one parameter can be selected which is shown as below:
  710. \arg FMC_INT_END: enable FMC end of program interrupt
  711. \arg FMC_INT_ERR: enable FMC error interrupt
  712. \param[out] none
  713. \retval none
  714. */
  715. void fmc_interrupt_enable(uint32_t fmc_int)
  716. {
  717. FMC_CTL |= fmc_int;
  718. }
  719. /*!
  720. \brief disable FMC interrupt
  721. \param[in] fmc_int: the FMC interrupt source
  722. only one parameter can be selected which is shown as below:
  723. \arg FMC_INT_END: disable FMC end of program interrupt
  724. \arg FMC_INT_ERR: disable FMC error interrupt
  725. \param[out] none
  726. \retval none
  727. */
  728. void fmc_interrupt_disable(uint32_t fmc_int)
  729. {
  730. FMC_CTL &= ~(uint32_t)fmc_int;
  731. }
  732. /*!
  733. \brief get flag set or reset
  734. \param[in] fmc_flag: check FMC flag
  735. only one parameter can be selected which is shown as below:
  736. \arg FMC_FLAG_BUSY: FMC busy flag bit
  737. \arg FMC_FLAG_RDDERR: FMC read D-bus protection error flag bit
  738. \arg FMC_FLAG_PGSERR: FMC program sequence error flag bit
  739. \arg FMC_FLAG_PGMERR: FMC program size not match error flag bit
  740. \arg FMC_FLAG_WPERR: FMC Erase/Program protection error flag bit
  741. \arg FMC_FLAG_OPERR: FMC operation error flag bit
  742. \arg FMC_FLAG_END: FMC end of operation flag bit
  743. \param[out] none
  744. \retval FlagStatus: SET or RESET
  745. */
  746. FlagStatus fmc_flag_get(uint32_t fmc_flag)
  747. {
  748. if(FMC_STAT & fmc_flag){
  749. return SET;
  750. }
  751. /* return the state of corresponding FMC flag */
  752. return RESET;
  753. }
  754. /*!
  755. \brief clear the FMC pending flag
  756. \param[in] FMC_flag: clear FMC flag
  757. only one parameter can be selected which is shown as below:
  758. \arg FMC_FLAG_RDDERR: FMC read D-bus protection error flag bit
  759. \arg FMC_FLAG_PGSERR: FMC program sequence error flag bit
  760. \arg FMC_FLAG_PGMERR: FMC program size not match error flag bit
  761. \arg FMC_FLAG_WPERR: FMC erase/program protection error flag bit
  762. \arg FMC_FLAG_OPERR: FMC operation error flag bit
  763. \arg FMC_FLAG_END: FMC end of operation flag bit
  764. \param[out] none
  765. \retval none
  766. */
  767. void fmc_flag_clear(uint32_t fmc_flag)
  768. {
  769. /* clear the flags */
  770. FMC_STAT = fmc_flag;
  771. }
  772. /*!
  773. \brief get the FMC state
  774. \param[in] none
  775. \param[out] none
  776. \retval state of FMC
  777. \arg FMC_READY: the operation has been completed
  778. \arg FMC_BUSY: the operation is in progress
  779. \arg FMC_RDDERR: read D-bus protection error
  780. \arg FMC_PGSERR: program sequence error
  781. \arg FMC_PGMERR: program size not match error
  782. \arg FMC_WPERR: erase/program protection error
  783. \arg FMC_OPERR: operation error
  784. \arg FMC_PGERR: program error
  785. */
  786. fmc_state_enum fmc_state_get(void)
  787. {
  788. fmc_state_enum fmc_state = FMC_READY;
  789. if((FMC_STAT & FMC_FLAG_BUSY) == FMC_FLAG_BUSY){
  790. fmc_state = FMC_BUSY;
  791. }else{
  792. if((FMC_STAT & FMC_FLAG_WPERR) != (uint32_t)0x00){
  793. fmc_state = FMC_WPERR;
  794. }else{
  795. if((FMC_STAT & FMC_FLAG_RDDERR) != (uint32_t)0x00){
  796. fmc_state = FMC_RDDERR;
  797. }else{
  798. if((FMC_STAT & (uint32_t)0xEF) != (uint32_t)0x00){
  799. fmc_state = FMC_PGERR;
  800. }else{
  801. if((FMC_STAT & FMC_FLAG_OPERR) != (uint32_t)0x00){
  802. fmc_state = FMC_OPERR;
  803. }else{
  804. fmc_state = FMC_READY;
  805. }
  806. }
  807. }
  808. }
  809. }
  810. /* return the FMC state */
  811. return fmc_state;
  812. }
  813. /*!
  814. \brief check whether FMC is ready or not
  815. \param[in] none
  816. \param[out] none
  817. \retval state of FMC
  818. \arg FMC_READY: the operation has been completed
  819. \arg FMC_BUSY: the operation is in progress
  820. \arg FMC_RDDERR: read D-bus protection error
  821. \arg FMC_PGSERR: program sequence error
  822. \arg FMC_PGMERR: program size not match error
  823. \arg FMC_WPERR: erase/program protection error
  824. \arg FMC_OPERR: operation error
  825. \arg FMC_PGERR: program error
  826. */
  827. fmc_state_enum fmc_ready_wait(void)
  828. {
  829. fmc_state_enum fmc_state = FMC_BUSY;
  830. /* wait for FMC ready */
  831. do{
  832. /* get FMC state */
  833. fmc_state = fmc_state_get();
  834. }while(FMC_BUSY == fmc_state);
  835. /* return the FMC state */
  836. return fmc_state;
  837. }