You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1984 lines
77 KiB
1984 lines
77 KiB
/*!
|
|
\file gd32h75e_fmc.c
|
|
\brief FMC driver
|
|
|
|
\version 2025-08-07, V1.2.0, firmware for GD32H75E
|
|
*/
|
|
|
|
/*
|
|
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
|
|
|
Redistribution and use in source and binary forms, with or without modification,
|
|
are permitted provided that the following conditions are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright notice, this
|
|
list of conditions and the following disclaimer.
|
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation
|
|
and/or other materials provided with the distribution.
|
|
3. Neither the name of the copyright holder nor the names of its contributors
|
|
may be used to endorse or promote products derived from this software without
|
|
specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "gd32h75e_fmc.h"
|
|
|
|
#define FLASH_DENSITY_ADDRESS ((uint32_t)0x1FF0F7E0U) /*!< memory density information address */
|
|
#define FLASH_DENSITY_OFFSET ((uint32_t)0x00000010U) /*!< bit offset of FLASH_DENSITY in memory density information */
|
|
|
|
/* FMC register bit offset */
|
|
#define BTADDR_BOOT_ADDR0_OFFSET ((uint32_t)0x00000000U) /*!< bit offset of BOOT_ADDR0 in FMC_BTADDR_EFT/FMC_BTADDR_MDF register*/
|
|
#define BTADDR_BOOT_ADDR1_OFFSET ((uint32_t)0x00000010U) /*!< bit offset of BOOT_ADDR1 in FMC_BTADDR_EFT/FMC_BTADDR_MDF register */
|
|
#define SCRADDR_SCR_AREA_START_OFFSET ((uint32_t)0x00000000U) /*!< bit offset of SCR_AREA_START in FMC_SCRADDR_EFT/FMC_SCRADDR_MDF register */
|
|
#define SCRADDR_SCR_AREA_END_OFFSET ((uint32_t)0x00000010U) /*!< bit offset of SCR_AREA_END in FMC_SCRADDR_EFT/FMC_SCRADDR_MDF register */
|
|
#define DCRPADDR_DCRP_AREA_START_OFFSET ((uint32_t)0x00000000U) /*!< bit offset of DCRP_AREA_START in FMC_DCRPADDR_EFT/FMC_DCRPADDR_MDF register */
|
|
#define DCRPADDR_DCRP_AREA_END_OFFSET ((uint32_t)0x00000010U) /*!< bit offset of DCRP_AREA_END in FMC_DCRPADDR_EFT/FMC_DCRPADDR_MDF register */
|
|
#define OBSTAT0_SPC_OFFSET ((uint32_t)0x00000008U) /*!< bit offset of SPC in FMC_OBSTAT0_EFT/FMC_OBSTAT0_MDF register */
|
|
#define OBSTAT1_DATA_OFFSET ((uint32_t)0x00000010U) /*!< bit offset of DATA in FMC_OBSTAT1_EFT/FMC_OBSTAT1_MDF register */
|
|
#define NODEC_NODEC_AREA_START_OFFSET ((uint32_t)0x00000000U) /*!< bit offset of SCR_AREA_START in FMC_SCRADDR_EFT/FMC_SCRADDR_MDF register */
|
|
#define NODEC_NODEC_AREA_END_OFFSET ((uint32_t)0x00000010U) /*!< bit offset of SCR_AREA_END in FMC_SCRADDR_EFT/FMC_SCRADDR_MDF register */
|
|
|
|
/* option byte factory value */
|
|
#define OB_OBSTAT0_FACTORY_VALUE ((uint32_t)0x01C6AAD0U) /*!< the factory value of option byte in FMC_OBSTAT0_EFT/FMC_OBSTAT0_MDF */
|
|
#define OB_OBSTAT1_FACTORY_VALUE ((uint32_t)0x00000087U) /*!< the factory value of option byte in FMC_OBSTAT1_EFT/FMC_OBSTAT1_MDF */
|
|
#define OB_BTADDR_FACTORY_VALUE ((uint32_t)0x1FF00800U) /*!< the factory value of option byte in FMC_BTADDR_EFT/FMC_BTADDR_MDF */
|
|
#define OB_DCRPADDR_FACTORY_VALUE ((uint32_t)0x000000FFU) /*!< the factory value of option byte in FMC_DCRPADDR_EFT/FMC_DCRPADDR_MDF */
|
|
#define OB_SCRADDR_FACTORY_VALUE ((uint32_t)0x000000FFU) /*!< the factory value of option byte in FMC_SCRADDR_EFT/FMC_SCRADDR_MDF */
|
|
#define OB_WP_FACTORY_VALUE ((uint32_t)0x3FFFFFFFU) /*!< the factory value of option byte in FMC_WP_EFT/FMC_WP_MDF */
|
|
|
|
/* invalid DCRP area value */
|
|
#define INVALID_DCRP_START_ADDR ((uint32_t)0x000000FFU) /*!< the start address to make DCRP area invalid */
|
|
#define INVALID_DCRP_END_ADDR ((uint32_t)0x00000000U) /*!< the end address to make DCRP area invalid */
|
|
|
|
/* invalid SCR area value */
|
|
#define INVALID_SCR_START_ADDR ((uint32_t)0x000000FFU) /*!< the start address to make SCR area invalid */
|
|
#define INVALID_SCR_END_ADDR ((uint32_t)0x00000000U) /*!< the end address to make SCR area invalid */
|
|
|
|
/* get FMC state */
|
|
static fmc_state_enum fmc_state_get(void);
|
|
/* check whether FMC is ready or not */
|
|
static fmc_state_enum fmc_ready_wait(uint32_t timeout);
|
|
|
|
/*!
|
|
\brief unlock FMC_CTL register (API_ID(0x0001U))
|
|
\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 FMC_CTL register (API_ID(0x0002U))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void fmc_lock(void)
|
|
{
|
|
/* set the LK bit*/
|
|
FMC_CTL |= FMC_CTL_LK;
|
|
}
|
|
|
|
/*!
|
|
\brief FMC erase sector (API_ID(0x0003U))
|
|
\param[in] address: address to erase
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum fmc_sector_erase(uint32_t address)
|
|
{
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_VALID_PAGEERASE_ADDR(address)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0003U), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
if(FMC_READY == fmc_state) {
|
|
FMC_CTL |= FMC_CTL_SER;
|
|
/* write the sector address */
|
|
FMC_ADDR = address;
|
|
/* start sector erase */
|
|
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);
|
|
}
|
|
}
|
|
/* return the FMC state */
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief FMC typical mass erase (API_ID(0x0004U))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum fmc_typical_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) {
|
|
/* enable mass erase operation */
|
|
FMC_CTL |= FMC_CTL_MER;
|
|
/* start whole chip erase */
|
|
FMC_CTL |= FMC_CTL_START;
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
/* reset the MER bit */
|
|
FMC_CTL &= ~FMC_CTL_MER;
|
|
}
|
|
|
|
/* return the fmc state */
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief FMC protection-removed mass erase (API_ID(0x0005U))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum fmc_protection_removed_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) {
|
|
/* remove DCRP area */
|
|
ob_dcrp_area_config(OB_DCRP_AREA_ERASE_ENABLE, INVALID_DCRP_START_ADDR, INVALID_DCRP_END_ADDR);
|
|
/* remove secure-access area */
|
|
ob_secure_area_config(OB_SCR_AREA_ERASE_ENABLE, INVALID_SCR_START_ADDR, INVALID_SCR_END_ADDR);
|
|
/* disable all sectors' erase/program protection */
|
|
ob_write_protection_disable(OB_WP_ALL);
|
|
/* enable mass erase operation */
|
|
FMC_CTL |= FMC_CTL_MER;
|
|
/* start chip erase */
|
|
FMC_CTL |= FMC_CTL_START;
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
/* reset the MER bit */
|
|
FMC_CTL &= ~FMC_CTL_MER;
|
|
}
|
|
|
|
/* return the fmc state */
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief FMC program a word at the corresponding address (API_ID(0x0006U))
|
|
\param[in] address: address to program
|
|
\param[in] data: word to program
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum fmc_word_program(uint32_t address, uint32_t data)
|
|
{
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_VALID_PROGRAM_ADDR(address)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
/* 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_PG;
|
|
__ISB();
|
|
__DSB();
|
|
REG32(address) = data;
|
|
__ISB();
|
|
__DSB();
|
|
/* 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 FMC program a double-word at the corresponding address (API_ID(0x0007U))
|
|
\param[in] address: address to program
|
|
\param[in] data: double word to program
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum fmc_doubleword_program(uint32_t address, uint64_t data)
|
|
{
|
|
uint32_t data0, data1;
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_VALID_PROGRAM_ADDR(address)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0007U), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
data0 = (uint32_t)(data & 0xFFFFFFFFU);
|
|
data1 = (uint32_t)((data >> 32U) & 0xFFFFFFFFU);
|
|
if(FMC_READY == fmc_state) {
|
|
/* set the PG bit to start program */
|
|
FMC_CTL |= FMC_CTL_PG;
|
|
__ISB();
|
|
__DSB();
|
|
REG32(address) = data0;
|
|
REG32(address + 4U) = data1;
|
|
__ISB();
|
|
__DSB();
|
|
/* 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 enable check programming area (API_ID(0x0008U))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum fmc_check_programming_area_enable(void)
|
|
{
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
fmc_unlock();
|
|
FMC_CTL |= FMC_CTL_PGCHEN;
|
|
fmc_lock();
|
|
/* return the FMC state */
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief disable check programming area (API_ID(0x0009U))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum fmc_check_programming_area_disable(void)
|
|
{
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
fmc_unlock();
|
|
FMC_CTL &= ~FMC_CTL_PGCHEN;
|
|
fmc_lock();
|
|
/* return the FMC state */
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief unlock the option byte operation (API_ID(0x000AU))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ob_unlock(void)
|
|
{
|
|
if(RESET != (FMC_OBCTL & FMC_OBCTL_OBLK)) {
|
|
/* write the FMC key */
|
|
FMC_OBKEY = OB_UNLOCK_KEY0;
|
|
FMC_OBKEY = OB_UNLOCK_KEY1;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief lock the option byte operation (API_ID(0x000BU))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ob_lock(void)
|
|
{
|
|
/* set the OB_LK bit */
|
|
FMC_OBCTL |= FMC_OBCTL_OBLK;
|
|
}
|
|
|
|
/*!
|
|
\brief send option bytes modification start command (API_ID(0x000CU))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_start(void)
|
|
{
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
/* set the OB_START bit in OBCTL register */
|
|
FMC_OBCTL |= FMC_OBCTL_OBSTART;
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief modify option byte to factory value (API_ID(0x000DU))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_factory_value_config(void)
|
|
{
|
|
uint32_t obstat0_reg;
|
|
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) {
|
|
/* get the option byte security protection value */
|
|
obstat0_reg = (FMC_OBSTAT0_EFT & FMC_OBSTAT0_EFT_SPC);
|
|
/* write factory value to FMC_OBSTAT0_MDF */
|
|
FMC_OBSTAT0_MDF = obstat0_reg | OB_OBSTAT0_FACTORY_VALUE;
|
|
/* write factory value to FMC_OBSTAT1_MDF */
|
|
FMC_OBSTAT1_MDF = OB_OBSTAT1_FACTORY_VALUE;
|
|
/* write factory value to FMC_BTADDR_MDF */
|
|
FMC_BTADDR_MDF = OB_BTADDR_FACTORY_VALUE;
|
|
/* write factory value to FMC_DCRPADDR_MDF */
|
|
FMC_DCRPADDR_MDF = OB_DCRPADDR_FACTORY_VALUE;
|
|
/* write factory value to FMC_SCRADDR_MDF */
|
|
FMC_SCRADDR_MDF = OB_SCRADDR_FACTORY_VALUE;
|
|
/* write factory value to FMC_WP_MDF */
|
|
FMC_WP_MDF = OB_WP_FACTORY_VALUE;
|
|
}
|
|
|
|
fmc_state = ob_start();
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief enable secure access mode (API_ID(0x000EU))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_secure_access_mode_enable(void)
|
|
{
|
|
uint32_t obstat0_reg;
|
|
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) {
|
|
obstat0_reg = FMC_OBSTAT0_EFT;
|
|
/* enable secure access mode */
|
|
obstat0_reg |= FMC_OBSTAT0_MDF_SCR;
|
|
FMC_OBSTAT0_MDF = obstat0_reg;
|
|
}
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief disable secure access mode (API_ID(0x000FU))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_secure_access_mode_disable(void)
|
|
{
|
|
uint32_t obstat0_reg;
|
|
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) {
|
|
obstat0_reg = FMC_OBSTAT0_EFT;
|
|
/* disable secure access mode */
|
|
obstat0_reg &= ~FMC_OBSTAT0_MDF_SCR;
|
|
FMC_OBSTAT0_MDF = obstat0_reg;
|
|
}
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief configure the option byte security protection level (API_ID(0x0010U))
|
|
\param[in] ob_spc: specify security protection level
|
|
only one parameter can be selected which is shown as below:
|
|
\arg FMC_NSPC: no protection
|
|
\arg FMC_LSPC: protection level low
|
|
\arg FMC_HSPC: protection level high
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_security_protection_config(uint8_t ob_spc)
|
|
{
|
|
uint32_t obstat0_reg;
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_SPC_VALUE(ob_spc)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0010U), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
if(FMC_READY == fmc_state) {
|
|
obstat0_reg = FMC_OBSTAT0_EFT;
|
|
/* reset the OBSTAT0_SPC, set according to ob_spc */
|
|
obstat0_reg &= ~FMC_OBSTAT0_MDF_SPC;
|
|
obstat0_reg |= ((uint32_t)ob_spc << OBSTAT0_SPC_OFFSET);
|
|
FMC_OBSTAT0_MDF = obstat0_reg;
|
|
}
|
|
}
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief configure the option byte BOR threshold value (API_ID(0x0011U))
|
|
\param[in] ob_bor_th: option byte BOR threshold value
|
|
only one parameter can be selected which is shown as below:
|
|
\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 state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_bor_threshold_config(uint32_t ob_bor_th)
|
|
{
|
|
uint32_t obstat0_reg;
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_BOR_TH(ob_bor_th)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0011U), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
if(FMC_READY == fmc_state) {
|
|
obstat0_reg = FMC_OBSTAT0_EFT;
|
|
/* set BOR threshold level */
|
|
obstat0_reg &= ~FMC_OBSTAT0_MDF_BOR_TH;
|
|
FMC_OBSTAT0_MDF = (uint32_t)(obstat0_reg | ob_bor_th);
|
|
}
|
|
}
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief configure low power related option byte (API_ID(0x0012U))
|
|
\param[in] ob_fwdgt: option byte watchdog value
|
|
only one parameter can be selected which is shown as below:
|
|
\arg OB_FWDGT_SW: software free watchdog
|
|
\arg OB_FWDGT_HW: hardware free watchdog
|
|
\param[in] ob_deepsleep: option byte deepsleep reset value
|
|
only one parameter can be selected which is shown as below:
|
|
\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
|
|
only one parameter can be selected which is shown as below:
|
|
\arg OB_STDBY_NRST: no reset when entering standby mode
|
|
\arg OB_STDBY_RST: generate a reset instead of entering standby mode
|
|
\param[in] ob_fwdg_suspend_deepsleep: option byte FWDG suspend status in deep-sleep mode
|
|
only one parameter can be selected which is shown as below:
|
|
\arg OB_DPSLP_FWDGT_SUSPEND: free watchdog is suspended in deep-sleep mode
|
|
\arg OB_DPSLP_FWDGT_RUN: free watchdog is running in deep-sleep mode
|
|
\param[in] ob_fwdg_suspend_standby: option byte FWDG suspend status in standby mode
|
|
only one parameter can be selected which is shown as below:
|
|
\arg OB_STDBY_FWDGT_SUSPEND: free watchdog is suspended in standby mode
|
|
\arg OB_STDBY_FWDGT_RUN: free watchdog is running in standby mode
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_low_power_config(uint32_t ob_fwdgt, uint32_t ob_deepsleep, uint32_t ob_stdby, uint32_t ob_fwdg_suspend_deepsleep,
|
|
uint32_t ob_fwdg_suspend_standby)
|
|
{
|
|
uint32_t obstat0_reg;
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_FWDGT_VALUE(ob_fwdgt)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0012U), ERR_PARAM_INVALID);
|
|
} else if(NOT_FMC_DEEPSLEEP_VALUE(ob_deepsleep)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0012U), ERR_PARAM_INVALID);
|
|
} else if(NOT_FMC_STDBY_VALUE(ob_stdby)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0012U), ERR_PARAM_INVALID);
|
|
} else if(NOT_FMC_DPSLP_FWDGT_VALUE(ob_fwdg_suspend_deepsleep)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0012U), ERR_PARAM_INVALID);
|
|
} else if(NOT_FMC_STDBY_FWDGT_VALUE(ob_fwdg_suspend_standby)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0012U), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
if(FMC_READY == fmc_state) {
|
|
obstat0_reg = FMC_OBSTAT0_EFT;
|
|
/* set according to ob_fwdgt, ob_deepsleep, ob_stdby, ob_fwdg_suspend_deepsleep, ob_fwdg_suspend_standby */
|
|
obstat0_reg &= ~(FMC_OBSTAT0_MDF_NWDG_HW | FMC_OBSTAT0_MDF_NRST_DPSLP | FMC_OBSTAT0_MDF_NRST_STDBY
|
|
| FMC_OBSTAT0_MDF_FWDGSPD_DPSLP | FMC_OBSTAT0_MDF_FWDGSPD_STDBY);
|
|
FMC_OBSTAT0_MDF = (uint32_t)(obstat0_reg | ob_fwdgt | ob_deepsleep | ob_stdby | ob_fwdg_suspend_deepsleep | ob_fwdg_suspend_standby);
|
|
}
|
|
}
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief configure TCM ECC option byte (API_ID(0x0013U))
|
|
\param[in] ob_itcmecc: ITCM ECC function enable bit
|
|
only one parameter can be selected which is shown as below:
|
|
\arg OB_ITCMECCEN_DISABLE: disabled ITCM ECC function
|
|
\arg OB_ITCMECCEN_ENABLE: enabled ITCM ECC function
|
|
\param[in] ob_dtcm0ecc: DTCM0 ECC function enable bit
|
|
only one parameter can be selected which is shown as below:
|
|
\arg OB_DTCM0ECCEN_DISABLE: disabled DTCM0 ECC function
|
|
\arg OB_DTCM0ECCEN_ENABLE: enabled DTCM0 ECC function
|
|
\param[in] ob_dtcm1ecc: DTCM1 ECC function enable bit
|
|
only one parameter can be selected which is shown as below:
|
|
\arg OB_DTCM1ECCEN_DISABLE: disabled DTCM1 ECC function
|
|
\arg OB_DTCM1ECCEN_ENABLE: enabled DTCM1 ECC function
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_tcm_ecc_config(uint32_t ob_itcmecc, uint32_t ob_dtcm0ecc, uint32_t ob_dtcm1ecc)
|
|
{
|
|
uint32_t obstat0_reg;
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_ITCMECCEN_VALUE(ob_itcmecc)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0013U), ERR_PARAM_INVALID);
|
|
} else if(NOT_FMC_DTCM0ECCEN_VALUE(ob_dtcm0ecc)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0013U), ERR_PARAM_INVALID);
|
|
} else if(NOT_FMC_DTCM1ECCEN_VALUE(ob_dtcm1ecc)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0013U), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
if(FMC_READY == fmc_state) {
|
|
obstat0_reg = FMC_OBSTAT0_EFT;
|
|
/* set according to ob_itcmecc, ob_dtcm0ecc, ob_stdby, ob_dtcm1ecc */
|
|
obstat0_reg &= ~(FMC_OBSTAT0_MDF_ITCMECCEN | FMC_OBSTAT0_MDF_DTCM0ECCEN | FMC_OBSTAT0_MDF_DTCM1ECCEN);
|
|
FMC_OBSTAT0_MDF = (uint32_t)(obstat0_reg | ob_itcmecc | ob_dtcm0ecc | ob_dtcm1ecc);
|
|
}
|
|
}
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief configure I/O speed optimization option byte (API_ID(0x0014U))
|
|
\param[in] ob_iospeed_op: configure I/O speed optimization, high-speed at low-voltage enable bit
|
|
only one parameter can be selected which is shown as below:
|
|
\arg OB_IOSPDOPEN_DISABLE: disabled I/O speed optimization
|
|
\arg OB_IOSPDOPEN_ENABLE: enabled I/O speed optimization
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_iospeed_optimize_config(uint32_t ob_iospeed_op)
|
|
{
|
|
uint32_t obstat0_reg;
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_IOSPDOPEN_VALUE(ob_iospeed_op)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0014U), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
if(FMC_READY == fmc_state) {
|
|
obstat0_reg = FMC_OBSTAT0_EFT;
|
|
/* set according to ob_iospeed_op */
|
|
obstat0_reg &= ~(FMC_OBSTAT0_MDF_IOSPDOPEN);
|
|
FMC_OBSTAT0_MDF = (uint32_t)(obstat0_reg | ob_iospeed_op);
|
|
}
|
|
}
|
|
return fmc_state;
|
|
}
|
|
|
|
|
|
/*!
|
|
\brief configure option byte TCM shared RAM size (API_ID(0x0015U))
|
|
ITCM RAM + DTCM RAM size should not exceed 512KB
|
|
\param[in] itcm_shared_ram_size: ITCM shared RAM size
|
|
only one parameter can be selected which is shown as below:
|
|
\arg OB_ITCM_SHARED_RAM_0KB: ITCM shared RAM size is 0KB
|
|
\arg OB_ITCM_SHARED_RAM_64KB: ITCM shared RAM size is 64KB
|
|
\arg OB_ITCM_SHARED_RAM_128KB: ITCM shared RAM size is 128KB
|
|
\arg OB_ITCM_SHARED_RAM_256KB: ITCM shared RAM size is 256KB
|
|
\arg OB_ITCM_SHARED_RAM_512KB: ITCM shared RAM size is 512KB
|
|
\param[in] dtcm_shared_ram_size: DTCM shared RAM size
|
|
only one parameter can be selected which is shown as below:
|
|
\arg OB_DTCM_SHARED_RAM_0KB: DTCM shared RAM size is 0KB
|
|
\arg OB_DTCM_SHARED_RAM_64KB: DTCM shared RAM size is 64KB
|
|
\arg OB_DTCM_SHARED_RAM_128KB: DTCM shared RAM size is 128KB
|
|
\arg OB_DTCM_SHARED_RAM_256KB: DTCM shared RAM size is 256KB
|
|
\arg OB_DTCM_SHARED_RAM_512KB: DTCM shared RAM size is 512KB
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_tcm_shared_ram_config(uint32_t itcm_shared_ram_size, uint32_t dtcm_shared_ram_size)
|
|
{
|
|
uint32_t obstat1_reg;
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_ITCM_SHARED_RAM_VALUE(itcm_shared_ram_size)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0015U), ERR_PARAM_INVALID);
|
|
} else if(NOT_FMC_DTCM_SHARED_RAM_VALUE(dtcm_shared_ram_size)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0015U), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
if(FMC_READY == fmc_state) {
|
|
obstat1_reg = FMC_OBSTAT1_EFT;
|
|
|
|
/* set ITCM shared ram size according to itcm_shared_ram_size */
|
|
obstat1_reg &= ~FMC_OBSTAT1_MDF_ITCM_SZ_SHRRAM;
|
|
obstat1_reg |= itcm_shared_ram_size;
|
|
|
|
/* set DTCM shared ram size according to dtcm_shared_ram_size */
|
|
obstat1_reg &= ~FMC_OBSTAT1_MDF_DTCM_SZ_SHRRAM;
|
|
obstat1_reg |= dtcm_shared_ram_size;
|
|
|
|
FMC_OBSTAT1_MDF = obstat1_reg;
|
|
}
|
|
}
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief modify option byte DATA (API_ID(0x0016U))
|
|
\param[in] ob_data: option bytes user data
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_data_program(uint16_t ob_data)
|
|
{
|
|
uint32_t obstat1_reg;
|
|
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) {
|
|
obstat1_reg = FMC_OBSTAT1_EFT;
|
|
|
|
/* modify user data according to ob_data */
|
|
obstat1_reg &= ~FMC_OBSTAT1_MDF_DATA;
|
|
obstat1_reg |= ((uint32_t)ob_data << OBSTAT1_DATA_OFFSET);
|
|
FMC_OBSTAT1_MDF = obstat1_reg;
|
|
}
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief configure boot address (API_ID(0x0017U))
|
|
\param[in] boot_pin: boot pin configuration
|
|
only one parameter can be selected which is shown as below:
|
|
\arg BOOT_PIN_0: boot pin value is 0
|
|
\arg BOOT_PIN_1: boot pin value is 1
|
|
\param[in] boot_address: specify the MSB of boot address
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_boot_address_config(uint8_t boot_pin, uint16_t boot_address)
|
|
{
|
|
uint32_t btaddr_reg;
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_BOOT_PIN_VALUE(boot_pin)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0017U), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
if(FMC_READY == fmc_state) {
|
|
btaddr_reg = FMC_BTADDR_EFT;
|
|
|
|
if(BOOT_PIN_0 == boot_pin) {
|
|
/* set to boot address 0 */
|
|
btaddr_reg &= ~FMC_BTADDR_MDF_BOOT_ADDR0;
|
|
btaddr_reg |= (uint32_t)((uint32_t)boot_address << BTADDR_BOOT_ADDR0_OFFSET);
|
|
} else {
|
|
/* set to boot address 1 */
|
|
btaddr_reg &= ~FMC_BTADDR_MDF_BOOT_ADDR1;
|
|
btaddr_reg |= (uint32_t)((uint32_t)boot_address << BTADDR_BOOT_ADDR1_OFFSET);
|
|
}
|
|
FMC_BTADDR_MDF = btaddr_reg;
|
|
}
|
|
}
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief configure DCRP area (API_ID(0x0018U))
|
|
\param[in] dcrp_eren: DCRP area erase enable bit
|
|
\arg OB_DCRP_AREA_ERASE_DISABLE: DCRP area erase disable
|
|
\arg OB_DCRP_AREA_ERASE_ENABLE: DCRP area erase enable
|
|
\param[in] dcrp_start: DCRP area start address, contain the first 4K-byte block of the DCRP area.(0 - 0x3BF)
|
|
\param[in] dcrp_end: DCRP area end address, contain the last 4K-byte block of the DCRP area.(0 - 0x3BF)
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_dcrp_area_config(uint32_t dcrp_eren, uint32_t dcrp_start, uint32_t dcrp_end)
|
|
{
|
|
uint32_t dcrpaddr_reg;
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_DCRP_AREA_ERASE_STATUS(dcrp_eren)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0018U), ERR_PARAM_INVALID);
|
|
} else if(NOT_FMC_DCRP_AREA_START(dcrp_start)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0018U), ERR_PARAM_INVALID);
|
|
} else if(NOT_FMC_DCRP_AREA_END(dcrp_end)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0018U), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
if(FMC_READY == fmc_state) {
|
|
dcrpaddr_reg = 0U;
|
|
dcrpaddr_reg |= dcrp_eren;
|
|
dcrpaddr_reg |= dcrp_start;
|
|
dcrpaddr_reg |= (uint32_t)(dcrp_end << DCRPADDR_DCRP_AREA_END_OFFSET);
|
|
FMC_DCRPADDR_MDF = dcrpaddr_reg;
|
|
}
|
|
}
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief configure secure-access area (API_ID(0x0019U))
|
|
\param[in] scr_eren: secure-access area erase enable bit
|
|
\arg OB_SCR_AREA_ERASE_DISABLE: secure-access area erase disable
|
|
\arg OB_SCR_AREA_ERASE_ENABLE: secure-access area erase enable
|
|
\param[in] scr_start: secure-access area start address, contain the first 4K-byte block of the secure-access area.(0 - 0x3BF)
|
|
\param[in] scr_end: secure-access area end address, contain the last 4K-byte block of the secure-access area.(0 - 0x3BF)
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_secure_area_config(uint32_t scr_eren, uint32_t scr_start, uint32_t scr_end)
|
|
{
|
|
uint32_t scraddr_reg;
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_SCR_AREA_ERASE_STATUS(scr_eren)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0019U), ERR_PARAM_INVALID);
|
|
} else if(NOT_FMC_SCR_AREA_START(scr_start)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0019U), ERR_PARAM_INVALID);
|
|
} else if(NOT_FMC_SCR_AREA_END(scr_end)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0019U), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
if(FMC_READY == fmc_state) {
|
|
scraddr_reg = 0U;
|
|
scraddr_reg |= scr_eren;
|
|
scraddr_reg |= scr_start;
|
|
scraddr_reg |= (uint32_t)(scr_end << SCRADDR_SCR_AREA_END_OFFSET);
|
|
FMC_SCRADDR_MDF = scraddr_reg;
|
|
}
|
|
}
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief enable erase/program protection (API_ID(0x001AU))
|
|
\param[in] ob_wp: specify sector to be erase/program protected
|
|
one or more parameters can be selected which are shown as below:
|
|
\arg OB_WP_0 erase/program protect sector 0 ~ sector 15
|
|
\arg OB_WP_1: erase/program protect sector 16 ~ sector 31
|
|
\arg OB_WP_2: erase/program protect sector 32 ~ sector 47
|
|
\arg OB_WP_3: erase/program protect sector 48 ~ sector 63
|
|
\arg OB_WP_4: erase/program protect sector 64 ~ sector 79
|
|
\arg OB_WP_5: erase/program protect sector 80 ~ sector 95
|
|
\arg OB_WP_6: erase/program protect sector 96 ~ sector 111
|
|
\arg OB_WP_7: erase/program protect sector 112 ~ sector 127
|
|
\arg OB_WP_8: erase/program protect sector 128 ~ sector 143
|
|
\arg OB_WP_9: erase/program protect sector 144 ~ sector 159
|
|
\arg OB_WP_10: erase/program protect sector 160 ~ sector 175
|
|
\arg OB_WP_11: erase/program protect sector 176 ~ sector 191
|
|
\arg OB_WP_12: erase/program protect sector 192 ~ sector 207
|
|
\arg OB_WP_13: erase/program protect sector 208 ~ sector 223
|
|
\arg OB_WP_14: erase/program protect sector 224 ~ sector 239
|
|
\arg OB_WP_15: erase/program protect sector 240 ~ sector 255
|
|
\arg OB_WP_16: erase/program protect sector 256 ~ sector 383
|
|
\arg OB_WP_17: erase/program protect sector 384 ~ sector 511
|
|
\arg OB_WP_18: erase/program protect sector 512 ~ sector 639
|
|
\arg OB_WP_19: erase/program protect sector 640 ~ sector 767
|
|
\arg OB_WP_20: erase/program protect sector 768 ~ sector 895
|
|
\arg OB_WP_21: erase/program protect sector 896 ~ sector 959
|
|
\arg OB_WP_ALL: all sectors
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_write_protection_enable(uint32_t ob_wp)
|
|
{
|
|
uint32_t wp_reg = FMC_WP_EFT;
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_OB_WP_VALUE(ob_wp)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x001AU), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
if(FMC_READY == fmc_state) {
|
|
wp_reg &= ~ob_wp;
|
|
FMC_WP_MDF = wp_reg;
|
|
}
|
|
}
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief disable erase/program protection (API_ID(0x001BU))
|
|
\param[in] ob_wp: specify sector to be erase/program protected
|
|
one or more parameters can be selected which are shown as below:
|
|
\arg OB_WP_0 ee/program protect sector 0 ~ sector 15
|
|
\arg OB_WP_1: erase/program protect sector 16 ~ sector 31
|
|
\arg OB_WP_2: erase/program protect sector 32 ~ sector 47
|
|
\arg OB_WP_3: erase/program protect sector 48 ~ sector 63
|
|
\arg OB_WP_4: erase/program protect sector 64 ~ sector 79
|
|
\arg OB_WP_5: erase/program protect sector 80 ~ sector 95
|
|
\arg OB_WP_6: erase/program protect sector 96 ~ sector 111
|
|
\arg OB_WP_7: erase/program protect sector 112 ~ sector 127
|
|
\arg OB_WP_8: erase/program protect sector 128 ~ sector 143
|
|
\arg OB_WP_9: erase/program protect sector 144 ~ sector 159
|
|
\arg OB_WP_10: erase/program protect sector 160 ~ sector 175
|
|
\arg OB_WP_11: erase/program protect sector 176 ~ sector 191
|
|
\arg OB_WP_12: erase/program protect sector 192 ~ sector 207
|
|
\arg OB_WP_13: erase/program protect sector 208 ~ sector 223
|
|
\arg OB_WP_14: erase/program protect sector 224 ~ sector 239
|
|
\arg OB_WP_15: erase/program protect sector 240 ~ sector 255
|
|
\arg OB_WP_16: erase/program protect sector 256 ~ sector 383
|
|
\arg OB_WP_17: erase/program protect sector 384 ~ sector 511
|
|
\arg OB_WP_18: erase/program protect sector 512 ~ sector 639
|
|
\arg OB_WP_19: erase/program protect sector 640 ~ sector 767
|
|
\arg OB_WP_20: erase/program protect sector 768 ~ sector 895
|
|
\arg OB_WP_21: erase/program protect sector 896 ~ sector 959
|
|
\arg OB_WP_ALL: all sectors
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum ob_write_protection_disable(uint32_t ob_wp)
|
|
{
|
|
uint32_t wp_reg = FMC_WP_EFT;
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_OB_WP_VALUE(ob_wp)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x001BU), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
if(FMC_READY == fmc_state) {
|
|
wp_reg |= ob_wp;
|
|
FMC_WP_MDF = wp_reg;
|
|
}
|
|
}
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief get the option byte secure access mode (API_ID(0x001CU))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval FlagStatus: SET or RESET
|
|
*/
|
|
FlagStatus ob_secure_mode_get(void)
|
|
{
|
|
FlagStatus secure_mode_state = RESET;
|
|
|
|
if(OB_SECURE_MODE_ENABLE == (uint32_t)(FMC_OBSTAT0_EFT & FMC_OBSTAT0_EFT_SCR)) {
|
|
secure_mode_state = SET;
|
|
} else {
|
|
secure_mode_state = RESET;
|
|
}
|
|
return secure_mode_state;
|
|
}
|
|
|
|
/*!
|
|
\brief get the option byte security protection level (API_ID(0x001DU))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval FlagStatus: SET or RESET
|
|
*/
|
|
FlagStatus ob_security_protection_flag_get(void)
|
|
{
|
|
FlagStatus spc_state = RESET;
|
|
|
|
if(((uint8_t)(FMC_OBSTAT0_EFT >> OBSTAT0_SPC_OFFSET)) != (uint8_t)FMC_NSPC) {
|
|
spc_state = SET;
|
|
} else {
|
|
spc_state = RESET;
|
|
}
|
|
return spc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief get the option byte BOR threshold value (API_ID(0x001EU))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval the BOR threshold value:
|
|
\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
|
|
*/
|
|
uint32_t ob_bor_threshold_get(void)
|
|
{
|
|
return (uint32_t)((uint32_t)FMC_OBSTAT0_EFT & FMC_OBSTAT0_EFT_BOR_TH);
|
|
}
|
|
|
|
/*!
|
|
\brief get low power related option byte (API_ID(0x001FU))
|
|
\param[in] none
|
|
\param[out] fwdgt: watchdog option
|
|
\arg OB_FWDGT_HW: hardware free watchdog
|
|
\arg OB_FWDGT_SW: software free watchdog
|
|
\param[out] deepsleep: deepsleep reset option
|
|
\arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode
|
|
\arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode
|
|
\param[out] standby: standby reset option
|
|
\arg OB_STDBY_RST: generate a reset instead of entering standby mode
|
|
\arg OB_STDBY_NRST: no reset when entering standby mode
|
|
\param[out] fwdg_suspend_deepsleep: FWDG suspend status in deepsleep mode option
|
|
\arg OB_DPSLP_FWDGT_SUSPEND: free watchdog is suspended in deepsleep mode
|
|
\arg OB_DPSLP_FWDGT_RUN: free watchdog is running in deepsleep mode
|
|
\param[out] fwdg_suspend_standby: FWDG suspend status in standby mode option
|
|
\arg OB_STDBY_FWDGT_SUSPEND: free watchdog is suspended in standby mode
|
|
\arg OB_STDBY_FWDGT_RUN: free watchdog is running in standby mode
|
|
\retval none
|
|
*/
|
|
void ob_low_power_get(uint32_t *fwdgt, uint32_t *deepsleep, uint32_t *standby, uint32_t *fwdg_suspend_deepsleep, uint32_t *fwdg_suspend_standby)
|
|
{
|
|
uint32_t obstat0_reg;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if((NOT_VALID_POINTER(fwdgt)) || (NOT_VALID_POINTER(deepsleep)) || (NOT_VALID_POINTER(standby)) || (NOT_VALID_POINTER(fwdg_suspend_deepsleep)) ||
|
|
(NOT_VALID_POINTER(fwdg_suspend_standby))) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x001FU), ERR_PARAM_POINTER);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
obstat0_reg = FMC_OBSTAT0_EFT;
|
|
*fwdgt = (uint32_t)(obstat0_reg & FMC_OBSTAT0_EFT_NWDG_HW);
|
|
*deepsleep = (uint32_t)(obstat0_reg & FMC_OBSTAT0_EFT_NRST_DPSLP);
|
|
*standby = (uint32_t)(obstat0_reg & FMC_OBSTAT0_EFT_NRST_STDBY);
|
|
*fwdg_suspend_deepsleep = (uint32_t)(obstat0_reg & FMC_OBSTAT0_EFT_FWDGSPD_DPSLP);
|
|
*fwdg_suspend_standby = (uint32_t)(obstat0_reg & FMC_OBSTAT0_EFT_FWDGSPD_STDBY);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief get TCM ECC configuration (API_ID(0x0020U))
|
|
\param[in] none
|
|
\param[out] itcmecc_option: CPU ITCM ECC function enable option
|
|
\arg OB_ITCMECCEN_DISABLE: ITCM ECC function disable
|
|
\arg OB_ITCMECCEN_ENABLE: ITCM ECC function enable
|
|
\param[out] dtcm0ecc_option: CPU DTCM0 ECC function enable option
|
|
\arg OB_DTCM0ECCEN_DISABLE: DTCM0 ECC function disable
|
|
\arg OB_DTCM0ECCEN_ENABLE: DTCM0 ECC function enable
|
|
\param[out] dtcm1ecc_option: CPU DTCM1 ECC function enable option
|
|
\arg OB_DTCM1ECCEN_DISABLE: DTCM1 ECC function disable
|
|
\arg OB_DTCM1ECCEN_ENABLE: DTCM1 ECC function enable
|
|
\retval none
|
|
*/
|
|
void ob_tcm_ecc_get(uint32_t *itcmecc_option, uint32_t *dtcm0ecc_option, uint32_t *dtcm1ecc_option)
|
|
{
|
|
uint32_t obstat0_reg;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if((NOT_VALID_POINTER(itcmecc_option)) || (NOT_VALID_POINTER(dtcm0ecc_option)) || (NOT_VALID_POINTER(dtcm1ecc_option))) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0020U), ERR_PARAM_POINTER);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
obstat0_reg = FMC_OBSTAT0_EFT;
|
|
*itcmecc_option = (uint32_t)(obstat0_reg & FMC_OBSTAT0_EFT_ITCMECCEN);
|
|
*dtcm0ecc_option = (uint32_t)(obstat0_reg & FMC_OBSTAT0_EFT_DTCM0ECCEN);
|
|
*dtcm1ecc_option = (uint32_t)(obstat0_reg & FMC_OBSTAT0_EFT_DTCM1ECCEN);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief get IO speed optimize configuration (API_ID(0x0021U))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval FlagStatus: SET or RESET
|
|
*/
|
|
FlagStatus ob_iospeed_optimize_get(void)
|
|
{
|
|
FlagStatus iospeed_opt_state = RESET;
|
|
|
|
if(OB_IOSPDOPEN_ENABLE == (uint32_t)(FMC_OBSTAT0_EFT & FMC_OBSTAT0_EFT_IOSPDOPEN)) {
|
|
iospeed_opt_state = SET;
|
|
} else {
|
|
iospeed_opt_state = RESET;
|
|
}
|
|
return iospeed_opt_state;
|
|
}
|
|
|
|
/*!
|
|
\brief get the option byte ITCM shared RAM size (API_ID(0x0022U))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval ITCM shared RAM size in KB unit
|
|
*/
|
|
uint32_t ob_itcm_shared_ram_size_get(void)
|
|
{
|
|
uint32_t itcm_size_value;
|
|
uint32_t itcm_kb_size;
|
|
|
|
itcm_size_value = (uint32_t)((uint32_t)FMC_OBSTAT1_EFT & FMC_OBSTAT1_EFT_ITCM_SZ_SHRRAM);
|
|
|
|
switch(itcm_size_value) {
|
|
case OB_ITCM_SHARED_RAM_0KB:
|
|
/* ITCM shared RAM size is 0KB */
|
|
itcm_kb_size = 0U;
|
|
break;
|
|
case OB_ITCM_SHARED_RAM_64KB:
|
|
/* ITCM shared RAM size is 64KB */
|
|
itcm_kb_size = 64U;
|
|
break;
|
|
case OB_ITCM_SHARED_RAM_128KB:
|
|
/* ITCM shared RAM size is 128KB */
|
|
itcm_kb_size = 128U;
|
|
break;
|
|
case OB_ITCM_SHARED_RAM_256KB:
|
|
/* ITCM shared RAM size is 256KB */
|
|
itcm_kb_size = 256U;
|
|
break;
|
|
case OB_ITCM_SHARED_RAM_512KB:
|
|
/* ITCM shared RAM size is 512KB */
|
|
itcm_kb_size = 512U;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return itcm_kb_size;
|
|
}
|
|
|
|
/*!
|
|
\brief get the option byte DTCM shared RAM size (API_ID(0x0023U))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval DTCM shared RAM size in KB unit
|
|
*/
|
|
uint32_t ob_dtcm_shared_ram_size_get(void)
|
|
{
|
|
uint32_t dtcm_size_value;
|
|
uint32_t dtcm_kb_size;
|
|
|
|
dtcm_size_value = (uint32_t)((uint32_t)FMC_OBSTAT1_EFT & FMC_OBSTAT1_EFT_DTCM_SZ_SHRRAM);
|
|
|
|
switch(dtcm_size_value) {
|
|
case OB_DTCM_SHARED_RAM_0KB:
|
|
/* DTCM shared RAM size is 0KB */
|
|
dtcm_kb_size = 0U;
|
|
break;
|
|
case OB_DTCM_SHARED_RAM_64KB:
|
|
/* DTCM shared RAM size is 64KB */
|
|
dtcm_kb_size = 64U;
|
|
break;
|
|
case OB_DTCM_SHARED_RAM_128KB:
|
|
/* DTCM shared RAM size is 128KB */
|
|
dtcm_kb_size = 128U;
|
|
break;
|
|
case OB_DTCM_SHARED_RAM_256KB:
|
|
/* DTCM shared RAM size is 256KB */
|
|
dtcm_kb_size = 256U;
|
|
break;
|
|
case OB_DTCM_SHARED_RAM_512KB:
|
|
/* DTCM shared RAM size is 512KB */
|
|
dtcm_kb_size = 512U;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return dtcm_kb_size;
|
|
}
|
|
|
|
/*!
|
|
\brief get user data value (API_ID(0x0024U))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval option bytes user data
|
|
*/
|
|
uint16_t ob_data_get(void)
|
|
{
|
|
return (uint16_t)(FMC_OBSTAT1_EFT >> OBSTAT1_DATA_OFFSET);
|
|
}
|
|
|
|
/*!
|
|
\brief get boot address (API_ID(0x0025U))
|
|
\param[in] boot_pin: boot pin configuration
|
|
only one parameter can be selected which is shown as below:
|
|
\arg BOOT_PIN_0: boot pin value is 0
|
|
\arg BOOT_PIN_1: boot pin value is 1
|
|
\param[out] none
|
|
\retval boot_address: boot address
|
|
*/
|
|
uint32_t ob_boot_address_get(uint8_t boot_pin)
|
|
{
|
|
uint32_t boot_address;
|
|
uint32_t btaddr_reg = FMC_BTADDR_EFT;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_BOOT_PIN(boot_pin)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0025U), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
if(BOOT_PIN_0 == boot_pin) {
|
|
/* get boot address 0 */
|
|
boot_address = (uint32_t)((btaddr_reg & FMC_BTADDR_EFT_BOOT_ADDR0) << 16U);
|
|
} else {
|
|
/* get boot address 1 */
|
|
boot_address = (uint32_t)((btaddr_reg & FMC_BTADDR_EFT_BOOT_ADDR1));
|
|
}
|
|
}
|
|
|
|
return boot_address;
|
|
}
|
|
|
|
/*!
|
|
\brief get DCRP area configuration (API_ID(0x0026U))
|
|
\param[in] none
|
|
\param[out] dcrp_erase_option: DCRP area erase option
|
|
\arg OB_DCRP_AREA_ERASE_DISABLE: DCRP area erase disable
|
|
\arg OB_DCRP_AREA_ERASE_ENABLE: DCRP area erase enable
|
|
\param[out] dcrp_start_addr: DCRP area start address, contain the first 4K-byte block of the DCRP area.(0 - 0x3BF)
|
|
\param[out] dcrp_end_addr: DCRP area end address, contain the last 4K-byte block of the DCRP area.(0 - 0x3BF)
|
|
\retval state of DCRP area address
|
|
\arg INVLD_AREA_ADDRESS: the area address is invalid
|
|
\arg VLD_AREA_ADDRESS: the area address is valid
|
|
*/
|
|
uint8_t ob_dcrp_area_get(uint32_t *dcrp_erase_option, uint32_t *dcrp_area_start_addr, uint32_t *dcrp_area_end_addr)
|
|
{
|
|
uint32_t dcrpaddr_reg;
|
|
uint32_t main_flash_size;
|
|
dcrpaddr_reg = FMC_DCRPADDR_EFT;
|
|
uint8_t reval = VLD_AREA_ADDRESS;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if((NOT_VALID_POINTER(dcrp_erase_option)) || (NOT_VALID_POINTER(dcrp_area_start_addr)) || (NOT_VALID_POINTER(dcrp_area_end_addr))) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0026U), ERR_PARAM_POINTER);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
main_flash_size = REG32(FLASH_DENSITY_ADDRESS) >> FLASH_DENSITY_OFFSET;
|
|
|
|
/* get DCRP area erase option */
|
|
*dcrp_erase_option = (uint32_t)(dcrpaddr_reg & FMC_DCRPADDR_EFT_DCRP_EREN);
|
|
*dcrp_area_start_addr = ((uint32_t)(dcrpaddr_reg & FMC_DCRPADDR_EFT_DCRP_AREA_START)) >> DCRPADDR_DCRP_AREA_START_OFFSET;
|
|
*dcrp_area_end_addr = ((uint32_t)(dcrpaddr_reg & FMC_DCRPADDR_EFT_DCRP_AREA_END)) >> DCRPADDR_DCRP_AREA_END_OFFSET;
|
|
if((*dcrp_area_start_addr) == (*dcrp_area_end_addr)) {
|
|
/* the whole main flash memory is DCRP area */
|
|
*dcrp_area_start_addr = MAIN_FLASH_BASE_ADDRESS;
|
|
*dcrp_area_end_addr = MAIN_FLASH_BASE_ADDRESS + main_flash_size - 1U;
|
|
reval = VLD_AREA_ADDRESS;
|
|
} else if((*dcrp_area_start_addr) < (*dcrp_area_end_addr)) {
|
|
/* get DCRP area start address */
|
|
*dcrp_area_start_addr = (*dcrp_area_start_addr) * DCRP_SIZE_UNIT;
|
|
*dcrp_area_start_addr += MAIN_FLASH_BASE_ADDRESS;
|
|
/* get DCRP area end address */
|
|
*dcrp_area_end_addr = ((*dcrp_area_end_addr) + 1U) * DCRP_SIZE_UNIT - 1U;
|
|
*dcrp_area_end_addr += MAIN_FLASH_BASE_ADDRESS;
|
|
reval = VLD_AREA_ADDRESS;
|
|
} else {
|
|
/* no valid DCRP area */
|
|
reval = INVLD_AREA_ADDRESS;
|
|
}
|
|
}
|
|
|
|
return reval;
|
|
}
|
|
|
|
/*!
|
|
\brief get secure-access area configuration (API_ID(0x0027U))
|
|
\param[in] none
|
|
\param[out] secure_erase_option: secure-access area erase option
|
|
\arg OB_SCR_AREA_ERASE_DISABLE: secure-access area erase disable
|
|
\arg OB_SCR_AREA_ERASE_ENABLE: secure-access area erase enable
|
|
\param[out] scr_area_start_addr: secure-access area start address, contain the first 4K-byte block of the secure-access area.(0 - 0x3BF)
|
|
\param[out] scr_area_end_addr: secure-access area end address, contain the last 4K-byte block of the secure-access area.(0 - 0x3BF)
|
|
\retval state of secure-access area address
|
|
\arg INVLD_AREA_ADDRESS: the area address is invalid
|
|
\arg VLD_AREA_ADDRESS: the area address is valid
|
|
*/
|
|
uint8_t ob_secure_area_get(uint32_t *secure_area_option, uint32_t *scr_area_start_addr, uint32_t *scr_area_end_addr)
|
|
{
|
|
uint32_t scraddr_reg;
|
|
uint32_t main_flash_size;
|
|
scraddr_reg = FMC_SCRADDR_EFT;
|
|
uint8_t reval = VLD_AREA_ADDRESS;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if((NOT_VALID_POINTER(secure_area_option)) || (NOT_VALID_POINTER(scr_area_start_addr)) || (NOT_VALID_POINTER(scr_area_end_addr))) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0027U), ERR_PARAM_POINTER);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
main_flash_size = REG32(FLASH_DENSITY_ADDRESS) >> FLASH_DENSITY_OFFSET;
|
|
|
|
/* get secure-access area erase option */
|
|
*secure_area_option = (uint32_t)(scraddr_reg & FMC_SCRADDR_EFT_SCR_EREN);
|
|
*scr_area_start_addr = ((uint32_t)(scraddr_reg & FMC_SCRADDR_EFT_SCR_AREA_START)) >> SCRADDR_SCR_AREA_START_OFFSET;
|
|
*scr_area_end_addr = ((uint32_t)(scraddr_reg & FMC_SCRADDR_EFT_SCR_AREA_END)) >> SCRADDR_SCR_AREA_END_OFFSET;
|
|
if((*scr_area_start_addr) == (*scr_area_end_addr)) {
|
|
/* the whole main flash memory is secure-access area */
|
|
*scr_area_start_addr = MAIN_FLASH_BASE_ADDRESS;
|
|
*scr_area_end_addr = MAIN_FLASH_BASE_ADDRESS + main_flash_size - 1U;
|
|
reval = VLD_AREA_ADDRESS;
|
|
} else if((*scr_area_start_addr) < (*scr_area_end_addr)) {
|
|
/* get secure-access area start address */
|
|
*scr_area_start_addr = (*scr_area_start_addr) * SCR_SIZE_UNIT;
|
|
*scr_area_start_addr += MAIN_FLASH_BASE_ADDRESS;
|
|
/* get secure-access area end address */
|
|
*scr_area_end_addr = ((*scr_area_end_addr) + 1U) * SCR_SIZE_UNIT - 1U;
|
|
*scr_area_end_addr += MAIN_FLASH_BASE_ADDRESS;
|
|
reval = VLD_AREA_ADDRESS;
|
|
} else {
|
|
/* no valid area */
|
|
reval = INVLD_AREA_ADDRESS;
|
|
}
|
|
}
|
|
|
|
return reval;
|
|
}
|
|
|
|
/*!
|
|
\brief get the option byte erase/program protection (API_ID(0x0028U))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval the FMC erase/program protection option byte value(0 - 0x3FFFFFFF)
|
|
*/
|
|
uint32_t ob_write_protection_get(void)
|
|
{
|
|
/* return the FMC erase/program protection option byte value */
|
|
return (uint32_t)(FMC_WP_EFT);
|
|
}
|
|
|
|
/*!
|
|
\brief configure NO-RTDEC area (API_ID(0x0029U))
|
|
\param[in] nodec_area_start: no rtdec area start address, contain the last 4K-byte block that reading main flash block without decryption.
|
|
\param[in] nodec_area_end: no rtdec area end address, contain the first 4K-byte block that reading main flash block without decryption.
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum fmc_no_rtdec_config(uint32_t nodec_area_start, uint32_t nodec_area_end)
|
|
{
|
|
uint32_t nodec_reg;
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_FMC_NODEC_AREA_START(nodec_area_start)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0029U), ERR_PARAM_INVALID);
|
|
} else if(NOT_FMC_NODEC_AREA_END(nodec_area_end)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x0029U), ERR_PARAM_INVALID);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
if(FMC_READY == fmc_state) {
|
|
fmc_unlock();
|
|
nodec_reg = 0U;
|
|
nodec_reg |= nodec_area_start;
|
|
nodec_reg |= (uint32_t)(nodec_area_end << NODEC_NODEC_AREA_END_OFFSET);
|
|
FMC_NODEC = nodec_reg;
|
|
fmc_lock();
|
|
}
|
|
}
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief configure AES initialization vector (API_ID(0x002AU))
|
|
\param[in] aes_iv: high 96 bits of AES initialization vector
|
|
\param[out] none
|
|
\retval state of FMC
|
|
\arg FMC_READY: the operation has been completed
|
|
\arg FMC_BUSY: the operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
fmc_state_enum fmc_aes_iv_config(uint32_t *aes_iv)
|
|
{
|
|
uint32_t aes_iv_addr = (uint32_t)aes_iv;
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_VALID_POINTER(aes_iv)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x002AU), ERR_PARAM_POINTER);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
/* wait for the FMC ready */
|
|
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
|
|
|
|
if(FMC_READY == fmc_state) {
|
|
fmc_unlock();
|
|
FMC_AESIV0_MDF = *(uint32_t *)(aes_iv_addr);
|
|
aes_iv_addr += 4U;
|
|
FMC_AESIV1_MDF = *(uint32_t *)(aes_iv_addr);
|
|
aes_iv_addr += 4U;
|
|
FMC_AESIV2_MDF = *(uint32_t *)(aes_iv_addr);
|
|
fmc_lock();
|
|
}
|
|
}
|
|
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief get Flash ECC function enable flag (API_ID(0x002BU))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval FlagStatus: SET or RESET
|
|
*/
|
|
FlagStatus fmc_flash_ecc_get(void)
|
|
{
|
|
return fmc_flag_get((fmc_flag_enum)FMC_FLAG_FECC);
|
|
}
|
|
|
|
/*!
|
|
\brief get NO-RTDEC area (API_ID(0x002CU))
|
|
\param[in] none
|
|
\param[out] nodec_area_start: no rtdec area start address, contain the last 4K-byte block that reading main flash block without decryption.
|
|
\param[out] nodec_area_end: no rtdec area end address, contain the first 4K-byte block that reading main flash block without decryption.
|
|
\retval none
|
|
*/
|
|
void fmc_no_rtdec_get(uint32_t *nodec_area_start, uint32_t *nodec_area_end)
|
|
{
|
|
uint32_t nodec_reg;
|
|
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if((NOT_VALID_POINTER(nodec_area_start)) || (NOT_VALID_POINTER(nodec_area_end))) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x002CU), ERR_PARAM_POINTER);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
nodec_reg = FMC_NODEC;
|
|
*nodec_area_start = (uint32_t)(nodec_reg & FMC_NODEC_NODEC_AREA_START);
|
|
*nodec_area_end = (uint32_t)(nodec_reg & FMC_NODEC_NODEC_AREA_END);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief get AES initialization vector (API_ID(0x002DU))
|
|
\param[in] none
|
|
\param[out] aes_iv: high 96 bits of AES initialization vector
|
|
\retval none
|
|
*/
|
|
void fmc_aes_iv_get(uint32_t *aes_iv)
|
|
{
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_VALID_POINTER(aes_iv)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x002DU), ERR_PARAM_POINTER);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
uint32_t aes_iv_addr = (uint32_t)aes_iv;
|
|
*(uint32_t *)aes_iv_addr = (uint32_t)(FMC_AESIV0_EFT);
|
|
aes_iv_addr += 4U;
|
|
*(uint32_t *)aes_iv_addr = (uint32_t)(FMC_AESIV1_EFT);
|
|
aes_iv_addr += 4U;
|
|
*(uint32_t *)aes_iv_addr = (uint32_t)(FMC_AESIV2_EFT);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief get product ID (API_ID(0x002EU))
|
|
\param[in] none
|
|
\param[out] pid: product ID
|
|
\retval none
|
|
*/
|
|
void fmc_pid_get(uint32_t *pid)
|
|
{
|
|
#ifdef FW_DEBUG_ERR_REPORT
|
|
/* check parameter */
|
|
if(NOT_VALID_POINTER(pid)) {
|
|
fw_debug_report_err(FMC_MODULE_ID, API_ID(0x002EU), ERR_PARAM_POINTER);
|
|
} else
|
|
#endif /* FW_DEBUG_ERR_REPORT */
|
|
{
|
|
uint32_t pid_addr = (uint32_t)pid;
|
|
*(uint32_t *)pid_addr = (uint32_t)(FMC_PID0);
|
|
pid_addr += 4U;
|
|
*(uint32_t *)pid_addr = (uint32_t)(FMC_PID1);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief get FMC flag status (API_ID(0x002FU))
|
|
\param[in] flag: FMC flag
|
|
only one parameter can be selected which is shown as below:
|
|
\arg FMC_FLAG_BUSY: flash busy flag bit
|
|
\arg FMC_FLAG_END: flash end of operation flag bit
|
|
\arg FMC_FLAG_WPERR: flash erase/program protection error flag bit
|
|
\arg FMC_FLAG_PGSERR: flash program sequence error flag bit
|
|
\arg FMC_FLAG_RPERR: flash read protection error flag bit
|
|
\arg FMC_FLAG_RSERR: flash read secure error flag bit
|
|
\arg FMC_FLAG_ECCCOR: flash one bit correct error flag bit
|
|
\arg FMC_FLAG_ECCDET: flash two bits detect error flag bit
|
|
\arg FMC_FLAG_OBMERR: flash option byte modify error flag bit
|
|
\arg FMC_FLAG_FECC: flash ECC function flag
|
|
\param[out] none
|
|
\retval FlagStatus: SET or RESET
|
|
*/
|
|
FlagStatus fmc_flag_get(fmc_flag_enum flag)
|
|
{
|
|
if(RESET != (FMC_REG_VAL(flag) & BIT(FMC_BIT_POS(flag)))) {
|
|
return SET;
|
|
} else {
|
|
return RESET;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief clear FMC flag status (API_ID(0x0030U))
|
|
\param[in] flag: FMC flag
|
|
only one parameter can be selected which is shown as below:
|
|
\arg FMC_FLAG_END: flash end of operation flag bit
|
|
\arg FMC_FLAG_WPERR: flash erase/program protection error flag bit
|
|
\arg FMC_FLAG_PGSERR: flash program sequence error flag bit
|
|
\arg FMC_FLAG_RPERR: flash read protection error flag bit
|
|
\arg FMC_FLAG_RSERR: flash read secure error flag bit
|
|
\arg FMC_FLAG_ECCCOR: flash one bit correct error flag bit
|
|
\arg FMC_FLAG_ECCDET: flash two bits detect error flag bit
|
|
\arg FMC_FLAG_OBMERR: flash option byte modify error flag bit
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void fmc_flag_clear(fmc_flag_enum flag)
|
|
{
|
|
/* clear the flags */
|
|
FMC_REG_VAL(flag) = BIT(FMC_BIT_POS(flag));
|
|
}
|
|
|
|
/*!
|
|
\brief enable FMC interrupt (API_ID(0x0031U))
|
|
\param[in] interrupt: the FMC interrupt source
|
|
only one parameter can be selected which is shown as below:
|
|
\arg FMC_INT_END : FMC end of program interrupt
|
|
\arg FMC_INT_WPERR: FMC erase/program protection error interrupt
|
|
\arg FMC_INT_PGSERR: FMC program sequence error interrupt
|
|
\arg FMC_INT_RPERR: FMC read protection error interrupt
|
|
\arg FMC_INT_RSERR: FMC read secure error interrupt
|
|
\arg FMC_INT_ECCCOR: FMC one bit correct error interrupt
|
|
\arg FMC_INT_ECCDET: FMC two bits detect error interrupt
|
|
\arg FMC_INT_OBMERR: FMC option byte modify error interrupt
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void fmc_interrupt_enable(fmc_interrupt_enum interrupt)
|
|
{
|
|
FMC_REG_VAL(interrupt) |= BIT(FMC_BIT_POS(interrupt));
|
|
}
|
|
|
|
/*!
|
|
\brief disable FMC interrupt (API_ID(0x0032U))
|
|
\param[in] interrupt: the FMC interrupt source
|
|
only one parameter can be selected which is shown as below:
|
|
\arg FMC_INT_END : FMC end of program interrupt
|
|
\arg FMC_INT_WPERR: FMC erase/program protection error interrupt
|
|
\arg FMC_INT_PGSERR: FMC program sequence error interrupt
|
|
\arg FMC_INT_RPERR: FMC read protection error interrupt
|
|
\arg FMC_INT_RSERR: FMC read secure error interrupt
|
|
\arg FMC_INT_ECCCOR: FMC one bit correct error interrupt
|
|
\arg FMC_INT_ECCDET: FMC two bits detect error interrupt
|
|
\arg FMC_INT_OBMERR: FMC option byte modify error interrupt
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void fmc_interrupt_disable(fmc_interrupt_enum interrupt)
|
|
{
|
|
FMC_REG_VAL(interrupt) &= ~BIT(FMC_BIT_POS(interrupt));
|
|
}
|
|
|
|
/*!
|
|
\brief get FMC interrupt flag status (API_ID(0x0033U))
|
|
\param[in] flag: FMC interrupt flag
|
|
only one parameter can be selected which is shown as below:
|
|
\arg FMC_INT_FLAG_END: flash end of operation interrupt flag
|
|
\arg FMC_INT_FLAG_WPERR: flash erase/program protection error interrupt flag
|
|
\arg FMC_INT_FLAG_PGSERR: flash program sequence error interrupt flag
|
|
\arg FMC_INT_FLAG_RPERR: flash read protection error interrupt flag
|
|
\arg FMC_INT_FLAG_RSERR: flash read secure error interrupt flag
|
|
\arg FMC_INT_FLAG_ECCCOR: flash one bit error detected and correct interrupt flag
|
|
\arg FMC_INT_FLAG_ECCDET: flash two bit errors detect interrupt flag
|
|
\arg FMC_INT_FLAG_OBMERR: option byte modify error flag
|
|
\param[out] none
|
|
\retval FlagStatus: SET or RESET
|
|
*/
|
|
FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum int_flag)
|
|
{
|
|
uint32_t intenable = 0U, flagstatus = 0U;
|
|
/* get the interrupt enable bit status */
|
|
intenable = (FMC_REG_VAL(int_flag) & BIT(FMC_BIT_POS(int_flag)));
|
|
/* get the corresponding flag bit status */
|
|
flagstatus = (FMC_REG_VAL2(int_flag) & BIT(FMC_BIT_POS2(int_flag)));
|
|
|
|
if(flagstatus && intenable) {
|
|
return SET;
|
|
} else {
|
|
return RESET;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief clear FMC interrupt flag status (API_ID(0x0034U))
|
|
\param[in] flag: FMC interrupt flag
|
|
only one parameter can be selected which is shown as below:
|
|
\arg FMC_INT_FLAG_END: flash end of operation interrupt flag
|
|
\arg FMC_INT_FLAG_WPERR: flash erase/program protection error interrupt flag
|
|
\arg FMC_INT_FLAG_PGSERR: flash program sequence error interrupt flag
|
|
\arg FMC_INT_FLAG_RPERR: flash read protection error interrupt flag
|
|
\arg FMC_INT_FLAG_RSERR: flash read secure error interrupt flag
|
|
\arg FMC_INT_FLAG_ECCCOR: flash one bit error detected and correct interrupt flag
|
|
\arg FMC_INT_FLAG_ECCDET: flash two bit errors detect interrupt flag
|
|
\arg FMC_INT_FLAG_OBMERR: option byte modify error flag
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum int_flag)
|
|
{
|
|
/* clear the intrrupt flag */
|
|
FMC_REG_VAL2(int_flag) = BIT(FMC_BIT_POS2(int_flag));
|
|
}
|
|
|
|
/*!
|
|
\brief get FMC state (API_ID(0x0035U))
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval state of FMC, refer to fmc_state_enum
|
|
\arg FMC_READY: operation has been completed
|
|
\arg FMC_BUSY: operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
*/
|
|
static fmc_state_enum fmc_state_get(void)
|
|
{
|
|
fmc_state_enum fmc_state = FMC_READY;
|
|
|
|
if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_BUSY)) {
|
|
fmc_state = FMC_BUSY;
|
|
} else {
|
|
if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_WPERR)) {
|
|
fmc_state = FMC_WPERR;
|
|
} else if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_PGSERR)) {
|
|
fmc_state = FMC_PGSERR;
|
|
} else if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_RPERR)) {
|
|
fmc_state = FMC_RPERR;
|
|
} else if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_RSERR)) {
|
|
fmc_state = FMC_RSERR;
|
|
} else if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_ECCCOR)) {
|
|
fmc_state = FMC_ECCCOR;
|
|
} else if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_ECCDET)) {
|
|
fmc_state = FMC_ECCDET;
|
|
} else if((uint32_t)0x00U != (FMC_STAT & FMC_STAT_OBMERR)) {
|
|
fmc_state = FMC_OBMERR;
|
|
} else {
|
|
/* illegal parameters */
|
|
}
|
|
}
|
|
|
|
/* return the FMC state */
|
|
return fmc_state;
|
|
}
|
|
|
|
/*!
|
|
\brief check whether FMC is ready or not (API_ID(0x0036U))
|
|
\param[in] timeout: timeout count
|
|
\param[out] none
|
|
\retval state of FMC, refer to fmc_state_enum
|
|
\arg FMC_READY: operation has been completed
|
|
\arg FMC_BUSY: operation is in progress
|
|
\arg FMC_WPERR: erase/program protection error
|
|
\arg FMC_PGSERR: program sequence error
|
|
\arg FMC_RPERR: read protection error
|
|
\arg FMC_RSERR: read secure error
|
|
\arg FMC_ECCCOR: one bit correct error
|
|
\arg FMC_ECCDET: two bits detect error
|
|
\arg FMC_OBMERR: option byte modify error
|
|
\arg FMC_TOERR: timeout error
|
|
*/
|
|
static fmc_state_enum fmc_ready_wait(uint32_t timeout)
|
|
{
|
|
fmc_state_enum fmc_state = FMC_BUSY;
|
|
|
|
/* wait for FMC ready */
|
|
do {
|
|
/* get FMC state */
|
|
fmc_state = fmc_state_get();
|
|
timeout--;
|
|
} while((FMC_BUSY == fmc_state) && (0U != timeout));
|
|
|
|
if(FMC_BUSY == fmc_state) {
|
|
fmc_state = FMC_TOERR;
|
|
}
|
|
/* return the FMC state */
|
|
return fmc_state;
|
|
}
|
|
|