IMXRT1176 construct of FLEXSPI LUT entry

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

IMXRT1176 construct of FLEXSPI LUT entry

Jump to solution
717 Views
burhanhagi
Contributor III

I am constructing LUT for W25Q128 QSPI Flash on my board. It is connected on FLEXSPI2 controller. I am trying to understand SDK example named "flexspi_nor_polling_transfer" on this purpose. I have several questions on that;

1- My first question, According to the reference manual IMXRT1170, one LUT is made up of 16 Sequences. Each sequence (total 16bytes) is made up of 8 instructions and each instruction is made up of 16bits (2 bytes). Here is the picture from ref manual;

burhanhagi_0-1711633247682.png

Actually, "Sequence" means one entry in LUT. In other words, it is total action when sending any command to the connected Flash, such as all actions in one Read Status Register command or Erase Sector command. 

ın SDK example, there is a constructor of  FLEXSPI_LUT_SEQ as follows;

#define FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \

(FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) | \

FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1))

 

So actually above define FLEXSPI_LUT_SEQ constructs 2 instructions with 4 bytes length. (produces uint32_t). Now in custom LUT[CUSTOM_LUT_LENGTH] array, there is an entry for "Page Program (Quad)" sequence as below;

/* Page Program - single mode */

#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE    4

[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x02, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),

[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE + 1] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

 

Actually, I am totally confused on above. Why we seperate single pageprogram sequence LUT Entry as 2 different entries? I mean in "one sequence", I can construct 8 instructions with each of 2 bytes. Then why we add one more extra entry as [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE + 1] ? Is not it possible to define above as below;

[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x02, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

So I can use entry 5 for the other sequence such as 

#define NOR_CMD_LUT_SEQ_IDX_ERASECHIP 5

[4 * NOR_CMD_LUT_SEQ_IDX_ERASECHIP ] = ....

2- Second question is; In SDK example some of LUT entries includes meaningless 0x04 number. See the below in red colour;

/* Read extend parameters */

[4 * NOR_CMD_LUT_SEQ_IDX_READSTATUS] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x81, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

or 

/* Enable Quad mode */

[4 * NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x01, kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04),

What is the meaning of that ? I saw one of the blogs it means "byte number". However for example, in above "writestatusregister" sequence, I am reading only 1 byte from QSPI chip. Then why I am defining it =0x04 instead of 0x01?

3- My last question is; Ref manual says that,

burhanhagi_0-1711636127300.png

So in example SDK, I see that some LUT entries has not STOP command. 

burhanhagi_1-1711636341966.png

 

In above, STOP command was put there only if the define of

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x06, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0) has only one instruction.

However, such as in below entry, it has 2 instructions. But it has no kFLEXSPI_Command_STOP as in the above.

[4 * NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x01, kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04),

 

Actually what I am trying to explain s that in one entry (Sequence) Can I write 

[4 * NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG] = 

FLEXSPI_LUT_SEQ(..., ..., ..., ..., ..., ...),  // 2instruction

FLEXSPI_LUT_SEQ(..., ..., ..., ..., ..., ...),  // 2instruction

FLEXSPI_LUT_SEQ(..., ..., ..., ..., ..., ...),  // 2instruction

FLEXSPI_LUT_SEQ(..., ..., ..., ..., ..., ...),  // 2instruction

If correct, then all LUT entries have missing STOP command.

 

Thanks in advance.

 

Labels (3)
0 Kudos
1 Solution
547 Views
HangZhang
NXP Employee
NXP Employee

Hi @burhanhagi 

In fact, the parameter of kFLEXSPI_Command_READ_SDR is 0x4, but it is meaningless. The reading length is configured in flashXfer.dataSize.

Hope this will help you.

BR

Hang

View solution in original post

8 Replies
633 Views
HangZhang
NXP Employee
NXP Employee

Hi @burhanhagi 

1.Each instruction is made up of 16bits (2 bytes).

#define FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) | FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1))

So One FLEXSPI_LUT_SEQ includes two instructions(32 bits).
#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE 4
And const uint32_t customLUT[CUSTOM_LUT_LENGTH] = {
[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x02, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),

[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE + 1] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
};

The type of array elements is uint32_t, [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE] represents the 16th element of the array. This element can be up to 32 bits, so it can only contain two instructions.
and [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE +1 ] represents the 17th element of the array.

2./* Read extend parameters */

[4 * NOR_CMD_LUT_SEQ_IDX_READSTATUS] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x81, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

or

/* Enable Quad mode */

[4 * NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x01, kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04),
0x1 and 0x4 represents the command sent to flash. Different numbers represent different commands.
It does not mean byte number.

status_t flexspi_nor_flash_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src, uint32_t length)
{
status_t status;
flexspi_transfer_t flashXfer;

/* Write enable */
status = flexspi_nor_write_enable(base, dstAddr);

if (status != kStatus_Success)
{
return status;
}

/* Prepare page program command */
flashXfer.deviceAddress = dstAddr;
flashXfer.port = FLASH_PORT;
flashXfer.cmdType = kFLEXSPI_Write;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD;
flashXfer.data = (uint32_t *)src;
flashXfer.dataSize = length;
status = FLEXSPI_TransferBlocking(base, &flashXfer);

if (status != kStatus_Success)
{
return status;
}

status = flexspi_nor_wait_bus_busy(base);

return status;
}
flashXfer.dataSize = length;
the flashXfer.dataSize means transfer byte number.
3.[4 * NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG] =

FLEXSPI_LUT_SEQ(..., ..., ..., ..., ..., ...), // 2instruction

FLEXSPI_LUT_SEQ(..., ..., ..., ..., ..., ...), // 2instruction

FLEXSPI_LUT_SEQ(..., ..., ..., ..., ..., ...), // 2instruction

FLEXSPI_LUT_SEQ(..., ..., ..., ..., ..., ...), // 2instruction
You can't do that, for the reason I explained in the first item.

Hope this will help you.

BR

Hang

0 Kudos
695 Views
Masmiseim
Senior Contributor I

Hello @burhanhagi 

You can find a LUT example for Winbond flashes here: https://github.com/Masmiseim36/iMXRT/blob/master/targets/iMXRT/Loader2/FlexSPI_Winbond.h

Maybe this will help you understand.

Regarding question three: Filling the instructions with zeros is an implicit stop-command.

Regards

624 Views
burhanhagi
Contributor III

Thank you @Masmiseim . I reviewed your supplied link. That is what I am thinking that it must be for a single sequence in LUT Table. Actually, after looking your code with filling 0 means implicit STOP command, I realized that in SDK example, it is correct; 

[4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL] = ....

[4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL + 1] = ...

The above lines 2 entities of one single sequence. The other 2

[4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL + 2] = ... and [4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL + 3] = ...  is also set with "0" while initializing.

So there must be total 4 x sizeof(uint32_t) gaps between each sequence. So example satisfies it.

Every section in any command is very clear when together looking with Flash DAHATSHEET (Single/Quad/Octal) except that;

Both in your code & example code in SDK, I see the 

Such as; in SDK---

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x9F, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

What is the meaning of 0x04 there? Or else

in Github you supplied such as FlexSPI_MAcronix.h,

for "Page Program" Command

FLEXSPI_LUT_SEQ (kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x02, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 24),
FLEXSPI_LUT_SEQ (kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 128, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

 

However in FlexSPI_Winbond.h the same command for "Page "Program" is as

FLEXSPI_LUT_SEQ (kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x32, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 24),
FLEXSPI_LUT_SEQ (kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD, 255, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

 

One of them is 255 but the other is 128 following kFLEXSPI_Command_WRITE_SDR opcode?

 

@HangZhang Is there any link/document what is the meaning of those operands in different commands?

 

 

0 Kudos
578 Views
Masmiseim
Senior Contributor I

As far as I have understood it. The number in the LUT after a write / read command is just a placeholder. The amount of data to be transferred is set via FLEXSPI_IPCR1_IDATSZ

 

Regards

595 Views
HangZhang
NXP Employee
NXP Employee

Hi @burhanhagi 

The operands for different devices are different. So please search for the Reference manual of the device you need.

BR

Hang

0 Kudos
581 Views
burhanhagi
Contributor III

@HangZhang   Eval Board uses IS25WP128-JBLE Flash. 

I am using W25Q128JVSIM Flash. Both of them includes "0x04" as I specified.

Yes I am aware of that every device has different operands. Also, I have understanding for each field while constructing  FLEXSPI_LUT_SEQ() except that 0x04?

In Flash datasheet, there is not any meaningful section explaining 0x04. So what is its meaning there?

Thanks a lot

 

0 Kudos
548 Views
HangZhang
NXP Employee
NXP Employee

Hi @burhanhagi 

In fact, the parameter of kFLEXSPI_Command_READ_SDR is 0x4, but it is meaningless. The reading length is configured in flashXfer.dataSize.

Hope this will help you.

BR

Hang

101 Views
jrreinhart
Contributor I

Hi Hang,

Can you please confirm this statement: The operand for the following commands is meaningless:

  • kFLEXSPI_Command_READ_SDR
  • kFLEXSPI_Command_READ_DDR
  • kFLEXSPI_Command_WRITE_SDR
  • kFLEXSPI_Command_WRITE_DDR

In other words, all of the following lines are equivalent:

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x0),
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x08, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x0),
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0xFF, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x0),

 

I'm using RT595, but I assume this applies to all FLEXSPI blocks.

In the SDK and examples, I've found operands of 0x00, 0x04, 0x08, and even 0xFF. It's very confusing that all of these different values exist if they don't actually mean anything.

0 Kudos