Hello, we have a custom board using an iMXRT1170 (model i.MX RT1172) with an external QSPI flash memory. We want to run our program from it, using XIP and boot mode "10" (external boot). The QSPI connection is made using the pins GPIO_SD_B1_[00:05]. These pins belong to the FlexSPI2, secondary pin group, port A, as shown in the next image:
Hello @jingpan, I am Antonio's coworker.
We now are able to write and read from the flash. We had to change the readSampleClkSrc option in the flash driver's memory configuration to the internal loopback:
flashConfig.memConfig.readSampleClksrc=kFlexSPIReadSampleClk_LoopbackInternally;
By default this option is set to kFlexSPIReadSampleClk_LoopbackFromDqsPad, but with our pin configuration (FlexSPI2, secondary pin group) there is no DQS pin available.
Now we are trying to boot from the flash.
We see that the Boot ROM tries to access the memory at boot time, but we don't know if it can read the 512-byte FlexSPI NOR configuration parameters. ¿Do you know if there is a similar configuration that needs to be done to the fuses regarding the FlexSPI read clock so the Boot ROM can read the configuration block, or is it this not necessary?
Thank you. Regards,
José Andrés
Hi @jagarcia,
Yes, it can. When boot up, RT1172 will use 30Mhz clock and single wire mode to read flash. So, if your BOOT_CFG pin set correct, it can read out configuration from any flash.
You also can use eFuse to set boot config. Please refer to table 10-10 in RM.
Regards,
Jing
Hello @jingpan, we still are not able to boot from the flash memory.
The memory we are using is the W25Q32JV (QSPI), connected to FlexSPI2, secondary pin group.
What we have done untill now is:
- Burn this eFuse configuration in the device:
BT_FUSE_SEL=1
FLEXSPI_INSTANCE=1
FLEXSPI_PIN_GROUP_SEL=1
FLASH_CONNECTION_SEL=0
- Build a flash driver with the next configuration:
CONFIG_OPTION0 0xC1000003
CONFIG_OPTION1 0x00010000
Added the next line before flexspi_nor_flash_init in the driver:
flashConfig.memConfig.readSampleClksrc=kFlexSPIReadSampleClk_LoopbackInternally
With this we can program the memory, but cannot start a debug session.
- Added the FlexSPI configuration parameters to our project:
We have the next XIP options in our preprocessor settings:
XIP_EXTERNAL_FLASH=1
XIP_BOOT_HEADER_ENABLE=1
XIP_BOOT_HEADER_DCD_ENABLE=0
Also, we have added the next files to the project:
evkmimxrt1170_flexspi_nor_config.c
evkmimxrt1170_flexspi_nor_config.h
fsl_flexspi_nor_boot.c
fsl_flexspi_nor_boot.h
In the first file we have modified the qspiflash_config structure to fit our memory:
const flexspi_nor_config_t qspiflash_config = {
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClksrc=kFlexSPIReadSampleClk_LoopbackInternally,
.csHoldTime = 3u,
.csSetupTime = 3u,
.columnAddressWidth = 0,
.deviceModeCfgEnable = 0, // Para HyprRAM
.deviceModeType = 1, //Quad enable
.waitTimeCfgCommands = 0,
.controllerMiscOption = 0x100,
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_60MHz,
.lutCustomSeqEnable = 0u,
.sflashA1Size = 4u * 1024u * 1024u,
.lookupTable =
{
// Read LUTs
[0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
[1] = FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04),
// Read Status LUTs
[4 * 1 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05, READ_SDR, FLEXSPI_1PAD, 0x04),
// Write Enable LUTs
[4 * 3 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06, STOP, FLEXSPI_1PAD, 0x0),
// Erase Sector LUTs
[4 * 5 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20, RADDR_SDR, FLEXSPI_1PAD, 0x18),
// Erase Block LUTs
[4 * 8 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD8, RADDR_SDR, FLEXSPI_1PAD, 0x18),
// Pape Program LUTs
[4 * 9 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x32, RADDR_SDR, FLEXSPI_1PAD, 0x18),
[4 * 9 + 1] = FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_4PAD, 0x04, STOP, FLEXSPI_1PAD, 0x0),
// Erase Chip LUTs
[4 * 11 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xC7, STOP, FLEXSPI_1PAD, 0x0),
},
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.ipcmdSerialClkFreq = 0x3, //60 MHz
.blockSize = 64u * 1024u,
.isUniformBlockSize = false,
};
We can see that this structure is present in the compiled file, in the correct location (offset 0x400):
But we still are not able to make the microcontroller start our program, or to start a debug session.
Do you know what we could be missing? Could you give us any pointers to the right direction?
Thank you very much.
Cheers,
José Andrés
Hi @jagarcia ,
Please refer to this article.
https://community.nxp.com/t5/i-MX-RT-Knowledge-Base/i-MX-RT-FLEXSPI-booting-guide/ta-p/1669262
Regards,
Jing
Hello @jingpan, we still cannot boot from the flash or start a debug session. I see that the FlexSPI communication starts at 30MHz, but then changes to ~100MHz. I'm trying to burn the xSPI_FLASH_FREQ efuse (table 26-2 of the RM) to limit the frequency to 60MHz. I'm using the OCOTP peripheral, but I don't see this efuse location in the OTP Memory Footprint (Figure 27-2 of the RM).
Is there a way to burn this efuse without changing the boot mode signals in our PCB? We have them set to internal boot mode, so we can't use the MCUBootUtility.
Thank you very much.
Regards,
José Andrés
Hi @jagarcia ,
It's not a good idea to fix the chip to internal boot mode by hardware in project development stage. Let it boot up flexible could avoid many inconvenient problem.
Since you have burned BOOT_CFG fuse by a multilink, burn 0xc80 is same. Figure 27-2 is shadow register, not efuse. It's value is get from efuse when boot up. For example, 0x14 BOOT_CFG1 is read from efuse 0x940, 0x48 BOOT_CFG_MISC1 is read from 0xc80.
But I think you needn't burn this fuse currently. If it work correctly, boot ROM will read frequency data from FCB and set to flexspi. So, flexspi will not run at 100M.
I'm not clear about your situation. It seems you still can't use multilink to download code to flash, isn't it?
Regards,
Jing
Hi @jingpan, we burned the other efuses with PEMicro´s Cyclone, but the efuse xSPI_FLASH_FREQ does not appear and can't be burned with their utility. I have opened also a ticket with them in this regard.
I have the frequency defined in the FCB as 60MHz, but the SPI clock signal runs first at 30MHz and then at 100MHz, as we observe in the oscilloscope. You can see the FCB in hexadecimal in the image upper in this thread. The byte for the serialClkFreq option is set to 0x03, which is the value corresponding to kFlexSpiSerialClk_60MHz. It appears then that the FCB is not being read correctly during the startup.
We can program the flash with the flash driver, but the MCU won't boot. In order to make the flash driver work we had to add this option, as with our pin configuration we don't have a DQS pad:
readSampleClksrc=kFlexSPIReadSampleClk_LoopbackInternally.
Do you know if there is a similar configuration that can be done to the ROM API, and we may be missing it?
Thank you. Regards,
José Andrés
Hi @jagarcia ,
Did you always use multilink to download? Have you tried MCUBootutility or SPT to download application? The difference is MCUBootutility or SPT will program the QE bit in W25Q32. So, please use SPT to download an application, like led_blinky for example. Note that fexspi2 start address is 0x60000000. You must modify the project settings.
readSampleClksrc=kFlexSPIReadSampleClk_LoopbackInternally is correct.
Regards,
Jing
Hello @jingpan ,
Yes we have tried MCUBootUtility. Also, we tried building our flash driver with the option to set the QE bit of the second status register of the memory. Anyway, this is not needed, as per our memory datasheet this bit is already enabled from factory with our part number. We also confirmed the memory operation by modifying one of our prototype boards to connect the memory to FlexSPI1, port A, primary pin group. In this case the board performs correctly, but we still are not able to make it work when the memory is connected to our chosen pinout: FlexSPI2, secondary pin group.
We also update the Flash location in the project configuration accordingly: 0x60000000 for the FlexSPI2 and 0x30000000 for the board we are using to test the memory connected to FlexSPI1
This is our project status at this time:
1. The USB1 PHY is powered correctly, in case this matters.
2. We can program the flash memory, but the debugger is not able to start the debug session and neither the ROM bootloader is able to boot from there.
3. Our application is just a simple LED blink, with no other peripherals usage than GPIO and typical boot routines. When we run this application from RAM it works fine. It also works when we run it from the same flash chip connected to the FlexSPI1-primary-A (more info about this test given below).
4. We can see the QSPI lines, but we do not have the necessary equipment to make a full capture of the boot process. We can see that the clock starts at 30MHz and then goes to 100MHz, when it should be limited to 60MHz according to the FCB configuration.
Important fact: we have modified one board by removing some components and soldering the flash memory to the FlexSPI1-primary-A pins. On this board the same application runs from flash, we can program and debug it correctly. Be aware that this configuration uses the same hardware, the same power signals and the same FCB configuration, it just changes the FlexSPI pins. This is the reason why we think that the problem is not related to points 1, 2 or 3. It seems that the ROM bootloader is not capable of reading the FCB over the FlexSPI2.
More info: on the oscilloscope we see that the FlexSPI2 clock boots at 30MHz for a while and then goes to 100MHz. In one of the boards we have burned the xSPI_FLASH_FREQ eFuse to value 0x6 (thinking that there was a problem with the 100 MHz clock). With this change the FlexSPI2 now goes from 30 MHz to 60 MHz (so the limit of the eFuse is working), but the application still does not work.
Regards,
José Andrés.
Hi @jagarcia ,
You told me the QSPI flash part number is w25q32jv, it seems not a QE=1 part.
You can use MCUBootUtility to download code to flexspi2 flash and read back data is correct, isn't it? Can you share your binary image?
What's the status of GPIO_DISP_B1_06 when boot up and BOOT_CFG1[0] efuse?
Regards,
Jing
Hello @jingpan.
Sorry, the complete part name for the memory is 25Q32QJVIQ.
We cannot use the MCUBootUtility to write/read from the flash. The utility connects succesfully via the UART but we get an error when trying to write/read from the flash. The only way that we have been able to program the flash is with the customized driver in the MCUXpresso IDE.
The GPIO_DISP_B1_06 is free floating when booting up. We burnt the BT_FUSE_SEL efuse, so the BOOT_CFG1[0] value is read from the efuses. We burnt this efuse to see if it helped, so we have the FLASH_AUTO_PROBE_EN to 1. We did not observe any diference after setting this.
Regards,
José Andrés
Hi @jagarcia ,
You have the FLASH_AUTO_PROBE_EN to 1, this is why the system always set clock to 100M unless xSPI_FLASH_Frequency is burned to 60M. This bit has priority over FCB configuration.
But MCUBootUtility/SPT is very very important. It needn't eFuse help. If MCUBootUtility fail, we even not sure if the borad is fine. SPT/MCUBootUtility is the best starting point for flash configuration. Does your board has USB? It is more stable than UART.
If you have other efuse bit burned, please tell me.
Regards,
Jing