1 /*!
2 * @file apm32f4xx_fmc.c
3 *
4 * @brief This file provides all the FMC firmware functions
5 *
6 * @version V1.0.2
7 *
8 * @date 2022-06-23
9 *
10 * @attention
11 *
12 * Copyright (C) 2021-2022 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 #include "apm32f4xx_fmc.h"
27 #include "apm32f4xx_rcm.h"
28
29 /** @addtogroup APM32F4xx_StdPeriphDriver
30 @{
31 */
32
33 /** @defgroup FMC_Driver
34 * @brief FMC driver modules
35 @{
36 */
37
38 /** @defgroup FMC_Functions
39 @{
40 */
41
42 /*!
43 * @brief Configs the code latency value.
44 *
45 * @param latency: the FMC Latency value.
46 * This parameter can be one of the following values:
47 * @arg FMC_LTNCY_0: FMC 0 Latency cycle
48 * @arg FMC_LTNCY_1: FMC 1 Latency cycle
49 * @arg FMC_LTNCY_2: FMC 2 Latency cycles
50 * @arg FMC_LTNCY_3: FMC 3 Latency cycles
51 * @arg FMC_LTNCY_4: FMC 4 Latency cycles
52 * @arg FMC_LTNCY_5: FMC 5 Latency cycles
53 * @arg FMC_LTNCY_6: FMC 6 Latency cycles
54 * @arg FMC_LTNCY_7: FMC 7 Latency cycles
55 *
56 * @retval None
57 */
FMC_ConfigLatency(FMC_LATENCY_T latency)58 void FMC_ConfigLatency(FMC_LATENCY_T latency)
59 {
60 *(__IO uint8_t *)ACCTRL_BYTE0_ADDRESS = (uint8_t)latency;
61 }
62
63 /*!
64 * @brief Enable the Prefetch Buffer.
65 *
66 * @param None
67 *
68 * @retval None
69 */
FMC_EnablePrefetchBuffer(void)70 void FMC_EnablePrefetchBuffer(void)
71 {
72 FMC->ACCTRL |= FMC_ACCTRL_PREFEN;
73 }
74
75 /*!
76 * @brief Disable the Prefetch Buffer.
77 *
78 * @param None
79 *
80 * @retval None
81 */
FMC_DisablePrefetchBuffer(void)82 void FMC_DisablePrefetchBuffer(void)
83 {
84 FMC->ACCTRL &= (~FMC_ACCTRL_PREFEN);
85 }
86
87 /*!
88 * @brief Enable the Instruction Cache feature.
89 *
90 * @param None
91 *
92 * @retval None
93 */
FMC_EnableInstructionCache(void)94 void FMC_EnableInstructionCache(void)
95 {
96 FMC->ACCTRL |= FMC_ACCTRL_ICACHEEN;
97 }
98
99 /*!
100 * @brief Disable the Instruction Cache feature.
101 *
102 * @param None
103 *
104 * @retval None
105 */
FMC_DisableInstructionCache(void)106 void FMC_DisableInstructionCache(void)
107 {
108 FMC->ACCTRL &= (~FMC_ACCTRL_ICACHEEN);
109 }
110
111 /*!
112 * @brief Enable the Data Cache feature.
113 *
114 * @param None
115 *
116 * @retval None
117 */
FMC_EnableDataCache(void)118 void FMC_EnableDataCache(void)
119 {
120 FMC->ACCTRL |= FMC_ACCTRL_DCACHEEN;
121 }
122
123 /*!
124 * @brief Disable the Data Cache feature.
125 *
126 * @param None
127 *
128 * @retval None
129 */
FMC_DisableDataCache(void)130 void FMC_DisableDataCache(void)
131 {
132 FMC->ACCTRL &= (~FMC_ACCTRL_DCACHEEN);
133 }
134
135 /*!
136 * @brief Reset the Instruction Cache feature.
137 *
138 * @param None
139 *
140 * @retval None
141 */
FMC_ResetInstructionCache(void)142 void FMC_ResetInstructionCache(void)
143 {
144 FMC->ACCTRL |= FMC_ACCTRL_ICACHERST;
145 }
146
147 /*!
148 * @brief Reset the Data Cache feature.
149 *
150 * @param None
151 *
152 * @retval None
153 */
FMC_ResetDataCache(void)154 void FMC_ResetDataCache(void)
155 {
156 FMC->ACCTRL |= FMC_ACCTRL_DCACHERST;
157 }
158
159 /*!
160 * @brief Unlocks the FMC control register access.
161 *
162 * @param None
163 *
164 * @retval None
165 */
FMC_Unlock(void)166 void FMC_Unlock(void)
167 {
168 if ((FMC->CTRL & FMC_CTRL_LOCK) != RESET)
169 {
170 FMC->KEY = FMC_KEY1;
171 FMC->KEY = FMC_KEY2;
172 }
173 }
174
175 /*!
176 * @brief Locks the FMC control register access.
177 *
178 * @param None
179 *
180 * @retval None
181 */
FMC_Lock(void)182 void FMC_Lock(void)
183 {
184 FMC->CTRL |= FMC_CTRL_LOCK;
185 }
186
187 /*!
188 * @brief Erases a specified FMC Sector.
189 *
190 * @param sector: The Sector number to be erased.
191 * This parameter can be a value between FMC_SECTOR_0 and FMC_SECTOR_11.
192 *
193 * @param voltageRange: The device voltage range which defines the erase parallelism.
194 * This parameter can be one of the following values:
195 * @arg FMC_VOLTAGE_1: when the device voltage range is 1.8V to 2.1V,
196 * the operation will be done by byte (8-bit)
197 * @arg FMC_VOLTAGE_2: when the device voltage range is 2.1V to 2.7V,
198 * the operation will be done by half word (16-bit)
199 * @arg FMC_VOLTAGE_3: when the device voltage range is 2.7V to 3.6V,
200 * the operation will be done by word (32-bit)
201 * @arg FMC_VOLTAGE_4: when the device voltage range is 2.7V to 3.6V + External Vpp,
202 * the operation will be done by double word (64-bit)
203 *
204 * @retval FMC_STATUS_T: The returned value can be:
205 * FMC_BUSY, FMC_ERROR_PROGRAM, FMC_ERROR_WRP, FMC_ERROR_OPERATION or FMC_COMPLETE.
206 */
FMC_EraseSector(FMC_SECTOR_T sector,FMC_VOLTAGE_T voltageRange)207 FMC_STATUS_T FMC_EraseSector(FMC_SECTOR_T sector, FMC_VOLTAGE_T voltageRange)
208 {
209 uint32_t tmp_psize = 0x00;
210 FMC_STATUS_T status = FMC_COMPLETE;
211
212 if (voltageRange == FMC_VOLTAGE_1)
213 {
214 tmp_psize = FMC_PSIZE_BYTE;
215 }
216 else if (voltageRange == FMC_VOLTAGE_2)
217 {
218 tmp_psize = FMC_PSIZE_HALF_WORD;
219 }
220 else if (voltageRange == FMC_VOLTAGE_3)
221 {
222 tmp_psize = FMC_PSIZE_WORD;
223 }
224 else if (voltageRange == FMC_VOLTAGE_4)
225 {
226 tmp_psize = FMC_PSIZE_DOUBLE_WORD;
227 }
228
229 status = FMC_WaitForLastOperation();
230
231 if (status == FMC_COMPLETE)
232 {
233 FMC->CTRL &= 0xFFFFFCFF;
234 FMC->CTRL |= tmp_psize;
235 FMC->CTRL &= 0xFFFFFF07;
236 FMC->CTRL |= FMC_CTRL_SERS | sector;
237 FMC->CTRL |= FMC_CTRL_START;
238 status = FMC_WaitForLastOperation();
239 FMC->CTRL &= (~FMC_CTRL_SERS);
240 FMC->CTRL &= 0xFFFFFF07;
241 }
242
243 return status;
244 }
245
246 /*!
247 * @brief Clears all FMC Sectors.
248 *
249 * @param voltageRange: The device voltage range which defines the erase parallelism.
250 * This parameter can be one of the following values:
251 * @arg FMC_VOLTAGE_1: when the device voltage range is 1.8V to 2.1V,
252 * the operation will be done by byte (8-bit)
253 * @arg FMC_VOLTAGE_2: when the device voltage range is 2.1V to 2.7V,
254 * the operation will be done by half word (16-bit)
255 * @arg FMC_VOLTAGE_3: when the device voltage range is 2.7V to 3.6V,
256 * the operation will be done by word (32-bit)
257 * @arg FMC_VOLTAGE_4: when the device voltage range is 2.7V to 3.6V + External Vpp,
258 * the operation will be done by double word (64-bit)
259 *
260 * @retval FMC_STATUS_T: The returned value can be:
261 * FMC_BUSY, FMC_ERROR_PROGRAM, FMC_ERROR_WRP, FMC_ERROR_OPERATION or FMC_COMPLETE.
262 */
FMC_EraseAllSectors(FMC_VOLTAGE_T voltageRange)263 FMC_STATUS_T FMC_EraseAllSectors(FMC_VOLTAGE_T voltageRange)
264 {
265 uint32_t tmp_psize = 0x00;
266 FMC_STATUS_T status = FMC_COMPLETE;
267 status = FMC_WaitForLastOperation();
268
269 if (voltageRange == FMC_VOLTAGE_1)
270 {
271 tmp_psize = FMC_PSIZE_BYTE;
272 }
273 else if (voltageRange == FMC_VOLTAGE_2)
274 {
275 tmp_psize = FMC_PSIZE_HALF_WORD;
276 }
277 else if (voltageRange == FMC_VOLTAGE_3)
278 {
279 tmp_psize = FMC_PSIZE_WORD;
280 }
281 else if (voltageRange == FMC_VOLTAGE_4)
282 {
283 tmp_psize = FMC_PSIZE_DOUBLE_WORD;
284 }
285
286 if (status == FMC_COMPLETE)
287 {
288 FMC->CTRL &= 0xFFFFFCFF;
289 FMC->CTRL |= tmp_psize;
290 FMC->CTRL |= FMC_CTRL_MERS;
291 FMC->CTRL |= FMC_CTRL_START;
292 status = FMC_WaitForLastOperation();
293 FMC->CTRL &= (~FMC_CTRL_MERS);
294 }
295
296 return status;
297 }
298
299 /*!
300 * @brief Programs a double word (64-bit) at a specified address.
301 *
302 * @param address:the address to be programmed.
303 * ((address) >= 0x08000000) && ((address) <= 0x080FFFFF))
304 * ((address) >= 0x1FFF7800) && ((address) <= 0x1FFF7A0F)))
305 *
306 * @param data: the data to be programmed.
307 *
308 * @retval FMC_STATUS_T: The returned value can be:
309 * FMC_BUSY, FMC_ERROR_PROGRAM, FMC_ERROR_WRP, FMC_ERROR_OPERATION or FMC_COMPLETE.
310 */
FMC_ProgramDoubleWord(uint32_t address,uint64_t data)311 FMC_STATUS_T FMC_ProgramDoubleWord(uint32_t address, uint64_t data)
312 {
313 FMC_STATUS_T status = FMC_COMPLETE;
314 status = FMC_WaitForLastOperation();
315
316 if (status == FMC_COMPLETE)
317 {
318 FMC->CTRL &= 0xFFFFFCFF;
319 FMC->CTRL |= FMC_PSIZE_DOUBLE_WORD;
320 FMC->CTRL |= FMC_CTRL_PG;
321 *(__IO uint64_t *)address = data;
322 status = FMC_WaitForLastOperation();
323 FMC->CTRL &= (~FMC_CTRL_PG);
324 }
325
326 return status;
327 }
328
329 /*!
330 * @brief Programs a word (32-bit) at a specified address.
331 *
332 * @param address:the address to be programmed.
333 * ((address) >= 0x08000000) && ((address) <= 0x080FFFFF))
334 * ((address) >= 0x1FFF7800) && ((address) <= 0x1FFF7A0F)))
335 *
336 * @param data: the data to be programmed.
337 *
338 * @retval FMC_STATUS_T: The returned value can be:
339 * FMC_BUSY, FMC_ERROR_PROGRAM, FMC_ERROR_WRP, FMC_ERROR_OPERATION or FMC_COMPLETE.
340 */
341
FMC_ProgramWord(uint32_t address,uint32_t data)342 FMC_STATUS_T FMC_ProgramWord(uint32_t address, uint32_t data)
343 {
344 FMC_STATUS_T status = FMC_COMPLETE;
345 status = FMC_WaitForLastOperation();
346
347 if (status == FMC_COMPLETE)
348 {
349 FMC->CTRL &= 0xFFFFFCFF;
350 FMC->CTRL |= FMC_PSIZE_WORD;
351 FMC->CTRL |= FMC_CTRL_PG;
352 *(__IO uint32_t *)address = data;
353 status = FMC_WaitForLastOperation();
354 FMC->CTRL &= (~FMC_CTRL_PG);
355 }
356
357 return status;
358 }
359
360 /*!
361 * @brief Programs a half word (16-bit) at a specified address.
362 *
363 * @param address:the address to be programmed.
364 * ((address) >= 0x08000000) && ((address) <= 0x080FFFFF))
365 * ((address) >= 0x1FFF7800) && ((address) <= 0x1FFF7A0F)))
366 *
367 * @param data: the data to be programmed.
368 *
369 * @retval FMC_STATUS_T: The returned value can be:
370 * FMC_BUSY, FMC_ERROR_PROGRAM, FMC_ERROR_WRP, FMC_ERROR_OPERATION or FMC_COMPLETE.
371 */
FMC_ProgramHalfWord(uint32_t address,uint16_t data)372 FMC_STATUS_T FMC_ProgramHalfWord(uint32_t address, uint16_t data)
373 {
374 FMC_STATUS_T status = FMC_COMPLETE;
375 status = FMC_WaitForLastOperation();
376
377 if (status == FMC_COMPLETE)
378 {
379 FMC->CTRL &= 0xFFFFFCFF;
380 FMC->CTRL |= FMC_PSIZE_HALF_WORD;
381 FMC->CTRL |= FMC_CTRL_PG;
382 *(__IO uint16_t *)address = data;
383 status = FMC_WaitForLastOperation();
384 FMC->CTRL &= (~FMC_CTRL_PG);
385 }
386
387 return status;
388 }
389
390 /*!
391 * @brief Programs a byte (8-bit) at a specified address.
392 *
393 * @param address:the address to be programmed.
394 * ((address) >= 0x08000000) && ((address) <= 0x080FFFFF))
395 * ((address) >= 0x1FFF7800) && ((address) <= 0x1FFF7A0F)))
396 *
397 * @param data: the data to be programmed.
398 *
399 * @retval FMC_STATUS_T: The returned value can be:
400 * FMC_BUSY, FMC_ERROR_PROGRAM, FMC_ERROR_WRP, FMC_ERROR_OPERATION or FMC_COMPLETE.
401 */
FMC_ProgramByte(uint32_t address,uint8_t data)402 FMC_STATUS_T FMC_ProgramByte(uint32_t address, uint8_t data)
403 {
404 FMC_STATUS_T status = FMC_COMPLETE;
405 status = FMC_WaitForLastOperation();
406
407 if (status == FMC_COMPLETE)
408 {
409 FMC->CTRL &= 0xFFFFFCFF;
410 FMC->CTRL |= FMC_PSIZE_BYTE;
411 FMC->CTRL |= FMC_CTRL_PG;
412 *(__IO uint8_t *)address = data;
413 status = FMC_WaitForLastOperation();
414 FMC->CTRL &= (~FMC_CTRL_PG);
415 }
416
417 return status;
418 }
419
420 /*!
421 * @brief Unlocks the option bytes block access
422 *
423 * @param None
424 *
425 * @retval None
426 */
FMC_UnlockOptionByte(void)427 void FMC_UnlockOptionByte(void)
428 {
429 if ((FMC->OPTCTRL & FMC_OPTCTRL_OPTLOCK) != RESET)
430 {
431 FMC->OPTKEY = FMC_OPT_KEY1;
432 FMC->OPTKEY = FMC_OPT_KEY2;
433 }
434 }
435
436 /*!
437 * @brief Locks the option bytes block access
438 *
439 * @param None
440 *
441 * @retval None
442 */
FMC_LockOptionByte(void)443 void FMC_LockOptionByte(void)
444 {
445 FMC->OPTCTRL |= FMC_OPTCTRL_OPTLOCK;
446 }
447
448 /*!
449 * @brief Enable the write protection of the desired sectors,
450 * for the first 1 Mb of the FMC
451 *
452 * @param wrp: specifies the sector(s) to be write protected or unprotected.
453 * This parameter can be one of the following values:
454 * @arg wrp: The value between FMC_OPT_WRP_SECTOR_0 and FMC_OPT_WRP_SECTOR_11
455 * @arg FMC_OPT_WRP_SECTOR_All
456 *
457 * @retval None
458 */
FMC_OPT_EnableWriteProtect(FMC_OPT_WRP_T wrp)459 void FMC_OPT_EnableWriteProtect(FMC_OPT_WRP_T wrp)
460 {
461 FMC_STATUS_T status = FMC_COMPLETE;
462 status = FMC_WaitForLastOperation();
463
464 if (status == FMC_COMPLETE)
465 {
466 *(__IO uint16_t *)(OPTCTRL_BYTE2_ADDRESS) &= (~(uint16_t)wrp);
467 }
468 }
469
470 /*!
471 * @brief Disable the write protection of the desired sectors,
472 * for the first 1 Mb of the FMC
473 *
474 * @param wrp: Specifies the sector(s) to be write protected or unprotected.
475 * This parameter can be one of the following values:
476 * @arg wrp: The value between FMC_OPT_WRP_SECTOR_0 and FMC_OPT_WRP_SECTOR_11
477 * @arg FMC_OPT_WRP_SECTOR_All
478 *
479 * @retval None
480 */
FMC_OPT_DisableWriteProtect(FMC_OPT_WRP_T wrp)481 void FMC_OPT_DisableWriteProtect(FMC_OPT_WRP_T wrp)
482 {
483 FMC_STATUS_T status = FMC_COMPLETE;
484 status = FMC_WaitForLastOperation();
485
486 if (status == FMC_COMPLETE)
487 {
488 *(__IO uint16_t *)(OPTCTRL_BYTE2_ADDRESS) |= (uint16_t)wrp;
489 }
490 }
491 /*!
492 * @brief Sets the read protection level.
493 *
494 * @param rdp: Specifies the read protection level.
495 * This parameter can be one of the following values:
496 * @arg FMC_OPT_RDP_LV0: No protection
497 * @arg FMC_OPT_RDP_LV1: Read protection of the memory
498 *
499 * @retval None
500 */
FMC_OPT_ConfigReadProtect(FMC_OPT_RDP_T rdp)501 void FMC_OPT_ConfigReadProtect(FMC_OPT_RDP_T rdp)
502 {
503 FMC_STATUS_T status = FMC_COMPLETE;
504 status = FMC_WaitForLastOperation();
505
506 if (status == FMC_COMPLETE)
507 {
508 *(__IO uint8_t *)OPTCTRL_BYTE1_ADDRESS = rdp;
509 }
510 }
511
512 /*!
513 * @brief Programs the FMC User Option Byte: WDTSEL / RSTSTOP / RSTSTDB.
514 *
515 * @param iwdt: Selects the IWDT mode
516 * This parameter can be one of the following values:
517 * @arg FMC_OPT_IWDT_SOFT: Software IWDT selected
518 * @arg FMC_OPT_IWDT_HARD: Hardware IWDT selected
519 * @param stop: Reset event when entering STOP mode.
520 * This parameter can be one of the following values:
521 * @arg FMC_OPT_STOP_NORST: No reset generated when entering in STOP
522 * @arg FMC_OPT_STOP_RST: Reset generated when entering in STOP
523 * @param stdby: Reset event when entering Standby mode.
524 * This parameter can be one of the following values:
525 * @arg FMC_OPT_STDBY_NORST: No reset generated when entering in STANDBY
526 * @arg FMC_OPT_STDBY_RST: Reset generated when entering in STANDBY
527 *
528 * @retval None
529 */
FMC_OPT_ConfigUser(FMC_OPT_IWDT_T iwdt,FMC_OPT_STOP_T stop,FMC_OPT_STDBY_T stdby)530 void FMC_OPT_ConfigUser(FMC_OPT_IWDT_T iwdt, FMC_OPT_STOP_T stop, FMC_OPT_STDBY_T stdby)
531 {
532 uint8_t option = 0xFF;
533 FMC_STATUS_T status = FMC_COMPLETE;
534 status = FMC_WaitForLastOperation();
535
536 if (status == FMC_COMPLETE)
537 {
538 option = (uint8_t)((*(__IO uint8_t *)OPTCTRL_BYTE0_ADDRESS) & 0x0F);
539 *(__IO uint8_t *)OPTCTRL_BYTE0_ADDRESS = ((uint8_t)iwdt | stop | stdby | option);
540 }
541 }
542
543 /*!
544 * @brief Sets the Brownout Reset Level.
545 *
546 * @param bor: specifies the Option Bytes BOR Reset Level.
547 * This parameter can be one of the following values:
548 * @arg FMC_OPT_BOR_LV3: Supply voltage ranges from 2.7 to 3.6 V
549 * @arg FMC_OPT_BOR_LV2: Supply voltage ranges from 2.4 to 2.7 V
550 * @arg FMC_OPT_BOR_LV1: Supply voltage ranges from 2.1 to 2.4 V
551 * @arg FMC_OPT_BOR_OFF: Supply voltage ranges from 1.62 to 2.1 V
552 *
553 * @retval None
554 */
FMC_OPT_ConfigBrownoutReset(FMC_OPT_BOR_T bor)555 void FMC_OPT_ConfigBrownoutReset(FMC_OPT_BOR_T bor)
556 {
557 *(__IO uint8_t *)(OPTCTRL_BYTE0_ADDRESS) &= (~(FMC_OPTCTRL_BORLVL));
558 *(__IO uint8_t *)(OPTCTRL_BYTE0_ADDRESS) |= bor;
559 }
560
561 /*!
562 * @brief Launch the option byte loading.
563 *
564 * @param None
565 *
566 * @retval FMC_STATUS_T: The returned value can be:
567 * FMC_BUSY, FMC_ERROR_PROGRAM, FMC_ERROR_WRP, FMC_ERROR_OPERATION or FMC_COMPLETE.
568 */
FMC_OPT_Launch(void)569 FMC_STATUS_T FMC_OPT_Launch(void)
570 {
571 FMC_STATUS_T status = FMC_COMPLETE;
572
573 *(__IO uint8_t *)(OPTCTRL_BYTE0_ADDRESS) |= (uint32_t)FMC_OPTCTRL_OPTSTART;
574 status = FMC_WaitForLastOperation();
575
576 return status;
577 }
578
579 /*!
580 * @brief Returns the FMC User Option Bytes values.
581 *
582 * @param None
583 *
584 * @retval The FMC User Option Bytes values: WDTSEL(Bit0), RSTSTOP(Bit1)
585 * and RSTSTDBY(Bit2).
586 */
FMC_OPT_ReadUser(void)587 uint8_t FMC_OPT_ReadUser(void)
588 {
589 return (uint8_t)(FMC->OPTCTRL >> 5);
590 }
591
592 /*!
593 * @brief Returns the FMC Write Protection Option Bytes value.
594 *
595 * @param None
596 *
597 * @retval The FMC Write Protection Option Bytes value
598 */
FMC_OPT_ReadWriteProtect(void)599 uint16_t FMC_OPT_ReadWriteProtect(void)
600 {
601 return (*(__IO uint16_t *)(OPTCTRL_BYTE2_ADDRESS));
602 }
603
604 /*!
605 * @brief Returns the FMC Read Protection level.
606 *
607 * @param None
608 *
609 * @retval tmp: ReadOut Protection Status:
610 * - SET, when FMC_OPT_RDP_LV1 is set
611 * - RESET, when FMC_OPT_RDP_LV0 is set
612 */
FMC_OPT_ReadProtectLevel(void)613 uint8_t FMC_OPT_ReadProtectLevel(void)
614 {
615 uint8_t tmp = RESET;
616
617 if ((*(__IO uint8_t *)((OPTCTRL_BYTE1_ADDRESS)) != (uint8_t)FMC_OPT_RDP_LV0))
618 {
619 tmp = SET;
620 }
621
622 return tmp;
623 }
624
625 /*!
626 * @brief Returns the FMC BOR level.
627 *
628 * @param None
629 *
630 * @retval The FMC BOR level:
631 * - FMC_OPT_BOR_LV1: Supply voltage ranges from 2.7 to 3.6 V
632 * - FMC_OPT_BOR_LV1: Supply voltage ranges from 2.4 to 2.7 V
633 * - FMC_OPT_BOR_LV1: Supply voltage ranges from 2.1 to 2.4 V
634 * - FMC_OPT_BOR_OFF : Supply voltage ranges from 1.62 to 2.1 V
635 */
FMC_OPT_ReadBrownoutReset(void)636 uint8_t FMC_OPT_ReadBrownoutReset(void)
637 {
638 return (uint8_t)(*(__IO uint8_t *)((OPTCTRL_BYTE0_ADDRESS)) & FMC_OPT_BOR_OFF);
639 }
640
641 /*!
642 * @brief Enables the specified FMC interrupts.
643 *
644 * @param interrupt: Select the FMC interrupt sources
645 * This parameter can be any combination of the following values:
646 * @arg FMC_INT_ERR : Error Interrupt
647 * @arg FMC_INT_OC : Operation Complete Interrupt
648 *
649 * @retval None
650 */
FMC_EnableInterrupt(uint32_t interrupt)651 void FMC_EnableInterrupt(uint32_t interrupt)
652 {
653 if (interrupt == FMC_INT_ERR)
654 {
655 FMC->CTRL |= FMC_INT_ERR;
656 }
657 else
658 {
659 FMC->CTRL |= FMC_INT_OC;
660 }
661 }
662
663 /*!
664 * @brief Disable the specified FMC interrupts.
665 *
666 * @param interrupt: Select the FMC interrupt sources
667 * This parameter can be any combination of the following values:
668 * @arg FMC_INT_ERR : Error Interrupt
669 * @arg FMC_INT_OC : Operation Complete Interrupt
670 *
671 * @retval None
672 */
FMC_DisableInterrupt(uint32_t interrupt)673 void FMC_DisableInterrupt(uint32_t interrupt)
674 {
675 if (interrupt == FMC_INT_ERR)
676 {
677 FMC->CTRL &= ~(uint32_t)FMC_INT_ERR;
678 }
679 else
680 {
681 FMC->CTRL &= ~(uint32_t)FMC_INT_OC;
682 }
683 }
684
685 /*!
686 * @brief Read the FMC flag
687 *
688 * @param flag: specifies the FMC flag to check.
689 * This parameter can be one of the following values:
690 * @arg FMC_FLAG_ENDOP : FMC End of Operation flag
691 * @arg FMC_FLAG_ERROP : FMC operation Error flag
692 * @arg FMC_FLAG_ERRWRP : FMC Write protected error flag
693 * @arg FMC_FLAG_ERRPGA : FMC Programming Alignment error flag
694 * @arg FMC_FLAG_ERRPGP : FMC Programming Parallelism error flag
695 * @arg FMC_FLAG_ERRPGS : FMC Programming Sequence error flag
696 * @arg FMC_FLAG_BUSY : FMC Busy flag
697 *
698 * @retval SET or RESET.
699 */
FMC_ReadStatusFlag(FMC_FLAG_T flag)700 uint8_t FMC_ReadStatusFlag(FMC_FLAG_T flag)
701 {
702 uint8_t temp = RESET;
703
704 if ((FMC->STS & flag) != (uint32_t)RESET)
705 {
706 temp = SET;
707 }
708
709 return temp;
710 }
711
712 /*!
713 * @brief Clears the FMC flag.
714 *
715 * @param flag: specifies the FMC flags to clear.
716 * This parameter can be any combination of the following values:
717 * @arg FMC_FLAG_ENDOP : FMC End of Operation flag
718 * @arg FMC_FLAG_ERROP : FMC operation Error flag
719 * @arg FMC_FLAG_ERRWRP : FMC Write protected error flag
720 * @arg FMC_FLAG_ERRPGA : FMC Programming Alignment error flag
721 * @arg FMC_FLAG_ERRPGP : FMC Programming Parallelism error flag
722 * @arg FMC_FLAG_ERRPGS : FMC Programming Sequence error flag
723 *
724 * @retval None
725 */
FMC_ClearStatusFlag(uint32_t flag)726 void FMC_ClearStatusFlag(uint32_t flag)
727 {
728 FMC->STS = flag;
729 }
730
731 /*!
732 * @brief Returns the FMC Status.
733 *
734 * @param None
735 *
736 * @retval FMC_STATUS_T: The returned value can be:
737 * FMC_BUSY, FMC_ERROR_PROGRAM, FMC_ERROR_WRP, FMC_ERROR_OPERATION or FMC_COMPLETE.
738 */
FMC_ReadStatus(void)739 FMC_STATUS_T FMC_ReadStatus(void)
740 {
741 FMC_STATUS_T status = FMC_COMPLETE;
742
743 if ((FMC->STS & FMC_FLAG_BUSY) == FMC_FLAG_BUSY)
744 {
745 status = FMC_BUSY;
746 }
747 else if ((FMC->STS & FMC_FLAG_ERRWRP) != RESET)
748 {
749 status = FMC_ERROR_WRP;
750 }
751 else if ((FMC->STS & (uint32_t)0xE0) != RESET)
752 {
753 status = FMC_ERROR_PROGRAM;
754 }
755 else if ((FMC->STS & FMC_FLAG_ERROP) != RESET)
756 {
757 status = FMC_ERROR_OPERATION;
758 }
759 else
760 {
761 status = FMC_COMPLETE;
762 }
763
764 return status;
765 }
766
767 /*!
768 * @brief Waits for a FMC operation to complete.
769 *
770 * @param None
771 *
772 * @retval FMC_STATUS_T: The returned value can be:
773 * FMC_BUSY, FMC_ERROR_PROGRAM, FMC_ERROR_WRP, FMC_ERROR_OPERATION or FMC_COMPLETE.
774 */
FMC_WaitForLastOperation(void)775 FMC_STATUS_T FMC_WaitForLastOperation(void)
776 {
777 __IO FMC_STATUS_T status = FMC_COMPLETE;
778
779 status = FMC_ReadStatus();
780
781 while (status == FMC_BUSY)
782 {
783 status = FMC_ReadStatus();
784 }
785
786 return status;
787 }
788
789 /**@} end of group FMC_Functions */
790 /**@} end of group FMC_Driver */
791 /**@} end of group APM32F4xx_StdPeriphDriver */
792