mbed library sources. Supersedes mbed-src.
Fork of mbed-dev by
Diff: targets/cmsis/TARGET_NUVOTON/TARGET_NUC472/StdDriver/nuc472_fmc.c
- Revision:
- 144:ef7eb2e8f9f7
diff -r 423e1876dc07 -r ef7eb2e8f9f7 targets/cmsis/TARGET_NUVOTON/TARGET_NUC472/StdDriver/nuc472_fmc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/targets/cmsis/TARGET_NUVOTON/TARGET_NUC472/StdDriver/nuc472_fmc.c Fri Sep 02 15:07:44 2016 +0100 @@ -0,0 +1,432 @@ +/**************************************************************************//** + * @file fmc.c + * @version V1.10 + * $Revision: 16 $ + * $Date: 14/10/06 11:57a $ + * @brief NUC472/NUC442 FMC driver source file + * + * @note + * Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved. +*****************************************************************************/ + +//* Includes ------------------------------------------------------------------*/ +#include <stdio.h> +#include "NUC472_442.h" + + +/** @addtogroup NUC472_442_Device_Driver NUC472/NUC442 Device Driver + @{ +*/ + +/** @addtogroup NUC472_442_FMC_Driver FMC Driver + @{ +*/ + + +/** @addtogroup NUC472_442_FMC_EXPORTED_FUNCTIONS FMC Exported Functions + @{ +*/ + + +/** + * @brief Set boot from APROM or LDROM of next software reset. + * @param[in] i32BootSrc Next software boot selection. + * - \ref IS_BOOT_FROM_LDROM + * - \ref IS_BOOT_FROM_APROM + * @return None + */ +void FMC_SetBootSource (int32_t i32BootSrc) +{ + if (i32BootSrc == 1) + FMC->ISPCTL |= FMC_ISPCTL_BS_Msk; + else + FMC->ISPCTL &= ~FMC_ISPCTL_BS_Msk; +} + + +/** + * @brief Disable FMC ISP function. + * @return None + */ +void FMC_Close(void) +{ + FMC->ISPCTL &= ~FMC_ISPCTL_ISPEN_Msk; +} + + +/** + * @brief Disable ISP erase/program APROM function. + * @return None + */ +void FMC_DisableAPUpdate(void) +{ + FMC->ISPCTL &= ~FMC_ISPCTL_APUEN_Msk; +} + + +/** + * @brief Disable ISP erase/program User Configuration function. + * @return None + */ +void FMC_DisableConfigUpdate(void) +{ + FMC->ISPCTL &= ~FMC_ISPCTL_CFGUEN_Msk; +} + + +/** + * @brief Disable ISP erase/program LDROM function. + * @return None + */ +void FMC_DisableLDUpdate(void) +{ + FMC->ISPCTL &= ~FMC_ISPCTL_LDUEN_Msk; +} + + +/** + * @brief Enable ISP erase/program APROM function. + * @return None + */ +void FMC_EnableAPUpdate(void) +{ + FMC->ISPCTL |= FMC_ISPCTL_APUEN_Msk; +} + + +/** + * @brief Enable ISP erase/program User Configuration function. + * @return None + */ +void FMC_EnableConfigUpdate(void) +{ + FMC->ISPCTL |= FMC_ISPCTL_CFGUEN_Msk; +} + + +/** + * @brief Enable ISP erase/program LDROM function. + * @return None + */ +void FMC_EnableLDUpdate(void) +{ + FMC->ISPCTL |= FMC_ISPCTL_LDUEN_Msk; +} + + +/** + * @brief Erase a page. The page size is 2048 bytes. + * @param[in] u32PageAddr Flash page address. Must be a 2048-byte aligned address. + * @return Success or not. + * @retval 0 Success + * @retval -1 Erase failed + */ +int32_t FMC_Erase(uint32_t u32PageAddr) +{ + FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE; + FMC->ISPADDR = u32PageAddr; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ; + + if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) { + FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk; + return -1; + } + return 0; +} + + +/** + * @brief Get the current boot source. + * @return The current boot source. + * @retval 0 Is boot from APROM. + * @retval 1 Is boot from LDROM. + */ +int32_t FMC_GetBootSource (void) +{ + if (FMC->ISPCTL & FMC_ISPCTL_BS_Msk) + return 1; + else + return 0; +} + + +/** + * @brief Enable FMC ISP function + * @return None + */ +void FMC_Open(void) +{ + FMC->ISPCTL |= FMC_ISPCTL_ISPEN_Msk; +} + + +/** + * @brief Execute ISP command to read a word from flash. + * @param[in] u32Addr Address of the flash location to be read. + * It must be a word aligned address. + * @return The word data read from specified flash address. + */ +uint32_t FMC_Read(uint32_t u32Addr) +{ + FMC->ISPCMD = FMC_ISPCMD_READ; + FMC->ISPADDR = u32Addr; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ; + + return FMC->ISPDAT; +} + + +/** + * @brief Execute ISP 64-bits read command to read two words from flash. + * @param[in] u32Addr Flash word address. Must be a double word aligned address. + * @param[out] u32Data0 The first word read from flash. + * @param[out] u32Data1 The second word read from flash. + * @return None + */ +void FMC_Read_64(uint32_t u32Addr, uint32_t *u32Data0, uint32_t *u32Data1) +{ + FMC->ISPCMD = FMC_ISPCMD_READ_64; + FMC->ISPADDR = u32Addr; + FMC->ISPDAT = 0x0; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ; + + *u32Data0 = FMC->MPDAT0; + *u32Data1 = FMC->MPDAT1; +} + + +/** + * @brief Read company ID. + * @return The company ID. + */ +uint32_t FMC_ReadCID(void) +{ + FMC->ISPCMD = FMC_ISPCMD_READ_CID; + FMC->ISPADDR = 0x0; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ; + return FMC->ISPDAT; +} + + +/** + * @brief Read device ID. + * @return The device ID. + */ +uint32_t FMC_ReadDID(void) +{ + FMC->ISPCMD = FMC_ISPCMD_READ_DID; + FMC->ISPADDR = 0; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ; + return FMC->ISPDAT; +} + + +/** + * @brief Read product ID. + * @return The product ID. + */ +uint32_t FMC_ReadPID(void) +{ + FMC->ISPCMD = FMC_ISPCMD_READ_DID; + FMC->ISPADDR = 0x04; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ; + return FMC->ISPDAT; +} + + +/** + * @brief This function reads one of the four UCID. + * @param[in] u32Index Index of the UCID to read. u32Index must be 0, 1, 2, or 3. + * @return The UCID. + */ +uint32_t FMC_ReadUCID(uint32_t u32Index) +{ + FMC->ISPCMD = FMC_ISPCMD_READ_UID; + FMC->ISPADDR = (0x04 * u32Index) + 0x10; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ; + + return FMC->ISPDAT; +} + + +/** + * @brief This function reads one of the three UID. + * @param[in] u32Index Index of the UID to read. u32Index must be 0, 1, or 2. + * @return The UID. + */ +uint32_t FMC_ReadUID(uint32_t u32Index) +{ + FMC->ISPCMD = FMC_ISPCMD_READ_UID; + FMC->ISPADDR = 0x04 * u32Index; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ; + + return FMC->ISPDAT; +} + + +/** + * @brief Get the base address of Data Flash if enabled. + * @return Base address of Data Flash + */ +uint32_t FMC_ReadDataFlashBaseAddr(void) +{ + return FMC->DFBA; +} + + +/** + * @brief This function will force re-map assigned flash page to CPU address 0x0. + * @param[in] u32PageAddr Address of the page to be mapped to CPU address 0x0. + * @return None + */ +void FMC_SetVectorPageAddr(uint32_t u32PageAddr) +{ + FMC->ISPCMD = FMC_ISPCMD_VECMAP; + FMC->ISPADDR = u32PageAddr; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ; +} + + +/** + * @brief Execute ISP command to program a word to flash. + * @param[in] u32Addr Address of the flash location to be programmed. + * It must be a word aligned address. + * @param[out] u32Data The word data to be programmed. + * @return None + */ +void FMC_Write(uint32_t u32Addr, uint32_t u32Data) +{ + FMC->ISPCMD = FMC_ISPCMD_WRITE; + FMC->ISPADDR = u32Addr; + FMC->ISPDAT = u32Data; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ; +} + + +/** + * @brief Execute ISP 64-bits write command to program two words to flash. + * @param[in] u32Addr Destination address. It must be double word aligned. + * @param[in] u32Data0 First word data to be written. + * @param[in] u32Data1 Second word data to be written. + * @return None + */ +void FMC_Write_64(uint32_t u32Addr, uint32_t u32Data0, uint32_t u32Data1) +{ + FMC->ISPCMD = FMC_ISPCMD_WRITE_64; + FMC->ISPADDR = u32Addr; + FMC->MPDAT0 = u32Data0; + FMC->MPDAT1 = u32Data0; + FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; + while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ; +} + + +/** + * @brief CRC8 Calculator + * @param[in] au32Data CRC8 input data words. + * @param[in] i32Count Number of words in au32Data[]. + * @return The CRC8 value. + */ +uint32_t FMC_CRC8(uint32_t au32Data[], int i32Count) +{ + int i32ByteIdx; + uint8_t i, u8Cnt, u8InData; + uint8_t au8CRC[4] = { 0xff, 0xff, 0xff, 0xff }; + + for (i32ByteIdx = 0; i32ByteIdx < 4; i32ByteIdx++) { + for (u8Cnt = 0; u8Cnt < i32Count; u8Cnt++) { + for (i = 0x80; i != 0; i /= 2) { + if ((au8CRC[i32ByteIdx] & 0x80)!=0) { + au8CRC[i32ByteIdx] *= 2; + au8CRC[i32ByteIdx] ^= 7; + } else + au8CRC[i32ByteIdx] *= 2; + + u8InData = (au32Data[u8Cnt] >> (i32ByteIdx * 8)) & 0xff; + + if ((u8InData & i) != 0) + au8CRC[i32ByteIdx]^=0x7; + } + } + } + return (au8CRC[0] | au8CRC[1] << 8 | au8CRC[2] << 16 | au8CRC[3] << 24); +} + + +/** + * @brief Read the User Configuration words. + * @param[out] u32Config: The word array to store words read from flash. + * @param[in] u32Count: Maximum length of u32Config. + * @return Success or not. + * @retval 0 Success + * @retval -1 User Configuration CRC check error + */ +int32_t FMC_ReadConfig(uint32_t *u32Config, uint32_t u32Count) +{ + int i; + + for (i = 0; i < u32Count; i++) { + u32Config[i] = FMC_Read(FMC_CONFIG_BASE + i*4); + } + + if (FMC->ISPSTS & FMC_ISPSTS_CFGCRCF_Msk) + return -1; + + return 0; +} + + +/** + * @brief Write User Configuration + * @param[in] u32Config The word array to store data. MUST be a four word array. + * @param[in] u32Count MUST be 4. + * @return Success or not. + * @retval 0 Success + * @retval -1 Failed + */ +int32_t FMC_WriteConfig(uint32_t *u32Config, uint32_t u32Count) +{ + uint32_t i, u32CRC, u32Data; + + FMC_Erase(FMC_CONFIG_BASE); + + u32CRC = FMC_CRC8(u32Config, 3); + + for (i = 0; i < 4; i++) { + FMC_Write(FMC_CONFIG_BASE + i * 4, (i < 3) ? u32Config[i] : u32CRC); + } + + for (i = 0; i < 4; i++) { + u32Data = FMC_Read(FMC_CONFIG_BASE + i * 4); + + if (u32Data != ((i < 3) ? u32Config[i] : u32CRC)) + return -1; + } + return 0; +} + + +/*@}*/ /* end of group NUC472_442_FMC_EXPORTED_FUNCTIONS */ + +/*@}*/ /* end of group NUC472_442_FMC_Driver */ + +/*@}*/ /* end of group NUC472_442_Device_Driver */ + +/*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/ + +