Finally got QSPI flash and USBMSD working

The QSPIFormat and AccessFlashAsUSBDisk examples were never working on the Portenta H7 Lite as is well known to those who tried to use the QSPI flash. The problem appears to be with the creation of the QSPIFBlockDevice.

To find out what the problem was I installed the MBED-OS source code of QSPIFBlockDevice and SFDP in the Arduino/mbed installation tree and started debugging the code in an STM32CubeIDE makefile project that emulates the Arduino 1.8 GUI build.

I found that it failed in the section where it tries to set the QPI mode. This is in the function QSPIFBlockDevice::_sfdp_parse_basic_param_table . If you comment out the lines after "Detect and Set fastest Bus mode (default 1-1-1)" then you can format the disk with the QSPIFormat example and run the USBMSD example to bring up a USB mass storage device in the Windows file explorer. I was able to copy a file to one of the 3 USB drives, reboot and see the file again.

The speed is nothing to write home about because it operates in (1-1-1) mode not the (4-4-4) QPI mode. While this is only a workaround, something is better than nothing so to me that means success. I hope I will be able to use the FATFS from my application without trouble.

HTH someone.

I had also trouble to get QSPI with Arduino/mbed LIB to work (it does not look working).
Based on STM HAL drivers (as native STM32 project) - I got it to work.

Some remarks based on my experience:

  • not all commands are 4-4-4, most of the commands needed, e.g. RESET, configure chip etc. are 1-1-1
  • 4-4-4 is mainly just the FAST_READ command (see the chip datasheet), just one single, specific READ command
  • I had to tweak the timing, mainly via:
hqspi.Init.SampleShifting = QSPI_SHIFTING_SAMPLES;
  • also very important to know how many dummy cycles for a FAST_READ command:
#define MT25TL01G_DUMMY_CYCLES_READ			  	6U		//not 8U !

I have used a QSPI driver from a NUCLEO board and modified the parameters, the driver code (names are still for another chip). It was necessary to go along with the QSPI chip datasheet.

Remark: the best is, when you read - to use the MemoryMappedMode. It should be a real 4-4-4 FAST_READ command. The beauty: you can access directly, via a simple data pointer and if caches are enabled for QSPI address region (MPU setting) - it is pretty fast and efficient.
Just to bear in mind: in MemoryMappedMode you cannot erase, program etc. You had to disable MemoryMappedMode and use the functions for "indirect" access.

It works for me.
Find my HAL based QSPI driver attached here:
QSPI.zip (18.9 KB)

There is clock enable for QSPI needed, which is in my system_clock.c:

PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_USB | RCC_PERIPHCLK_SPI2 | RCC_PERIPHCLK_QSPI | RCC_PERIPHCLK_ADC;
    PeriphClkInitStruct.QspiClockSelection = RCC_QSPICLKSOURCE_PLL2;

My general experience:

  • you have to know exactly which QSPI chip is used: go with its datasheet: chips differ a lot in terms of which commands possible and their parameters (the chip on Portenta H7 is not really "the best one")
  • try to "tweak" the timing, e.g. play with:
hqspi.Init.SampleShifting = QSPI_SHIFTING_SAMPLES;	//QSPI_SAMPLE_SHIFTING_HALFCYCLE;	//QSPI_SAMPLE_SHIFTING_NONE;

My function void QSPI_demo(int par, uint32_t addr) is the main function: via par I can select "Init", "Erase", "Program", "Read" and "MemoryMappedMode".
I use it in order to flash pages in QSPI with man pages (text), reading is done in "MemoryMappedMode" - see void QSPI_ManPage(EResultOut out, int num)

Works fine for me, as 4-4-4 for FAST_READ. But just in STR mode, not DDR: this one I could not bring to work. DDR is more tricky in terms of timing. And there is this DLY (Delay block) which can be trimmed.

1 Like

Thanks Tjaekel.

I have played with your QSPI files a number of times and debugged it in an STM32CubeIDE project. Indeed, the basic commands work. My trouble is that I would rather rely on code that is supported by a community instead of one (highly valued) individual that may decide to move on at some point.

Writing my own STM32 support for QSPI, USB mass storage, SDRAM, boot loader, serial and multicore support is more than I want to do so for those things I like to rely on MBED-OS. QSPI flash has generic support and MBED-OS has a good support group. Chip specific features are retrieved using the SFDP functionality so I should not have to worry about different settings for different situations. I don't know how well MBED-OS supports all that, but it works well enough with my bug fix.

Normally I hack my way through hardware support using the various STM32 examples and documentation, then integrate it into an MBED-OS project hoping that they don't step on each other. MBED-OS invokes the QSPI flash sooner than the setup and loop code where I have my STM32 features.

So, I will work with it as I have it now also since speed is not critical - just a script file for configuration and maybe a place to dump the result files of my application - though it's usually fine to upload them right away to a host computer without storing them on flash first. It's nice to have the USB mass storage available so we can see the files from Windows too.

I may tweak my solution with your suggested settings, maybe they make things work that otherwise would not but frankly the SFDP management by MBED-OS ought to handle that I think.