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