Skip to content

STM32 QSPI sample shifting prevents communication with GD25Q128E flash chip #99099

@azo-trackunit

Description

@azo-trackunit

Describe the bug

We have a custom board with STM32G473VET6 MCU and GD25Q128EWIGR SPI flash connected to QSPI. With the upcoming Zephyr v4.3 communication with the chip stopped working properly (in terms of init process and filesystem access).

Releases v3.7 LTS, v4.2 and v4.3-rc{1,2} have been tested:

  • v3.7.0 OK
  • v4.2.0 OK
  • v4.3.0-rc1 NOK
  • v4.3.0-rc2 NOK

git bisect lead to identifying cause of behavior change to be commit b147d78 which enabled sample shifting (SSHIFT) for non-dual flash configurations.

Disabling SSHIFT fixes the issue in our case.

Working around with dummy cycles and QSPI CLK does not really solve the problem:

  • setting dummy cycles for SFDP from fixed 8 to 7 does help in this case only
  • setting dummy cycles for JEDEC ID reading from default 8 to 7 does not help
    • st,read-id-dummy-cycles = <N>;
  • lowering dummy cycles for data access not tested -- default 0 dummy cycles
  • changing QSPI CLK from 104 MHz to 1 MHz does not help
  • SPI bus width is not set (i.e. 1-bit); tested with 4 bits too
    • spi-bus-width = <N>;
  • all of the above tested in different mixups
  • the only way communication, filesystem and filesystem tests (read/write/verify) were working again was disabling sample shifting

Regression

  • This is a regression.

Steps to reproduce

  1. clean build the firmware (new build dir, west update)
  2. flash & run the firmware
  3. observe zephyr shell for flash_stm32_qspi and littlefs entries
  4. read JEDED ID with flash_read_jedec_id()

Relevant log output

## OK uart:~$ kernel reboot cold [00:00:00.000,000] <inf> flash_stm32_qspi: Reading SFDP [00:00:00.000,000] <inf> flash_stm32_qspi: qspi-nor-flash@90000000: SFDP v 1.6 AP ff with 2 PH [00:00:00.000,000] <inf> flash_stm32_qspi: PH0: ff00 rev 1.6: 16 DW @ 30 [00:00:00.000,000] <inf> flash_stm32_qspi: Reading SFDP [00:00:00.001,000] <inf> flash_stm32_qspi: qspi-nor-flash@90000000: 16 MiBy flash [00:00:00.001,000] <inf> flash_stm32_qspi: PH1: ffc8 rev 1.0: 3 DW @ 90 [00:00:00.001,000] <inf> flash_stm32_qspi: NOR quad-flash at 0x90000000 (0x1000000 bytes) [00:00:00.299,000] <inf> littlefs: littlefs partition at /lfs [00:00:00.299,000] <inf> littlefs: LittleFS version 2.11, disk version 2.1 [00:00:00.301,000] <inf> littlefs: FS at qspi-nor-flash@90000000:0x0 is 4096 0x1000-byte blocks with 512 cycle [00:00:00.301,000] <inf> littlefs: partition sizes: rd 16 ; pr 16 ; ca 64 ; la 64 [00:00:00.302,000] <inf> littlefs: Automount /lfs succeeded ## NOK uart:~$ kernel reboot cold [00:00:00.001,000] <inf> flash_stm32_qspi: Reading SFDP [00:00:00.001,000] <err> flash_stm32_qspi: SFDP magic a0888ca6 invalid [00:00:00.300,000] <inf> littlefs: littlefs partition at /lfs [00:00:00.300,000] <inf> littlefs: LittleFS version 2.11, disk version 2.1 [00:00:00.300,000] <err> littlefs: can't open flash area 0, err -19 [00:00:00.300,000] <err> fs: fs mount error (-19) [00:00:00.300,000] <err> littlefs: Automount /lfs failed: -19

Impact

Functional Limitation – Some features not working as expected, but system usable.

Environment

  • OS: Linux Ubuntu 24.04 LTS
  • toolchain: Zephyr SDK 0.16.9 and 0.17.4
  • commits tested:
    • git bisect: from v3.7.1/9f824289b28d7aea2eee74f62787c385a5005453 to v4.3.0-rc2 (~13.7k commits)
    • manual verification: v3.7.0, v4.2.0, v4.3.0-rc2

Additional Context

&quadspi {	pinctrl-0 = <&quadspi1_clk_pa3 &quadspi1_bk1_ncs_pa2 &quadspi1_bk1_io0_pb1 &quadspi1_bk1_io1_pb0 &quadspi1_bk1_io2_pa7 &quadspi1_bk1_io3_pa6>;	pinctrl-1 = <&analog_pa3 &analog_pa2 &analog_pb1 &analog_pb0 &analog_pa7 &analog_pa6>;	pinctrl-names = "default", "sleep";	status = "okay";	gd25q128e: qspi-nor-flash@90000000 {	compatible = "st,stm32-qspi-nor";	reg = <0x90000000>;	size = <DT_SIZE_M(128)>;	qspi-max-frequency = <DT_FREQ_M(104)>;	label = "ext_flash";	status = "okay";	partitions {	compatible = "fixed-partitions";	#address-cells = <1>;	#size-cells = <1>;	storage_partition: partition@0 {	label = "storage";	reg = <0x00000000 DT_SIZE_M(16)>;	};	};	}; }; 
/ {	fstab {	compatible = "zephyr,fstab";	lfs_cfg: lfs {	compatible = "zephyr,fstab,littlefs";	mount-point = "/lfs";	partition = <&storage_partition>;	read-size = <16>;	prog-size = <16>;	cache-size = <64>;	lookahead-size = <64>;	block-cycles = <512>;	automount;	};	}; }; 

Needed before v4.3:

/ {	soc {	quadspi: spi@a0001000 {	compatible = "st,stm32-qspi";	#address-cells = <1>;	#size-cells = <0>;	reg = <0xa0001000 0x400>, <0x90000000 DT_SIZE_M(256)>;	interrupts = <95 0>;	clocks = <&rcc STM32_CLOCK_BUS_AHB3 0x00000100>;	status = "disabled";	};	}; }; 

Disabling SSHIFT for testing, v4.3.0-rc2:

diff --git a/drivers/flash/flash_stm32_qspi.c b/drivers/flash/flash_stm32_qspi.c index e853d91d9a7..49f75d5c1df 100644 --- a/drivers/flash/flash_stm32_qspi.c +++ b/drivers/flash/flash_stm32_qspi.c @@ -1631,10 +1631,10 @@ static int flash_stm32_qspi_init(const struct device *dev) dev_data->hqspi.Init.ClockPrescaler = prescaler; /* Give a bit position from 0 to 31 to the HAL init minus 1 for the DCR1 reg */ dev_data->hqspi.Init.FlashSize = find_lsb_set(dev_cfg->flash_size) - 2; - dev_data->hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; dev_data->hqspi.Init.ChipSelectHighTime = dev_cfg->cs_high_time - 1; #if STM32_QSPI_DOUBLE_FLASH dev_data->hqspi.Init.DualFlash = QSPI_DUALFLASH_ENABLE; + dev_data->hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; /* * When the DTS has <dual-flash>, it means Dual Flash Mode 

Setting SFDP dummy cycles for testing, example for 7, v4.3.0-rc2:

diff --git a/drivers/flash/flash_stm32_qspi.c b/drivers/flash/flash_stm32_qspi.c index e853d91d9a7..ccf76d95347 100644 --- a/drivers/flash/flash_stm32_qspi.c +++ b/drivers/flash/flash_stm32_qspi.c @@ -495,7 +495,7 @@ static int qspi_read_sfdp(const struct device *dev, off_t addr, void *data, .Instruction = JESD216_CMD_READ_SFDP, .Address = addr, .AddressSize = QSPI_ADDRESS_24_BITS, - .DummyCycles = 8, + .DummyCycles = 7, .InstructionMode = QSPI_INSTRUCTION_1_LINE, .AddressMode = QSPI_ADDRESS_1_LINE, .DataMode = QSPI_DATA_1_LINE, 

Output for SFDP reading with 7 dummy cycles:

[00:00:00.001,000] <inf> flash_stm32_qspi: Reading SFDP [00:00:00.001,000] <inf> flash_stm32_qspi: qspi-nor-flash@90000000: SFDP v 1.6 AP ff with 2 PH [00:00:00.001,000] <inf> flash_stm32_qspi: PH0: ff00 rev 1.6: 16 DW @ 30 [00:00:00.001,000] <inf> flash_stm32_qspi: Reading SFDP [00:00:00.001,000] <inf> flash_stm32_qspi: qspi-nor-flash@90000000: 16 MiBy flash [00:00:00.001,000] <inf> flash_stm32_qspi: PH1: ffc8 rev 1.0: 3 DW @ 90 [00:00:00.001,000] <inf> flash_stm32_qspi: NOR quad-flash at 0x90000000 (0x1000000 bytes) [00:00:00.300,000] <inf> littlefs: littlefs partition at /lfs [00:00:00.300,000] <inf> littlefs: LittleFS version 2.11, disk version 2.1 [00:00:00.302,000] <inf> littlefs: FS at qspi-nor-flash@90000000:0x0 is 4096 0x1000-byte blocks with 512 cycle [00:00:00.302,000] <inf> littlefs: partition sizes: rd 16 ; pr 16 ; ca 64 ; la 64 [00:00:00.302,000] <err> littlefs: WEST_TOPDIR/modules/fs/littlefs/lfs.c:1386: Corrupted dir pair at {0x1, 0x0} [00:00:00.302,000] <wrn> littlefs: can't mount (LFS -84); formatting [00:00:00.302,000] <wrn> littlefs: WEST_TOPDIR/modules/fs/littlefs/lfs.c:2109: Superblock 0x0 has become unwritable [00:00:00.302,000] <err> littlefs: format failed (LFS -28) [00:00:00.302,000] <err> fs: fs mount error (-28) [00:00:00.302,000] <err> littlefs: Automount /lfs failed: -28 

Making sure flash is erased and rebooting in case SFDP looks ok:

uart:~$ flash erase ext_flash 0 1000000 uart:~$ flash erase qspi-nor-flash@90000000 0 1000000 uart:~$ flash read qspi-nor-flash@90000000 0 128 00000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 000000A0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 000000B0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 000000C0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 000000D0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 000000E0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 000000F0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00000100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00000110: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00000120: ff ff ff ff ff ff ff ff |........ | uart:~$ flash read qspi-nor-flash@90000000 1000 128 00001000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00001010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00001020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00001030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00001040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00001050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00001060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00001070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00001080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00001090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 000010A0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 000010B0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 000010C0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 000010D0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 000010E0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 000010F0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00001100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00001110: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ........| 00001120: ff ff ff ff ff ff ff ff |........ | uart:~ kernel reboot cold 

JEDEC ID testing:

// CONFIG_FLASH_JESD216_API=y const struct device *flash_dev = device_get_binding("ext_flash"); uint8_t jedec_id[3]; int ret = flash_read_jedec_id(flash_dev, jedec_id); if (ret == 0) { // expected 18 C8 40 } 

Metadata

Metadata

Assignees

No one assigned

    Labels

    RegressionSomething, which was working, does not anymorearea: FlashbugThe issue is a bug, or the PR is fixing a bugplatform: STM32ST Micro STM32

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions