1 /*!
2  * @file        apm32s10x_fmc.c
3  *
4  * @brief       This file provides all the FMC firmware functions
5  *
6  * @version     V1.0.1
7  *
8  * @date        2022-12-31
9  *
10  * @attention
11  *
12  *  Copyright (C) 2022-2023 Geehy Semiconductor
13  *
14  *  You may not use this file except in compliance with the
15  *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
16  *
17  *  The program is only for reference, which is distributed in the hope
18  *  that it will be usefull and instructional for customers to develop
19  *  their software. Unless required by applicable law or agreed to in
20  *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
21  *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
22  *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
23  *  and limitations under the License.
24  */
25 
26 /* Includes */
27 #include "apm32s10x_fmc.h"
28 #include "apm32s10x_rcm.h"
29 
30 /** @addtogroup APM32S10x_StdPeriphDriver
31   @{
32 */
33 
34 /** @addtogroup FMC_Driver FMC Driver
35   @{
36 */
37 
38 /** @defgroup FMC_Functions Functions
39   @{
40 */
41 
42 /*!
43  * @brief     Configure the code latency value.
44  *
45  * @param     latency: the FMC Latency value.
46  *
47  * @retval    None
48  */
FMC_ConfigLatency(FMC_LATENCY_T latency)49 void FMC_ConfigLatency(FMC_LATENCY_T latency)
50 {
51     FMC->CTRL1_B.WS = latency;
52 }
53 
54 /*!
55  * @brief     Enable the Half cycle flash access.
56  *
57  * @param     None
58  *
59  * @retval    None
60  */
FMC_EnableHalfCycleAccess(void)61 void FMC_EnableHalfCycleAccess(void)
62 {
63     FMC->CTRL1_B.HCAEN = BIT_SET;
64 }
65 
66 /*!
67  * @brief     Disable the Half cycle flash access.
68  *
69  * @param     None
70  *
71  * @retval    None
72  */
FMC_DisableHalfCycleAccess(void)73 void FMC_DisableHalfCycleAccess(void)
74 {
75     FMC->CTRL1_B.HCAEN = BIT_RESET;
76 }
77 
78 /*!
79  * @brief     Enable the Prefetch Buffer.
80  *
81  * @param     None
82  *
83  * @retval    None
84  */
FMC_EnablePrefetchBuffer(void)85 void FMC_EnablePrefetchBuffer(void)
86 {
87     FMC->CTRL1_B.PBEN = ENABLE;
88 }
89 
90 /*!
91  * @brief     Disable the Prefetch Buffer.
92  *
93  * @param     None
94  *
95  * @retval    None
96  */
FMC_DisablePrefetchBuffer(void)97 void FMC_DisablePrefetchBuffer(void)
98 {
99     FMC->CTRL1_B.PBEN = DISABLE;
100 }
101 
102 /*!
103  * @brief     Unlock the FMC Program Erase Controller
104  *
105  * @param     None
106  *
107  * @retval    None
108  */
FMC_Unlock(void)109 void FMC_Unlock(void)
110 {
111     FMC->KEY = 0x45670123;
112     FMC->KEY = 0xCDEF89AB;
113 }
114 
115 /*!
116  * @brief     Lock the FMC Program Erase Controller.
117  *
118  * @param     None
119  *
120  * @retval    None
121  */
FMC_Lock(void)122 void FMC_Lock(void)
123 {
124     FMC->CTRL2_B.LOCK = BIT_SET;
125 }
126 
127 /*!
128  * @brief     Erase a specified FMC page.
129  *
130  * @param     pageAddr: The page address to be erased.
131  *
132  * @retval    Return the flash state.It can be one of value:
133  *                 @arg FMC_STATUS_BUSY
134  *                 @arg FMC_STATUS_ERROR_PG
135  *                 @arg FMC_STATUS_ERROR_WRP
136  *                 @arg FMC_STATUS_COMPLETE
137  *                 @arg FMC_STATUS_TIMEOUT
138  */
FMC_ErasePage(uint32_t pageAddr)139 FMC_STATUS_T FMC_ErasePage(uint32_t pageAddr)
140 {
141     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
142 
143     status = FMC_WaitForLastOperation(0x000B0000);
144     if (status == FMC_STATUS_COMPLETE)
145     {
146         FMC->CTRL2_B.PAGEERA = BIT_SET;
147         FMC->ADDR = pageAddr;
148         FMC->CTRL2_B.STA = BIT_SET;
149 
150         status = FMC_WaitForLastOperation(0x000B0000);
151         FMC->CTRL2_B.PAGEERA = BIT_RESET;
152     }
153     return status;
154 }
155 
156 /*!
157  * @brief     Erase all FMC pages.
158  *
159  * @param     None
160  *
161  * @retval    Return the flash state.It can be one of value:
162  *                 @arg FMC_STATUS_ERROR_PG
163  *                 @arg FMC_STATUS_ERROR_WRP
164  *                 @arg FMC_STATUS_COMPLETE
165  *                 @arg FMC_STATUS_TIMEOUT
166  */
FMC_EraseAllPage(void)167 FMC_STATUS_T FMC_EraseAllPage(void)
168 {
169     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
170 
171     status = FMC_WaitForLastOperation(0x000B0000);
172     if (status == FMC_STATUS_COMPLETE)
173     {
174         FMC->CTRL2_B.MASSERA = BIT_SET;
175         FMC->CTRL2_B.STA = BIT_SET;
176 
177         status = FMC_WaitForLastOperation(0x000B0000);
178         FMC->CTRL2_B.MASSERA = BIT_RESET;
179     }
180     return status;
181 }
182 
183 /*!
184  * @brief     Erase the FMC option bytes.
185  *
186  * @param     None
187  *
188  * @retval    Return the flash state.It can be one of value:
189  *                 @arg FMC_STATUS_ERROR_PG
190  *                 @arg FMC_STATUS_ERROR_WRP
191  *                 @arg FMC_STATUS_COMPLETE
192  *                 @arg FMC_STATUS_TIMEOUT
193  */
FMC_EraseOptionBytes(void)194 FMC_STATUS_T FMC_EraseOptionBytes(void)
195 {
196     uint16_t rdtemp = 0x00A5;
197     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
198 
199     if (FMC_GetReadProtectionStatus() != RESET)
200     {
201         rdtemp = 0x00;
202     }
203     status = FMC_WaitForLastOperation(0x000B0000);
204     if (status == FMC_STATUS_COMPLETE)
205     {
206         FMC->OBKEY = 0x45670123;
207         FMC->OBKEY = 0xCDEF89AB;
208 
209         FMC->CTRL2_B.OBE = BIT_SET;
210         FMC->CTRL2_B.STA = BIT_SET;
211 
212         status = FMC_WaitForLastOperation(0x000B0000);
213 
214         if (status == FMC_STATUS_COMPLETE)
215         {
216             FMC->CTRL2_B.OBE = BIT_RESET;
217             FMC->CTRL2_B.OBP = BIT_SET;
218             OB->RDP = rdtemp;
219             status = FMC_WaitForLastOperation(0x000B0000);
220             if (status != FMC_STATUS_TIMEOUT)
221             {
222                 FMC->CTRL2_B.OBP = BIT_RESET;
223             }
224         }
225         else if (status != FMC_STATUS_TIMEOUT)
226         {
227             FMC->CTRL2_B.OBP = BIT_RESET;
228         }
229     }
230     return status;
231 }
232 
233 /*!
234  * @brief     Program a word at a specified address.
235  *
236  * @param     address:the address to be programmed.
237  *
238  * @param     data: the data to be programmed.
239  *
240  * @retval    Return the flash state.It can be one of value:
241  *                 @arg FMC_STATUS_ERROR_PG
242  *                 @arg FMC_STATUS_ERROR_WRP
243  *                 @arg FMC_STATUS_COMPLETE
244  *                 @arg FMC_STATUS_TIMEOUT
245  */
FMC_ProgramWord(uint32_t address,uint32_t data)246 FMC_STATUS_T FMC_ProgramWord(uint32_t address, uint32_t data)
247 {
248     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
249     __IOM uint32_t temp = 0;
250 
251 #ifdef APM32S10X_HD
252     __set_PRIMASK(1);
253 #endif
254 
255     status = FMC_WaitForLastOperation(0x000B0000);
256 
257     if (status == FMC_STATUS_COMPLETE)
258     {
259         FMC->CTRL2_B.PG = BIT_SET;
260 
261         *(__IOM uint16_t*)address = data;
262 
263         status = FMC_WaitForLastOperation(0x000B0000);
264 
265         if (status == FMC_STATUS_COMPLETE)
266         {
267             temp = address + 2;
268 
269             *(__IOM uint16_t*) temp = data >> 16;
270 
271             status = FMC_WaitForLastOperation(0x000B0000);
272             FMC->CTRL2_B.PG = BIT_RESET;
273         }
274         else
275         {
276             FMC->CTRL2_B.PG = BIT_RESET;
277         }
278     }
279 
280 #ifdef APM32S10X_HD
281     __set_PRIMASK(0);
282 #endif
283 
284     return status;
285 }
286 
287 /*!
288  * @brief     Program a half word at a specified address.
289  *
290  * @param     address:the address to be programmed.
291  *
292  * @param     data: the data to be programmed.
293  *
294  * @retval    Return the flash state.It can be one of value:
295  *                 @arg FMC_STATUS_ERROR_PG
296  *                 @arg FMC_STATUS_ERROR_WRP
297  *                 @arg FMC_STATUS_COMPLETE
298  *                 @arg FMC_STATUS_TIMEOUT
299  */
FMC_ProgramHalfWord(uint32_t address,uint16_t data)300 FMC_STATUS_T FMC_ProgramHalfWord(uint32_t address, uint16_t data)
301 {
302     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
303 
304 #ifdef APM32S10X_HD
305     __set_PRIMASK(1);
306 #endif
307 
308     status = FMC_WaitForLastOperation(0x000B0000);
309 
310     if (status == FMC_STATUS_COMPLETE)
311     {
312         FMC->CTRL2_B.PG = BIT_SET;
313         *(__IOM uint16_t*)address = data;
314         status = FMC_WaitForLastOperation(0x000B0000);
315         FMC->CTRL2_B.PG = BIT_RESET;
316     }
317 
318 #ifdef APM32S10X_HD
319     __set_PRIMASK(0);
320 #endif
321 
322     return status;
323 }
324 
325 /*!
326  * @brief     Program a half word at a specified Option Byte Data address.
327  *
328  * @param     address:the address to be programmed.
329  *
330  * @param     data: the data to be programmed.
331  *
332  * @retval    Return the flash state.It can be one of value:
333  *                 @arg FMC_STATUS_ERROR_PG
334  *                 @arg FMC_STATUS_ERROR_WRP
335  *                 @arg FMC_STATUS_COMPLETE
336  *                 @arg FMC_STATUS_TIMEOUT
337  */
FMC_ProgramOptionByteData(uint32_t address,uint8_t data)338 FMC_STATUS_T FMC_ProgramOptionByteData(uint32_t address, uint8_t data)
339 {
340     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
341 
342     status = FMC_WaitForLastOperation(0x000B0000);
343 
344     if (status == FMC_STATUS_COMPLETE)
345     {
346         FMC->OBKEY = 0x45670123;
347         FMC->OBKEY = 0xCDEF89AB;
348 
349         FMC->CTRL2_B.OBP = BIT_SET;
350         *(__IOM uint16_t*)address = data;
351         status = FMC_WaitForLastOperation(0x000B0000);
352         if (status == FMC_STATUS_TIMEOUT)
353         {
354             FMC->CTRL2_B.OBP = BIT_RESET;
355         }
356     }
357     return status;
358 }
359 
360 /*!
361  * @brief     Write protects the desired pages
362  *
363  * @param     page:the address of the pages to be write protection
364  *                This parameter can be any combination of the following values:
365  *                 @arg FLASH_WRP_PAGE_0_3 to FLASH_WRP_PAGE_124_127
366  *
367  * @retval    Return the flash state.It can be one of value:
368  *                 @arg FMC_STATUS_ERROR_PG
369  *                 @arg FMC_STATUS_ERROR_WRP
370  *                 @arg FMC_STATUS_COMPLETE
371  *                 @arg FMC_STATUS_TIMEOUT
372  */
FMC_EnableWriteProtection(uint32_t page)373 FMC_STATUS_T FMC_EnableWriteProtection(uint32_t page)
374 {
375     uint16_t WPP0_Data = 0xFFFF, WPP1_Data = 0xFFFF, WPP2_Data = 0xFFFF, WPP3_Data = 0xFFFF;
376     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
377 
378     page = ~page;
379     WPP0_Data = (page & 0x000000FF);
380     WPP1_Data = (page & 0x0000FF00) >> 8;
381     WPP2_Data = (page & 0x00FF0000) >> 16;
382     WPP3_Data = (page & 0xFF000000) >> 24;
383 
384     status = FMC_WaitForLastOperation(0x000B0000);
385 
386     if (status == FMC_STATUS_COMPLETE)
387     {
388         FMC->OBKEY = 0x45670123;
389         FMC->OBKEY = 0xCDEF89AB;
390         FMC->CTRL2_B.OBP = BIT_SET;
391 
392         if (WPP0_Data != 0xFF)
393         {
394             OB->WRP0 = WPP0_Data;
395             status = FMC_WaitForLastOperation(0x000B0000);
396         }
397         if ((status == FMC_STATUS_COMPLETE) && (WPP1_Data != 0xFF))
398         {
399             OB->WRP1 = WPP1_Data;
400             status = FMC_WaitForLastOperation(0x000B0000);
401         }
402         if ((status == FMC_STATUS_COMPLETE) && (WPP2_Data != 0xFF))
403         {
404             OB->WRP2 = WPP2_Data;
405             status = FMC_WaitForLastOperation(0x000B0000);
406         }
407         if ((status == FMC_STATUS_COMPLETE) && (WPP3_Data != 0xFF))
408         {
409             OB->WRP3 = WPP3_Data;
410             status = FMC_WaitForLastOperation(0x000B0000);
411         }
412 
413         if (status != FMC_STATUS_TIMEOUT)
414         {
415             FMC->CTRL2_B.OBP = BIT_RESET;
416         }
417     }
418     return status;
419 }
420 
421 /*!
422  * @brief     Enable the read out protection.
423  *
424  * @param     None
425  *
426  * @retval    Return the flash state.It can be one of value:
427  *                 @arg FMC_STATUS_ERROR_PG
428  *                 @arg FMC_STATUS_ERROR_WRP
429  *                 @arg FMC_STATUS_COMPLETE
430  *                 @arg FMC_STATUS_TIMEOUT
431  */
FMC_EnableReadOutProtection(void)432 FMC_STATUS_T FMC_EnableReadOutProtection(void)
433 {
434     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
435 
436     status = FMC_WaitForLastOperation(0x000B0000);
437 
438     if (status == FMC_STATUS_COMPLETE)
439     {
440         FMC->OBKEY = 0x45670123;
441         FMC->OBKEY = 0xCDEF89AB;
442 
443         FMC->CTRL2_B.OBE = BIT_SET;
444         FMC->CTRL2_B.STA = BIT_SET;
445 
446         status = FMC_WaitForLastOperation(0x000B0000);
447 
448         if (status == FMC_STATUS_COMPLETE)
449         {
450             FMC->CTRL2_B.OBE = BIT_RESET;
451             FMC->CTRL2_B.OBP = BIT_SET;
452             OB->RDP = 0x00;
453 
454             status = FMC_WaitForLastOperation(0x000B0000);
455 
456             if (status != FMC_STATUS_TIMEOUT)
457             {
458                 FMC->CTRL2_B.OBP = BIT_RESET;
459             }
460         }
461         else if (status != FMC_STATUS_TIMEOUT)
462         {
463             FMC->CTRL2_B.OBE = BIT_RESET;
464         }
465     }
466     return status;
467 }
468 
469 /*!
470  * @brief     Disable the read out protection.
471  *
472  * @param     None
473  *
474  * @retval    Return the flash state.It can be one of value:
475  *                 @arg FMC_STATUS_ERROR_PG
476  *                 @arg FMC_STATUS_ERROR_WRP
477  *                 @arg FMC_STATUS_COMPLETE
478  *                 @arg FMC_STATUS_TIMEOUT
479  */
FMC_DisableReadOutProtection(void)480 FMC_STATUS_T FMC_DisableReadOutProtection(void)
481 {
482     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
483 
484     status = FMC_WaitForLastOperation(0x000B0000);
485 
486     if (status == FMC_STATUS_COMPLETE)
487     {
488         FMC->OBKEY = 0x45670123;
489         FMC->OBKEY = 0xCDEF89AB;
490         FMC->CTRL2_B.OBE = BIT_SET;
491         FMC->CTRL2_B.STA = BIT_SET;
492 
493         status = FMC_WaitForLastOperation(0x000B0000);
494 
495         if (status == FMC_STATUS_COMPLETE)
496         {
497             FMC->CTRL2_B.OBE = BIT_RESET;
498             FMC->CTRL2_B.OBP = BIT_SET;
499             OB->RDP = 0xA5;
500 
501             status = FMC_WaitForLastOperation(0x000B0000);
502 
503             if (status != FMC_STATUS_TIMEOUT)
504             {
505                 FMC->CTRL2_B.OBP = BIT_RESET;
506             }
507         }
508         else if (status != FMC_STATUS_TIMEOUT)
509         {
510             FMC->CTRL2_B.OBE = BIT_RESET;
511         }
512     }
513     return status;
514 }
515 
516 /*!
517  * @brief     Program the FMC User Option Byte.
518  *
519  * @param     userConfig: Point to a FMC_UserConfig_T structure.
520  *
521  * @retval    Return the flash state.It can be one of value:
522  *                 @arg FMC_STATUS_ERROR_PG
523  *                 @arg FMC_STATUS_ERROR_WRP
524  *                 @arg FMC_STATUS_COMPLETE
525  *                 @arg FMC_STATUS_TIMEOUT
526  */
FMC_ConfigUserOptionByte(FMC_UserConfig_T * userConfig)527 FMC_STATUS_T FMC_ConfigUserOptionByte(FMC_UserConfig_T* userConfig)
528 {
529     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
530 
531     FMC->OBKEY = 0x45670123;
532     FMC->OBKEY = 0xCDEF89AB;
533 
534     status = FMC_WaitForLastOperation(0x000B0000);
535 
536     if (status == FMC_STATUS_COMPLETE)
537     {
538         FMC->CTRL2_B.OBP = BIT_SET;
539         OB->USER = (uint32_t)userConfig->iwdtSet | \
540                    (uint32_t)userConfig->stopSet | \
541                    (uint32_t)userConfig->stdbySet | 0xF8;
542         status = FMC_WaitForLastOperation(0x000B0000);
543         if (status == FMC_STATUS_TIMEOUT)
544         {
545             FMC->CTRL2_B.OBP = BIT_RESET;
546         }
547     }
548     return status;
549 }
550 
551 /*!
552  * @brief     Read the FMC User Option Bytes values.
553  *
554  * @param     None
555  *
556  * @retval    Return User Option Bytes values
557  */
FMC_ReadUserOptionByte(void)558 uint32_t FMC_ReadUserOptionByte(void)
559 {
560     return (FMC->OBCS_B.UOB >> 2);
561 }
562 
563 /*!
564  * @brief     Read the FMC Write Protection Option Bytes Register value.
565  *
566  * @param     None
567  *
568  * @retval    Return the value of Option Bytes Write Protection Register.
569  */
FMC_ReadOptionByteWriteProtection(void)570 uint32_t FMC_ReadOptionByteWriteProtection(void)
571 {
572     return FMC->WRTPROT;
573 }
574 
575 /*!
576  * @brief     Get the FMC Read Out Protection Status is set or not.
577  *
578  * @param     None
579  *
580  * @retval    status : set or reset.
581  */
FMC_GetReadProtectionStatus(void)582 uint8_t FMC_GetReadProtectionStatus(void)
583 {
584     uint8_t flagstatus = RESET;
585 
586     if (FMC->OBCS_B.READPROT != RESET)
587     {
588         flagstatus = SET;
589     }
590     else
591     {
592         flagstatus = RESET;
593     }
594     return flagstatus;
595 }
596 
597 /*!
598  * @brief     FMC Prefetch Buffer status is set or not.
599  *
600  * @param     None
601  *
602  * @retval    status : set or reset.
603  */
FMC_ReadPrefetchBufferStatus(void)604 uint8_t FMC_ReadPrefetchBufferStatus(void)
605 {
606     return FMC->CTRL1_B.PBSF;
607 }
608 
609 /*!
610  * @brief     Enable the specified FMC interrupts.
611  *
612  * @param     interrupt: Select the FMC interrupt sources
613  *                       This parameter can be one of the following values:
614  *                       @arg FMC_INT_ERR :  Error Interrupt
615  *                       @arg FMC_INT_OC  :  Operation Complete Interrupt
616  *
617  * @retval    None
618  */
FMC_EnableInterrupt(FMC_INT_T interrupt)619 void FMC_EnableInterrupt(FMC_INT_T interrupt)
620 {
621     if (interrupt == FMC_INT_ERR)
622     {
623         FMC->CTRL2_B.ERRIE = ENABLE;
624     }
625     else
626     {
627         FMC->CTRL2_B.OCIE = ENABLE;
628     }
629 }
630 
631 /*!
632  * @brief     Disable the specified FMC interrupts.
633  *
634  * @param     interrupt: Select the FMC interrupt sources
635  *                       This parameter can be one of the following values:
636  *                       @arg FMC_INT_ERR :  Error Interrupt
637  *                       @arg FMC_INT_OC  :  Operation Complete Interrupt
638  *
639  * @retval    None
640  */
FMC_DisableInterrupt(FMC_INT_T interrupt)641 void FMC_DisableInterrupt(FMC_INT_T interrupt)
642 {
643     if (interrupt == FMC_INT_ERR)
644     {
645         FMC->CTRL2_B.ERRIE = DISABLE;
646     }
647     else
648     {
649         FMC->CTRL2_B.OCIE = DISABLE;
650     }
651 }
652 
653 /*!
654  * @brief     Read FMC flag is set or not
655  *
656  * @param     flag: status flag of FMC
657  *                  This parameter can be one of the following values:
658  *                  @arg FMC_FLAG_BUSY : FMC Busy flag
659  *                  @arg FMC_FLAG_OC   : FMC Operation Complete flag
660  *                  @arg FMC_FLAG_PE   : FMC Program error flag
661  *                  @arg FMC_FLAG_WPE  : FMC Write protected error flag
662  *                  @arg FMC_FLAG_OBE  : FMC Option Byte error flag
663  *
664  * @retval    flag status : set or reset
665  */
FMC_ReadStatusFlag(FMC_FLAG_T flag)666 uint8_t FMC_ReadStatusFlag(FMC_FLAG_T flag)
667 {
668     if (flag == FMC_FLAG_OBE)
669     {
670         return FMC->OBCS_B.OBE;
671     }
672     else if ((FMC->STS & flag) != RESET)
673     {
674         return SET;
675     }
676     return RESET;
677 }
678 
679 /*!
680  * @brief     Clear the FMC's flag.
681  *
682  * @param     flag: status flag of FMC
683  *                  This parameter can be any combination of the following values:
684  *                  @arg FMC_FLAG_OC   : FMC Operation Complete flag
685  *                  @arg FMC_FLAG_PE   : FMC Program error flag
686  *                  @arg FMC_FLAG_WPE  : FMC Write protected error flag
687  *
688  * @retval    None
689  *
690  */
FMC_ClearStatusFlag(uint32_t flag)691 void FMC_ClearStatusFlag(uint32_t flag)
692 {
693     FMC->STS = flag;
694 }
695 
696 /*!
697  * @brief     Read the FMC Status.
698  *
699  * @param     None
700  *
701  * @retval    Return the flash state.It can be one of value:
702  *                 @arg FMC_STATUS_BUSY
703  *                 @arg FMC_STATUS_ERROR_PG
704  *                 @arg FMC_STATUS_ERROR_WRP
705  *                 @arg FMC_STATUS_COMPLETE
706  */
FMC_ReadStatus(void)707 FMC_STATUS_T  FMC_ReadStatus(void)
708 {
709     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
710 
711     if (FMC->STS_B.BUSYF == BIT_SET)
712     {
713         status = FMC_STATUS_BUSY;
714     }
715     else if (FMC->STS_B.PEF == BIT_SET)
716     {
717         status = FMC_STATUS_ERROR_PG;
718     }
719     else if (FMC->STS_B.WPEF == BIT_SET)
720     {
721         status = FMC_STATUS_ERROR_WRP;
722     }
723     else
724     {
725         status = FMC_STATUS_COMPLETE;
726     }
727     return status;
728 }
729 
730 /*!
731  * @brief     Wait for a Flash operation to complete or a TIMEOUT to occur.
732  *
733  * @param     timeOut:FMC programming timeout value.
734  *
735  * @retval    Return the flash state.It can be one of value:
736  *                 @arg FMC_STATUS_ERROR_PG
737  *                 @arg FMC_STATUS_ERROR_WRP
738  *                 @arg FMC_STATUS_COMPLETE
739  *                 @arg FMC_STATUS_TIMEOUT
740  */
FMC_WaitForLastOperation(uint32_t timeOut)741 FMC_STATUS_T FMC_WaitForLastOperation(uint32_t timeOut)
742 {
743     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
744 
745     /* Check for the Flash Status */
746     status = FMC_ReadStatus();
747 
748     /* Wait for a Flash operation to complete or a TIMEOUT to occur */
749     while ((status == FMC_STATUS_BUSY) && (timeOut != 0))
750     {
751         status = FMC_ReadStatus();
752         timeOut--;
753     }
754     if (timeOut == 0x00)
755     {
756         status = FMC_STATUS_TIMEOUT;
757     }
758     return status;
759 }
760 
761 /**@} end of group FMC_Functions */
762 /**@} end of group FMC_Driver */
763 /**@} end of group APM32S10x_StdPeriphDriver */
764