fix xidatong-arm32 NorFlash init bug

This commit is contained in:
wgzAIIT 2023-04-17 15:08:10 +08:00
parent 85105cb65d
commit 198fabf970
3 changed files with 538 additions and 260 deletions

View File

@ -414,5 +414,7 @@ void InitBoardHardware()
KPrintf("start kernel...\n");
#ifdef BSP_USING_OTA
FLASH_Init();
//Flash operation
FLASH_DeInit();
#endif
}

View File

@ -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 <stdio.h>
#include <xs_base.h>
#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<sectorNum;i++)
{
@ -453,6 +690,7 @@ status_t NOR_FLASH_Erase(uint32_t app_base_addr,uint32_t imageSize)
return kStatus_Success;
}
void NorFlash_Write_PageProgram(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
uint8_t temp_data[256] = {0xff};
@ -464,7 +702,8 @@ void NorFlash_Write_PageProgram(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t Num
{
KPrintf("Write_PageProgram 0x%x faild!\r\n",WriteAddr);
}
}
}
void NorFlash_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
@ -500,7 +739,8 @@ void NorFlash_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByte
}
}
}
}
}
void NorFlash_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
@ -540,7 +780,7 @@ void NorFlash_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
NorFlash_BUF[i+secOff] = pBuffer[i];
}
NorFlash_Write_NoCheck(NorFlash_BUF,FLASH_BASE + secPos*4096,4096);//写入整个扇区
NorFlash_Write_NoCheck(NorFlash_BUF,FLASH_BASE + secPos*SECTOR_SIZE,SECTOR_SIZE);//写入整个扇区
}
else
{
@ -559,9 +799,9 @@ void NorFlash_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
pBuffer += secRemain;//指针偏移
WriteAddr += secRemain;//写地址偏移
NumByteToWrite -= secRemain;//字节数递减
if(NumByteToWrite > 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
#endif

View File

@ -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