I've altered the flexspi_nor_polling_transfer demo (for RT1015 MCUXpresso) to fit my board's SPI Flash (the TC58CVG2S0HRAIG NAND FLASH).
Could you clarify the usage of the LUT command + FlexSPI command?
/* Read Status */ [4 * NAND_CMD_LUT_SEQ_IDX_READSTATUS] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x0F, kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xC0), [4 * NAND_CMD_LUT_SEQ_IDX_READSTATUS + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x01, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
Should the calling function that uses that to wait while busy look like this: (isn't the 0xC0 here redundant?)
status_t flexspi_nand_wait_bus_busy(FLEXSPI_Type *base){ /* Wait status ready. */ bool isBusy; uint32_t readValue; status_t status; flexspi_transfer_t flashXfer; flashXfer.deviceAddress = 0xC0; flashXfer.port = kFLEXSPI_PortA1; flashXfer.cmdType = kFLEXSPI_Read; flashXfer.SeqNumber = 1; flashXfer.seqIndex = NAND_CMD_LUT_SEQ_IDX_READSTATUS; flashXfer.data = &readValue; flashXfer.dataSize = 1; do { status = FLEXSPI_TransferBlocking(base, &flashXfer); if (status != kStatus_Success) { return status; } isBusy = (readValue & 0x01) == 0x01; } while (isBusy); return status; }
When I run - the data on the SPI lines aren't right (CS asserts in the middle of a byte, SCK isn't consistent, sometimes doesn't toggle for a full transfer, etc).
(Below images show examples of weird behavior on the FlexSPI_D0, CS, and SCK pins in order)
1. What might cause the above erratic behavior on the
2. Where should the SCK frequency/baud rate be set? I assumed it's by updating flexspiRootClk as per:
flexspi_device_config_t deviceconfig = {
.flexspiRootClk = 104000000, //133000000,
.flashSize = FLASH_SIZE,
.CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle,
.CSInterval = 2,
.CSHoldTime = 3,
.CSSetupTime = 3,
.dataValidTime = 0,
.columnspace = 0,
.enableWordAddress = 0,
.AWRSeqIndex = 0,
.AWRSeqNumber = 0,
.ARDSeqIndex = NAND_CMD_LUT_SEQ_IDX_READ_FROM_CACHE,
.ARDSeqNumber = 1,
.AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,
.AHBWriteWaitInterval = 0,
};
Solved! Go to Solution.
Hi variable_andrew ,
Answer your several questions:
1. should I replace 0xC0 with the # of bits expected for the transfer?
Answer:
[4 * NAND_CMD_LUT_SEQ_IDX_READSTATUS] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x0F, kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xC0),
You can find the 0XC0 commander is still kFLEXSPI_Command_SDR
,
kFLEXSPI_Command_SDR = 0x01U, /*!< Transmit Command code to Flash, using SDR mode. */
it means the 0XC0 is the send out commander data, you can consider it as the send out data is 0XC0, from the readstatus :
Actually, you can know the 1 byte address is 0XC0, but I think you can modify the data to your own real address.
2. is the 0x01 on the READ_SDR supplosed to be 0x08 for bits? or are read arguments in bytes, while addresses are in bits?
Answer:
kFLEXSPI_Command_READ_SDR = 0x09U, /*!< Receive Read Data from Flash, using SDR mode. */
[4 * NAND_CMD_LUT_SEQ_IDX_READSTATUS + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x01, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
Check the RT Flexspi RM:
So, the 0X01 is no meaning, the OPEARAND content for READ_SDR can be any value. Becuase the read back size is defined by the datasize in the code.
3. About your flexspi_nand_wait_bus_busy
I don't know why you need to modify it, and add the address, I think you don't need to add the address, because the address you already defined in the LUT.
4. About your wave is not correct
Please check your tool sample rate, as I know the FlexSPI clock is very quick, in the practical usage, the tool need to be 5-10 times than the wave which it wants to sample. I don't think your wave is acquired correctly, maybe caused by the tool.
Wish it helps you!
If you still have questions about it, please kindly let me know.
Have a great day,
Kerry
-------------------------------------------------------------------------------
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.
-------------------------------------------------------------------------------
Hi variable_andrew,
I think I am a little understand your question.
You want to know the SeqNumber detail meaning, actually, it is just the Sequence number, one sequence include 8 instructions.
I think you can check this code, it will be more useful to your understanding:
SDK_2.6.1_EVKB-IMXRT1050\boards\evkbimxrt1050\driver_examples\flexspi\hyper_flash\polling_transfer
Because you can find the customLUT has different numbers for each operation, read data just 4 instruction, 2 LUT item.
read status contains 7 LUT numbers, actually, 7*2 =14 instruction.
each CMD_LUT_SEQ contains 4 LUT items, 8 instructions, 1 sequence.
As you know, each LUT items contains 2 sequence:
So, please note, the SeqNumber is determined by your flash operation sequence number.
Just take the hyper flash as an example:
Do you know, why this seqNumber is 2?
You can find this program page flash operation is larger than 1 sequence, it needs to use 2 sequence, so it is 2.
Take another example:
Why the erase seqNumber is 4?
So, now, if talk back to the HyperRam code, do you understanding why the sequence is 1 for both the read and write?
because the related LUT table just used one sequence for each flash operation.
Wish it helps you!
Have a great day,
Kerry
-------------------------------------------------------------------------------
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.
-------------------------------------------------------------------------------
thanks for the clarification kerryzhou,
The thing that was tripping me up before is in the Ref Manual description of Sequence Number, the explicit +1 ; indicating you were supposed to set the sequence count - 1 to that register. It looks like the +1 should be removed from the reference manual text based on what I'm understanding from your post above?
Thanks again!
Hi variable_andrew,
No, I DON'T think the reference manual is wrong.
Just take the register description is correct.
Please note these points:
Please note, ARDSEQNUM is the register data, the real sequence number is ARDSEQNUM+1.
flashXfer.SeqNumber = 4;
This SeqNumber data is the real sequence number, that's why in the code, when configure the register, it need to -1.
Because Sequence number = FLSHCR2[ARDSEQNUM] +1.
Wish it helps you!
If you still have question about it, please kindly let me know.
Have a great day,
Kerry
-------------------------------------------------------------------------------
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.
-------------------------------------------------------------------------------
Hi kerryzhou,
Thanks for helping me understand the Seq Number - and yes, the confusion I had was because I didn't realize the driver had the -1.
Marked the answer you put to the orig question as correct and done on this thread.
Thanks again!
Hi variable_andrew,
That's very good to hear you understand it now.
So, do you still have any question about your case:00227305?
If your question is solved, please tell me to close that case, and help me to fill the feedback as resolved in the case, thank you!
Have a great day,
Kerry
-------------------------------------------------------------------------------
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.
-------------------------------------------------------------------------------
Hi variable_andrew ,
Answer your several questions:
1. should I replace 0xC0 with the # of bits expected for the transfer?
Answer:
[4 * NAND_CMD_LUT_SEQ_IDX_READSTATUS] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x0F, kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xC0),
You can find the 0XC0 commander is still kFLEXSPI_Command_SDR
,
kFLEXSPI_Command_SDR = 0x01U, /*!< Transmit Command code to Flash, using SDR mode. */
it means the 0XC0 is the send out commander data, you can consider it as the send out data is 0XC0, from the readstatus :
Actually, you can know the 1 byte address is 0XC0, but I think you can modify the data to your own real address.
2. is the 0x01 on the READ_SDR supplosed to be 0x08 for bits? or are read arguments in bytes, while addresses are in bits?
Answer:
kFLEXSPI_Command_READ_SDR = 0x09U, /*!< Receive Read Data from Flash, using SDR mode. */
[4 * NAND_CMD_LUT_SEQ_IDX_READSTATUS + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x01, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
Check the RT Flexspi RM:
So, the 0X01 is no meaning, the OPEARAND content for READ_SDR can be any value. Becuase the read back size is defined by the datasize in the code.
3. About your flexspi_nand_wait_bus_busy
I don't know why you need to modify it, and add the address, I think you don't need to add the address, because the address you already defined in the LUT.
4. About your wave is not correct
Please check your tool sample rate, as I know the FlexSPI clock is very quick, in the practical usage, the tool need to be 5-10 times than the wave which it wants to sample. I don't think your wave is acquired correctly, maybe caused by the tool.
Wish it helps you!
If you still have questions about it, please kindly let me know.
Have a great day,
Kerry
-------------------------------------------------------------------------------
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.
-------------------------------------------------------------------------------
Sorry about the extra replies - but it looks like I have read and write working after fixing an index in my LUT.
Can you help me understand why fixing the LUT index fixed r/w to FLASH (ie - how does the CPU know which index to use for read vs write when I didn't explicitly supply a mapping of indeces to commands to the CPU)?
The only place where LUT indeces were mentioned was in the boot section of the RT1015 RM, I didn't see it in the FlexSPI main chapter for normal operation?
Hi variable_andrew ,
Thanks a lot for your updated information, and let me know you make it works on your side now.
Could you tell me your LUT index which you have modified and make it works?
Then I will help you to check the details. About the LUT information, you also can find it in the FlexSPI module chapter in the RM, there also have the detail description.
Have a great day,
Kerry
-------------------------------------------------------------------------------
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.
-------------------------------------------------------------------------------
I tried to get a bit more info on the ARDSeqIndex/ ARDSeqNumber from this NXP appnote: https://www.nxp.com/docs/en/nxp/application-notes/AN12239.pdf
But it actually confused me further. If you look at the code for AN12239 - it has the following LUT / seq indexes / numbers:
If the sequence number is set to 1 for both read and write, then wouldn't a AHB read access end up running 2 sequences (in order)? If so - in this case it would be running the read data sequence, followed by running the write data sequence above.
If sequence number really means "number of instructions" instead of "number of sequences", then AN12239 still seems off as both the read and write sequences appear to need 6 instructions each, not 2.
Hi variable_andrew,
Thanks a lot for your patience.
Today, I checked the AN12239SW, the LUT sequence is:
#define HYPERRAM_CMD_LUT_SEQ_IDX_READDATA 0
#define HYPERRAM_CMD_LUT_SEQ_IDX_WRITEDATA 1
#define HYPERRAM_CMD_LUT_SEQ_IDX_READREG 2
#define HYPERRAM_CMD_LUT_SEQ_IDX_WRITEREG 3
But your question is: "If the sequence number is set to 1 for both read and write"
Could you give me more details about it, why you set the sequence number to 1 for both read and write? Or I am checking the wrong area? Could you tell me where you find the sequence number is set to 1 for both read and write?
Do you mean the above SeqNumber in the read and write API?
I think I am still not very clear about your question about AN12239SW.
Have a great day,
Kerry
-------------------------------------------------------------------------------
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.
-------------------------------------------------------------------------------
I will check more details about the AN12239 code, and give you reply later, please keep patient, thank you!
Best Regards,
kerry
Thanks kerryzhou - looking forward to your insight on AN12239!
Hi kerryzhou,
I think I found the explanation I'm looking for on how the FlexSPI knows which LUT index to use in order to do reads and writes: this should be set in FLASH Control Register 2:
FLSHCR2[port][AWRSEQNUM] FLSHCR2[port][AWRSEQID]
and
FLSHCR2[port][ARDSEQNUM] FLSHCR2[port][ARDSEQID]
Where
ARDSEQID is the index of the LUT, and...
ARDSEQNUM is.... the (total count - 1) of sequences to run starting at the index number?
I don't understand how the FlexSPI knows to load different pages for read and write tho?
In order for the FLASH to load a page before doing a buffer read, shouldn't the READ_CACHE_INDEX == READ_PAGE_INDEX + 1?
Then you can have the ARDSEQID = READ_CACHE_INDEX and ARDSEQNUM = 1
The below is what my current (somewhat working - for FLASH page 0 at least) LUT looks like:
The LUT indexes are in order - so read from cache is 4*0, read status is 4*1, write enable is 4*2, etc...
With the above, instead of
flexspi_device_config_t deviceconfig = { .flexspiRootClk = 104000000, //133000000, .flashSize = FLASH_SIZE, .CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle, .CSInterval = 2, .CSHoldTime = 3, .CSSetupTime = 3, .dataValidTime = 0, .columnspace = 0, .enableWordAddress = 0, .AWRSeqIndex = 0, .AWRSeqNumber = 0, .ARDSeqIndex = NAND_CMD_LUT_SEQ_IDX_READ_FROM_CACHE, .ARDSeqNumber = 1, .AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle, .AHBWriteWaitInterval = 0, };
Shouldn't I have AWRSeqIndex start at NAND_CMD_LUT_SEQ_IDX_WRITEENABLE, and then it needs to do NAND_CMD_LUT_SEQ_IDX_PROGRAMLOAD and then NAND_CMD_LUT_SEQ_IDX_PROGRAM_EXECUTE somehow???
If so, then I should re-order my LUT from the above to:
Hi variable_andrew,
Sorry for my later reply.
1.ARDSEQID and ARDSEQNUM
You can find the related information from the RM register, and the SDK sample code:
ARDSEQID is AHB reading the LUT sequence ID, it is the sequence index for AHB write trigged command.
ARDSEQNUM, it configues the sequence number.
2. I don't understand how the FlexSPI knows to load different pages for read and write tho?
About the difference page, actually when you want to read and write, you will write the related address, I think that will defined the related pages, you can check the flexSPI write API function, about the read, you don't need to use the API code, you can just read the related map address for the FlexSPI.
3.In order for the FLASH to load a page before doing a buffer read, shouldn't the READ_CACHE_INDEX == READ_PAGE_INDEX + 1?
Then you can have the ARDSEQID = READ_CACHE_INDEX and ARDSEQNUM = 1
Answer: I am not very clear about this question, as I know, the read just need to read the related the address, you don't need to run the other API, after you already set the correct LUT table, and the related index sequence.
4. About your LUT table,
Could you also share some Index number, just like the SDK code in the app.h
5. It's better to share your newest code, I am not sure your code in the case is the newest one or not.
Best Regards,
kerry
Hi kerryzhou
Thanks as always - I've responded directly via the support channel - but for posterity:
1.
ARDSEQNUM, it configues the sequence number
Still not sure I follow this - from various sources it appears this was supposed to indicate the total # of sequences +1 the AHB would run starting from ARDSEQID, but as noted below - and in all example code - this doesn't seem to be the case in practice....
2.
about the read, you don't need to use the API code, you can just read the related map address for the FlexSPI
As noted in email - we set the ARDSEQID to the AHB so it knows how to read from the current page/buffer, but we don't provide anything to indicate the LUT index for loading page.
So if I read from address 0x6000_0000 + PAGE_SIZE, how will the AHB know to change pages on the external HW?
3. same question as #2 - was asking how we force the AHB to set current page in flash.
4. LUT indexes for the Toshiba commands
#define NAND_CMD_LUT_SEQ_IDX_READ_FROM_CACHE 0 #define NAND_CMD_LUT_SEQ_IDX_READSTATUS 1 #define NAND_CMD_LUT_SEQ_IDX_WRITEENABLE 2 #define NAND_CMD_LUT_SEQ_IDX_BLOCKERASE 3 #define NAND_CMD_LUT_SEQ_IDX_PROGRAMLOAD 4 #define NAND_CMD_LUT_SEQ_IDX_READ_PAGE 5 #define NAND_CMD_LUT_SEQ_IDX_READ_ECC_STATUS 6 #define NAND_CMD_LUT_SEQ_IDX_PROGRAM_EXECUTE 7 #define NAND_CMD_LUT_SEQ_IDX_READ_FROM_CACHE_ODD 8 #define NAND_CMD_LUT_SEQ_IDX_PROGRAM_LOAD_ODD 9 #define NAND_CMD_LUT_SEQ_IDX_READID 10
5.
zipped and sent directly
Thanks!!
I'm able to access the FLASH status registers and successfully erase flash
I hadn't updated the flexspi_config_t rxSampleClock according to our board design, so with that fixed I'm able to communicate and get status, device/mfr ID, erase - but I get an exception (hard fault) when running:
memcpy(s_nand_read_buffer, (void *)(flashBaseAddress), sizeof(s_nand_read_buffer));
(Where flashBaseAddress = 0x60000000 and the s_nand_read_buffer size is 0x1000)
I assume this could either be caused by incorrect memory setup (in board.c) or incorrect read commands in the LUT?
My code is running from SRAM_OC:
Memory region Used Size Region Size %age Used BOARD_FLASH: 0 GB 16 MB 0.00% SRAM_OC: 38308 B 64 KB 58.45% SRAM_DTC: 0 GB 32 KB 0.00% SRAM_ITC: 3568 B 32 KB 10.89%
Without XIP, so BOARD_ConfigMPU runs this:
/* Setting Memory with Device type, not shareable, non-cacheable. */ MPU->RBAR = ARM_MPU_RBAR(2, 0x60000000U); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_RO, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_16MB);
I believe the Toshiba part requires a read cell array and then read from cache command sets to read data, how can I ensure the RT chip does this in the right order - maybe that's what's causing the hard fault?
Hi kerryzhou , thanks for the thorough response!
Wanted to ping you about the last point - is the way I'm setting the frequency for the clock correct above?
If my tool maxes out at 100MS/s - maybe I can slow the SPI clock down to 20MHz to do basic testing before speeding back up...