rt-thread-official/bsp/gd32450z-eval/Libraries/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c

825 lines
23 KiB
C

/*!
\file gd32f4xx_fmc.c
\brief FMC driver
*/
/*
Copyright (C) 2016 GigaDevice
2016-08-15, V1.0.0, firmware for GD32F4xx
*/
#include "gd32f4xx_fmc.h"
/*!
\brief set the wait state counter value
\param[in] wscnt£ºwait state counter value
\arg WS_WSCNT_0: FMC 0 wait
\arg WS_WSCNT_1: FMC 1 wait
\arg WS_WSCNT_2: FMC 2 wait
\arg WS_WSCNT_3: FMC 3 wait
\arg WS_WSCNT_4: FMC 4 wait
\arg WS_WSCNT_5: FMC 5 wait
\arg WS_WSCNT_6: FMC 6 wait
\arg WS_WSCNT_7: FMC 7 wait
\arg WS_WSCNT_8: FMC 8 wait
\arg WS_WSCNT_9: FMC 9 wait
\arg WS_WSCNT_10: FMC 10 wait
\arg WS_WSCNT_11: FMC 11 wait
\arg WS_WSCNT_12: FMC 12 wait
\arg WS_WSCNT_13: FMC 13 wait
\arg WS_WSCNT_14: FMC 14 wait
\arg WS_WSCNT_15: FMC 15 wait
\param[out] none
\retval none
*/
void fmc_wscnt_set(uint32_t wscnt)
{
uint32_t reg;
reg = FMC_WS;
/* set the wait state counter value */
reg &= ~FMC_WC_WSCNT;
FMC_WS = (reg | wscnt);
}
/*!
\brief unlock the main FMC operation
\param[in] none
\param[out] none
\retval none
*/
void fmc_unlock(void)
{
if((RESET != (FMC_CTL & FMC_CTL_LK))){
/* write the FMC key */
FMC_KEY = UNLOCK_KEY0;
FMC_KEY = UNLOCK_KEY1;
}
}
/*!
\brief lock the main FMC operation
\param[in] none
\param[out] none
\retval none
*/
void fmc_lock(void)
{
/* set the LK bit*/
FMC_CTL |= FMC_CTL_LK;
}
/*!
\brief erase sector
\param[in] fmc_sector: select the sector to erase
\arg CTL_SECTOR_NUMBER_0: sector 0
\arg CTL_SECTOR_NUMBER_1: sector 1
\arg CTL_SECTOR_NUMBER_2: sector 2
\arg CTL_SECTOR_NUMBER_3: sector 3
\arg CTL_SECTOR_NUMBER_4: sector 4
\arg CTL_SECTOR_NUMBER_5: sector 5
\arg CTL_SECTOR_NUMBER_6: sector 6
\arg CTL_SECTOR_NUMBER_7: sector 7
\arg CTL_SECTOR_NUMBER_8: sector 8
\arg CTL_SECTOR_NUMBER_9: sector 9
\arg CTL_SECTOR_NUMBER_10: sector 10
\arg CTL_SECTOR_NUMBER_11: sector 11
\arg CTL_SECTOR_NUMBER_12: sector 12
\arg CTL_SECTOR_NUMBER_13: sector 13
\arg CTL_SECTOR_NUMBER_14: sector 14
\arg CTL_SECTOR_NUMBER_15: sector 15
\arg CTL_SECTOR_NUMBER_16: sector 16
\arg CTL_SECTOR_NUMBER_17: sector 17
\arg CTL_SECTOR_NUMBER_18: sector 18
\arg CTL_SECTOR_NUMBER_19: sector 19
\arg CTL_SECTOR_NUMBER_20: sector 20
\arg CTL_SECTOR_NUMBER_21: sector 21
\arg CTL_SECTOR_NUMBER_22: sector 22
\arg CTL_SECTOR_NUMBER_23: sector 23
\arg CTL_SECTOR_NUMBER_24: sector 24
\arg CTL_SECTOR_NUMBER_25: sector 25
\arg CTL_SECTOR_NUMBER_26: sector 26
\arg CTL_SECTOR_NUMBER_27: sector 27
\arg CTL_SECTOR_NUMBER_28: sector 28
\arg CTL_SECTOR_NUMBER_29: sector 29
\arg CTL_SECTOR_NUMBER_30: sector 30
\param[out] none
\retval fmc_state_enum
*/
fmc_state_enum fmc_sector_erase(uint32_t fmc_sector)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
/* start sector erase */
FMC_CTL &= ~FMC_CTL_SN;
FMC_CTL |= (FMC_CTL_SER | fmc_sector);
FMC_CTL |= FMC_CTL_START;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* reset the SER bit */
FMC_CTL &= (~FMC_CTL_SER);
FMC_CTL &= ~FMC_CTL_SN;
}
/* return the FMC state */
return fmc_state;
}
/*!
\brief erase whole chip
\param[in] none
\param[out] none
\retval fmc_state_enum
*/
fmc_state_enum fmc_mass_erase(void)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
/* start whole chip erase */
FMC_CTL |= (FMC_CTL_MER0 | FMC_CTL_MER1);
FMC_CTL |= FMC_CTL_START;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* reset the MER bits */
FMC_CTL &= ~(FMC_CTL_MER0 | FMC_CTL_MER1);
}
/* return the fmc state */
return fmc_state;
}
/*!
\brief erase all FMC sectors in bank0
\param[in] none
\param[out] none
\retval fmc_state_enum
*/
fmc_state_enum fmc_bank0_erase(void)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
/* start FMC bank0 erase */
FMC_CTL |= FMC_CTL_MER0;
FMC_CTL |= FMC_CTL_START;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* reset the MER0 bit */
FMC_CTL &= (~FMC_CTL_MER0);
}
/* return the fmc state */
return fmc_state;
}
/*!
\brief erase all FMC sectors in bank1
\param[in] none
\param[out] none
\retval fmc_state_enum
*/
fmc_state_enum fmc_bank1_erase(void)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
/* start FMC bank1 erase */
FMC_CTL |= FMC_CTL_MER1;
FMC_CTL |= FMC_CTL_START;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* reset the MER1 bit */
FMC_CTL &= (~FMC_CTL_MER1);
}
/* return the fmc state */
return fmc_state;
}
/*!
\brief program a word at the corresponding address
\param[in] address: address to program
\param[in] data: word to program
\param[out] none
\retval fmc_state_enum
*/
fmc_state_enum fmc_word_program(uint32_t address, uint32_t data)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
/* set the PG bit to start program */
FMC_CTL &= ~FMC_CTL_PSZ;
FMC_CTL |= CTL_PSZ_WORD;
FMC_CTL |= FMC_CTL_PG;
REG32(address) = data;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* reset the PG bit */
FMC_CTL &= ~FMC_CTL_PG;
}
/* return the FMC state */
return fmc_state;
}
/*!
\brief program a half word at the corresponding address
\param[in] address: address to program
\param[in] data: halfword to program
\param[out] none
\retval fmc_state_enum
*/
fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
/* set the PG bit to start program */
FMC_CTL &= ~FMC_CTL_PSZ;
FMC_CTL |= CTL_PSZ_HALF_WORD;
FMC_CTL |= FMC_CTL_PG;
REG16(address) = data;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* reset the PG bit */
FMC_CTL &= ~FMC_CTL_PG;
}
/* return the FMC state */
return fmc_state;
}
/*!
\brief program a byte at the corresponding address
\param[in] address: address to program
\param[in] data: byte to program
\param[out] none
\retval fmc_state_enum
*/
fmc_state_enum fmc_byte_program(uint32_t address, uint8_t data)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
/* set the PG bit to start program */
FMC_CTL &= ~FMC_CTL_PSZ;
FMC_CTL |= CTL_PSZ_BYTE;
FMC_CTL |= FMC_CTL_PG;
REG8(address) = data;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* reset the PG bit */
FMC_CTL &= ~FMC_CTL_PG;
}
/* return the FMC state */
return fmc_state;
}
/*!
\brief unlock the option byte operation
\param[in] none
\param[out] none
\retval none
*/
void ob_unlock(void)
{
if(RESET != (FMC_OBCTL0 & FMC_OBCTL0_OB_LK)){
/* write the FMC key */
FMC_OBKEY = OB_UNLOCK_KEY0;
FMC_OBKEY = OB_UNLOCK_KEY1;
}
}
/*!
\brief lock the option byte operation
\param[in] none
\param[out] none
\retval none
*/
void ob_lock(void)
{
/* reset the OB_LK bit */
FMC_OBCTL0 &= ~FMC_OBCTL0_OB_LK;
}
/*!
\brief send option byte change command
\param[in] none
\param[out] none
\retval none
*/
void ob_start(void)
{
/* set the OB_START bit in OBCTL0 register */
FMC_OBCTL0 |= FMC_OBCTL0_OB_START;
}
/*!
\brief enable write protection
\param[in] ob_wp: specify sector to be write protected
\arg OB_WPx(x=0..11): write protect specify sector
\arg OB_WP_ALL: write protect all sector
\param[out] none
\retval none
*/
void ob_write_protection0_enable(uint32_t ob_wp)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
FMC_OBCTL0 &= (~((uint32_t)ob_wp << 16));
}
}
/*!
\brief disable write protection
\param[in] ob_wp: specify sector to be write protected
\arg OB_WPx(x=0..11): write protect specify sector
\arg OB_WP_ALL: write protect all sector
\param[out] none
\retval none
*/
void ob_write_protection0_disable(uint32_t ob_wp)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
FMC_OBCTL0 |= ((uint32_t)ob_wp << 16);
}
}
/*!
\brief enable write protection
\param[in] ob_wp: specify sector to be write protected
\arg OB_WPx(x=12..30): write protect specify sector
\arg OB_WP_ALL: write protect all sector
\param[out] none
\retval none
*/
void ob_write_protection1_enable(uint32_t ob_wp)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
FMC_OBCTL1 &= (~((uint32_t)ob_wp << 16));
}
}
/*!
\brief disable write protection
\param[in] ob_wp: specify sector to be write protected
\arg OB_WPx(x=12..30): write protect specify sector
\arg OB_WP_ALL: write protect all sector
\param[out] none
\retval none
*/
void ob_write_protection1_disable(uint32_t ob_wp)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
FMC_OBCTL1 |= ((uint32_t)ob_wp << 16);
}
}
/*!
\brief configure the protection mode
\param[in] ob_drp: configure the protection mode of WPx bits
\arg OB_DRP_DISABLE: the WPx bits used as erase/program protection of each sector
\arg OB_DRP_ENABLE: the WPx bits used as erase/program protection and D-bus read protection of each sector
\param[out] none
\retval none
*/
void ob_drp_config(uint32_t ob_drp)
{
FMC_OBCTL0 &= ~FMC_OBCTL0_DRP;
FMC_OBCTL0 |= ob_drp;
}
/*!
\brief enable erase/program protection and D-bus read protection
\param[in] ob_drp: enable the WPx bits used as erase/program protection and D-bus read protection of each sector
\arg OB_DRPx(x=0..11): erase/program protection and D-bus read protection of specify sector
\arg OB_DRP_ALL: erase/program protection and D-bus read protection of all sector
\param[out] none
\retval none
*/
void ob_drp0_enable(uint32_t ob_drp)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
FMC_OBCTL0 |= ((uint32_t)ob_drp << 16);
}
}
/*!
\brief disable erase/program protection and D-bus read protection
\param[in] ob_drp: disable the WPx bits used as erase/program protection and D-bus read protection of each sector
\arg OB_DRPx(x=0..11): erase/program protection and D-bus read protection of specify sector
\arg OB_DRP_ALL: erase/program protection and D-bus read protection of all sector
\param[out] none
\retval none
*/
void ob_drp0_disable(uint32_t ob_drp)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
FMC_OBCTL0 &= (~((uint32_t)ob_drp << 16));
}
}
/*!
\brief enable erase/program protection and D-bus read protection
\param[in] ob_drp: enable the WPx bits used as erase/program protection and D-bus read protection of each sector
\arg OB_DRPx(x=12..30): erase/program protection and D-bus read protection of specify sector
\arg OB_DRP_ALL: erase/program protection and D-bus read protection of all sector
\param[out] none
\retval none
*/
void ob_drp1_enable(uint32_t ob_drp)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
FMC_OBCTL1 |= ((uint32_t)ob_drp << 16);
}
}
/*!
\brief disable erase/program protection and D-bus read protection
\param[in] ob_drp: disable the WPx bits used as erase/program protection and D-bus read protection of each sector
\arg OB_DRPx(x=12..30): erase/program protection and D-bus read protection of specify sector
\arg OB_DRP_ALL: erase/program protection and D-bus read protection of all sector
\param[out] none
\retval none
*/
void ob_drp1_disable(uint32_t ob_drp)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
FMC_OBCTL1 &= (~((uint32_t)ob_drp << 16));
}
}
/*!
\brief configure security protection level
\param[in] ob_spc: specify security protection level
\arg FMC_NSPC: no security protection
\arg FMC_LSPC: low security protection
\arg FMC_HSPC: high security protection
\param[out] none
\retval none
*/
void ob_security_protection_config(uint8_t ob_spc)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
uint32_t reg;
reg = FMC_OBCTL0;
/* reset the OBCTL0_SPC, set according to ob_spc */
reg &= ~FMC_OBCTL0_SPC;
FMC_OBCTL0 |= ((uint32_t)ob_spc << 8);
}
}
/*!
\brief program the FMC user option byte
\param[in] ob_fwdgt: option byte watchdog value
\arg OB_FWDGT_SW: software free watchdog
\arg OB_FWDGT_HW: hardware free watchdog
\param[in] ob_deepsleep: option byte deepsleep reset value
\arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode
\arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode
\param[in] ob_stdby:option byte standby reset value
\arg OB_STDBY_NRST: no reset when entering standby mode
\arg OB_STDBY_RST: generate a reset instead of entering standby mode
\param[out] none
\retval none
*/
void ob_user_write(uint32_t ob_fwdgt, uint32_t ob_deepsleep, uint32_t ob_stdby)
{
fmc_state_enum fmc_state = FMC_READY;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
uint32_t reg;
reg = FMC_OBCTL0;
/* reset the OB_FWDGT, OB_DEEPSLEEP and OB_STDBY, set according to ob_fwdgt ,ob_deepsleep and ob_stdby */
reg &= ~(FMC_OBCTL0_NWDG_HW | FMC_OBCTL0_NRST_DPSLP | FMC_OBCTL0_NRST_STDBY);
FMC_OBCTL0 = (reg | ob_fwdgt | ob_deepsleep | ob_stdby);
}
}
/*!
\brief program the option byte BOR threshold value
\param[in] ob_bor_th: user option byte
\arg OB_BOR_TH_VALUE3: BOR threshold value 3
\arg OB_BOR_TH_VALUE2: BOR threshold value 2
\arg OB_BOR_TH_VALUE1: BOR threshold value 1
\arg OB_BOR_TH_OFF: no BOR function.
\param[out] none
\retval none
*/
void ob_user_bor_threshold(uint32_t ob_bor_th)
{
uint32_t reg;
reg = FMC_OBCTL0;
/* set the BOR level */
reg &= ~FMC_OBCTL0_BOR_TH;
FMC_OBCTL0 = (reg | ob_bor_th);
}
/*!
\brief configure the option byte boot bank value
\param[in] boot_mode: specifies the option byte boot bank value
\arg OB_BB_DISABLE: boot from bank0
\arg OB_BB_ENABLE: boot from bank1 or bank0 if bank1 is void
\param[out] none
\retval none
*/
void ob_boot_mode_config(uint32_t boot_mode)
{
uint32_t reg;
reg = FMC_OBCTL0;
/* set option byte boot bank value */
reg &= ~FMC_OBCTL0_BB;
FMC_OBCTL0 = (reg | boot_mode);
}
/*!
\brief get the FMC user option byte
\param[in] none
\param[out] none
\retval the FMC user option byte values: ob_fwdgt(Bit0), ob_deepsleep(Bit1), ob_stdby(Bit2).
*/
uint8_t ob_user_get(void)
{
return (uint8_t)((uint8_t)(FMC_OBCTL0 >> 5) & (uint8_t)0x07);
}
/*!
\brief get the FMC option byte write protection
\param[in] none
\param[out] none
\retval the FMC write protection option byte value
*/
uint16_t ob_write_protection0_get(void)
{
/* return the FMC write protection option byte value */
return (uint16_t)(((uint16_t)(FMC_OBCTL0 >> 16)) & (uint16_t)0x0FFF);
}
/*!
\brief get the FMC option byte write protection
\param[in] none
\param[out] none
\retval the FMC write protection option byte value
*/
uint16_t ob_write_protection1_get(void)
{
/* return the the FMC write protection option byte value */
return (uint16_t)(((uint16_t)(FMC_OBCTL1 >> 16)) & (uint16_t)0x0FFF);
}
/*!
\brief get the FMC D-bus read protection protection
\param[in] none
\param[out] none
\retval the FMC erase/program protection and D-bus read protection option bytes value
*/
uint16_t ob_drp0_get(void)
{
/* return the FMC erase/program protection and D-bus read protection option bytes value */
return (uint16_t)(((uint16_t)(FMC_OBCTL0 >> 16)) & (uint16_t)0x0FFF);
}
/*!
\brief get the FMC D-bus read protection protection
\param[in] none
\param[out] none
\retval the FMC erase/program protection and D-bus read protection option bytes value
*/
uint16_t ob_drp1_get(void)
{
/* return the FMC erase/program protection and D-bus read protection option bytes value */
return (uint16_t)(((uint16_t)(FMC_OBCTL1 >> 16)) & (uint16_t)0x0FFF);
}
/*!
\brief get the FMC option byte security protection
\param[in] none
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus ob_spc_get(void)
{
FlagStatus spc_state = RESET;
if (((uint8_t)(FMC_OBCTL0 >> 8)) != (uint8_t)FMC_NSPC){
spc_state = SET;
}else{
spc_state = RESET;
}
return spc_state;
}
/*!
\brief get the FMC option byte BOR threshold value
\param[in] none
\param[out] none
\retval the FMC BOR threshold value:OB_BOR_TH_OFF,OB_BOR_TH_VALUE1,OB_BOR_TH_VALUE2,OB_BOR_TH_VALUE3
*/
uint8_t ob_user_bor_threshold_get(void)
{
/* return the FMC BOR threshold value */
return (uint8_t)((uint8_t)FMC_OBCTL0 & (uint8_t)0x0C);
}
/*!
\brief enable FMC interrupt
\param[in] the FMC interrupt source
\arg FMC_INTEN_END: enable FMC end of program interrupt
\arg FMC_INTEN_ERR: enable FMC error interrupt
\param[out] none
\retval none
*/
void fmc_interrupt_enable(uint32_t fmc_int)
{
FMC_CTL |= fmc_int;
}
/*!
\brief disable FMC interrupt
\param[in] the FMC interrupt source
\arg FMC_INTEN_END: disable FMC end of program interrupt
\arg FMC_INTEN_ERR: disable FMC error interrupt
\param[out] none
\retval none
*/
void fmc_interrupt_disable(uint32_t fmc_int)
{
FMC_CTL &= ~(uint32_t)fmc_int;
}
/*!
\brief get flag set or reset
\param[in] fmc_flag: check FMC flag
\arg FMC_FLAG_BUSY: FMC busy flag
\arg FMC_FLAG_RDDERR: FMC read D-bus protection error flag bit
\arg FMC_FLAG_PGSERR: FMC program sequence error flag bit
\arg FMC_FLAG_PGMERR: FMC program size not match error flag bit
\arg FMC_FLAG_WPERR: FMC Erase/Program protection error flag bit
\arg FMC_FLAG_OPERR: FMC operation error flag bit
\arg FMC_FLAG_END: FMC end of operation flag bit
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus fmc_flag_get(uint32_t fmc_flag)
{
if(FMC_STAT & fmc_flag){
return SET;
}
/* return the state of corresponding FMC flag */
return RESET;
}
/*!
\brief clear the FMC pending flag
\param[in] FMC_flag: clear FMC flag
\arg FMC_FLAG_RDDERR: FMC read D-bus protection error flag bit
\arg FMC_FLAG_PGSERR: FMC program sequence error flag bit
\arg FMC_FLAG_PGMERR: FMC program size not match error flag bit
\arg FMC_FLAG_WPERR: FMC erase/program protection error flag bit
\arg FMC_FLAG_OPERR: FMC operation error flag bit
\arg FMC_FLAG_END: FMC end of operation flag bit
\param[out] none
\retval none
*/
void fmc_flag_clear(uint32_t fmc_flag)
{
/* clear the flags */
FMC_STAT = fmc_flag;
}
/*!
\brief get the FMC state
\param[in] none
\param[out] none
\retval fmc_state_enum
*/
fmc_state_enum fmc_state_get(void)
{
fmc_state_enum fmc_state = FMC_READY;
if((FMC_STAT & FMC_FLAG_BUSY) == FMC_FLAG_BUSY){
fmc_state = FMC_BUSY;
}else{
if((FMC_STAT & FMC_FLAG_WPERR) != (uint32_t)0x00){
fmc_state = FMC_WPERR;
}else{
if((FMC_STAT & FMC_FLAG_RDDERR) != (uint32_t)0x00){
fmc_state = FMC_RDDERR;
}else{
if((FMC_STAT & (uint32_t)0xEF) != (uint32_t)0x00){
fmc_state = FMC_PGERR;
}else{
if((FMC_STAT & FMC_FLAG_OPERR) != (uint32_t)0x00){
fmc_state = FMC_OPERR;
}else{
fmc_state = FMC_READY;
}
}
}
}
}
/* return the FMC state */
return fmc_state;
}
/*!
\brief check whether FMC is ready or not
\param[in] count: FMC_TIMEOUT_COUNT
\param[out] none
\retval fmc_state_enum
*/
fmc_state_enum fmc_ready_wait(uint32_t count)
{
fmc_state_enum fmc_state = FMC_BUSY;
/* wait for FMC ready */
do{
/* get FMC state */
fmc_state = fmc_state_get();
count--;
}while((FMC_BUSY == fmc_state) && ((uint32_t)RESET != count));
if(FMC_BUSY == fmc_state){
fmc_state = FMC_TOERR;
}
/* return the FMC state */
return fmc_state;
}