How do I properly define a flexspi LUT entry?

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

How do I properly define a flexspi LUT entry?

2,382 Views
estacey
Contributor III

I've gotten along nicely with using the flexspi example project to help me use the flash chip on the RT1020 EVK board but now I need to erase a block instead of a sector so I'm forced to understand how the LUT is configured.  I couldn't find any clues in the spec for the on board flash chip or the driver.  Where do I find out how to create an LUT entry?  Any help would be appreciated.

Thank you!

Labels (1)
3 Replies

2,189 Views
estacey
Contributor III

Thank you so much for the quick response!  So the last parameter is meaningless?  The 0x18, 0x04, or 0 at the end of each command sequence does nothing?
Thanks again,

Ellen

0 Kudos

2,189 Views
mjbcswitzerland
Specialist V

Ellen

No, all parameters are necessary.

The 0x18 (using a more meaningful define ADDRESS_LENGTH_24BITS make is more clear) is telling the FlexSPI that it needs to sent 3 bytes (24 bit) to represent the address. Larger SPI types will use a value of 0x20 (ADDRESS_LENGTH_32BYTES) since 24 bits is not enough.

The 0 tells the FlexSPI that the sequence has reached its end, otherwise it may do random stuff.

Etc.

Regards

Mark

[uTasker project developer for Kinetis and i.MX RT]

2,189 Views
mjbcswitzerland
Specialist V

Ellen

In the example you will find the sector erase defined like this:

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

where the index is defined as

#define NOR_CMD_LUT_SEQ_IDX_READ_NORMAL 7
#define NOR_CMD_LUT_SEQ_IDX_READ_FAST 13
#define NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD 0
#define NOR_CMD_LUT_SEQ_IDX_READSTATUS 1
#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE 2
#define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR 3
#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE 6
#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD 4
#define NOR_CMD_LUT_SEQ_IDX_READID 8
#define NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG 9
#define NOR_CMD_LUT_SEQ_IDX_ENTERQPI 10
#define NOR_CMD_LUT_SEQ_IDX_EXITQPI 11
#define NOR_CMD_LUT_SEQ_IDX_READSTATUSREG 12
#define NOR_CMD_LUT_SEQ_IDX_ERASECHIP 5

which means that it will be inserted in the 3rd LUT location (which occupies 4 long words, but only max. 2 are used for your SPI Flash chip and the erase command only needs one of the 4 entries in its sequence).

The 0xd7 is the sector erase command for the SPI flash so if you were to change that to 0x52 instead it would do a half-block erase, or to 0xd8 it would do a 64k block erase instead.

Probably one would prefer to mix sector, half-clock and block erases so that the most suitable one can be used and thus expand the LUT (up to 16 entries can be defined), so - for example - adding

    /* Erase Sector  */
    [4 * NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xD8, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),

would add a block erase to the list. You will need to add a new define for NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK  and make sure that it doesn't collide with any of the existing ones (that is, it fits in an unused entry or replaces one that you don't need and remove). Then you could use the new command!

Note that the uTasker project has a more refined method and allows the SPI flash to be used as parameter system, FAT or uFileSystem (for a range of SPI Flash types) and it also allows the FlexSPI/QSPI Flash interface to be simulated in VisualStudio which ensures that any incorrect configuration or incorrect use is immediately identified without needing to debug in the HW - which makes learning and understanding the operation simpler.

static const FLEXSPI_LUT_ENTRY tableLUT_main[] = {                       // look-up table used during main operation

    {   // Erase sector - 4k
        NOR_CMD_LUT_SEQ_IDX_ERASESECTOR,
        {
        FLEXSPI_LUT_1PAD_SEQ_1(FLEXSPI_Command_SDR, SUB_SECTOR_ERASE) | FLEXSPI_LUT_1PAD_SEQ_2(FLEXSPI_Command_RADDR_SDR, ADDRESS_LENGTH_24BITS),
        0,
        },
    },
    {   // Erase half-block - 32k
        NOR_CMD_LUT_SEQ_IDX_ERASE_HALF_BLOCK,
        {
        FLEXSPI_LUT_1PAD_SEQ_1(FLEXSPI_Command_SDR, HALF_BLOCK_ERASE) | FLEXSPI_LUT_1PAD_SEQ_2(FLEXSPI_Command_RADDR_SDR, ADDRESS_LENGTH_24BITS),
        0,
        },
    },
    {   // Erase block - 64k
        NOR_CMD_LUT_SEQ_IDX_ERASE_BLOCK,
        {
        FLEXSPI_LUT_1PAD_SEQ_1(FLEXSPI_Command_SDR, BLOCK_ERASE) | FLEXSPI_LUT_1PAD_SEQ_2(FLEXSPI_Command_RADDR_SDR, ADDRESS_LENGTH_24BITS),
        0,
        },
    },

    {   // End of LUT
        NOR_CMD_LUT_SEQ_IDX_END_OF_TABLE,
        {
            0,0
        },
    },
};

Regards

Mark
[uTasker project developer for Kinetis and i.MX RT]

Experience a complete i.MX RT 1020 solution (rather than an example of a single operation) here

- https://www.utasker.com/iMX/RT1020.html