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