diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/board.c b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/board.c index 23600e8ed..6fea57bb5 100644 --- a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/board.c +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/board.c @@ -414,5 +414,7 @@ void InitBoardHardware() KPrintf("start kernel...\n"); #ifdef BSP_USING_OTA FLASH_Init(); + //Flash operation + FLASH_DeInit(); #endif } diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/common/flash.c b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/common/flash.c index 69f97ddf2..b8965c6d7 100644 --- a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/common/flash.c +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/common/flash.c @@ -6,7 +6,7 @@ */ /** -* @file flash.c +* @file fsl_flash.c * @brief support flexspi norflash function * @version 2.0 * @author AIIT XUOS Lab @@ -16,173 +16,437 @@ #include #include #include "flash.h" +#include "MIMXRT1052.h" -/******************************************************************************* - * Definitions - ******************************************************************************/ -#define APP_FLASH_SIZE 0x100000 //Application package size is limited to 1M -#define FLASH_PAGE_SIZE 256 //每次写入256个字节 -/******************************************************************************* - * Prototypes - ******************************************************************************/ uint8_t NorFlash_BUFFER[4096]; //4K buffer cache uint8_t buffer[FLASH_PAGE_SIZE]; //256 bytes buffer cache /******************************************************************************* - * Variables + * Prototypes ******************************************************************************/ -/*! @brief FLEXSPI NOR flash driver Structure in XIP config */ -extern flexspi_nor_config_t Qspiflash_config; -/*! @brief FLEXSPI NOR flash driver Structure in flash driver */ -static flexspi_nor_config_t norConfig; +static status_t Flexspi_Nor_Wait_Busy(uint32_t instance, uint32_t baseAddr); +static status_t Flexspi_Nor_Write_Enable(uint32_t instance, uint32_t baseAddr); +static void flexspi_clock_config(uint32_t instance, uint32_t freq, uint32_t sampleClkMode); +static void flexspi_clock_gate_enable(uint32_t instance); +static void flexspi_clock_gate_disable(uint32_t instance); +static status_t flexspi_get_clock(uint32_t instance, flexspi_clock_type_t type, uint32_t *freq); +static status_t flexspi_get_ticks(uint32_t *ticks, uint32_t intervalNs, uint32_t freq, uint32_t unit); +static status_t flexspi_configure_dll(uint32_t instance, flexspi_mem_config_t *config); +static status_t flexspi_config_mcr1(uint32_t instance, flexspi_mem_config_t *config); -/******************************************************************************* - * Code - ******************************************************************************/ -/* Get FLEXSPI NOR Configuration Block */ -void FLEXSPI_NorFlash_GetConfig(flexspi_nor_config_t *config) +static const lookuptable_t FlashLookupTable={ +.ReadStatus_Seq= { - /* Copy norflash config block from xip config */ - memcpy(config, &Qspiflash_config, sizeof(flexspi_nor_config_t)); -#ifndef HYPER_FLASH //QSPI Flash - /* Override some default config */ - config->memConfig.deviceType = kFLEXSPIDeviceType_SerialNOR; - config->memConfig.deviceModeType = kDeviceConfigCmdType_Generic; - config->memConfig.serialClkFreq = kFLEXSPISerialClk_30MHz; //Safe Serial Flash Frequencey - config->ipcmdSerialClkFreq = kFLEXSPISerialClk_30MHz; //Safe Clock frequency for IP command - config->memConfig.controllerMiscOption = FSL_ROM_FLEXSPI_BITMASK(kFLEXSPIMiscOffset_SafeConfigFreqEnable);//Always enable Safe configuration Frequency + FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05, READ_SDR, FLEXSPI_1PAD, 0x04), +}, +/* Write Enable */ +.WriteEnable_Seq= +{ + FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06, STOP, FLEXSPI_1PAD, 0x00), +}, +/* Erase Sector */ +.EraseSector_Seq= +{ + FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20, RADDR_SDR, FLEXSPI_1PAD, 0x18), +}, +/* Page Program */ +.PageProgram_Seq= +{ + FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x32, RADDR_SDR, FLEXSPI_1PAD, 0x18), + FSL_ROM_FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_4PAD, 0x00, 0x00, 0x00, 0x00), +}, +}; - /* Read Status */ - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_READSTATUS] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05U, READ_SDR, FLEXSPI_1PAD, 0x1U); - /* Write Enable */ - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06U, STOP, FLEXSPI_1PAD, 0x0U); +static status_t Flexspi_Nor_Wait_Busy(uint32_t instance, uint32_t baseAddr) +{ + status_t status = kStatus_InvalidArgument; + flexspi_xfer_t flashXfer; + uint32_t statusDataBuffer; + uint32_t busyMask; + uint32_t busyPolarity; + bool isBusy = false; + + flashXfer.operation = kFLEXSPIOperation_Read; + flashXfer.seqNum = 1; + busyMask = 1; + busyPolarity = 0; + flashXfer.seqId = NOR_CMD_LUT_SEQ_IDX_READSTATUS; + flashXfer.isParallelModeEnable = false; + flashXfer.baseAddress = baseAddr; + flashXfer.rxBuffer = &statusDataBuffer; + flashXfer.rxSize = sizeof(statusDataBuffer); + do + { + status = ROM_FLEXSPI_NorFlash_CommandXfer(instance, &flashXfer); + // Busy bit is 0 if polarity is 1 + if(busyPolarity) + { + isBusy = (~statusDataBuffer) & busyMask; + } + else + { + isBusy = statusDataBuffer & busyMask; + } + }while (isBusy); - /* Page Program - quad mode */ - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM + 0U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x32U, RADDR_SDR, FLEXSPI_1PAD, 0x18U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM + 1U] = - FSL_ROM_FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_4PAD, 0x04U, STOP, FLEXSPI_1PAD, 0x0U); - - /* Sector Erase */ - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD7U, RADDR_SDR, FLEXSPI_1PAD, 0x18U); -#else - /* Override some default config */ - config->memConfig.deviceType = kFLEXSPIDeviceType_SerialNOR; - config->memConfig.deviceModeType = kDeviceConfigCmdType_Generic; - config->memConfig.lutCustomSeqEnable = true; - config->memConfig.busyOffset = 15U; - config->memConfig.busyBitPolarity = 1U; - config->ipcmdSerialClkFreq = kFLEXSPISerialClk_30MHz; //Safe Clock frequency for IP command - config->serialNorType = kSerialNorType_HyperBus; - // Read Status - // 0 - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_READSTATUS] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x00U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_READSTATUS + 1U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0xAAU); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_READSTATUS + 2U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x05U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_READSTATUS + 3U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x70U); - // 1 - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_READSTATUS + 4U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0xA0U, RADDR_DDR, FLEXSPI_8PAD, 0x18U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_READSTATUS + 5U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CADDR_DDR, FLEXSPI_8PAD, 0x10U, DUMMY_RWDS_DDR, FLEXSPI_8PAD, 0x0BU); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_READSTATUS + 6U] = - FSL_ROM_FLEXSPI_LUT_SEQ(READ_DDR, FLEXSPI_8PAD, 0x04U, STOP, FLEXSPI_1PAD, 0x00U); - - // Write Enable - // 0 - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x00U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE + 1U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0xAAU); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE + 2U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x05U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE + 3U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0xAAU); - // 1 - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE + 4U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x00U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE + 5U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x55U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE + 6U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x02U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE + 7U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x55U); - - // Page Program - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x00U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM + 1U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0xAAU); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM + 2U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x05U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM + 3U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0xA0U); - // 1 - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM + 4U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, RADDR_DDR, FLEXSPI_8PAD, 0x18U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM + 5U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CADDR_DDR, FLEXSPI_8PAD, 0x10U, WRITE_DDR, FLEXSPI_8PAD, 0x80U); - - // Erase Sector - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x00U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR + 1U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0xAAU); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR + 2U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x05U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR + 3U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x80U); - // 1 - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR + 4U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x00U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR + 5U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0xAAU); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR + 6U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x05U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR + 7U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0xAAU); - // 2 - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR + 8U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x00U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR + 9U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x55U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR + 10U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x02U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR + 11U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, CMD_DDR, FLEXSPI_8PAD, 0x55U); - // 3 - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR + 12U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x00U, RADDR_DDR, FLEXSPI_8PAD, 0x18U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR + 13U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CADDR_DDR, FLEXSPI_8PAD, 0x10U, CMD_DDR, FLEXSPI_8PAD, 0x00U); - config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR + 14U] = - FSL_ROM_FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0x30U, STOP, FLEXSPI_1PAD, 0x0U); - - // LUT customized sequence - config->memConfig.lutCustomSeq[NOR_CMD_INDEX_WRITEENABLE].seqNum = 2U; - config->memConfig.lutCustomSeq[NOR_CMD_INDEX_WRITEENABLE].seqId = NOR_CMD_LUT_SEQ_IDX_WRITEENABLE; - config->memConfig.lutCustomSeq[NOR_CMD_INDEX_READSTATUS].seqNum = 2U; - config->memConfig.lutCustomSeq[NOR_CMD_INDEX_READSTATUS].seqId = NOR_CMD_LUT_SEQ_IDX_READSTATUS; - config->memConfig.lutCustomSeq[NOR_CMD_INDEX_PAGEPROGRAM].seqNum = 2U; - config->memConfig.lutCustomSeq[NOR_CMD_INDEX_PAGEPROGRAM].seqId = NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM; - config->memConfig.lutCustomSeq[NOR_CMD_INDEX_ERASESECTOR].seqNum = 4U; - config->memConfig.lutCustomSeq[NOR_CMD_INDEX_ERASESECTOR].seqId = NOR_CMD_LUT_SEQ_IDX_ERASESECTOR; -#endif + return status; } - /** - * @brief 获得扇区大小 - * @note None - * @param None - * @retval Flash扇区尺寸 - */ + +static status_t Flexspi_Nor_Write_Enable(uint32_t instance, uint32_t baseAddr) +{ + status_t status = kStatus_InvalidArgument; + flexspi_xfer_t flashXfer; + + flashXfer.operation = kFLEXSPIOperation_Command; + flashXfer.seqNum = 1; + flashXfer.seqId = NOR_CMD_LUT_SEQ_IDX_WRITEENABLE; + flashXfer.isParallelModeEnable = false; + flashXfer.baseAddress = baseAddr; + + status = ROM_FLEXSPI_NorFlash_CommandXfer(instance, &flashXfer); + + return status; +} + + +static void flexspi_clock_config(uint32_t instance, uint32_t freq, uint32_t sampleClkMode) +{ + uint32_t pfd480 = 0; + uint32_t cscmr1 = 0; + uint32_t frac = 0; + uint32_t podf = 0; + + typedef struct _flexspi_clock_param + { + uint8_t frac; + uint8_t podf; + } flexspi_clock_param_t; + + const flexspi_clock_param_t k_sdr_clock_config[kFLEXSPISerialClk_200MHz + 1] = { + //Reserved, 30MHz 50MHz 60MHz 75MHz 80MHz 100MHz 133MHz 166MHz 200MHz + {0, 0}, {34, 8}, {22, 8}, {24, 6}, {30, 4}, {18, 6}, {14, 6}, {17, 4}, {26, 2}, {22, 2} + }; + const flexspi_clock_param_t k_ddr_clock_config[kFLEXSPISerialClk_200MHz + 1] = { + //Reserved, 30MHz 50MHz 60MHz 75MHz 80MHz 100MHz 133MHz 166MHz 200MHz + {0, 0}, {24, 6}, {22, 4}, {12, 6}, {30, 2}, {18, 3}, {22, 2}, {33, 1}, {26, 1}, {22, 1} + }; + + do + { + if((sampleClkMode != kFLEXSPIClk_SDR) && (sampleClkMode != kFLEXSPIClk_DDR)) + { + break; + } + + pfd480 = CCM_ANALOG->PFD_480 & (~CCM_ANALOG_PFD_480_PFD0_FRAC_MASK); + cscmr1 = CCM->CSCMR1 & (~CCM_CSCMR1_FLEXSPI_PODF_MASK); + + const flexspi_clock_param_t *flexspi_config_array = NULL; + if(sampleClkMode == kFLEXSPIClk_SDR) + { + flexspi_config_array = &k_sdr_clock_config[0]; + } + else + { + flexspi_config_array = &k_ddr_clock_config[0]; + } + + if(freq >= kFLEXSPISerialClk_30MHz) + { + if(freq > kFLEXSPISerialClk_200MHz) + { + freq = kFLEXSPISerialClk_30MHz; + } + + frac = flexspi_config_array[freq].frac; + podf = flexspi_config_array[freq].podf; + + pfd480 |= CCM_ANALOG_PFD_480_PFD0_FRAC(frac); + cscmr1 |= CCM_CSCMR1_FLEXSPI_PODF(podf - 1); + + FLEXSPI->MCR0 |= FLEXSPI_MCR0_MDIS_MASK; + flexspi_clock_gate_disable(instance); + + if(pfd480 != CCM_ANALOG->PFD_480) + { + CCM_ANALOG->PFD_480 = pfd480; + } + if(cscmr1 != CCM->CSCMR1) + { + CCM->CSCMR1 = cscmr1; + } + flexspi_clock_gate_enable(instance); + FLEXSPI->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK; + } + else + { + //Do nothing + } + } while (0); +} + + +static void flexspi_clock_gate_enable(uint32_t instance) +{ + CCM->CCGR6 |= CCM_CCGR6_CG5_MASK; +} + + +static void flexspi_clock_gate_disable(uint32_t instance) +{ + CCM->CCGR6 &= (uint32_t)~CCM_CCGR6_CG5_MASK; +} + + +static status_t flexspi_get_clock(uint32_t instance, flexspi_clock_type_t type, uint32_t *freq) +{ + uint32_t clockFrequency = 0; + status_t status = kStatus_Success; + + uint32_t ahbBusDivider; + uint32_t seralRootClkDivider; + uint32_t arm_clock = SystemCoreClock; + + switch (type) + { + case kFlexSpiClock_CoreClock: + clockFrequency = SystemCoreClock; + break; + case kFlexSpiClock_AhbClock: + { + // Note: In I.MXRT_512, actual AHB clock is IPG_CLOCK_ROOT + ahbBusDivider = ((CCM->CBCDR & CCM_CBCDR_IPG_PODF_MASK) >> CCM_CBCDR_IPG_PODF_SHIFT) + 1; + clockFrequency = arm_clock / ahbBusDivider; + } + break; + case kFlexSpiClock_SerialRootClock: + { + uint32_t pfdFrac; + uint32_t pfdClk; + + // FLEXPI CLK SEL + uint32_t flexspi_clk_src = + (CCM->CSCMR1 & CCM_CSCMR1_FLEXSPI_CLK_SEL_MASK) >> CCM_CSCMR1_FLEXSPI_CLK_SEL_SHIFT; + + // PLL_480_PFD0 + pfdFrac = (CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT; + pfdClk = (480000000UL) / pfdFrac * 18; + + seralRootClkDivider = ((CCM->CSCMR1 & CCM_CSCMR1_FLEXSPI_PODF_MASK) >> CCM_CSCMR1_FLEXSPI_PODF_SHIFT) + 1; + + clockFrequency = pfdClk / seralRootClkDivider; + } + break; + default: + status = kStatus_InvalidArgument; + break; + } + *freq = clockFrequency; + + return status; +} + + +static status_t flexspi_get_ticks(uint32_t *ticks, uint32_t intervalNs, uint32_t freq, uint32_t unit) +{ + status_t status = kStatus_InvalidArgument; + do + { + if((ticks == NULL) || (freq < 1) || (unit < 1)) + { + break; + } + + // Get clock cycle in terms of ns + int32_t calculatedTicks; + uint32_t cycleNs = FLEXSPI_FREQ_1GHz / freq; + + calculatedTicks = intervalNs / (cycleNs * unit); + while(calculatedTicks * cycleNs * unit < intervalNs) + { + calculatedTicks++; + } + + *ticks = calculatedTicks; + + status = kStatus_Success; + + } while (0); + + return status; +} + + +static status_t flexspi_configure_dll(uint32_t instance, flexspi_mem_config_t *config) +{ + status_t status = kStatus_InvalidArgument; + bool mdisConfigRequired; + + do + { + bool isUnifiedConfig = true; + uint32_t flexspiRootClk; + uint32_t flexspiDll[2]; + uint32_t dllValue; + uint32_t temp; + if(config->readSampleClkSrc > kFLEXSPIReadSampleClk_ExternalInputFromDqsPad) + { + break; + } + switch (config->readSampleClkSrc) + { + case kFLEXSPIReadSampleClk_LoopbackInternally: + case kFLEXSPIReadSampleClk_LoopbackFromDqsPad: + case kFLEXSPIReadSampleClk_LoopbackFromSckPad: + isUnifiedConfig = true; + break; + case kFLEXSPIReadSampleClk_ExternalInputFromDqsPad: + isUnifiedConfig = false; + break; + default: // Never reach here + break; + } + + if(isUnifiedConfig) + { + flexspiDll[0] = FLEXSPI_DLLCR_DEFAULT; // 1 fixed delay cells in DLL delay chain) + flexspiDll[1] = FLEXSPI_DLLCR_DEFAULT; // 1 fixed delay cells in DLL delay chain) + } + else + { + flexspi_get_clock(instance, kFlexSpiClock_SerialRootClock, &flexspiRootClk); + + bool useDLL = false; + + //See FlexSPI Chapter for more details + if((flexspiRootClk >= 100 * FREQ_1MHz) && + (!(config->controllerMiscOption & (1U << kFLEXSPIMiscOffset_UseValidTimeForAllFreq)))) + { + useDLL = true; + } + if(useDLL) + { + flexspiDll[0] = FLEXSPI_DLLCR_DLLEN(1) | FLEXSPI_DLLCR_SLVDLYTARGET(0x0F); + flexspiDll[1] = FLEXSPI_DLLCR_DLLEN(1) | FLEXSPI_DLLCR_SLVDLYTARGET(0x0F); + } + else + { + for(uint32_t i = 0; i < 2; i++) + { + uint32_t dataValidTimeH = config->dataValidTime[i].delay_cells; + uint32_t dataValidTimeL = config->dataValidTime[i].time_100ps; + if(dataValidTimeH < 1) + { + // Convert the data valid time to n ps. + temp = dataValidTimeL * 100ul; + if(temp < 1) + { + uint32_t maxFreq = (166UL * 1000 * 1000); + bool is_ddr_enabled = (config->controllerMiscOption & 1<< kFLEXSPIMiscOffset_DdrModeEnable)?true:false; + /* For SDR mode, the delay cell configuration must ensure that the delay time is greater + than Half cycle of max supported frequency*/ + if(!is_ddr_enabled) + { + dllValue = FLEXSPI_FREQ_1GHz / maxFreq / 2 * 1000 / kFlexSpiDelayCellUnit_Min + 1; + } + /* For SDR mode, the delay cell configuration must ensure that the delay time is greater + than 1/4 cycle of max supported frequency */ + else + { + dllValue = FLEXSPI_FREQ_1GHz / maxFreq / 4 * 1000 / kFlexSpiDelayCellUnit_Min + 1; + } + } + else + { + dllValue = temp / kFlexSpiDelayCellUnit_Min; + if(dllValue * kFlexSpiDelayCellUnit_Min < temp) + { + dllValue++; + } + } + } + else + { + dllValue = dataValidTimeH; + } + // Calculate maximum dll value; + temp = (FLEXSPI_DLLCR_OVRDVAL_MASK >> FLEXSPI_DLLCR_OVRDVAL_SHIFT); + if(dllValue > temp) + { + dllValue = temp; + } + flexspiDll[i] = FLEXSPI_DLLCR_OVRDEN(1) | FLEXSPI_DLLCR_OVRDVAL(dllValue); + } + } + } + + if(FLEXSPI->MCR0 & FLEXSPI_MCR0_MDIS_MASK) + { + mdisConfigRequired = false; + } + else + { + mdisConfigRequired = true; + } + + if(mdisConfigRequired) + { + FLEXSPI->MCR0 |= FLEXSPI_MCR0_MDIS_MASK; + } + + FLEXSPI->DLLCR[0] = flexspiDll[0]; + FLEXSPI->DLLCR[1] = flexspiDll[1]; + + if(mdisConfigRequired) + { + FLEXSPI->MCR0 &= (uint32_t)~FLEXSPI_MCR0_MDIS_MASK; + } + /* Wait at least 100 NOPs*/ + for(uint8_t delay = 100U; delay > 0U; delay--) + { + __NOP(); + } + status = kStatus_Success; + } while (0); + + return status; +} + + +static status_t flexspi_config_mcr1(uint32_t instance, flexspi_mem_config_t *config) +{ + uint32_t seqWaitTicks = 0xFFFFu; + uint32_t ahbBusWaitTicks = 0xFFFFu; + uint32_t serialRootClockFreq; + uint32_t ahbBusClockFreq; + + if(config == NULL) + { + return kStatus_InvalidArgument; + } + + flexspi_get_clock(instance, kFlexSpiClock_SerialRootClock, &serialRootClockFreq); + flexspi_get_clock(instance, kFlexSpiClock_AhbClock, &ahbBusClockFreq); + flexspi_get_ticks(&seqWaitTicks, FLEXSPI_WAIT_TIMEOUT_NS, serialRootClockFreq, 1024); + flexspi_get_ticks(&ahbBusWaitTicks, FLEXSPI_WAIT_TIMEOUT_NS, ahbBusClockFreq, 1024); + + if(seqWaitTicks > 0xFFFF) + { + seqWaitTicks = 0xFFFF; + } + if(ahbBusWaitTicks > 0xFFFF) + { + ahbBusWaitTicks = 0xFFFF; + } + + // Configure MCR1 + FLEXSPI->MCR1 = FLEXSPI_MCR1_SEQWAIT(seqWaitTicks) | FLEXSPI_MCR1_AHBBUSWAIT(ahbBusWaitTicks); + + return kStatus_Success; +} + + uint32_t FLASH_GetSectorSize(void) { #ifndef HYPER_FLASH @@ -192,96 +456,92 @@ uint32_t FLASH_GetSectorSize(void) #endif } - /** - * @brief 获得最小编程长度 - * @note None - * @param None - * @retval 256 or 512 for QSPI Flash - */ + uint32_t FLASH_GetProgramCmd(void) { + uint32_t Program_Unit; #ifndef HYPER_FLASH - return 256;//QSPI Flash Page Program + Program_Unit = 256;//QSPI Flash Page Program #else - return 512;//Hyper Flash Page Program + Program_Unit = 512;//Hyper Flash Page Program #endif + + return Program_Unit; } - /** - * @brief 初始化Flash - * @note None - * @param None - * @retval None - */ + + void FLASH_Init(void) { - /* Clean up FLEXSPI NOR flash driver Structure */ - memset(&norConfig, 0U, sizeof(flexspi_nor_config_t)); - /* Setup FLEXSPI NOR Configuration Block */ - FLEXSPI_NorFlash_GetConfig(&norConfig); - /* Initializes the FLEXSPI module for the other FLEXSPI APIs */ - ROM_FLEXSPI_NorFlash_Init(0, &norConfig); - /* Reset the Flexspi's Cache */ + /* Update LUT Table for Status, Write Enable, Erase and Program */ + ROM_FLEXSPI_NorFlash_UpdateLut(0, NOR_CMD_LUT_SEQ_IDX_READSTATUS, (const uint32_t *)FlashLookupTable.ReadStatus_Seq, 10U); + /* Use 30MHz Flexspi clock for safe operation */ + flexspi_clock_config(0, kFLEXSPISerialClk_30MHz, kFLEXSPIClk_DDR); + extern flexspi_nor_config_t Qspiflash_config; + flexspi_config_mcr1(0, &Qspiflash_config.memConfig); + flexspi_configure_dll(0, &Qspiflash_config.memConfig); ROM_FLEXSPI_NorFlash_ClearCache(0); } - /** - * @brief 反初始化Flash - * @note None - * @param None - * @retval None - */ + + void FLASH_DeInit(void) { - /* Clear the FlexSPI LUT to avoid unexpected erase or program operion trigger */ - memset(&norConfig, 0U, sizeof(flexspi_nor_config_t)); - ROM_FLEXSPI_NorFlash_UpdateLut(0, NOR_CMD_LUT_SEQ_IDX_READSTATUS, norConfig.memConfig.lookupTable, sizeof(norConfig.memConfig.lookupTable)-(4*NOR_CMD_LUT_SEQ_IDX_READSTATUS)); - /* Reset the Flexspi's Cache */ + lookuptable_t clearlut; + memset(&clearlut, 0, sizeof(lookuptable_t)); + ROM_FLEXSPI_NorFlash_UpdateLut(0, NOR_CMD_LUT_SEQ_IDX_READSTATUS, (const uint32_t *)FlashLookupTable.ReadStatus_Seq, 10U); + /* Use 30MHz Flexspi clock for safe operation */ + flexspi_clock_config(0, kFLEXSPISerialClk_30MHz, kFLEXSPIClk_DDR); +} + + +uint8_t FLASH_EraseSector(uint32_t addr) +{ + status_t status; + flexspi_xfer_t flashXfer; + addr &= 0x0FFFFFFF; + + flashXfer.operation = kFLEXSPIOperation_Command; + flashXfer.seqNum = 1; + flashXfer.seqId = NOR_CMD_LUT_SEQ_IDX_ERASESECTOR; + flashXfer.baseAddress = addr; + flashXfer.isParallelModeEnable = false; + + __disable_irq(); + status = Flexspi_Nor_Write_Enable(0, addr); + status = ROM_FLEXSPI_NorFlash_CommandXfer(0, &flashXfer); + status = Flexspi_Nor_Wait_Busy(0, addr); ROM_FLEXSPI_NorFlash_ClearCache(0); -} - - /** - * @brief 擦除Flash扇区 - * @note 该功能将删除一个Flash扇区的内容 - * @param addr: 擦除区域起始地址 - * @retval 返回操作结果 - */ -status_t FLASH_EraseSector(uint32_t addr) -{ - status_t status; - addr &= 0x0FFFFFFF; - - __disable_irq(); - status = ROM_FLEXSPI_NorFlash_Erase(0, &norConfig, addr, norConfig.sectorSize); __enable_irq(); return status; } - /** - * @brief 写Flash一个页 - * @note 字节数小于等于一页 - * @param addr: 开始地址 - * @param buf : 写入数据起始指针 - * @param len : 字节数 - * @retval kStatus_Success:完成 - */ -status_t FLASH_WritePage(uint32_t addr, const uint32_t *buf, uint32_t len) + +uint8_t FLASH_WritePage(uint32_t addr, const uint32_t *buf, uint32_t len) { status_t status; + flexspi_xfer_t flashXfer; addr &= 0x0FFFFFFF; + + + flashXfer.operation = kFLEXSPIOperation_Write; + flashXfer.seqNum = 1; + flashXfer.seqId = NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM; + flashXfer.baseAddress = addr; + flashXfer.isParallelModeEnable = false; + flashXfer.txBuffer = (uint32_t *)buf; + flashXfer.txSize = len; + __disable_irq(); - norConfig.pageSize = len; - status = ROM_FLEXSPI_NorFlash_ProgramPage(0, &norConfig, addr, buf); + status = Flexspi_Nor_Write_Enable(0, addr); + status = ROM_FLEXSPI_NorFlash_CommandXfer(0, &flashXfer); + status = Flexspi_Nor_Wait_Busy(0, addr); + ROM_FLEXSPI_NorFlash_ClearCache(0); __enable_irq(); return status; } - /** - * @brief 读Flash内容 - * @param addr: 开始地址 - * @param buf : 读缓存指针 - * @param len : 字节数 - * @retval kStatus_Success:完成 - */ + + status_t FLASH_Read(uint32_t addr, uint32_t *buf, uint32_t len) { status_t status; @@ -305,12 +565,7 @@ status_t FLASH_Read(uint32_t addr, uint32_t *buf, uint32_t len) return status; } - /** - * @brief 擦除flash指定地址指定长度的空间 - * @param start_addr: 开始地址 - * @param byte_cnt : 要擦除的字节数 - * @retval kStatus_Success:擦除成功 - */ + status_t flash_erase(uint32_t start_addr, uint32_t byte_cnt) { uint32_t addr; @@ -329,25 +584,12 @@ status_t flash_erase(uint32_t start_addr, uint32_t byte_cnt) return status; } - /** - * @brief 在flash指定地址写入指定长度的数据 - * @param start_addr: 开始地址 - * @param buf : 数据buffer - * @param byte_cnt : 要写入的字节数 - * @retval kStatus_Success:写入成功 - */ status_t flash_write(uint32_t start_addr, uint8_t *buf, uint32_t byte_cnt) { return FLASH_WritePage(start_addr, (void *)buf, byte_cnt); } - /** - * @brief 在flash指定开始读取一定长度的数据到缓存中 - * @param start_addr: 开始地址 - * @param buf : 数据buffer - * @param byte_cnt : 要读取的字节数 - * @retval kStatus_Success:读取成功 - */ + status_t flash_read(uint32_t addr, uint8_t *buf, uint32_t len) { /* For FlexSPI Memory ReadBack, use IP Command instead of AXI command for security */ @@ -371,13 +613,7 @@ status_t flash_read(uint32_t addr, uint8_t *buf, uint32_t len) } } - /** - * @brief 实现两块连续flash地址空间之间的数据拷贝 - * @param srcAddr: 源flash的起始地址 - * @param dstAddr : 目标flash的起始地址 - * @param imageSize : 要拷贝的flash空间大小,单位为字节 - * @retval kStatus_Success:拷贝成功 - */ + status_t flash_copy(uint32_t srcAddr,uint32_t dstAddr, uint32_t imageSize) { uint32_t PageNum, Remain, i; @@ -435,10 +671,11 @@ status_t flash_copy(uint32_t srcAddr,uint32_t dstAddr, uint32_t imageSize) return (status_t)kStatus_Success; } + status_t NOR_FLASH_Erase(uint32_t app_base_addr,uint32_t imageSize) { uint16_t i; - uint32_t sectorNum = (imageSize%4096 != 0)? (imageSize/4096 + 1):(imageSize/4096); + uint32_t sectorNum = (imageSize%SECTOR_SIZE != 0)? (imageSize/SECTOR_SIZE + 1):(imageSize/SECTOR_SIZE); for(i=0;i 4096) + if(NumByteToWrite > SECTOR_SIZE) { - secRemain = 4096;//下一个扇区还是写不完 + secRemain = SECTOR_SIZE;//下一个扇区还是写不完 } else { @@ -571,6 +811,7 @@ void NorFlash_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite) } } + #ifndef USE_HIGHT_SPEED_TRANS uint32_t NOR_FLASH_Write(uint32_t* FlashAddress, uint8_t* Data ,uint16_t DataLength) { @@ -597,7 +838,7 @@ uint32_t NOR_FLASH_Write(uint32_t* FlashAddress, uint8_t* Data ,uint16_t DataLen WriteAddr = *FlashAddress; } - if(dataLen>=4096) + if(dataLen>=SECTOR_SIZE) { NorFlash_Write(dataBuff,WriteAddr,dataLen); packetNum = 0; @@ -613,4 +854,4 @@ uint32_t NOR_FLASH_Write(uint32_t* FlashAddress, uint8_t* Data ,uint16_t DataLen } return (0); } -#endif \ No newline at end of file +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/include/flash.h b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/include/flash.h index 190854ac4..a332ca55b 100644 --- a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/include/flash.h +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/include/flash.h @@ -6,7 +6,7 @@ */ /** -* @file flash.h +* @file fsl_flash.h * @brief support flexspi norflash function * @version 2.0 * @author AIIT XUOS Lab @@ -23,23 +23,58 @@ #define FLASH_BASE 0x60000000 #define SECTOR_SIZE 0x1000 #define FLASH_PAGE_SIZE 256 +#define APP_FLASH_SIZE 0x100000 //Application package size is limited to 1M +#define FLEXSPI_WAIT_TIMEOUT_NS (500000000UL) //FlexSPI timeout value, 500ms +#define FLEXSPI_FREQ_1GHz (1000000000UL) +#define FREQ_1MHz (1000000UL) +#define FLEXSPI_DLLCR_DEFAULT (0x100UL) + +enum +{ + kFlexSpiDelayCellUnit_Min = 75, // 75ps + kFlexSpiDelayCellUnit_Max = 225, // 225ps +}; + +typedef enum +{ + kFlexSpiClock_CoreClock, //ARM Core Clock + kFlexSpiClock_AhbClock, //AHB clock + kFlexSpiClock_SerialRootClock, //Serial Root Clock + kFlexSpiClock_IpgClock, //IPG clock +} flexspi_clock_type_t; + +typedef struct LookUpTable +{ + uint32_t Read_Seq[4]; + uint32_t ReadStatus_Seq[8]; + uint32_t WriteEnable_Seq[8]; + uint32_t EraseSector_Seq[16]; + uint32_t PageProgram_Seq[8]; + uint32_t ChipErase_Seq[8]; + uint32_t ReadSfdp_Seq[4]; + uint32_t Restore_NoCmd_Seq[4]; + uint32_t Exit_NoCmd_Seq[4]; +}lookuptable_t; + + +uint32_t FLASH_GetSectorSize(void); +uint32_t FLASH_GetProgramCmd(void); void FLASH_Init(void); void FLASH_DeInit(void); -uint32_t FLASH_GetSectorSize(void); -status_t FLASH_WritePage(uint32_t addr, const uint32_t *buf, uint32_t len); -status_t FLASH_EraseSector(uint32_t addr); +uint8_t FLASH_EraseSector(uint32_t addr); +uint8_t FLASH_WritePage(uint32_t addr, const uint32_t *buf, uint32_t len); status_t FLASH_Read(uint32_t addr, uint32_t *buf, uint32_t len); status_t flash_erase(uint32_t start_addr, uint32_t byte_cnt); status_t flash_write(uint32_t start_addr, uint8_t *buf, uint32_t byte_cnt); status_t flash_read(uint32_t addr, uint8_t *buf, uint32_t len); status_t flash_copy(uint32_t srcAddr,uint32_t dstAddr, uint32_t imageSize); -status_t NOR_FLASH_Erase(uint32_t app_base_addr,uint32_t imageSize); status_t NOR_FLASH_Erase(uint32_t app_base_addr,uint32_t imageSize); void NorFlash_Write_PageProgram(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite); void NorFlash_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite); void NorFlash_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite); + #ifndef USE_HIGHT_SPEED_TRANS uint32_t NOR_FLASH_Write(uint32_t* FlashAddress, uint8_t* Data ,uint16_t DataLength); #else