FlexSpi NOR and NAND Flash Configuration

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

FlexSpi NOR and NAND Flash Configuration

3,200 Views
pb2
Contributor II

Hello,

we are using a NOR flash on Port A1 and a NAND flash on Port B1. This configuration works when the project is downloaded via LPC-Link2 debugger. Our problem occurs without the debugger after power on. The FLEXSPI_TransferBlocking function doesn't exchange any data with the NAND flash. There is no clock and no chip select during FLEXSPI_TransferBlocking function call.

Why does the communication with the NAND flash works druing debugging and why does it fails after power on?

The MCUXpresso IDE is used for this project.

- flash configuration:

flexspi_device_config_t NORFlashConfig = {
    .flexspiRootClk = 96000000,
    .flashSize = NOR_FLASH_SIZE,
    .CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle,
    .CSInterval     = 2,
    .CSHoldTime     = 3,
    .CSSetupTime     = 3,
    .dataValidTime     = 0,
    .columnspace     = 0,
    .enableWordAddress = 0,
    .AWRSeqIndex     = 0,
    .AWRSeqNumber     = 0,
    .ARDSeqIndex     = NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD,
    .ARDSeqNumber     = 1,
    .AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,
    .AHBWriteWaitInterval = 0,
};

flexspi_device_config_t NANDFlashConfig = {
    .flexspiRootClk     = 96000000,
    .isSck2Enabled         = false,
    .flashSize             = NAND_FLASH_SIZE,
    .CSIntervalUnit     = kFLEXSPI_CsIntervalUnit1SckCycle,
    .CSInterval         = 2,
    .CSHoldTime         = 3,
    .CSSetupTime         = 3,
    .columnspace         = 0,
    .enableWordAddress     = false,
    .dataValidTime         = 0,
    .AWRSeqIndex         = 0,
    .AWRSeqNumber         = 0,
    .ARDSeqIndex         = 0,
    .ARDSeqNumber         = 0,
    .AHBWriteWaitUnit     = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,
    .AHBWriteWaitInterval = 0,
    .enableWriteMask     = false,
};

- clock settings:

    CLOCK_InitUsb1Pll(&g_ccmConfigUsbPll);
    CLOCK_InitUsb1Pfd(kCLOCK_Pfd0, 30);   /* Set PLL3 PFD0 clock 288MHZ. */
    CLOCK_SetMux(kCLOCK_FlexspiMux, 0x3); /* Choose PLL3 PFD0 clock as flexspi source clock. */
    CLOCK_SetDiv(kCLOCK_FlexspiDiv, 2);   /* kCLOCK_Pfd0, 30 -> flexspi clock 96M. */

- FLEXSPI settings and configuration:

void flexspi_set_config(flexspi_config_t *config)
{
    memset(config, 0, sizeof(*config));

//    config->rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackInternally;
    config->enableSckFreeRunning = false;
    config->enableCombination = false;
//    config->enableDoze = true;
    config->enableHalfSpeedAccess = false;
    config->enableSckBDiffOpt = false;
    config->enableSameConfigForAll = false;
    config->seqTimeoutCycle = 0xFFFFU;
    config->ipGrantTimeoutCycle = 0xFFU;
//    config->txWatermark = 8;
//    config->rxWatermark = 8;
    config->ahbConfig.enableAHBWriteIpTxFifo = false;
    config->ahbConfig.enableAHBWriteIpRxFifo = false;
    config->ahbConfig.ahbGrantTimeoutCycle = 0xFFU;
    config->ahbConfig.ahbBusTimeoutCycle = 0xFFFFU;
    config->ahbConfig.resumeWaitCycle = 0x20U;
    memset(config->ahbConfig.buffer, 0, sizeof(config->ahbConfig.buffer));
    for (uint8_t i = 0; i < FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT; i++)
    {
        config->ahbConfig.buffer[i].bufferSize = 256; /* Default buffer size 256 bytes*/
    }
    config->ahbConfig.enableClearAHBBufferOpt = false;
//    config->ahbConfig.enableReadAddressOpt = false;
//    config->ahbConfig.enableAHBPrefetch = false;
    config->ahbConfig.enableAHBBufferable = false;
    config->ahbConfig.enableAHBCachable = false;


    config->enableDoze = false;
    config->ahbConfig.enableClearAHBBufferOpt     = true;
    config->ahbConfig.enableAHBPrefetch         = true;
    config->rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackFromDqsPad;
    config->txWatermark = 128;
    config->rxWatermark = 128;
}

void flexspi_flash_init(FLEXSPI_Type *base)
{
    flexspi_config_t config;
    
    int_Disable();

    flexspi_flash_clock_init();

    flexspi_set_config(&config);
    FLEXSPI_Init(FLEXSPI, &config);

    FLEXSPI_SetFlashConfig(FLEXSPI, &NORFlashConfig, kFLEXSPI_PortA1);    
    FLEXSPI_SetFlashConfig(FLEXSPI, &NANDFlashConfig, kFLEXSPI_PortB1);

    FLEXSPI_Enable(FLEXSPI, true);

    FLEXSPI_UpdateLUT(base, 0, customLUT, sizeof(customLUT)/4);

    FLEXSPI_SoftwareReset(FLEXSPI);

    int_Enable();

    flexspi_nand_flash_wait_bus_busy(); // <- function can not read status register from NAND flash after power on
}

Labels (1)
3 Replies

2,911 Views
Sabina_Bruce
NXP Employee
NXP Employee

Hello Patrick,

Hope you are doing well.

Are you using a custom board or an evaluation board?

Also could you please confirm where your code is downloaded to?External Memory or SD Card?

Best Regards,

Sabina

-----------------------------------------------------------------------------------------------------------------------

Note: If this post answers your question, please click the Correct Answer button. Thank you!

----------------------------------------------------------------------------------------------------------------------- 

0 Kudos

2,911 Views
pb2
Contributor II

Hello Sabina,

thank you for your reply and i hope you are also doing well.

It seems to me the problem is a wrong configered LUT. I changed the entries in the LUT and also the according defines and the project works with and without debugger currently. I have parts of the previous and currently used LUT appended below.

to your questions:
We are using a custom board. The NOR flash stores our bootloader and firmware. Both, the bootloader and the firmware, are separate MCUXpresso projects. The NAND flash stores images currently.

main project components currently used:
NOR flash         0x6000 0000 - 0x6200 0000    size 0x0200 0000    32 Mb  (IS25LP256D)        flexspi port A1
NAND flash         0x6200 0000 - 0x6A00 0000    size 0x0800 0000    128 Mb (W25N01GVZEIGIT) flexspi port B1 (currently)

Which LUT entries are used, required for execute in place (XIP)? Exists there a specific LUT order for XIP equivalent to system boot? Do I have to use a kFLEXSPI_Command_STOP for each sequence?

Kind regards,
Patrick

previous used defines and LUT:

#define NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD         0
#define NAND_LUT_WRITE_ENABLE                                         1
#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE                 2
#define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR               3
#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD  4
#define NAND_LUT_ERASE_128KB                                            5

#define NAND_LUT_FAST_READ_QUAD_OUTPUT                   6
#define NAND_LUT_QUAD_LOAD_PROGRAM_DATA               7
#define NAND_LUT_DEVICE_RESET                                         8
#define NAND_LUT_PROGRAM_EXECUTE                               9

#define NAND_LUT_READ_DATA                                               10
#define NAND_LUT_PAGE_DATA_READ                                   11
#define NOR_CMD_LUT_SEQ_IDX_READSTATUSREG          12

#define NAND_LUT_WRITE_STATUS_REG                              13
#define NAND_LUT_READ_STATUS_REG                                14

const uint32_t customLUT[] = {
[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xEB,
                                                                            kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_4PAD, 0x18),
[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_4PAD, 0x06,
                                                                            kFLEXSPI_Command_READ_SDR,     kFLEXSPI_4PAD, 0x04),

[4 * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x06,
                                                                            kFLEXSPI_Command_STOP,         kFLEXSPI_1PAD, 0),

[4 * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xD7,
                                                                            kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),

[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x32,
                                                                            kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD, 0x04,
                                                                            kFLEXSPI_Command_STOP,         kFLEXSPI_1PAD, 0x00),

[4 * NOR_CMD_LUT_SEQ_IDX_READSTATUSREG] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x05,
                                                                            kFLEXSPI_Command_READ_SDR,     kFLEXSPI_1PAD, 0x04),

.....

currently used defines and LUT:

#define NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD         0
#define NOR_CMD_LUT_SEQ_IDX_READSTATUSREG           1
#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE                 2
#define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR               3
#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD  4

#define NAND_LUT_PAGE_DATA_READ                                    5
#define NAND_LUT_FAST_READ_QUAD_OUTPUT                  6
#define NAND_LUT_READ_DATA                                                7
#define NAND_LUT_READ_STATUS_REG                                 8

#define NAND_LUT_WRITE_ENABLE                                         9
#define NAND_LUT_QUAD_LOAD_PROGRAM_DATA              10
#define NAND_LUT_PROGRAM_EXECUTE                              11
#define NAND_LUT_WRITE_STATUS_REG                              12

#define NAND_LUT_DEVICE_RESET                                        13
#define NAND_LUT_ERASE_128KB                                           14

const uint32_t customLUT[] = {
[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xEB,
                                                                            kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_4PAD, 0x18),
[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_4PAD, 0x06,
                                                                            kFLEXSPI_Command_READ_SDR, kFLEXSPI_4PAD, 0x04),

[4 * NOR_CMD_LUT_SEQ_IDX_READSTATUSREG] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x05,
                                                                            kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

[4 * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x06,
                                                                            kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

[4 * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xD7,
                                                                            kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),

[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x32,
                                                                            kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD, 0x04,
                                                                            kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),

....

2,911 Views
Sabina_Bruce
NXP Employee
NXP Employee

Hello Patrick,

Hope you are doing well.

To answer your questions:

1. Which LUT entries are used, required for execute in place (XIP)?

The ROM will copy the read entry from the LUT portion of the FCB into the FlexSPI controller's LUT. So on a normal boot you should only see a read command used for executing in place copied into the FlexSPI LUT (command 0 by default). It is important that the read command is left untouched as this is what is used to read code uses AHB bus accesses. If you need to add additional commands into the LUT, then you need to use code executing from the RAM to update the LUT. To update the LUT you will temporarily corrupt the XIP process, so you need to make sure there are no FlexSPI accesses happening while the controller is being reconfigured. After the reconfiguration is complete, then you can re-enable the FlexSPI (clear MCR0[MDIS]) and jump back to executing in place.

2. Exists there a specific LUT order for XIP equivalent to system boot? 

I am not understanding your question completely. However, I believe that it may clarify the boot operation in section 9.6.1.2 and 9.6.1.3 of the reference manual. 

3. Do I have to use a kFLEXSPI_Command_STOP for each sequence?

For the command sequences please refer to chapter 27. Here you will find the sequence of each command. In addition, in the reference example you will find that not all have the Stop Command. You will see that some sequences end in 0, this is to tell it that the sequence has finished. 

Best Regards,

Sabina

-----------------------------------------------------------------------------------------------------------------------

Note: If this post answers your question, please click the Correct Answer button. Thank you!

-----------------------------------------------------------------------------------------------------------------------