1 /*!
2  * @file       apm32e10x_fmc.c
3  *
4  * @brief      This file provides all the FMC firmware functions
5  *
6  * @version     V1.0.2
7  *
8  * @date        2022-12-31
9  *
10  * @attention
11  *
12  *  Copyright (C) 2021-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 useful 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 #include "apm32e10x_fmc.h"
27 #include "apm32e10x_rcm.h"
28 
29 /** @addtogroup APM32E10x_StdPeriphDriver
30   @{
31 */
32 
33 /** @addtogroup FMC_Driver
34   * @brief FMC driver modules
35   @{
36 */
37 
38 /** @defgroup FMC_Functions Functions
39   @{
40 */
41 
42 /*!
43  * @brief     Configs 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     Enables 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     Enables 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     Disables 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     Unlocks 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     Locks 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     Erases a specified FMC page.
129  *
130  * @param     pageAddr: The page address to be erased.
131  *
132  * @retval    Returns 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     Erases all FMC pages.
158  *
159  * @param     None
160  *
161  * @retval    Returns 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     Erases the FMC option bytes.
185  *
186  * @param     None
187  *
188  * @retval    Returns 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     Programs 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    Returns 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 
252     __set_PRIMASK(1);
253 
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 
281     __set_PRIMASK(0);
282 
283 
284     return status;
285 }
286 
287 /*!
288  * @brief     Programs 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    Returns 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 
305     __set_PRIMASK(1);
306 
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 
319     __set_PRIMASK(0);
320 
321 
322     return status;
323 }
324 
325 /*!
326  * @brief     Programs 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    Returns 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  *                 for APM32E10X_LD :
366  *                    @arg FLASH_WRP_PAGE_0_3 to FLASH_WRP_PAGE_28_31
367  *                 for APM32E10X_MD :
368  *                    @arg FLASH_WRP_PAGE_0_3 to FLASH_WRP_PAGE_124_127
369  *                 for APM32E10X_HD :
370  *                 @arg FLASH_WRP_PAGE_0_1 to FLASH_WRP_PAGE_60_61 or FLASH_WRP_PAGE_62_127
371  *                 @arg FMC_WRP_PAGE_ALL
372  *
373  * @retval    Returns the flash state.It can be one of value:
374  *                 @arg FMC_STATUS_ERROR_PG
375  *                 @arg FMC_STATUS_ERROR_WRP
376  *                 @arg FMC_STATUS_COMPLETE
377  *                 @arg FMC_STATUS_TIMEOUT
378  */
FMC_EnableWriteProtection(uint32_t page)379 FMC_STATUS_T FMC_EnableWriteProtection(uint32_t page)
380 {
381     uint16_t WPP0_Data = 0xFFFF, WPP1_Data = 0xFFFF, WPP2_Data = 0xFFFF, WPP3_Data = 0xFFFF;
382     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
383 
384     page = ~page;
385     WPP0_Data = (page & 0x000000FF);
386     WPP1_Data = (page & 0x0000FF00) >> 8;
387     WPP2_Data = (page & 0x00FF0000) >> 16;
388     WPP3_Data = (page & 0xFF000000) >> 24;
389 
390     status = FMC_WaitForLastOperation(0x000B0000);
391 
392     if(status == FMC_STATUS_COMPLETE)
393     {
394         FMC->OBKEY = 0x45670123;
395         FMC->OBKEY = 0xCDEF89AB;
396         FMC->CTRL2_B.OBP = BIT_SET;
397 
398         if(WPP0_Data != 0xFF)
399         {
400             OB->WRP0 = WPP0_Data;
401             status = FMC_WaitForLastOperation(0x000B0000);
402         }
403         if((status == FMC_STATUS_COMPLETE) && (WPP1_Data != 0xFF))
404         {
405             OB->WRP1 = WPP1_Data;
406             status = FMC_WaitForLastOperation(0x000B0000);
407         }
408         if((status == FMC_STATUS_COMPLETE) && (WPP2_Data != 0xFF))
409         {
410             OB->WRP2 = WPP2_Data;
411             status = FMC_WaitForLastOperation(0x000B0000);
412         }
413         if((status == FMC_STATUS_COMPLETE) && (WPP3_Data != 0xFF))
414         {
415             OB->WRP3 = WPP3_Data;
416             status = FMC_WaitForLastOperation(0x000B0000);
417         }
418 
419         if(status != FMC_STATUS_TIMEOUT)
420         {
421             FMC->CTRL2_B.OBP = BIT_RESET;
422         }
423     }
424     return status;
425 }
426 
427 /*!
428  * @brief     Enables the read out protection.
429  *
430  * @param     None
431  *
432  * @retval    Returns the flash state.It can be one of value:
433  *                 @arg FMC_STATUS_ERROR_PG
434  *                 @arg FMC_STATUS_ERROR_WRP
435  *                 @arg FMC_STATUS_COMPLETE
436  *                 @arg FMC_STATUS_TIMEOUT
437  */
FMC_EnableReadOutProtection(void)438 FMC_STATUS_T FMC_EnableReadOutProtection(void)
439 {
440     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
441 
442     status = FMC_WaitForLastOperation(0x000B0000);
443 
444     if(status == FMC_STATUS_COMPLETE)
445     {
446         FMC->OBKEY = 0x45670123;
447         FMC->OBKEY = 0xCDEF89AB;
448 
449         FMC->CTRL2_B.OBE = BIT_SET;
450         FMC->CTRL2_B.STA = BIT_SET;
451 
452         status = FMC_WaitForLastOperation(0x000B0000);
453 
454         if(status == FMC_STATUS_COMPLETE)
455         {
456             FMC->CTRL2_B.OBE = BIT_RESET;
457             FMC->CTRL2_B.OBP = BIT_SET;
458             OB->RDP = 0x00;
459 
460             status = FMC_WaitForLastOperation(0x000B0000);
461 
462             if(status != FMC_STATUS_TIMEOUT)
463             {
464                 FMC->CTRL2_B.OBP = BIT_RESET;
465             }
466         }
467         else if(status != FMC_STATUS_TIMEOUT)
468         {
469             FMC->CTRL2_B.OBE = BIT_RESET;
470         }
471     }
472     return status;
473 }
474 
475 /*!
476  * @brief     Disables the read out protection.
477  *
478  * @param     None
479  *
480  * @retval    Returns the flash state.It can be one of value:
481  *                 @arg FMC_STATUS_ERROR_PG
482  *                 @arg FMC_STATUS_ERROR_WRP
483  *                 @arg FMC_STATUS_COMPLETE
484  *                 @arg FMC_STATUS_TIMEOUT
485  */
FMC_DisableReadOutProtection(void)486 FMC_STATUS_T FMC_DisableReadOutProtection(void)
487 {
488     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
489 
490     status = FMC_WaitForLastOperation(0x000B0000);
491 
492     if(status == FMC_STATUS_COMPLETE)
493     {
494         FMC->OBKEY = 0x45670123;
495         FMC->OBKEY = 0xCDEF89AB;
496         FMC->CTRL2_B.OBE = BIT_SET;
497         FMC->CTRL2_B.STA = BIT_SET;
498 
499         status = FMC_WaitForLastOperation(0x000B0000);
500 
501         if(status == FMC_STATUS_COMPLETE)
502         {
503             FMC->CTRL2_B.OBE = BIT_RESET;
504             FMC->CTRL2_B.OBP = BIT_SET;
505             OB->RDP = 0x00A5;
506 
507             status = FMC_WaitForLastOperation(0x000B0000);
508 
509             if(status != FMC_STATUS_TIMEOUT)
510             {
511                 FMC->CTRL2_B.OBP = BIT_RESET;
512             }
513         }
514         else if(status != FMC_STATUS_TIMEOUT)
515         {
516             FMC->CTRL2_B.OBE = BIT_RESET;
517         }
518     }
519     return status;
520 }
521 
522 /*!
523  * @brief     Programs the FMC User Option Byte.
524  *
525  * @param     userConfig: Point to a FMC_UserConfig_T structure.
526  *
527  * @retval    Returns the flash state.It can be one of value:
528  *                 @arg FMC_STATUS_ERROR_PG
529  *                 @arg FMC_STATUS_ERROR_WRP
530  *                 @arg FMC_STATUS_COMPLETE
531  *                 @arg FMC_STATUS_TIMEOUT
532  */
FMC_ConfigUserOptionByte(FMC_UserConfig_T * userConfig)533 FMC_STATUS_T FMC_ConfigUserOptionByte(FMC_UserConfig_T* userConfig)
534 {
535     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
536 
537     FMC->OBKEY = 0x45670123;
538     FMC->OBKEY = 0xCDEF89AB;
539 
540     status = FMC_WaitForLastOperation(0x000B0000);
541 
542     if(status == FMC_STATUS_COMPLETE)
543     {
544         FMC->CTRL2_B.OBP = BIT_SET;
545         OB->USER = (uint32_t)userConfig->iwdtSet | \
546                    (uint32_t)userConfig->stopSet | \
547                    (uint32_t)userConfig->stdbySet | 0xF8;
548         status = FMC_WaitForLastOperation(0x000B0000);
549         if(status == FMC_STATUS_TIMEOUT)
550         {
551             FMC->CTRL2_B.OBP = BIT_RESET;
552         }
553     }
554     return status;
555 }
556 
557 /*!
558  * @brief     Read the FMC User Option Bytes values.
559  *
560  * @param     None
561  *
562  * @retval    Returns User Option Bytes values
563  */
FMC_ReadUserOptionByte(void)564 uint32_t FMC_ReadUserOptionByte(void)
565 {
566     return (FMC->OBCS_B.UOB >> 2);
567 }
568 
569 /*!
570  * @brief     Read the FMC Write Protection Option Bytes Register value.
571  *
572  * @param     None
573  *
574  * @retval    Returns the value of Option Bytes Write Protection Register.
575  */
FMC_ReadOptionByteWriteProtection(void)576 uint32_t FMC_ReadOptionByteWriteProtection(void)
577 {
578     return FMC->WRTPROT;
579 }
580 
581 /*!
582  * @brief     Get the FMC Read Out Protection Status is set or not.
583  *
584  * @param     None
585  *
586  * @retval    status : set or reset.
587  */
FMC_GetReadProtectionStatus(void)588 uint8_t FMC_GetReadProtectionStatus(void)
589 {
590     uint8_t flagstatus = RESET;
591 
592     if(FMC->OBCS_B.READPROT != RESET)
593     {
594         flagstatus = SET;
595     }
596     else
597     {
598         flagstatus = RESET;
599     }
600     return flagstatus;
601 }
602 
603 /*!
604  * @brief     FMC Prefetch Buffer status is set or not.
605  *
606  * @param     None
607  *
608  * @retval    status : set or reset.
609  */
FMC_ReadPrefetchBufferStatus(void)610 uint8_t FMC_ReadPrefetchBufferStatus(void)
611 {
612     return FMC->CTRL1_B.PBSF;
613 }
614 
615 /*!
616  * @brief     Enables the specified FMC interrupts.
617  *
618  * @param     interrupt: Select the FMC interrupt sources
619  *                       This parameter can be one of the following values:
620  *                       @arg FMC_INT_ERR :  Error Interrupt
621  *                       @arg FMC_INT_OC  :  Operation Complete Interrupt
622  *
623  * @retval    None
624  */
FMC_EnableInterrupt(FMC_INT_T interrupt)625 void FMC_EnableInterrupt(FMC_INT_T interrupt)
626 {
627     if(interrupt == FMC_INT_ERR)
628     {
629         FMC->CTRL2_B.ERRIE = ENABLE;
630     }
631     else
632     {
633         FMC->CTRL2_B.OCIE = ENABLE;
634     }
635 }
636 
637 /*!
638  * @brief     Disable the specified FMC interrupts.
639  *
640  * @param     interrupt: Select the FMC interrupt sources
641  *                       This parameter can be one of the following values:
642  *                       @arg FMC_INT_ERR :  Error Interrupt
643  *                       @arg FMC_INT_OC  :  Operation Complete Interrupt
644  *
645  * @retval    None
646  */
FMC_DisableInterrupt(FMC_INT_T interrupt)647 void FMC_DisableInterrupt(FMC_INT_T interrupt)
648 {
649     if(interrupt == FMC_INT_ERR)
650     {
651         FMC->CTRL2_B.ERRIE = DISABLE;
652     }
653     else
654     {
655         FMC->CTRL2_B.OCIE = DISABLE;
656     }
657 }
658 
659 /*!
660  * @brief     Read FMC flag is set or not
661  *
662  * @param     flag: status flag of FMC
663  *                  This parameter can be one of the following values:
664  *                  @arg FMC_FLAG_BUSY : FMC Busy flag
665  *                  @arg FMC_FLAG_OC   : FMC Operation Complete flag
666  *                  @arg FMC_FLAG_PE   : FMC Program error flag
667  *                  @arg FMC_FLAG_WPE  : FMC Write protected error flag
668  *                  @arg FMC_FLAG_OBE  : FMC Option Byte error flag
669  *
670  * @retval    flag status : set or reset
671  */
FMC_ReadStatusFlag(FMC_FLAG_T flag)672 uint8_t FMC_ReadStatusFlag(FMC_FLAG_T flag)
673 {
674     if(flag == FMC_FLAG_OBE)
675     {
676         return FMC->OBCS_B.OBE;
677     }
678     else if((FMC->STS & flag ) != RESET)
679     {
680         return SET;
681     }
682     return RESET;
683 }
684 
685 /*!
686  * @brief     Clears the FMC's flag.
687  *
688  * @param     flag: status flag of FMC
689  *                  This parameter can be any combination of the following values:
690  *                  @arg FMC_FLAG_OC   : FMC Operation Complete flag
691  *                  @arg FMC_FLAG_PE   : FMC Program error flag
692  *                  @arg FMC_FLAG_WPE  : FMC Write protected error flag
693  *
694  * @retval    None
695  *
696  */
FMC_ClearStatusFlag(uint32_t flag)697 void FMC_ClearStatusFlag(uint32_t flag)
698 {
699     FMC->STS = flag;
700 }
701 
702 /*!
703  * @brief     Read the FMC Status.
704  *
705  * @param     None
706  *
707  * @retval    Returns the flash state.It can be one of value:
708  *                 @arg FMC_STATUS_BUSY
709  *                 @arg FMC_STATUS_ERROR_PG
710  *                 @arg FMC_STATUS_ERROR_WRP
711  *                 @arg FMC_STATUS_COMPLETE
712  */
FMC_ReadStatus(void)713 FMC_STATUS_T  FMC_ReadStatus(void)
714 {
715     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
716 
717     if(FMC->STS_B.BUSYF == BIT_SET)
718     {
719         status = FMC_STATUS_BUSY;
720     }
721     else if(FMC->STS_B.PEF == BIT_SET)
722     {
723         status = FMC_STATUS_ERROR_PG;
724     }
725     else if(FMC->STS_B.WPEF == BIT_SET)
726     {
727         status = FMC_STATUS_ERROR_WRP;
728     }
729     else
730     {
731         status = FMC_STATUS_COMPLETE;
732     }
733     return status;
734 }
735 
736 /*!
737  * @brief     Waits for a Flash operation to complete or a TIMEOUT to occur.
738  *
739  * @param     timeOut:FMC programming timeout value.
740  *
741  * @retval    Returns the flash state.It can be one of value:
742  *                 @arg FMC_STATUS_ERROR_PG
743  *                 @arg FMC_STATUS_ERROR_WRP
744  *                 @arg FMC_STATUS_COMPLETE
745  *                 @arg FMC_STATUS_TIMEOUT
746  */
FMC_WaitForLastOperation(uint32_t timeOut)747 FMC_STATUS_T FMC_WaitForLastOperation(uint32_t timeOut)
748 {
749     FMC_STATUS_T status = FMC_STATUS_COMPLETE;
750 
751     /** Check for the Flash Status */
752     status = FMC_ReadStatus();
753 
754     /** Wait for a Flash operation to complete or a TIMEOUT to occur */
755     while((status == FMC_STATUS_BUSY) && (timeOut !=0))
756     {
757         status = FMC_ReadStatus();
758         timeOut--;
759     }
760     if(timeOut == 0x00)
761     {
762         status = FMC_STATUS_TIMEOUT;
763     }
764     return status;
765 }
766 
767 /**@} end of group FMC_Functions */
768 /**@} end of group FMC_Driver */
769 /**@} end of group APM32E10x_StdPeriphDriver */
770