According to RM, memory map of FlexSPI is 0x60000000 - and SEMC is 0x80000000 - . After configuring SEMC and FlexSPI, I access the data directly.
volatile uint8_t *p = (volatile uint8_t*)0x60000000;
volatile uint8_t *q = (volatile uint8_t*)0x80000000;
printf("%d\n", *p);
printf("%d\n", *q);
Both 3rd and 4th line will take MCU to crash. But this only happened in A1 version(MIMXRT1052DVL6B), A0 version(MIMXRT1052DVL6A) did not crash and could get correct data. (I have two version of the board).
Code of my configuration:FlexSPI connect to a Quad SPI NOR Flash, W25Q64JV, SEMC is used connecting an FPGA via SRAM timing configuration.
IOMUXC_SetPinMux(FLEXSPI_D0_IOMUXC, 1U);
IOMUXC_SetPinMux(FLEXSPI_D1_IOMUXC, 1U);
IOMUXC_SetPinMux(FLEXSPI_D2_IOMUXC, 1U);
IOMUXC_SetPinMux(FLEXSPI_D3_IOMUXC, 1U);
IOMUXC_SetPinMux(FLEXSPI_CS_IOMUXC, 1U);
IOMUXC_SetPinMux(FLEXSPI_SCK_IOMUXC, 1U);
IOMUXC_SetPinConfig(FLEXSPI_D0_IOMUXC, 0x10F1U);
IOMUXC_SetPinConfig(FLEXSPI_D1_IOMUXC, 0x10F1U);
IOMUXC_SetPinConfig(FLEXSPI_D2_IOMUXC, 0x10F1U);
IOMUXC_SetPinConfig(FLEXSPI_D3_IOMUXC, 0x10F1U);
IOMUXC_SetPinConfig(FLEXSPI_CS_IOMUXC, 0x10F1U);
IOMUXC_SetPinConfig(FLEXSPI_SCK_IOMUXC, 0x10F1U);
flexspi_config_t config;
FLEXSPI_GetDefaultConfig(&config);
config.ahbConfig.enableAHBPrefetch = true;
config.ahbConfig.enableAHBCachable = true;
// config.ahbConfig.enableAHBBufferable = true;
// config.ahbConfig.enableAHBWriteIpTxFifo = true;
// config.ahbConfig.enableAHBWriteIpRxFifo = true;
// config.ahbConfig.enableClearAHBBufferOpt = true;
config.rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackFromSckPad;
FLEXSPI_Init(APP_FLEXSPI, &config);
flexspi_device_config_t device_config =
{
.flexspiRootClk = (uint32_t)clock_manager.FlexSPIFrequency,
.isSck2Enabled = false,
.flashSize = APP_FLASH_SIZE_KB,
.CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle,
.CSInterval = 2,
.CSHoldTime = 2,
.CSSetupTime = 2,
.dataValidTime = 0,
.columnspace = 0,
.enableWordAddress = 0,
.AWRSeqIndex = 0,
.AWRSeqNumber = 0,
.ARDSeqIndex = NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD, // FIXME:
.ARDSeqNumber = 1,
.AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,
.AHBWriteWaitInterval = 0,
.enableWriteMask = false,
};
FLEXSPI_SetFlashConfig(APP_FLEXSPI, &device_config, kFLEXSPI_PortA1);
FLEXSPI_UpdateLUT(APP_FLEXSPI, 0, customLUT, CUSTOM_LUT_LENGTH);
IOMUXC_SetPinMux(SEMC_DA0_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA1_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA2_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA3_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA4_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA5_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA6_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA7_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA8_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA9_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA10_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA11_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA12_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA13_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA14_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_DA15_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_WE_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_OE_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_CS1_IOMUXC, 0U);
IOMUXC_SetPinMux(SEMC_ADV_IOMUXC, 0U);
//IOMUXC_SetPinConfig(SEMC_DA0_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA1_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA2_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA3_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA4_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA5_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA6_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA7_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA8_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA9_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA10_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA11_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA12_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA13_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA14_IOMUXC, 0x10B0U);
//IOMUXC_SetPinConfig(SEMC_DA15_IOMUXC, 0x10B0U);
IOMUXC_SetPinConfig(SEMC_WE_IOMUXC, 0xD0F1U);
IOMUXC_SetPinConfig(SEMC_OE_IOMUXC, 0xD0F1U);
IOMUXC_SetPinConfig(SEMC_CS1_IOMUXC, 0xD0F1U);
// IOMUXC_SetPinConfig(SEMC_ADV_IOMUXC, 0xD0F1U);
IOMUXC_SetPinMux(FPGA_RST_IOMUXC, 0U);
IOMUXC_SetPinConfig(FPGA_RST_IOMUXC, 0x10B0U);
//
gpio_pin_config_t gpio_config;
gpio_config.direction = kGPIO_DigitalOutput;
gpio_config.interruptMode = kGPIO_NoIntmode;
gpio_config.outputLogic = 0;
GPIO_PinInit(FPGA_RST_GPIO, FPGA_RST_PIN, &gpio_config);
// initialize SEMC
semc_config_t semc_config;
SEMC_GetDefaultConfig(&semc_config);
SEMC_Init(APP_SEMC, &semc_config);
semc_sram_config_t sram_config;
sram_config.cePinMux = kSEMC_MUXA8; /*!< The CE# pin mux setting. */
sram_config.addr27 = kSEMC_MORA27_NONE; /*!< The Addr bit 27 pin mux setting. */
sram_config.address = 0x80000000; /*!< The base address. */
sram_config.memsize_kbytes = 64; /*!< The memory size in unit of kbytes. */
sram_config.addrPortWidth = 16; /*!< The address port width. */
sram_config.advActivePolarity = kSEMC_AdvActiveLow; /*!< ADV# polarity 1: active high, 0: active low. */
sram_config.addrMode = kSEMC_AddrDataMux; /*!< Address mode. */
sram_config.burstLen = kSEMC_Nor_BurstLen1; /*!< Burst length. */
sram_config.portSize = kSEMC_PortSize16Bit; /*!< Port size. */
sram_config.tCeSetup_Ns = 2; /*!< The CE setup time. */
sram_config.tCeHold_Ns = 2; /*!< The CE hold time. */
sram_config.tCeInterval_Ns = 30; /*!< CE interval minimum time. */
sram_config.tAddrSetup_Ns = 25; /*!< The address setup time. */
sram_config.tAddrHold_Ns = 0; /*!< The address hold time. */
sram_config.tWeLow_Ns = 25; /*!< WE low time for async mode. */
sram_config.tWeHigh_Ns = 0; /*!< WE high time for async mode. */
sram_config.tReLow_Ns = 25; /*!< RE low time for async mode. */
sram_config.tReHigh_Ns = 0; /*!< RE high time for async mode. */
sram_config.tTurnAround_Ns = 2; /*!< Turnaround time for async mode. */
sram_config.tAddr2WriteHold_Ns = 0; /*!< Address to write data hold time for async mode. */
sram_config.tWriteSetup_Ns = 0;
sram_config.tWriteHold_Ns = 0;
sram_config.latencyCount = 0;
sram_config.readCycle = 0;
SEMC_ConfigureSRAM(APP_SEMC, &sram_config, clock_manager.SEMCFrequency);
APP_SEMC->SRAMCR1 = SEMC_SRAMCR1_CES(0) | // CE setup 1-16 cycles
SEMC_SRAMCR1_CEH(1) | // CE hold 1-16 cycles
SEMC_SRAMCR1_AS(5) | // address setup 1-16 cycles
SEMC_SRAMCR1_AH(1) | // address hold 1-16 cycles
SEMC_SRAMCR1_WEL(5) | // WE low 1-16 cycles
SEMC_SRAMCR1_WEH(0) | // WE high 1-16 cycles
SEMC_SRAMCR1_REL(5) | // RE low 1-16 cycles
SEMC_SRAMCR1_REH(0); // RE high 1-16 cycles
APP_SEMC->SRAMCR2 = SEMC_SRAMCR2_WDS(0) | // Write data setup 1-16 cycles
SEMC_SRAMCR2_WDH(0) | // Write data hold 1-16 cycles
SEMC_SRAMCR2_TA(1) | // Turnaround 1-16 cycles
SEMC_SRAMCR2_AWDH(3) | // addr to write data hold time 1-16 cycles
SEMC_SRAMCR2_CEITV(3); // CE interval time 1-16 cycles
Hi Yuzhou
one can check AN12146 Migrating from silicon Rev A0 to Rev A1
which suggests specific for A1 software changes
https://www.nxp.com/docs/en/nxp/application-notes/AN12146.pdf
Also one can try to debug it using jtag debugger.
Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Thanks, igorpadykov.
The cause is described in AN12146 page 3.
SEMC CCM: add bit filed to control semc_exsc clock, must be enabled always
FLEXSPI CCM: add bit filed to control flexspi_exsc clock, must be enabled always
The old SDK(version 2.3.0) initialize register CCM CCGR0 and CCM CCGR1 by
CCM->CCGR0 = 0x00C0000FU;
CCM->CCGR1 = 0x30000000U;
This is not correct in revision A1. The correct value should be
CCM->CCGR0 = 0x00C000CFU;
CCM->CCGR1 = 0x300C0000U;
Hi,
i tried your example and its running.
Now, i do some tests with different burstlength (1-64), put an oscilloscope on the CS and use the assembler
instructions
VLDM r1, {s16-s17}
VSTM r0, {s16-s17}
Burst does not work here! There are 4 CS raising when calling VLDM? I excpected 2 CS raising.
A change to burstlen has no effect.
Please can you tell me, what i should do to enable burst access on SRAM?
My FPGA do an autoincrement of the address, so after the first access it do not need any further address info-
Christian