gd32f30x_fmc.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  1. /*!
  2. \file gd32f30x_fmc.c
  3. \brief FMC driver
  4. \version 2017-02-10, V1.0.0, firmware for GD32F30x
  5. \version 2018-10-10, V1.1.0, firmware for GD32F30x
  6. \version 2018-12-25, V2.0.0, firmware for GD32F30x
  7. \version 2020-09-30, V2.1.0, firmware for GD32F30x
  8. */
  9. /*
  10. Copyright (c) 2020, GigaDevice Semiconductor Inc.
  11. Redistribution and use in source and binary forms, with or without modification,
  12. are permitted provided that the following conditions are met:
  13. 1. Redistributions of source code must retain the above copyright notice, this
  14. list of conditions and the following disclaimer.
  15. 2. Redistributions in binary form must reproduce the above copyright notice,
  16. this list of conditions and the following disclaimer in the documentation
  17. and/or other materials provided with the distribution.
  18. 3. Neither the name of the copyright holder nor the names of its contributors
  19. may be used to endorse or promote products derived from this software without
  20. specific prior written permission.
  21. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  22. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  23. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  24. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  25. INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  26. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  28. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  30. OF SUCH DAMAGE.
  31. */
  32. #include "gd32f30x_fmc.h"
  33. /*!
  34. \brief set the wait state counter value
  35. \param[in] wscnt:wait state counter value
  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. \param[out] none
  40. \retval none
  41. */
  42. void fmc_wscnt_set(uint32_t wscnt)
  43. {
  44. uint32_t reg;
  45. reg = FMC_WS;
  46. /* set the wait state counter value */
  47. reg &= ~FMC_WS_WSCNT;
  48. FMC_WS = (reg | wscnt);
  49. }
  50. /*!
  51. \brief unlock the main FMC operation
  52. \param[in] none
  53. \param[out] none
  54. \retval none
  55. */
  56. void fmc_unlock(void)
  57. {
  58. if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){
  59. /* write the FMC unlock key */
  60. FMC_KEY0 = UNLOCK_KEY0;
  61. FMC_KEY0 = UNLOCK_KEY1;
  62. }
  63. if(FMC_BANK0_SIZE < FMC_SIZE){
  64. /* write the FMC unlock key */
  65. if(RESET != (FMC_CTL1 & FMC_CTL1_LK)){
  66. FMC_KEY1 = UNLOCK_KEY0;
  67. FMC_KEY1 = UNLOCK_KEY1;
  68. }
  69. }
  70. }
  71. /*!
  72. \brief unlock the FMC bank0 operation
  73. this function can be used for all GD32F30x devices.
  74. for GD32F30x with flash more than 512KB, this function unlocks bank0.
  75. for GD32F30x with flash no more than 512KB and it is equivalent to fmc_unlock function.
  76. \param[in] none
  77. \param[out] none
  78. \retval none
  79. */
  80. void fmc_bank0_unlock(void)
  81. {
  82. if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){
  83. /* write the FMC unlock key */
  84. FMC_KEY0 = UNLOCK_KEY0;
  85. FMC_KEY0 = UNLOCK_KEY1;
  86. }
  87. }
  88. /*!
  89. \brief unlock the FMC bank1 operation
  90. this function can be used for GD32F30x with flash more than 512KB.
  91. \param[in] none
  92. \param[out] none
  93. \retval none
  94. */
  95. void fmc_bank1_unlock(void)
  96. {
  97. if((RESET != (FMC_CTL1 & FMC_CTL1_LK))){
  98. /* write the FMC unlock key */
  99. FMC_KEY1 = UNLOCK_KEY0;
  100. FMC_KEY1 = UNLOCK_KEY1;
  101. }
  102. }
  103. /*!
  104. \brief lock the main FMC operation
  105. \param[in] none
  106. \param[out] none
  107. \retval none
  108. */
  109. void fmc_lock(void)
  110. {
  111. /* set the LK bit */
  112. FMC_CTL0 |= FMC_CTL0_LK;
  113. if(FMC_BANK0_SIZE < FMC_SIZE){
  114. /* set the LK bit */
  115. FMC_CTL1 |= FMC_CTL1_LK;
  116. }
  117. }
  118. /*!
  119. \brief lock the FMC bank0 operation
  120. this function can be used for all GD32F30X devices.
  121. for GD32F30x with flash more than 512KB, this function locks bank0.
  122. for GD32F30x with flash no more than 512KB and it is equivalent to fmc_lock function.
  123. \param[in] none
  124. \param[out] none
  125. \retval none
  126. */
  127. void fmc_bank0_lock(void)
  128. {
  129. /* set the LK bit*/
  130. FMC_CTL0 |= FMC_CTL0_LK;
  131. }
  132. /*!
  133. \brief lock the FMC bank1 operation
  134. this function can be used for GD32F30x with flash more than 512KB.
  135. \param[in] none
  136. \param[out] none
  137. \retval none
  138. */
  139. void fmc_bank1_lock(void)
  140. {
  141. /* set the LK bit*/
  142. FMC_CTL1 |= FMC_CTL1_LK;
  143. }
  144. /*!
  145. \brief erase page
  146. \param[in] page_address: the page address to be erased.
  147. \param[out] none
  148. \retval state of FMC, refer to fmc_state_enum
  149. */
  150. fmc_state_enum fmc_page_erase(uint32_t page_address)
  151. {
  152. fmc_state_enum fmc_state;
  153. if(FMC_BANK0_SIZE < FMC_SIZE){
  154. if(FMC_BANK0_END_ADDRESS > page_address){
  155. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  156. /* if the last operation is completed, start page erase */
  157. if(FMC_READY == fmc_state){
  158. FMC_CTL0 |= FMC_CTL0_PER;
  159. FMC_ADDR0 = page_address;
  160. FMC_CTL0 |= FMC_CTL0_START;
  161. /* wait for the FMC ready */
  162. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  163. /* reset the PER bit */
  164. FMC_CTL0 &= ~FMC_CTL0_PER;
  165. }
  166. }else{
  167. /* wait for the FMC ready */
  168. fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
  169. /* if the last operation is completed, start page erase */
  170. if(FMC_READY == fmc_state){
  171. FMC_CTL1 |= FMC_CTL1_PER;
  172. FMC_ADDR1 = page_address;
  173. if(FMC_OBSTAT & FMC_OBSTAT_SPC){
  174. FMC_ADDR0 = page_address;
  175. }
  176. FMC_CTL1 |= FMC_CTL1_START;
  177. /* wait for the FMC ready */
  178. fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
  179. /* reset the PER bit */
  180. FMC_CTL1 &= ~FMC_CTL1_PER;
  181. }
  182. }
  183. }else{
  184. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  185. /* if the last operation is completed, start page erase */
  186. if(FMC_READY == fmc_state){
  187. FMC_CTL0 |= FMC_CTL0_PER;
  188. FMC_ADDR0 = page_address;
  189. FMC_CTL0 |= FMC_CTL0_START;
  190. /* wait for the FMC ready */
  191. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  192. /* reset the PER bit */
  193. FMC_CTL0 &= ~FMC_CTL0_PER;
  194. }
  195. }
  196. /* return the FMC state */
  197. return fmc_state;
  198. }
  199. /*!
  200. \brief erase whole chip
  201. \param[in] none
  202. \param[out] none
  203. \retval state of FMC, refer to fmc_state_enum
  204. */
  205. fmc_state_enum fmc_mass_erase(void)
  206. {
  207. fmc_state_enum fmc_state;
  208. if(FMC_BANK0_SIZE < FMC_SIZE){
  209. /* wait for the FMC ready */
  210. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  211. if(FMC_READY == fmc_state){
  212. /* start whole chip erase */
  213. FMC_CTL0 |= FMC_CTL0_MER;
  214. FMC_CTL0 |= FMC_CTL0_START;
  215. /* wait for the FMC ready */
  216. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  217. if(FMC_READY != fmc_state){
  218. return fmc_state;
  219. }
  220. /* reset the MER bit */
  221. FMC_CTL0 &= ~FMC_CTL0_MER;
  222. }
  223. fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
  224. if(FMC_READY == fmc_state){
  225. /* start whole chip erase */
  226. FMC_CTL1 |= FMC_CTL1_MER;
  227. FMC_CTL1 |= FMC_CTL1_START;
  228. /* wait for the FMC ready */
  229. fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
  230. /* reset the MER bit */
  231. FMC_CTL1 &= ~FMC_CTL1_MER;
  232. }
  233. }else{
  234. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  235. if(FMC_READY == fmc_state){
  236. /* start whole chip erase */
  237. FMC_CTL0 |= FMC_CTL0_MER;
  238. FMC_CTL0 |= FMC_CTL0_START;
  239. /* wait for the FMC ready */
  240. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  241. /* reset the MER bit */
  242. FMC_CTL0 &= ~FMC_CTL0_MER;
  243. }
  244. }
  245. /* return the FMC state */
  246. return fmc_state;
  247. }
  248. /*!
  249. \brief erase bank0
  250. \param[in] none
  251. \param[out] none
  252. \retval state of FMC, refer to fmc_state_enum
  253. */
  254. fmc_state_enum fmc_bank0_erase(void)
  255. {
  256. fmc_state_enum fmc_state = FMC_READY;
  257. /* wait for the FMC ready */
  258. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  259. if(FMC_READY == fmc_state){
  260. /* start FMC bank0 erase */
  261. FMC_CTL0 |= FMC_CTL0_MER;
  262. FMC_CTL0 |= FMC_CTL0_START;
  263. /* wait for the FMC ready */
  264. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  265. /* reset the MER bit */
  266. FMC_CTL0 &= ~FMC_CTL0_MER;
  267. }
  268. /* return the fmc state */
  269. return fmc_state;
  270. }
  271. /*!
  272. \brief erase bank1
  273. \param[in] none
  274. \param[out] none
  275. \retval state of FMC, refer to fmc_state_enum
  276. */
  277. fmc_state_enum fmc_bank1_erase(void)
  278. {
  279. fmc_state_enum fmc_state = FMC_READY;
  280. /* wait for the FMC ready */
  281. fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
  282. if(FMC_READY == fmc_state){
  283. /* start FMC bank1 erase */
  284. FMC_CTL1 |= FMC_CTL1_MER;
  285. FMC_CTL1 |= FMC_CTL1_START;
  286. /* wait for the FMC ready */
  287. fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
  288. /* reset the MER bit */
  289. FMC_CTL1 &= ~FMC_CTL1_MER;
  290. }
  291. /* return the fmc state */
  292. return fmc_state;
  293. }
  294. /*!
  295. \brief program a word at the corresponding address
  296. \param[in] address: address to program
  297. \param[in] data: word to program
  298. \param[out] none
  299. \retval state of FMC, refer to fmc_state_enum
  300. */
  301. fmc_state_enum fmc_word_program(uint32_t address, uint32_t data)
  302. {
  303. fmc_state_enum fmc_state = FMC_READY;
  304. if(FMC_BANK0_SIZE < FMC_SIZE){
  305. if(FMC_BANK0_END_ADDRESS > address){
  306. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  307. if(FMC_READY == fmc_state){
  308. /* set the PG bit to start program */
  309. FMC_CTL0 |= FMC_CTL0_PG;
  310. REG32(address) = data;
  311. /* wait for the FMC ready */
  312. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  313. /* reset the PG bit */
  314. FMC_CTL0 &= ~FMC_CTL0_PG;
  315. }
  316. }else{
  317. fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
  318. if(FMC_READY == fmc_state){
  319. /* set the PG bit to start program */
  320. FMC_CTL1 |= FMC_CTL1_PG;
  321. REG32(address) = data;
  322. /* wait for the FMC ready */
  323. fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
  324. /* reset the PG bit */
  325. FMC_CTL1 &= ~FMC_CTL1_PG;
  326. }
  327. }
  328. }else{
  329. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  330. if(FMC_READY == fmc_state){
  331. /* set the PG bit to start program */
  332. FMC_CTL0 |= FMC_CTL0_PG;
  333. REG32(address) = data;
  334. /* wait for the FMC ready */
  335. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  336. /* reset the PG bit */
  337. FMC_CTL0 &= ~FMC_CTL0_PG;
  338. }
  339. }
  340. /* return the FMC state */
  341. return fmc_state;
  342. }
  343. /*!
  344. \brief program a half word at the corresponding address
  345. \param[in] address: address to program
  346. \param[in] data: halfword to program
  347. \param[out] none
  348. \retval state of FMC, refer to fmc_state_enum
  349. */
  350. fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data)
  351. {
  352. fmc_state_enum fmc_state = FMC_READY;
  353. if(FMC_BANK0_SIZE < FMC_SIZE){
  354. if(FMC_BANK0_END_ADDRESS > address){
  355. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  356. if(FMC_READY == fmc_state){
  357. /* set the PG bit to start program */
  358. FMC_CTL0 |= FMC_CTL0_PG;
  359. REG16(address) = data;
  360. /* wait for the FMC ready */
  361. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  362. /* reset the PG bit */
  363. FMC_CTL0 &= ~FMC_CTL0_PG;
  364. }
  365. }else{
  366. fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
  367. if(FMC_READY == fmc_state){
  368. /* set the PG bit to start program */
  369. FMC_CTL1 |= FMC_CTL1_PG;
  370. REG16(address) = data;
  371. /* wait for the FMC ready */
  372. fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
  373. /* reset the PG bit */
  374. FMC_CTL1 &= ~FMC_CTL1_PG;
  375. }
  376. }
  377. }else{
  378. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  379. if(FMC_READY == fmc_state){
  380. /* set the PG bit to start program */
  381. FMC_CTL0 |= FMC_CTL0_PG;
  382. REG16(address) = data;
  383. /* wait for the FMC ready */
  384. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  385. /* reset the PG bit */
  386. FMC_CTL0 &= ~FMC_CTL0_PG;
  387. }
  388. }
  389. /* return the FMC state */
  390. return fmc_state;
  391. }
  392. /*!
  393. \brief program a word at the corresponding address without erasing
  394. \param[in] address: address to program
  395. \param[in] data: word to program
  396. \param[out] none
  397. \retval fmc_state
  398. */
  399. fmc_state_enum fmc_word_reprogram(uint32_t address, uint32_t data)
  400. {
  401. fmc_state_enum fmc_state = FMC_READY;
  402. if(FMC_BANK0_SIZE < FMC_SIZE){
  403. if(FMC_BANK0_END_ADDRESS > address){
  404. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  405. FMC_WSEN |= FMC_WSEN_BPEN;
  406. if(FMC_READY == fmc_state){
  407. /* set the PG bit to start program */
  408. FMC_CTL0 |= FMC_CTL0_PG;
  409. REG32(address) = data;
  410. /* wait for the FMC ready */
  411. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  412. /* reset the PG bit */
  413. FMC_CTL0 &= ~FMC_CTL0_PG;
  414. }
  415. }else{
  416. fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
  417. FMC_WSEN |= FMC_WSEN_BPEN;
  418. if(FMC_READY == fmc_state){
  419. /* set the PG bit to start program */
  420. FMC_CTL1 |= FMC_CTL1_PG;
  421. REG32(address) = data;
  422. /* wait for the FMC ready */
  423. fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT);
  424. /* reset the PG bit */
  425. FMC_CTL1 &= ~FMC_CTL1_PG;
  426. }
  427. }
  428. }else{
  429. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  430. FMC_WSEN |= FMC_WSEN_BPEN;
  431. if(FMC_READY == fmc_state){
  432. /* set the PG bit to start program */
  433. FMC_CTL0 |= FMC_CTL0_PG;
  434. REG32(address) = data;
  435. /* wait for the FMC ready */
  436. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  437. /* reset the PG bit */
  438. FMC_CTL0 &= ~FMC_CTL0_PG;
  439. }
  440. }
  441. /* return the FMC state */
  442. return fmc_state;
  443. }
  444. /*!
  445. \brief unlock the option byte operation
  446. \param[in] none
  447. \param[out] none
  448. \retval none
  449. */
  450. void ob_unlock(void)
  451. {
  452. if(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){
  453. /* write the FMC key */
  454. FMC_OBKEY = UNLOCK_KEY0;
  455. FMC_OBKEY = UNLOCK_KEY1;
  456. }
  457. }
  458. /*!
  459. \brief lock the option byte operation
  460. \param[in] none
  461. \param[out] none
  462. \retval none
  463. */
  464. void ob_lock(void)
  465. {
  466. /* reset the OBWEN bit */
  467. FMC_CTL0 &= ~FMC_CTL0_OBWEN;
  468. }
  469. /*!
  470. \brief erase the FMC option byte
  471. unlock the FMC_CTL0 and option byte before calling this function
  472. \param[in] none
  473. \param[out] none
  474. \retval state of FMC, refer to fmc_state_enum
  475. */
  476. fmc_state_enum ob_erase(void)
  477. {
  478. uint16_t temp_spc = FMC_NSPC;
  479. fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  480. /* check the option byte security protection value */
  481. if(RESET != ob_spc_get()){
  482. temp_spc = FMC_USPC;
  483. }
  484. if(FMC_READY == fmc_state){
  485. /* start erase the option byte */
  486. FMC_CTL0 |= FMC_CTL0_OBER;
  487. FMC_CTL0 |= FMC_CTL0_START;
  488. /* wait for the FMC ready */
  489. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  490. if(FMC_READY == fmc_state){
  491. /* reset the OBER bit */
  492. FMC_CTL0 &= ~FMC_CTL0_OBER;
  493. /* set the OBPG bit */
  494. FMC_CTL0 |= FMC_CTL0_OBPG;
  495. /* no security protection */
  496. OB_SPC = (uint16_t)temp_spc;
  497. /* wait for the FMC ready */
  498. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  499. if(FMC_TOERR != fmc_state){
  500. /* reset the OBPG bit */
  501. FMC_CTL0 &= ~FMC_CTL0_OBPG;
  502. }
  503. }else{
  504. if(FMC_TOERR != fmc_state){
  505. /* reset the OBPG bit */
  506. FMC_CTL0 &= ~FMC_CTL0_OBPG;
  507. }
  508. }
  509. }
  510. /* return the FMC state */
  511. return fmc_state;
  512. }
  513. /*!
  514. \brief enable write protection
  515. \param[in] ob_wp: specify sector to be write protected
  516. \arg OB_WPx(x=0..31): write protect specify sector
  517. \arg OB_WP_ALL: write protect all sector
  518. \param[out] none
  519. \retval state of FMC, refer to fmc_state_enum
  520. */
  521. fmc_state_enum ob_write_protection_enable(uint32_t ob_wp)
  522. {
  523. uint16_t temp_wp0, temp_wp1, temp_wp2, temp_wp3;
  524. fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  525. ob_wp = (uint32_t)(~ob_wp);
  526. temp_wp0 = (uint16_t)(ob_wp & OB_WP0_WP0);
  527. temp_wp1 = (uint16_t)((ob_wp & OB_WP1_WP1) >> 8U);
  528. temp_wp2 = (uint16_t)((ob_wp & OB_WP2_WP2) >> 16U);
  529. temp_wp3 = (uint16_t)((ob_wp & OB_WP3_WP3) >> 24U);
  530. if(FMC_READY == fmc_state){
  531. /* set the OBPG bit*/
  532. FMC_CTL0 |= FMC_CTL0_OBPG;
  533. if(0xFFU != temp_wp0){
  534. OB_WP0 = temp_wp0;
  535. /* wait for the FMC ready */
  536. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  537. }
  538. if((FMC_READY == fmc_state) && (0xFFU != temp_wp1)){
  539. OB_WP1 = temp_wp1;
  540. /* wait for the FMC ready */
  541. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  542. }
  543. if((FMC_READY == fmc_state) && (0xFFU != temp_wp2)){
  544. OB_WP2 = temp_wp2;
  545. /* wait for the FMC ready */
  546. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  547. }
  548. if((FMC_READY == fmc_state) && (0xFFU != temp_wp3)){
  549. OB_WP3 = temp_wp3;
  550. /* wait for the FMC ready */
  551. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  552. }
  553. if(FMC_TOERR != fmc_state){
  554. /* reset the OBPG bit */
  555. FMC_CTL0 &= ~FMC_CTL0_OBPG;
  556. }
  557. }
  558. /* return the FMC state */
  559. return fmc_state;
  560. }
  561. /*!
  562. \brief configure security protection
  563. \param[in] ob_spc: specify security protection
  564. \arg FMC_NSPC: no security protection
  565. \arg FMC_USPC: under security protection
  566. \param[out] none
  567. \retval state of FMC, refer to fmc_state_enum
  568. */
  569. fmc_state_enum ob_security_protection_config(uint8_t ob_spc)
  570. {
  571. fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  572. if(FMC_READY == fmc_state){
  573. FMC_CTL0 |= FMC_CTL0_OBER;
  574. FMC_CTL0 |= FMC_CTL0_START;
  575. /* wait for the FMC ready */
  576. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  577. if(FMC_READY == fmc_state){
  578. /* reset the OBER bit */
  579. FMC_CTL0 &= ~FMC_CTL0_OBER;
  580. /* start the option byte program */
  581. FMC_CTL0 |= FMC_CTL0_OBPG;
  582. OB_SPC = (uint16_t)ob_spc;
  583. /* wait for the FMC ready */
  584. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  585. if(FMC_TOERR != fmc_state){
  586. /* reset the OBPG bit */
  587. FMC_CTL0 &= ~FMC_CTL0_OBPG;
  588. }
  589. }else{
  590. if(FMC_TOERR != fmc_state){
  591. /* reset the OBER bit */
  592. FMC_CTL0 &= ~FMC_CTL0_OBER;
  593. }
  594. }
  595. }
  596. /* return the FMC state */
  597. return fmc_state;
  598. }
  599. /*!
  600. \brief program the FMC user option byte
  601. \param[in] ob_fwdgt: option byte watchdog value
  602. \arg OB_FWDGT_SW: software free watchdog
  603. \arg OB_FWDGT_HW: hardware free watchdog
  604. \param[in] ob_deepsleep: option byte deepsleep reset value
  605. \arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode
  606. \arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode
  607. \param[in] ob_stdby:option byte standby reset value
  608. \arg OB_STDBY_NRST: no reset when entering standby mode
  609. \arg OB_STDBY_RST: generate a reset instead of entering standby mode
  610. \param[in] ob_boot: specifies the option byte boot bank value
  611. \arg OB_BOOT_B0: boot from bank0
  612. \arg OB_BOOT_B1: boot from bank1 or bank0 if bank1 is void
  613. \param[out] none
  614. \retval state of FMC, refer to fmc_state_enum
  615. */
  616. fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot)
  617. {
  618. fmc_state_enum fmc_state = FMC_READY;
  619. uint8_t temp;
  620. /* wait for the FMC ready */
  621. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  622. if(FMC_READY == fmc_state){
  623. /* set the OBPG bit*/
  624. FMC_CTL0 |= FMC_CTL0_OBPG;
  625. temp = ((uint8_t)((uint8_t)((uint8_t)(ob_boot | ob_fwdgt) | ob_deepsleep) | ob_stdby) | OB_USER_MASK);
  626. OB_USER = (uint16_t)temp;
  627. /* wait for the FMC ready */
  628. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  629. if(FMC_TOERR != fmc_state){
  630. /* reset the OBPG bit */
  631. FMC_CTL0 &= ~FMC_CTL0_OBPG;
  632. }
  633. }
  634. /* return the FMC state */
  635. return fmc_state;
  636. }
  637. /*!
  638. \brief program option bytes data
  639. \param[in] address: the option bytes address to be programmed
  640. \param[in] data: the byte to be programmed
  641. \param[out] none
  642. \retval state of FMC, refer to fmc_state_enum
  643. */
  644. fmc_state_enum ob_data_program(uint32_t address, uint8_t data)
  645. {
  646. fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  647. if(FMC_READY == fmc_state){
  648. /* set the OBPG bit */
  649. FMC_CTL0 |= FMC_CTL0_OBPG;
  650. REG16(address) = data;
  651. /* wait for the FMC ready */
  652. fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT);
  653. if(FMC_TOERR != fmc_state){
  654. /* reset the OBPG bit */
  655. FMC_CTL0 &= ~FMC_CTL0_OBPG;
  656. }
  657. }
  658. /* return the FMC state */
  659. return fmc_state;
  660. }
  661. /*!
  662. \brief get the FMC user option byte
  663. \param[in] none
  664. \param[out] none
  665. \retval the FMC user option byte values
  666. */
  667. uint8_t ob_user_get(void)
  668. {
  669. /* return the FMC user option byte value */
  670. return (uint8_t)(FMC_OBSTAT >> 2U);
  671. }
  672. /*!
  673. \brief get OB_DATA in register FMC_OBSTAT
  674. \param[in] none
  675. \param[out] none
  676. \retval ob_data
  677. */
  678. uint16_t ob_data_get(void)
  679. {
  680. return (uint16_t)(FMC_OBSTAT >> 10U);
  681. }
  682. /*!
  683. \brief get the FMC option byte write protection
  684. \param[in] none
  685. \param[out] none
  686. \retval the FMC write protection option byte value
  687. */
  688. uint32_t ob_write_protection_get(void)
  689. {
  690. /* return the FMC write protection option byte value */
  691. return FMC_WP;
  692. }
  693. /*!
  694. \brief get the FMC option byte security protection
  695. \param[in] none
  696. \param[out] none
  697. \retval FlagStatus: SET or RESET
  698. */
  699. FlagStatus ob_spc_get(void)
  700. {
  701. FlagStatus spc_state = RESET;
  702. if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)){
  703. spc_state = SET;
  704. }else{
  705. spc_state = RESET;
  706. }
  707. return spc_state;
  708. }
  709. /*!
  710. \brief enable FMC interrupt
  711. \param[in] interrupt: the FMC interrupt source
  712. \arg FMC_INT_BANK0_END: FMC bank0 end of program interrupt
  713. \arg FMC_INT_BANK0_ERR: FMC bank0 error interrupt
  714. \arg FMC_INT_BANK1_END: FMC bank1 end of program interrupt
  715. \arg FMC_INT_BANK1_ERR: FMC bank1 error interrupt
  716. \param[out] none
  717. \retval none
  718. */
  719. void fmc_interrupt_enable(uint32_t interrupt)
  720. {
  721. FMC_REG_VAL(interrupt) |= BIT(FMC_BIT_POS(interrupt));
  722. }
  723. /*!
  724. \brief disable FMC interrupt
  725. \param[in] interrupt: the FMC interrupt source
  726. \arg FMC_INT_BANK0_END: FMC bank0 end of program interrupt
  727. \arg FMC_INT_BANK0_ERR: FMC bank0 error interrupt
  728. \arg FMC_INT_BANK1_END: FMC bank1 end of program interrupt
  729. \arg FMC_INT_BANK1_ERR: FMC bank1 error interrupt
  730. \param[out] none
  731. \retval none
  732. */
  733. void fmc_interrupt_disable(uint32_t interrupt)
  734. {
  735. FMC_REG_VAL(interrupt) &= ~BIT(FMC_BIT_POS(interrupt));
  736. }
  737. /*!
  738. \brief check flag is set or not
  739. \param[in] flag: check FMC flag
  740. only one parameter can be selected which is shown as below:
  741. \arg FMC_FLAG_BANK0_BUSY: FMC bank0 busy flag bit
  742. \arg FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit
  743. \arg FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit
  744. \arg FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit
  745. \arg FMC_FLAG_OBERR: FMC option bytes read error flag bit
  746. \arg FMC_FLAG_BANK1_BUSY: FMC bank1 busy flag bit
  747. \arg FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit
  748. \arg FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit
  749. \arg FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit
  750. \param[out] none
  751. \retval FlagStatus: SET or RESET
  752. */
  753. FlagStatus fmc_flag_get(uint32_t flag)
  754. {
  755. if(RESET != (FMC_REG_VAL(flag) & BIT(FMC_BIT_POS(flag)))){
  756. return SET;
  757. }else{
  758. return RESET;
  759. }
  760. }
  761. /*!
  762. \brief clear the FMC flag
  763. \param[in] flag: clear FMC flag
  764. only one parameter can be selected which is shown as below:
  765. \arg FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit
  766. \arg FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit
  767. \arg FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit
  768. \arg FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit
  769. \arg FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit
  770. \arg FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit
  771. \param[out] none
  772. \retval none
  773. */
  774. void fmc_flag_clear(uint32_t flag)
  775. {
  776. FMC_REG_VAL(flag) |= BIT(FMC_BIT_POS(flag));
  777. }
  778. /*!
  779. \brief get FMC interrupt flag state
  780. \param[in] flag: FMC interrupt flags, refer to fmc_interrupt_flag_enum
  781. only one parameter can be selected which is shown as below:
  782. \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit
  783. \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit
  784. \arg FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit
  785. \arg FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit
  786. \arg FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit
  787. \arg FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit
  788. \param[out] none
  789. \retval FlagStatus: SET or RESET
  790. */
  791. FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag)
  792. {
  793. FlagStatus ret1 = RESET;
  794. FlagStatus ret2 = RESET;
  795. if(FMC_STAT0_REG_OFFSET == FMC_REG_OFFSET_GET(flag)){
  796. /* get the staus of interrupt flag */
  797. ret1 = (FlagStatus)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag)));
  798. /* get the staus of interrupt enale bit */
  799. ret2 = (FlagStatus)(FMC_CTL0 & BIT(FMC_BIT_POS1(flag)));
  800. }else{
  801. /* get the staus of interrupt flag */
  802. ret1 = (FlagStatus)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag)));
  803. /* get the staus of interrupt enale bit */
  804. ret2 = (FlagStatus)(FMC_CTL1 & BIT(FMC_BIT_POS1(flag)));
  805. }
  806. if(ret1 && ret2){
  807. return SET;
  808. }else{
  809. return RESET;
  810. }
  811. }
  812. /*!
  813. \brief clear FMC interrupt flag state
  814. \param[in] flag: FMC interrupt flags, refer to can_interrupt_flag_enum
  815. only one parameter can be selected which is shown as below:
  816. \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit
  817. \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit
  818. \arg FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit
  819. \arg FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit
  820. \arg FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit
  821. \arg FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit
  822. \param[out] none
  823. \retval none
  824. */
  825. void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag)
  826. {
  827. FMC_REG_VALS(flag) |= BIT(FMC_BIT_POS0(flag));
  828. }
  829. /*!
  830. \brief get the FMC bank0 state
  831. \param[in] none
  832. \param[out] none
  833. \retval state of FMC, refer to fmc_state_enum
  834. */
  835. fmc_state_enum fmc_bank0_state_get(void)
  836. {
  837. fmc_state_enum fmc_state = FMC_READY;
  838. if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_BUSY)){
  839. fmc_state = FMC_BUSY;
  840. }else{
  841. if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_WPERR)){
  842. fmc_state = FMC_WPERR;
  843. }else{
  844. if((uint32_t)0x00U != (FMC_STAT0 & (FMC_STAT0_PGERR))){
  845. fmc_state = FMC_PGERR;
  846. }
  847. }
  848. }
  849. /* return the FMC state */
  850. return fmc_state;
  851. }
  852. /*!
  853. \brief get the FMC bank1 state
  854. \param[in] none
  855. \param[out] none
  856. \retval state of FMC, refer to fmc_state_enum
  857. */
  858. fmc_state_enum fmc_bank1_state_get(void)
  859. {
  860. fmc_state_enum fmc_state = FMC_READY;
  861. if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_BUSY)){
  862. fmc_state = FMC_BUSY;
  863. }else{
  864. if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_WPERR)){
  865. fmc_state = FMC_WPERR;
  866. }else{
  867. if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_PGERR)){
  868. fmc_state = FMC_PGERR;
  869. }
  870. }
  871. }
  872. /* return the FMC state */
  873. return fmc_state;
  874. }
  875. /*!
  876. \brief check whether FMC bank0 is ready or not
  877. \param[in] timeout: count of loop
  878. \param[out] none
  879. \retval state of FMC, refer to fmc_state_enum
  880. */
  881. fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout)
  882. {
  883. fmc_state_enum fmc_state = FMC_BUSY;
  884. /* wait for FMC ready */
  885. do{
  886. /* get FMC state */
  887. fmc_state = fmc_bank0_state_get();
  888. timeout--;
  889. }while((FMC_BUSY == fmc_state) && (0x00U != timeout));
  890. if(FMC_BUSY == fmc_state){
  891. fmc_state = FMC_TOERR;
  892. }
  893. /* return the FMC state */
  894. return fmc_state;
  895. }
  896. /*!
  897. \brief check whether FMC bank1 is ready or not
  898. \param[in] timeout: count of loop
  899. \param[out] none
  900. \retval state of FMC, refer to fmc_state_enum
  901. */
  902. fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout)
  903. {
  904. fmc_state_enum fmc_state = FMC_BUSY;
  905. /* wait for FMC ready */
  906. do{
  907. /* get FMC state */
  908. fmc_state = fmc_bank1_state_get();
  909. timeout--;
  910. }while((FMC_BUSY == fmc_state) && (0x00U != timeout));
  911. if(FMC_BUSY == fmc_state){
  912. fmc_state = FMC_TOERR;
  913. }
  914. /* return the FMC state */
  915. return fmc_state;
  916. }