FlexSPI for non-Flash peripheral access?

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

FlexSPI for non-Flash peripheral access?

4,301 次查看
anthony_asterisk
Contributor II

With iMXRT106x FlexSPI is it possible to use IP command port to perform basic SPI transceive operations at 50MHz and above?  This would not be for flash chip access.  

I have been using LPSPI but have been informed the maximum clock rate is 30MHz, and this project requires 54 MHz.

 

 

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

4,235 次查看
anthony_asterisk
Contributor II

@Harry_Zhang @Kan_Li

I cannot find a specific example named flexspi_polling, Is this correct example,:

https://github.com/nxp-mcuxpresso/mcux-sdk-examples/tree/main/evkbmimxrt1060/driver_examples/flexspi...

 

Could you provide a link to th example I should refer to?

 

I'm working with zephyr, is there any available driver support for this or should I create my own custom driver?

 

 

0 项奖励
回复

4,223 次查看
Harry_Zhang
NXP Employee
NXP Employee

Hi @anthony_asterisk 

Select Board | MCUXpresso SDK Builder (nxp.com)

HangZhang_0-1713334604788.png

Please download the MIMXRT1062 SDK, and unzip it.

Flexspi polling_transfer example is in the SDK_2_15_0_EVK-MIMXRT1060\boards\evkmimxrt1060\driver_examples\flexspi\nor.

And Flexspi driver is in SDK_2_15_0_EVK-MIMXRT1060\devices\MIMXRT1062\drivers.

Hope this will help you.

BR

Hang

 

0 项奖励
回复

4,209 次查看
anthony_asterisk
Contributor II

@Harry_Zhang I downloaded the SDK files.  I am looking in the flexspi_nor_flash_ops.c,  All operations seem to be using LUT for flash specific operations.  They are all setting flashXfer.seqIndex to a LUT entry.  

Also when I look into fsl_flexspi.c I see the operations pass the sequenceIdx (LUT id) in when writing the IP command register.

How do I perform full-duplex SPI operations that read and write at the same time? 

I want to use FlexSPI and DMA to simultaneously read/write from TX/RX FIFO for a long transfer without CPU intervention.  For example I need to send/receive 2 buffers.

CS asserts

First operation has 4 bytes to be send from tx buffer and received important status in rx buffer.

Second operation has no tx buffer and received 6000 bytes

CS de-assert

Data would be moved by DMA to/from IP TX/RX FIFO.  Buffer addresses would change between each phase.  With the LP SPI, the processor polls status and re-configures DMA between each section.

Do I need to design a custom LUT for this operation?  

In the reference manual I see Programmable Sequence Engine (27.3.7) instructions only READ_SDR or WRITE_SDR, I don't see any instruction for a command that does both READ and WRITE. 

Is there a LUT instruction to read rx fifo and write tx fifo on the same byte?   

Maybe this is possible in parallel mode where one flexspi performs read operations and one flexspi performs write operations? 

Or maybe I need to alternate WRITE and READ instructions?

 

0 项奖励
回复

4,198 次查看
Harry_Zhang
NXP Employee
NXP Employee

Hi @anthony_asterisk 

It is impossible to one Flash performs read operations and one Flash performs write operations simultaneously in parallel mode.
One Lut only contains read or write command.
In parallel mode, FlexSPI send the same Lut to two flash, odd bytes for Port A flash, even bytes for Port B flash, they collectively form the data.

Hope this will help you.

BR

Hang

 

0 项奖励
回复

4,253 次查看
Harry_Zhang
NXP Employee
NXP Employee

Hi @anthony_asterisk

Yes, you can  use FlexSPI IP command over 50MHz with iMXRT106x.

And you can refer to flexspi_polling example in RT1060 SDK,the flexspi root clock is 133M.

Hope this will help you.

BR

Hang

0 项奖励
回复

4,114 次查看
anthony_asterisk
Contributor II

@Harry_Zhang 

The FLEXSPI cannot receive data to RXFIFO and transmit data from TXFIFO at the same time.  For full SPI operation this is an issue, but in our case we can limit our driver to only RX or only TX in a single sequence. 

I am now trying to make this work.  I created a custom LUT which I load with fsl_flexspi.c FLEXSPI_UpdateLUT.

#define LUT_SEQUENCE_SIZE_WORDS
enum {
LUT_SEQ_IDX_WRITE = 0,
LUT_SEQ_IDX_READ = 1,
};
//this LUT only supports a simple read and a simple write
const uint32_t customLUT[] = {
[LUT_SEQUENCE_SIZE_WORDS * LUT_SEQ_IDX_WRITE] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
[LUT_SEQUENCE_SIZE_WORDS * LUT_SEQ_IDX_READ] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
};

 

My first operation that I need to get working is a read of the chip id.  The operation consists of transmitting 1 byte and then reading 3 bytes.
 
During testing with the debugger I see that the DMA operation for the initial transmit completes.  My code then configures and starts the receive operation.  After this the code waits for the indication from the RX DMA however it never gets the interrupt with complete status.
 
I also noticed when viewing the LUT values with the debugger (using the svd)  for this chip that the LUT values are updated but do not match the values that I downloaded. 
 
I use DMA channel 2 for the rx operation.  I see in EDMA (DMA0 in peripherals) that ERQ is enabled for channel 2.   
anthony_asterisk_0-1713899795196.pnganthony_asterisk_1-1713899828990.pnganthony_asterisk_2-1713899873520.pnganthony_asterisk_3-1713900075616.png

 

The LUT shows unexpected values that do not match the data sent:

anthony_asterisk_0-1713900184568.png

 

 

 
0 项奖励
回复

4,096 次查看
Harry_Zhang
NXP Employee
NXP Employee

Hi @anthony_asterisk 

HangZhang_0-1713926985560.png

There is no opcode in this Lut, so it must be an error. And you say that "RX DMA however it never gets the interrupt with complete status."

You can first confirm whether there is data in RXFIFO. If there is no data in RXFIFO, it will not trigger DMA interrupt.

And i suggest that you can test polling_transfer. if the polling_transfer can work, you can test the DMA transfer.

Hope this will help you.

BR

Hang

0 项奖励
回复

4,082 次查看
anthony_asterisk
Contributor II

#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))

 

The opcode is the 1st and 4th argument, which in my case is kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_Command_STOP and kFLEXSPI_Command_READ_SDR.

The 3rd and 6th parameters are the operand which is only used for specific opcode and is unused in other cases.   Please let me know what operand should be used for WRITE, READ or STOP operations.

Also please explain why the LUT as viewed in the debugger does not match the LUT I programmed.

I have thoroughly reviewed polling_transfer and it does not perform simple READ or WRITE operation with DMA functionality.  Please explain how polling_transfer will help me fix my code?

I did not find any data in RXFIFO, however I suspect there are problems with the debugger since the LUT seen in debugger does not match actual LUT.

0 项奖励
回复

4,013 次查看
Harry_Zhang
NXP Employee
NXP Employee

Hi @anthony_asterisk 

1, About this question "Please explain how polling_transfer will help me fix my code?"
Because if you can run polling_transfer, it means that LUT is correct, and the data can return from flash succeffully.
2.I don't know what your Lut is, but the Lut you sent me last time was definitely incorrect.
const uint32_t customLUT[] = {
[LUT_SEQUENCE_SIZE_WORDS * LUT_SEQ_IDX_WRITE] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
[LUT_SEQUENCE_SIZE_WORDS * LUT_SEQ_IDX_READ] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
};
And this Lut doesn't match the register either.

HangZhang_0-1714036115552.png

3.You can refer to my lut, and the register.

HangZhang_1-1714036155082.png

HangZhang_2-1714036222573.png

Hope this will help you.

BR

Hang

 

0 项奖励
回复

3,987 次查看
anthony_asterisk
Contributor II

Since this is not a FLASH chip, the LUT you sent is not relevant.  The Command_SDR operation is a feature specifically for flash chip and is not part of a regular non-flash SPI read.

 

As I said, the chip I want to communicate is not a flash chip.  It uses a general purpose SPI bus communication.  The polling example is using flash chip operations which will not work.

0 项奖励
回复

3,933 次查看
Harry_Zhang
NXP Employee
NXP Employee

Hi @anthony_asterisk 

The picture I sent just wants to illustrate what you mentioned above.
"explain why the LUT as viewed in the debugger does not match the LUT I programmed."
And my LUT in picture can match the register in picture. Instead of configuring your Lut to be the same as mine

And I don't know if you mean that
const uint32_t customLUT[] = {
[LUT_SEQUENCE_SIZE_WORDS * LUT_SEQ_IDX_WRITE] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
[LUT_SEQUENCE_SIZE_WORDS * LUT_SEQ_IDX_READ] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
};

is not match

HangZhang_0-1714122878201.png

 

And this question,
" The polling example is using flash chip operations which will not work."
If you want to work on your non flash chip with DMA, you must need to change code, and you also need to debug polling_transfer first and then debug dma_transfer.

Hope this will help you.

BR

Hang

0 项奖励
回复