PI Ziheng embedded: a small mistake about configuring normal read in flexspi peripheral lookuptable in i.mxrt

Time:2021-7-21

Hello everyone, I’m a ruffian Heng. I’m a serious technical ruffian. Today, ruffian Heng introduces to youi. A small mistake of configuring normal read in flexspi peripheral lookuptable in mxrt

As for serial four wire nor flash, when it is used as a boot (XIP) device, the most commonly configured read mode should be fast read Quad I / O SDR (0xeb). In this mode, all four I / O lines (io0-3) are used for data transmission, and the SCK can reach the highest frequency (usually 133MHz). In this read mode, the flash performance is quite high. But sometimes in some designs, in order to ensure universality (for example, we want a boothead compatible with all types of flash models), we will try to configure the most basic read mode normal read (0x03). The basic read mode only uses one I / O line (IO1) during data transmission, and the SCK frequency is usually up to 50MHz, In fact, this mode is more compatible with EEPROM devices with SPI interface.

Normal read is a read mode supported by any serial nor flash, and it is also the simplest mode. However, there is a small misunderstanding about dummy cycle setting when configuring this mode in flexspi peripherals of i.mxrt

1、 Enable normal read in fdcb

For more information about fdcb and lookuptable, please refer to PI Ziheng’s old articleUnderstanding the lookuptable in fdcb。 Now we try to prepare a fdcb head to enable normal read. Take Huabang w25q64jws-iq as an example, check its data manual and find the following normal read sequence diagram:

From the normal read sequence diagram, it can be seen that it only contains four subsequences: command sequence, address sequence, read data sequence and stop sequence. Compared with fast read Quad I / O SDR sequence, it has less mode sequence and dummy sequence. Therefore, the example fdcb is as follows. According to the test of I. mxrt1050-evkb board, this example fdcb can be used to start normally.

const flexspi_ nor_ config_ t qspiflash_ config = {

According to the articleAHB read access under flexspi peripherals of mxrt (no cache) by grasping flash signal waveformIn the second section, we test memcpy ((void *) 0x20200000, (void *) 0x60002400, 8) without cache; The sequence of statement execution in flash side is as follows (in order to capture flash signal, the SCK frequency is reduced to 30MHz in actual test)

2、 What’s the little mistake about dummy cycle?

In the lookuptable of configuring fast read Quad I / O SDR timing, we often fill in different cycle values in dummy subsequence according to different flash device characteristics. Now we are configuring the normal read sequence. Some people may keep the dummy subsequence, but set its parameter value to 0 (as shown in the following code). According to the literal understanding, this seems to be OK, but in flexspi peripherals, this is not OK. This is the misunderstanding about dummy cycle.

#include "fsl_ flexspi.h"

3、 What are the consequences of the mistake of setting dummy cycle to 0?

Use s in the second section_ customLUT_ What are the consequences of configuring flexspi LUTAHB read access under flexspi peripherals of mxrt (no cache) by grasping flash signal waveformThe second section of the hardware and software testing environment to grasp the sequence diagram. The following two functions can be driven by flexspi in SDK to update LUT. Because it is ramfunc code executed in XIP environment, there is no need to initialize flexspi module from scratch.

#include "fsl_flexspi.h"

/* Update LUT table. */
FLEXSPI_UpdateLUT(FLEXSPI, 0, s_customLUT_wrong, 4);

/* Do software reset. */
FLEXSPI_SoftwareReset(FLEXSPI);

Now let’s debug online under IAR to see the results_ customLUT_ After updating the LUT of flexspi, the access to flash is abnormal immediately. The values observed in the memory window are all changed to 0xff, and the corresponding address of the internal RAM of the copy destination is also all 0xff, which indicates that the memcpy statement does not produce the expected effect from the functional point of view (but the ramfunc code can be executed normally at this time).

Taking out the flash waveform, we find that memcpy with only 8 bytes of data actually generates a 33 ms read sequence (converted, that is, it actually reads about 128 KB of data). When we zoom in on the front sequence, we can see that the command (0x03), address (0x002400), initial read data (0x01, 0x02, 0x03…) are normal, and there is no dummy cycle subsequence, After comparing the binary file of the application program, it is found that 128KB effective flash data is read out in order, so there is no problem with the timing response of the flash terminal itself. However, there is a problem with the coordination between AHB bus and flexspi peripherals, which leads to the CPU unable to get the effective flash data. This is also the reason why the development environment memory window can no longer see the real flash data. As for why read 128KB data to stop, ruffian Heng also don’t know. If this memcpy statement is executed in the code loop, the flash side will also have a reading sequence of 33ms.

Appendix, mimxrt1050 under the complete flexspi initialization code

If the above abnormal normal read timing test is not carried out in the XIP environment, you need to initialize the flexspi peripherals completely. You can use the following flexspi_ nor_ flash_ Init() function:

#include "clock_config.h"
#include "fsl_flexspi.h"

flexspi_device_config_t s_deviceconfig = {
    .flexspiRootClk       = 30000000,
    .flashSize            = 0x2000,  /* 64Mb/KByte */
    .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_NORMAL,
    .ARDSeqNumber         = 1,
    .AHBWriteWaitUnit     = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,
    .AHBWriteWaitInterval = 0,
};

static inline void flexspi_clock_init(void)
{
    const clock_usb_pll_config_t g_ccmConfigUsbPll = {.loopDivider = 0U};

    CLOCK_InitUsb1Pll(&g_ccmConfigUsbPll);
    CLOCK_InitUsb1Pfd(kCLOCK_Pfd0, 35);   /* Set PLL3 PFD0 clock 247MHZ. */
    CLOCK_SetMux(kCLOCK_FlexspiMux, 0x3); /* Choose PLL3 PFD0 clock as flexspi source clock. */
    CLOCK_SetDiv(kCLOCK_FlexspiDiv, 7);   /* flexspi clock 30M. */
}

void flexspi_nor_flash_init(void)
{
    flexspi_clock_init();

    /* Get FLEXSPI default settings and configure the flexspi. */
    flexspi_config_t config;
    FLEXSPI_GetDefaultConfig(&config);

    /* Set AHB buffer size for reading data through AHB bus. */
    config.ahbConfig.enableAHBPrefetch    = false;
    config.ahbConfig.enableAHBBufferable  = true;
    config.ahbConfig.enableReadAddressOpt = true;
    config.ahbConfig.enableAHBCachable    = false;
    config.rxSampleClock                  = kFLEXSPI_ReadSampleClkLoopbackInternally;
    FLEXSPI_Init(FLEXSPI, &config);

    /* Configure flash settings according to serial flash feature. */
    FLEXSPI_SetFlashConfig(FLEXSPI, &s_deviceconfig, kFLEXSPI_PortA1);

    /* Update LUT table. */
    FLEXSPI_UpdateLUT(FLEXSPI, 0, s_customLUT_wrong, 4);

    /* Do software reset. */
    FLEXSPI_SoftwareReset(FLEXSPI);
}

So far, i.mxrt flexspi peripherals lookuptable configuration of normal read in a small mistake, ruffian scale will be introduced, where is the applause~~~

Welcome to subscribe

The article will be published to me at the same timeBlog Garden Home PageCSDN home pageZhihu HomepageWeChat official accountOn the platform.

Wechat search“Ruffian scale embedded“Or scan the following QR code, you can see it on your mobile phone for the first time.