Skip to main content
Explorer
January 2, 2025
Question

QSPI reads only 0x9999

  • January 2, 2025
  • 4 replies
  • 1827 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.

    4 replies

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

    Explorer
    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?

    Super User
    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?

     

     

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

    Explorer
    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

     

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

     

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

    Explorer
    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!