forked from xuos/xiuos
fix xidatong-arm32 NorFlash init bug
This commit is contained in:
parent
85105cb65d
commit
198fabf970
|
@ -414,5 +414,7 @@ void InitBoardHardware()
|
|||
KPrintf("start kernel...\n");
|
||||
#ifdef BSP_USING_OTA
|
||||
FLASH_Init();
|
||||
//Flash operation
|
||||
FLASH_DeInit();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
/* 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);
|
||||
|
||||
FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05, READ_SDR, FLEXSPI_1PAD, 0x04),
|
||||
},
|
||||
/* 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);
|
||||
.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),
|
||||
},
|
||||
};
|
||||
|
||||
/* 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);
|
||||
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;
|
||||
|
||||
// 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);
|
||||
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
|
||||
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};
|
||||
|
@ -466,6 +704,7 @@ void NorFlash_Write_PageProgram(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t Num
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void NorFlash_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
|
||||
{
|
||||
uint16_t pageRemain;
|
||||
|
@ -502,6 +741,7 @@ 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)
|
||||
{
|
||||
uint32_t secPos;
|
||||
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue