Skip to main content
ronnietango
Associate II
January 2, 2025
Question

QSPI reads only 0x9999

  • January 2, 2025
  • 13 replies
  • 1893 views

I have a custom board with STM32H747IGT6 MCU, which communicates with a S25HL512TFAMHI010 flash memory chip over QSPI. I have made several iterations of this board, and the QSPI communication has always been fine.

However, on the most recent iteration of the board, I am finding a very strange problem. I am able to erase/program the flash chip with external loader file using STM32CubeProgrammer, and to use this to read the 0x90000000 address, which shows my data has been programmed as expected.

But when I try to run my code as normal, the memory mapped QSPI read always returns 0x9999 (39321) for every address.

I've tried several of the new boards with the same results, and checked that the exact same code still works on the previous iterations of the hardware.

I'm at something of a loss for how to debug this..!

This topic has been closed for replies.

13 replies

TDK
January 2, 2025

Since it's the same 4-bit 0b1001 pattern repeating, it's probably there is a hardware issue with how your QSPI data lines are connected to the chip, or how the clock line is connected, or something hardware problem. It's the absence of data.

Connect a logic analyzer to the leads on the actual QSPI chip to verify signal is as expected.

"If you feel a post has answered your question, please click ""Accept as Solution""."
ronnietango
Associate II
January 2, 2025

Unfortunately I don't have access to a logic analyser at present - I'll have to order one.

But I can't understand how it can be a hardware issue when the external loader file in STM32CubeProgrammer is able to program the QSPI chip?

TDK
January 2, 2025

Yep, reasonable conclusion. The logic analyzer would give you insight into what is happening at the chip level. Even if it's not a hardware issue, you will either see the chip returning 0x9999 everywhere, or (more likely) you will see the commands sent over QSPI don't line up with what you expect. You can use that information to troubleshoot the firmware.

 

> But when I try to run my code as normal, the memory mapped QSPI read always returns 0x9999 (39321) for every address.

How about in non-memory mapped mode? Does the Memory Map view also return 0x9999 everywhere in this region?

 

 

"If you feel a post has answered your question, please click ""Accept as Solution""."
Tesla DeLorean
Guru
January 2, 2025

It suggests a disparity between the mode the memory thinks it's in vs what the MCU is doing.

The S25HL512 has different commands for different modes, as I recollect, for 24 vs 32-bit addressing

Your BSP code on the app side needs to more tightly match what is being done on the External Loader side.

If using Memory Mapped Mode, the reading template command has to be correct.

At 64MB 4-byte (32-bit) addressing is going to be need.

Check that STM32 Cube Programmer + External Loader can Program and Validate large blocks of binary data in the 4, 16, 32, 64MB sense. If those are working it's not a hardware issue, but more one of software and BSP implementation.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
ronnietango
Associate II
January 2, 2025

Thanks for this. My code is already using 32-bit addressing - and the Memory Mapped Mode works properly with the same code on what *should be* exactly the same hardware configuration (the changes to the board for this iteration did not concern the QSPI section...)

 


@Tesla DeLorean wrote:

Check that STM32 Cube Programmer + External Loader can Program and Validate large blocks of binary data in the 4, 16, 32, 64MB sense.


My original binary data file is around 13MB - this loaded fine using STM32CubeProgrammer and External Loader. I then tried loading a file double this size, and it failed ("Error: failed to download the file"). Interestingly, it now doesn't seem to want to perform a Mass Erase operation, or even to re-load the original binary data file any more (log below in case that sheds any light)...

18:32:05:246 : Memory Programming ...
18:32:05:247 : Opening and parsing file: myBinaryFile.bin
18:32:05:269 : File : myBinaryFile.bin
18:32:05:269 : Size : 12.97 MB
18:32:05:269 : Address : 0x90000000
18:32:05:269 : Erasing Segment <0> Address <0x90000000> Size <13602182>Bytes
18:32:05:269 : Erasing memory corresponding to segment 0:
18:32:05:269 : Memory erase...
18:32:05:270 : halt ap 0 Status = 0
18:32:05:270 : halt ap 1 Status = 32
18:32:05:270 : halt ap 2 Status = 32
18:32:07:000 : halt ap 3 Status = 17
18:32:07:000 : w ap 0 reg 15 PC (0x24000000)
18:32:07:000 : w ap 0 reg 17 MSP (0x24000500)
18:32:07:002 : w ap 0 reg 16 xPSR (0x01000000)
18:32:07:003 : w ap 0 @0x24001F80 : 0x00000200 bytes, Data 0x00000000...
18:32:07:003 : w ap 0 @0x24000000 : 0x00000004 bytes, Data 0x0000BE00...
18:32:07:016 : w ap 0 @0x24000004 : 0x00001B54 bytes, Data 0x4000F080...
18:32:07:016 : Erasing external memory sectors [0 51]
18:32:07:016 : Init flashloader...
18:32:07:018 : halt ap 0
18:32:07:018 : w ap 0 reg 0 R0 0x00000001
18:32:07:019 : w ap 0 reg 1 R1 0x00000000
18:32:07:019 : w ap 0 reg 2 R2 0x00000000
18:32:07:019 : w ap 0 reg 3 R3 0x00000000
18:32:07:019 : w ap 0 reg 4 R4 0x00000000
18:32:07:019 : w ap 0 reg 5 R5 0x00000000
18:32:07:019 : w ap 0 reg 6 R6 0x00000000
18:32:07:019 : w ap 0 reg 7 R7 0x00000000
18:32:07:020 : w ap 0 reg 8 R8 0x00000000
18:32:07:020 : w ap 0 reg 9 R9 0x00000000
18:32:07:020 : w ap 0 reg 10 R10 0x00000000
18:32:07:021 : w ap 0 reg 11 R11 0x00000000
18:32:07:021 : w ap 0 reg 12 R12 0x00000000
18:32:07:022 : w ap 0 reg 13 SP 0x00000000
18:32:07:029 : w ap 0 reg 14 LR 0x24000001
18:32:07:030 : w ap 0 reg 15 PC 0x24000799
18:32:07:030 : w ap 0 reg 16 xPSR 0x01000000
18:32:07:030 : w ap 0 reg 17 MSP 0x24001F54
18:32:07:030 : w ap 0 reg 18 PSP 0x00000000
18:32:07:030 : run ap 0
18:32:07:031 : halt ap 0
18:32:07:031 : r ap 0 reg 0 R0 0x00000001
18:32:07:031 : Loader sector erase...
18:32:07:031 : w ap 0 reg 0 R0 0x90000000
18:32:07:031 : w ap 0 reg 1 R1 0x90CC0000
18:32:07:035 : w ap 0 reg 2 R2 0x00000002
18:32:07:035 : w ap 0 reg 3 R3 0x00000000
18:32:07:035 : w ap 0 reg 4 R4 0x00000000
18:32:07:035 : w ap 0 reg 5 R5 0x00000000
18:32:07:035 : w ap 0 reg 6 R6 0x00000000
18:32:07:035 : w ap 0 reg 7 R7 0x00000000
18:32:07:035 : w ap 0 reg 8 R8 0x00000000
18:32:07:035 : w ap 0 reg 9 R9 0x00000000
18:32:07:035 : w ap 0 reg 10 R10 0x00000000
18:32:07:035 : w ap 0 reg 11 R11 0x00000000
18:32:07:036 : w ap 0 reg 12 R12 0x00000000
18:32:07:036 : w ap 0 reg 13 SP 0x00000000
18:32:07:036 : w ap 0 reg 14 LR 0x24000001
18:32:07:036 : w ap 0 reg 15 PC 0x24000935
18:32:07:036 : w ap 0 reg 16 xPSR 0x01000000
18:32:07:036 : w ap 0 reg 17 MSP 0x24001F54
18:32:07:036 : w ap 0 reg 18 PSP 0x00000000
18:32:07:036 : run ap 0
18:32:57:366 : halt ap 0
18:32:57:366 : r ap 0 reg 0 R0 0x00000001
18:32:57:367 : erase: 52109ms
18:32:57:367 : Download in Progress:
18:32:57:369 : Size : 13602184 Bytes
18:32:57:369 : Address : 0x90000000
18:32:57:369 : Buffer program...
18:32:57:373 : halt ap 0 Status = 0
18:32:57:374 : halt ap 1 Status = 32
18:32:57:374 : halt ap 2 Status = 32
18:32:59:001 : halt ap 3 Status = 17
18:32:59:001 : w ap 0 reg 15 PC (0x24000000)
18:32:59:001 : w ap 0 reg 17 MSP (0x24000500)
18:32:59:001 : w ap 0 reg 16 xPSR (0x01000000)
18:32:59:008 : w ap 0 @0x24001F80 : 0x00000200 bytes, Data 0x00000000...
18:32:59:008 : w ap 0 @0x24000000 : 0x00000004 bytes, Data 0x0000BE00...
18:32:59:017 : w ap 0 @0x24000004 : 0x00001B54 bytes, Data 0x4000F080...
18:32:59:017 : Loader write range...
18:32:59:582 : w ap 0 @0x24001F80 : 0x0003EF00 bytes, Data 0x4EDAD666...
18:32:59:583 : W B1 in RAM @0x24001F80 size 0x0003EF00 : 0565ms
18:32:59:583 : Init flashloader...
18:32:59:587 : halt ap 0
18:32:59:588 : w ap 0 reg 0 R0 0x00000001
18:32:59:588 : w ap 0 reg 1 R1 0x00000000
18:32:59:588 : w ap 0 reg 2 R2 0x00000000
18:32:59:589 : w ap 0 reg 3 R3 0x00000000
18:32:59:589 : w ap 0 reg 4 R4 0x00000000
18:32:59:589 : w ap 0 reg 5 R5 0x00000000
18:32:59:589 : w ap 0 reg 6 R6 0x00000000
18:32:59:589 : w ap 0 reg 7 R7 0x00000000
18:32:59:590 : w ap 0 reg 8 R8 0x00000000
18:32:59:590 : w ap 0 reg 9 R9 0x00000000
18:32:59:591 : w ap 0 reg 10 R10 0x00000000
18:32:59:591 : w ap 0 reg 11 R11 0x00000000
18:32:59:592 : w ap 0 reg 12 R12 0x00000000
18:32:59:592 : w ap 0 reg 13 SP 0x00000000
18:32:59:592 : w ap 0 reg 14 LR 0x24000001
18:32:59:594 : w ap 0 reg 15 PC 0x24000799
18:32:59:595 : w ap 0 reg 16 xPSR 0x01000000
18:32:59:608 : w ap 0 reg 17 MSP 0x24001F54
18:32:59:613 : w ap 0 reg 18 PSP 0x00000000
18:32:59:613 : run ap 0
18:32:59:615 : halt ap 0
18:32:59:616 : r ap 0 reg 0 R0 0x00000001
18:32:59:616 : w ap 0 reg 0 R0 0x90000000
18:32:59:617 : w ap 0 reg 1 R1 0x0003EF00
18:32:59:617 : w ap 0 reg 2 R2 0x24001F80
18:32:59:617 : w ap 0 reg 3 R3 0x00000002
18:32:59:617 : w ap 0 reg 4 R4 0x00000000
18:32:59:617 : w ap 0 reg 5 R5 0x00000000
18:32:59:617 : w ap 0 reg 6 R6 0x00000000
18:32:59:618 : w ap 0 reg 7 R7 0x00000000
18:32:59:618 : w ap 0 reg 8 R8 0x00000000
18:32:59:618 : w ap 0 reg 9 R9 0x00000000
18:32:59:618 : w ap 0 reg 10 R10 0x00000000
18:32:59:618 : w ap 0 reg 11 R11 0x00000000
18:32:59:618 : w ap 0 reg 12 R12 0x00000000
18:32:59:618 : w ap 0 reg 13 SP 0x00000000
18:32:59:618 : w ap 0 reg 14 LR 0x24000001
18:32:59:618 : w ap 0 reg 15 PC 0x24000A35
18:32:59:618 : w ap 0 reg 16 xPSR 0x01000000
18:32:59:618 : w ap 0 reg 17 MSP 0x24001F54
18:32:59:619 : w ap 0 reg 18 PSP 0x00000000
18:32:59:619 : run ap 0
18:33:00:263 : w ap 0 @0x24040E80 : 0x0003EF00 bytes, Data 0xFE39FF0F...
18:33:00:265 : W B2 in RAM @0x24040E80 size 0x0003EF00: 0678ms
18:33:04:590 : r ap 0 reg 0 R0 0x00000000
18:33:04:594 : halt ap 0 Status = 0
18:33:04:594 : halt ap 1 Status = 32
18:33:04:594 : halt ap 2 Status = 32
18:33:06:001 : halt ap 3 Status = 17
18:33:06:001 : w ap 0 reg 15 PC (0x24000000)
18:33:06:001 : w ap 0 reg 17 MSP (0x24000500)
18:33:06:004 : w ap 0 reg 16 xPSR (0x01000000)
18:33:06:004 : Loader write range...
18:33:06:545 : w ap 0 @0x24001F80 : 0x0003EF00 bytes, Data 0x4EDAD666...
18:33:06:545 : W B1 in RAM @0x24001F80 size 0x0003EF00 : 0544ms
18:33:06:551 : halt ap 0
18:33:06:551 : r ap 0 reg 0 R0 0x00000000
18:33:06:552 : Error: failed to download Segment[0]
18:33:06:552 : Error: failed to download the File

 

Tesla DeLorean
Guru
January 2, 2025

Mass Erase can fail if any of the BP (Block Protect) bits in the Status Register (1) are set.

The Cypress/Infineon S25HL512T type memories can come in all kinds of variants with different sector/page sizes and combinations, or more uniform block sizes.

Perhaps dump all 6 bytes from the READ ID to ensure you're looking at the same devices.

Make sure to explicitly clear sCommand structure in auto/local variable usage, as otherwise can contain random stack junk.

 

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
TDK
January 7, 2025

Perhaps show a complete example that exhibits the problem. Remove the code complexity and only include writing to the QSPI and then reading from it, showing the issue.

Since you can read from it in non-memory mapped mode, and STM32CubeProgrammer can read it correctly, seems like a bug in the code to me.

"If you feel a post has answered your question, please click ""Accept as Solution""."
ronnietango
Associate II
January 21, 2025

OK I've managed to get it working, although the solution surprises me somewhat.

It turns out that in order for the memory mapped mode to work correctly, the Write Enable (0x06) command needs to be sent first. This only needs to happen once for each chip - if you comment it out after having run it once, everything still works properly.

This is how the same code (without Write Enable) was working on my old boards (but not the new ones) - they must have run the Write Enable command at some point in the distant past, which I then removed from the firmware because I thought it wasn't necessary (because I'm only ever reading from the memory in this application.)

I still can't find anything in the S25HL512TFAMHI010 datasheet which states that this should be required - the Write Enable command is listed as a Prerequisite Transaction for various operations, but not for the read operation (RDAY4_4_0 = 0x6C) that I'm using in memory mapped mode - perhaps I'm missing something? In any case it's working now.

Thanks everyone for your help!