External FlexSPI initialization in bootloader for 1062

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

External FlexSPI initialization in bootloader for 1062

3,024 次查看
jose_au_zone
Contributor II

Hello! We have two custom boards: one for the 1064 and another one for the 1062

We have a bootloader that works for the 1064 and I'm trying to port it to the 1062 (booting from the external hyperflash, the one with the base address 0x60000000, so connected to the FLEXSPI2). The base for that bootloader (the one that works for the 1064, which boots from the internal QSPI flash with has the base address 0x7000000, so connected to FLEXSPI) came from the SDK_folder/middleware/mcu-boot/src

I've got it to boot, and I can see messages coming from the debug console, so far so good

The part where I'm stuck at is: the bootloader does some hardware tests and it is supposed to write a flag to a specific address in the hyperflash to verify that such tests were run (the address it writes to is above the image end address, so it is not overwriting the bootloader code itself). But the erase function for the hyperflash is always returning an error.

I was able to track down the error to the initialization of the hyperflash.

Here's where the first error happens:

 

 

status_t flexspi_nor_get_config(uint32_t instance, flexspi_nor_config_t *config, serial_nor_config_option_t *option)
{
    status_t status = g_bootloaderTree->flexSpiNorDriver->get_config(instance, config, option);

    if ((status == kStatus_Success) && option->option0.B.option_size)
    {
        // A workaround to support drive strength configuration using Flash APIs
        if (option->option1.B.drive_strength)
        {
            flexspi_update_padsetting(&config->memConfig, option->option1.B.drive_strength);
        }

        // A workaround to support parallel mode using Flash APIs
        if (option->option1.B.flash_connection == kSerialNorConnection_Parallel)
        {
            config->memConfig.controllerMiscOption |= FLEXSPI_BITMASK(kFlexSpiMiscOffset_ParallelEnable);
            config->pageSize *= 2;
            config->sectorSize *= 2;
            config->blockSize *= 2;
            config->memConfig.sflashB1Size = config->memConfig.sflashA1Size;
        }g_bootloaderTree->flexSpiNorDriver->get_config
    }

    return status;
}

 

 

The call to:
g_bootloaderTree->flexSpiNorDriver->get_config

Returns with the error code 0x4, which should be kStatus_InvalidArgument? (correct me if I'm wrong on this)
So, I am not sure that the input parameters, namely the instance and option are correct.

With the 1064 bootloader, the instance number that we used for the internal QSPI flash (connected to FLEXSPI) was 1. Which value should we use for the instance when using the external hyperflash, which uses FLEXSPI2? I've tried with 0, and board simply reboots after it calls the get_config command. I've also tried with 2, with such value the board doesn't reboot but returns the aforementioned 0x4 error.

Also, for the option parameter it gets initialized in this snippet:

 

    serial_nor_config_option_t option;
    option.option0.U = BL_FLEXSPI_NOR_CFG_OPT0;
    option.option1.U = BL_FLEXSPI_NOR_CFG_OPT1;

    if (option.option0.B.tag == kSerialNorCfgOption_Tag)
    {
        return flexspi_nor_mem_config((uint32_t *)&option);
    }

 

 

 

And the values for BL_FLEXSPI_NOR_CFG_OPT0 and BL_FLEXSPI_NOR_CFG_OPT1 are:

#define BL_FLEXSPI_NOR_CFG_OPT0 (0xc0000008u)
#define BL_FLEXSPI_NOR_CFG_OPT1 (0x0u)

I'm not sure those are the correct values. I would like to know how to properly configure them, or if there's something else that I'm missing to be able to properly initialize the hyperflash so it can be written

Thank you so much!

标签 (1)
标记 (1)
0 项奖励
回复
7 回复数

2,973 次查看
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
In my opinion, the root cause of the issue is ROM code fails to recognize the Hyperflash, which makes the get_config API fetch an inappropriate flexspi_nor_config_t struct.
In my opinion, I'd like to suggest you use the custom flexspi driver instead of the ROM API to operate the Hyperflash, and in the SDK library, it has provided the template of the flexspi driver.
Have a great day,
TIC

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

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 项奖励
回复

2,945 次查看
jose_au_zone
Contributor II

You mean the function defined in flexspi_nor_flash.c?

 

For example, the flexspi_nor_get_config function would be replaced by the code in flexspi_nor_flash.c?

And such code is:

status_t flexspi_nor_get_config(uint32_t instance, flexspi_nor_config_t *config, serial_nor_config_option_t *option)
{
    status_t status = kStatus_InvalidArgument;

    do
    {
        if ((config == NULL) || (option == NULL))
        {
            break;
        }

        // Configure the Configuration block to default value
        memset(config, 0, sizeof(flexspi_nor_config_t));
        config->memConfig.serialClkFreq = kFlexSpiSerialClk_SafeFreq;
        config->memConfig.sflashA1Size = MAX_24BIT_ADDRESSING_SIZE;
        config->memConfig.tag = FLEXSPI_CFG_BLK_TAG;
        config->memConfig.version = FLEXSPI_CFG_BLK_VERSION;
        config->memConfig.csHoldTime = 3;
        config->memConfig.csSetupTime = 3;
        config->ipcmdSerialClkFreq = kFlexSpiSerialClk_SafeFreq;

        if (option->option0.B.option_size > 0)
        {
            // Switch to second pinmux group
            if (option->option1.B.pinmux_group == 1)
            {
                config->memConfig.controllerMiscOption |= FLEXSPI_BITMASK(kFlexSpiMiscOffset_SecondPinMux);
            }

            // Change the Pad Drive Strength
            if (option->option1.B.drive_strength)
            {
                flexspi_update_padsetting(&config->memConfig, option->option1.B.drive_strength);
            }
            // Enable parallel mode support
            if (option->option1.B.flash_connection)
            {
                if ((option->option0.B.device_type == kSerialNorCfgOption_DeviceType_ReadSFDP_SDR) ||
                    (option->option0.B.device_type == kSerialNorCfgOption_DeviceType_ReadSFDP_DDR))
                {
                    uint32_t flashConnection = option->option1.B.flash_connection;

                    switch (flashConnection)
                    {
                        default:
                        case kSerialNorConnection_SinglePortA:
                            // This is default setting, do nothing here
                            break;
                        case kSerialNorConnection_Parallel:
                            config->memConfig.controllerMiscOption |=
                                FLEXSPI_BITMASK(kFlexSpiMiscOffset_ParallelEnable);
                            break;
                        case kSerialNorConnection_SinglePortB:
                            config->memConfig.sflashA1Size = 0;
                            config->memConfig.sflashB1Size = MAX_24BIT_ADDRESSING_SIZE;
                            break;
                    }
                }
                else
                {
                    option->option1.B.flash_connection = 0;
                }
            }
        }

        switch (option->option0.B.device_type)
        {
            case kSerialNorCfgOption_DeviceType_ReadSFDP_SDR:
            case kSerialNorCfgOption_DeviceType_ReadSFDP_DDR:
                status = flexspi_nor_generate_config_block_using_sfdp(instance, config, option);
                break;
#if FLEXSPI_ENABLE_OCTAL_FLASH_SUPPORT
            case kSerialNorCfgOption_DeviceType_HyperFLASH1V8:
                status = flexspi_nor_generate_config_block_hyperflash(instance, config, true);
                break;
            case kSerialNorCfgOption_DeviceType_HyperFLASH3V0:
                status = flexspi_nor_generate_config_block_hyperflash(instance, config, false);
                break;
            case kSerialNorCfgOption_DeviceType_MacronixOctalDDR:
            case kSerialNorCfgOption_DeviceType_MacronixOctalSDR:
                status = flexspi_nor_generate_config_block_mxic_octalflash(instance, config, option);
                break;
            case kSerialNorCfgOption_DeviceType_MicronOctalDDR:
            case kSerialNorCfgOption_DeviceType_MicronOctalSDR:
                status = flexspi_nor_generate_config_block_micron_octalflash(instance, config, option);
                break;
            case kSerialNorCfgOption_DeviceType_AdestoOctalDDR:
            case kSerialNorCfgOption_DeviceType_AdestoOctalSDR:
                status = flexspi_nor_generate_config_block_adesto_octalflash(instance, config, option);
                break;
#endif // FLEXSPI_ENABLE_OCTAL_FLASH_SUPPORT
            default:
                status = kStatus_InvalidArgument;
                break;
        }

        if (status == kStatus_Success)
        {
            flexspi_set_failsafe_setting(&config->memConfig);
            config->memConfig.serialClkFreq = option->option0.B.max_freq;

            if (option->option0.B.option_size && (option->option1.B.flash_connection == kSerialNorConnection_BothPorts))
            {
                config->memConfig.sflashB1Size = config->memConfig.sflashA1Size;
            }
        }
        config->memConfig.deviceType = kFlexSpiDeviceType_SerialNOR;

    } while (0);

    return status;
}

 

If you can confirm that, then at least I know which code to replace in all functions

Thanks!

0 项奖励
回复

2,941 次查看
jose_au_zone
Contributor II

Doing some more tests, I've found something strange

Replacing the ROM code with the code from the API led me to the stack trace in the attached picture.

What I found odd is: this code is executing directly from hyperflash (XIP).

Once the code calls the flexspi_clock_gate_disable(...) the bootloader just hangs. Which I think is expected, because the code is killing the clock that's feeding the hyperflash, which is where it is reading the instructions from.

So I wonder if this is the correct path. The code is already running from the hyperflash, it shouldn't need to reconfigure the clock. 

If I comment that clock reconfiguration part out, it will go into a hard fault at the next command which is flexspi_swreset(...)

So I'm not 100% sure this is the correct way of doing this. The hyperflash is already configured, it shouldn't need to do all those initializations again

0 项奖励
回复

2,918 次查看
jose_au_zone
Contributor II

Hi Jeremy. I guess the problem is that I can't have code to read/write/erase the hyperflash that's XPIing from the same hyperflash
I've got to a point where the code enters an infinite loop in the function flexspi_command_xfer

It never exits the loop that starts around line 1036 with this snippet:

 // Start Read
base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
while (xferRemainingSize > 0)


I would say that what's causing this hanging is the fact that the code is trying to read the hyperflash which it is executing from, this is causing some UB

So I posted this other question about how I can fix this here: https://community.nxp.com/t5/i-MX-RT/Place-specific-functions-on-RAM-memory-using-custom-linker/m-p/...
Looks like the solution is to place the relevant parts of the code into a RAM memory section

Could you advise if this is the best solution?

Thanks!

0 项奖励
回复

2,869 次查看
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
1) Could you advise if this is the best solution?
-- Yes, it's a good method to place the relevant parts of the code into a RAM memory section and its pro is unnecessary to modify the structure of the bootloader demo.
BTW, there's an evkmimxrt1060_flexspi_hyper_flash_polling_transfer demo in the SDK library and the demo demonstrates how to operate the Hyperflash.
Have a great day,
TIC

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

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 项奖励
回复

3,001 次查看
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
Before answering your question, I think I need more information, so I was wondering if you can share the schematic about connecting the Hyperflash to RT1062, in addition, I was wondering if you can upload the bootloader code for the RT1062's board.
Looking forward to your reply.
Have a great day,
TIC

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

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 项奖励
回复

2,986 次查看
jose_au_zone
Contributor II

Hi Jeremy, thanks for the quick response.

The part where the hardware test happens (actually it just tests the SDRAM on our custom board) is on the bl_main.c:726 loop, I commented that out to make it easier for you. The whole folder project is attached

I also attached a image with a piece of the schematics that shows to which 1062`s pads the hyperflash signals are attached to.

Looking forward to get more information from you, thanks!

 

0 项奖励
回复