Using QSPI flash A1 for XIP and QSPI flash B1 for data storage

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

Using QSPI flash A1 for XIP and QSPI flash B1 for data storage

3,212 Views
thivya_ashokkum
Contributor II

I came across a few posts for using 2 QSPI devices like Can we use a XIP flash and a data flash at the same FlexSPI controller? 

One of the replies mentioned XIP uses AHB while programming the flash uses IP. 

1. Here is my flexspi_nor_flash_init()

flexspi_device_config_t codedeviceconfig = {
.flexspiRootClk = 120000000,
.flashSize = 0x2000,
.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_FAST_QUAD,
.ARDSeqNumber = 1,
.AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,
.AHBWriteWaitInterval = 0,
};
flexspi_device_config_t datadeviceconfig = {
.flexspiRootClk = 120000000,
.flashSize = 0x800,
.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_FAST_QUAD,
.ARDSeqNumber = 1,
.AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,
.AHBWriteWaitInterval = 0,
};

void flexspi_nor_flash_init(FLEXSPI_Type *base)
{
flexspi_config_t config;

flexspi_clock_init();

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

/*Set AHB buffer size for reading data through AHB bus. */
config.ahbConfig.enableAHBPrefetch = true;
config.ahbConfig.enableAHBBufferable = true;
config.ahbConfig.enableReadAddressOpt = true;
config.ahbConfig.enableAHBCachable = true;
config.rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackFromDqsPad;
FLEXSPI_Init(base, &config);
// FLEXSPI_EnableAHBParallelMode(EXAMPLE_FLEXSPI,true);

/* Configure flash settings according to serial flash feature. */
FLEXSPI_SetFlashConfig(base, &codedeviceconfig, kFLEXSPI_PortA1);
FLEXSPI_SetFlashConfig(base, &datadeviceconfig, kFLEXSPI_PortB1);

/* Update LUT table. */
FLEXSPI_UpdateLUT(base, 0, customLUT, CUSTOM_LUT_LENGTH);

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

1. FLEXSPI_SetFlashConfig(base, &datadeviceconfig, kFLEXSPI_PortB1);

When the above line of code is executed, a hex value is filled in the 2MB chip instead of the being set to 0xFF. Also, when I try to access the 2nd memory, I can't erase it or write to it. Reading using memcpy() gives weird values. From the RM, I understood that the address of the second flash would start at 0x60000000 + Flash1's size. 

2. I have all the flexspi code pulled into the RAM for execution and the interrupts are disabled before accessing the flash because I had to do that while I was using a single flash earlier for XIP and also for data storage. Could this be a problem?

3.  FLEXSPI_EnableAHBParallelMode(EXAMPLE_FLEXSPI,true);

Using this line of code causes the application to be stuck in a loop and does not recover. I believe that I need not use AHB in parallel mode since I'm using XIP only on Flash A1 but I should use IP in parallel. Is that correct?

4. I use kFLEXSPI_PortB1 while trying to access the second flash with the address calculated as above. But, no luck.

What am I doing wrong? Am I missing initialization steps?

Labels (1)
Tags (1)
0 Kudos
16 Replies

2,915 Views
thivya_ashokkum
Contributor II

Hi jeremyzhou‌,

When I was trying different things to get the 2nd flash working, I commented the below line in flexspi_init()

 

config.rxSampleClock                  = kFLEXSPI_ReadSampleClkLoopbackFromDqsPad;

 

so that the rxSampleClock remained the default setting of kFLEXSPI_ReadSampleClkLoopbackInternally and that fixed the flash issue. I’m able to both read and write to both flash1 and flash2 on ports A and B respectively.

 I have the modified sdk code attached here for your reference.

However, this trick works only in the sdk sample where the entire application runs from RAM. When I tried the same thing in my actual application running XIP, no luck at all. I even changed the qspi_flashconfig in xip folder to use the same clock option but nothing changes. Could you please help with this? 

0 Kudos

2,915 Views
mitterha
Senior Contributor I

Hello,

additionally to jeremys answer: keep in mind that the DQS pins should be left floating and for a flexspi root clock of 120MHz you have to use the option "loopback through DQS pad"  or if your flash provides a read strobe the option where the flash generates the read strobe.

https://community.nxp.com/message/1248438?commentID=1248438#comment-1248438 

Kind regards,

Stefan

0 Kudos

2,915 Views
thivya_ashokkum
Contributor II

Stefan,

I managed to get to initialize both the flash devices properly and I no loner have the weird hex values being written to my second flash.

Actually,after I got to a point where I was able to initialize both the flash devices to the correct configuration, when I disable all the XIP code running on flash A1, I’m able to read/write/erase flash B1 without any issues. However, when I bring back the XIP code running on Flash A1, I lose access to flash B1. Did you use DMA for data transfer when you used 2 QSPI flash devices?

0 Kudos

2,915 Views
mitterha
Senior Contributor I

Hello,

good to hear that you are making progress. Yes you are right, I am using DMA transfers for programming data (pages) and FLEXSPI_TransferBlocking for all other commands.

AN12564 has this note "For flash programming, as it only has one FlexSPI interface, so if the CPU transfers the data, it generates the hard fault. To avoid this issue, one way is to use DMA for data transfer instead CPU."

I just tried to use my flash devices without DMA which results in a HardFault.

2,915 Views
thivya_ashokkum
Contributor II

Hi Stefan,
Both my DQS pins are left floating but I hadn't configured them in my pinmux. I'll add that.

Thank you for bringing up the clock. When I had it set to loop back through DQS pad, I wasn't able to communicate with flash b1. When I changed it to loop back internally, my sample code that I've attached worked as expected. I don't understand this part.  

0 Kudos

2,915 Views
jeremyzhou
NXP Employee
NXP Employee

Hi ,

Thanks for your reply.
After having a brief review of your code, I'd like to suggest you try below advises.
1. Adding the initialization of the FLEXSPI_A_DQS and FLEXSPI_B_DQS pins in the BOARD_InitPins() function.
2) To enable the XIP mode, you need to modify the hyperflash_config struct to fit for the QSPI you used, as the default struct is for Hyperflash.
In further, it supports to configure the size of Flash connected to B1 in flexspi_nor_config_t struct.

Have a great day,
TIC

 

-------------------------------------------------------------------------------
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.
-------------------------------------------------------------------------------

0 Kudos

2,915 Views
thivya_ashokkum
Contributor II

Adding the DQS pins in the pinmux makes my application to be stuck in the ROM code. When I set a breakpoint at my flashconfig functions in flexspi_init() as below:

FLEXSPI_SetFlashConfig(base, &deviceconfig, kFLEXSPI_PortA1);
FLEXSPI_SetFlashConfig(base, &deviceconfig, kFLEXSPI_PortB1); 

I can see the code being stuck and keeps running in circles between these functions and I can see that the call is from the ROM as the calling address is 0x0.

I removed the pins from my pin_mux and the code is initialized, as usual and it runs properly but I'm still unable to talk to my second flash.

Even in the sdk example, I CANNOT talk to the second flash if I set the below:

config.rxSampleClock                  = kFLEXSPI_ReadSampleClkLoopbackFromDqsPad;

I can talk to flash2 only when I comment this line. Why is this happening?

0 Kudos

2,915 Views
jeremyzhou
NXP Employee
NXP Employee

Hi ,

Thanks for your reply.
Firstly, whether you can share the BOARD_InitPins() function after adding the initialization of DQS pins。
Secondly, which code line the code stall at, please point it out.
Last, you can refer to the application note (https://www.nxp.com/docs/en/application-note/AN12564.pdf) to implement RWW function on the two flash devices which connect on the FlexSPI port.
In further, you can give a try to remap the codes which operate the non-boot QSPI flash to internal RAM to execute.

Have a great day,
TIC

 

-------------------------------------------------------------------------------
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.
-------------------------------------------------------------------------------

0 Kudos

2,915 Views
thivya_ashokkum
Contributor II

Hi Jeremy,
1. I have the DQS pins floating as recommended. I'll add them to the pinmux, as well.
2. I do have the flexspi_nor_config_t modified for QSPI. I also added the size of B1 flash in that structure. Like I already mentioned, I don't have issues with XIP. My code runs XIP from flash connected to A1. But, I'm not able to talk to the flash connected to B1 while running XIP. I have all the flexspi code running from RAM. But from the example sdk code that I attached in my previous message, I can talk to the flash connected to B1. 

0 Kudos

2,915 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,

Thank you for your interest in NXP Semiconductor products and
for the opportunity to serve you.
To provide the fastest possible support, I'd highly recommend you to refer to the application note :
https://www.nxp.com/docs/en/application-note/AN12564.pdf for details.
In further, I've also attached the code for this application note.

Have a great day,
TIC

 

-------------------------------------------------------------------------------
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.
-------------------------------------------------------------------------------

0 Kudos

2,915 Views
mitterha
Senior Contributor I

Hello,

Is the configured timing correct for your devices and is the clock configuration correct?

1. FLEXSPI_SetFlashConfig does not write anything into flash it is only configuring FlexSPI registers.

2. If your flash access code does not use interrupts it is not a problem. Is all of the used code (functions + initialization structures) in RAM take a look at my answer to your other question.

3. No you do not need parallel mode. Parallel mode will split the written data and write part of it to port A and part to port B

pastedImage_1.png

4. If you use IP commands you have to specify the address offset in the external flash (0x000 to flash size) and not the AHB address.

Did you update the LUT entries for your used flash devices? Did you update all configuration structures (don't forget the flexspi_nor_config_t XIP structure)?

Kind regards,

Stefan

0 Kudos

2,915 Views
thivya_ashokkum
Contributor II

Hi Stefan, 

Thanks for responding! 

1. That's what throws me off why executing the I it sequence fills the second flash with weird data.

2. All my flexspi code runs from SRAM_DTC. I actually had flash 1 on port A1 working perfectly fine. It was a Winbond 8MB. I was running XIP and also storing data on the same flash. However, I had to constantly disable and enable interrupts for accessing the flash for read/write and that's the reason we decided to add another 2MB QSPI flash so that we can leave the XIP flash alone and use a separate flash for data stotage. 

3. Got it. I'll not try that route anymore.

4. My QSPI1 is a Winbond 8MB. So the address range will be 0x60000000 - 0x60800000. So, according to the RM, the second QSPI address range will be 0x60800000-0x60A00000. So, when I tried to erase the second QSPI, I used the offset 0x800 but that didn't erase the second flash at all. 

Regarding the LUT, since I use the same Winbond flash for both my QSPI devices, should I repeat the same sequence again for 2nd QSPI? 

I didn't make any changes to XIP structure in the XIP folder. Should I add the flash there, as well? I don't do that since I didn't want the second QSPI to run XIP. 

THANKS 

0 Kudos

2,915 Views
mitterha
Senior Contributor I

Hi,

1. Why do you think that it writes data to the flash/where do you see that? For me the EWARM Memory View did not show valid data until the flexspi initialization was done correctly.

2/4.

Sorry the IP Adress range should be as this
Flash A1: 0x0000 to 0x007FFFFF

Flash B1: 0x00800000 to 0x009FFFFF

pastedImage_1.png

THIVYA ASHOK KUMAR schrieb:

 So, when I tried to erase the second QSPI, I used the offset 0x800 but that didn't erase the second flash at all.

Why did you use 0x800  (2 kByte)? If you write 0x800 in the IP Control Register 0 as address the FlexSPI peripheral will select Flash A1 because this address belongs to your first 8 MB flash. If you want to delete the first sector of your Flash B1 you would need to write 0x00800000 to this register.

Are your flash access methods based on the NXP driver?

If yes I would use following flexspi_transfer_t setting to delete the complete flash b1:

flashXfer.deviceAddress = 0x00800000; // begin IP address of flash b1 -> 
                                      // if the winbond flash datasheet requires a 
                                      // special address for the delete command you 
                                      // would need to change accordingly
flashXfer.port          = kFLEXSPI_PortB1; // we want to access flash b1
flashXfer.cmdType       = kFLEXSPI_Command;
flashXfer.SeqNumber     = 1; // number of sequences needed for the chip erase command
flashXfer.seqIndex      = FLEXSPI_LUT_SEQ_IDX_CHIPERASE; // index of the LUT entry which 
                                                         // holds the command to delete a 
                                                         // complete winbond flash‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The flexspi peripheral will decide which chip select to use based on the flashXfer.deviceAddress which gets written to the ip control register 0 and automatically remove the base address of the flash (0x00800000) from the address before sending it to flash (so flash B1 would receive the address 0x00000000).

pastedImage_1.png

Regarding the LUT, since I use the same Winbond flash for both my QSPI devices, should I repeat the same sequence again for 2nd QSPI? 

I didn't make any changes to XIP structure in the XIP folder. Should I add the flash there, as well? I don't do that since I didn't want the second QSPI to run XIP. 

 

THANKS 

If both flash devices use the same commands you do not have to change anything (also there is only one LUT possible in flexspi peripheral). If you add the second flash to the XIP structure the boot ROM will already set the flash size in the flexspi register but it is not necessary because you are initializing it with the FLEXSPI_SetFlashConfig function. Which IMXRT device are you using?

Kind regards,

Stefan

0 Kudos

2,915 Views
thivya_ashokkum
Contributor II

Stefan, 

Regarding the memory config for the general application, I added the 2MB flash as an additional flash under memory indicating the address range and it is available in the linker files. I didn't think of this as an issue as I don't really put in any code in this memory region. However, I thought it wold be worth mentioning here.

Thanks 

0 Kudos

2,915 Views
mitterha
Senior Contributor I

Hi,

sorry I don't know how MCUXpresso works maybe somebody else can help you with the IDE.

If you use your functions to read the second flash what data will be read? Is it the same you can see in the memory view?

Without seeing the code I only have left these ideas:

1. does your flash need some initialization e.g. enable quad mode which is done for your first flash (e.g. in XIP configuration structure by configCmdEnable or in your code) but not for the second flash?

2. Are your IOMUXC registers set correctly?

Maybe somebody from NXP has another idea.

Kind regards,

Stefan

0 Kudos

2,915 Views
thivya_ashokkum
Contributor II

1. I use MCUXpresso IDE and when I set breakpoints within the flexspi_init function and view the memory in the memory viewer, once flash A1's config is set, I see the initial bytes being filled with the information from the boot_hdr we set in XIP and the rest of the flash is set to FF. However, when the flash config is set for flash B1, I see the entire 2MB being filled with weird hex values like "0x18DD7911". The same value is filled just for the 2MB range of the 2nd QSPI. Before I set the flash config, the values are indeterminate and the viewer shows all '?' for the memory range.

2. The 0x800 was a typo. I do use 0x800000 for the address but still I can't access the 2nd QSPI flash. When I use any address range within the first 8MB, it works as expected. I just can't access the 2nd QSPI.

3. I'm using the iMX.RT1050.

0 Kudos