2026-03-30 7:04 AM
I'm having an issue with STM32CubeProgrammer v2.22.0. I'm making an external loader for the stm32U031R8 (on the nucleo board). My spi flash code works fine in the my actual application program. If I strip my code down (removing Read,Verify, instrumentation, etc) and get it under the 8K of SRAM1, the programmer works. Once my object is into SRAM2 (0x20002000-0x20002FFF) the programmer behaves incorrectly.
First off, to make sure I understand whats going on, in the good case:
every operation begins with
w ap 0 reg 15 PC (0x20000000)
w ap 0 reg 17 MSP (0x20000500)
w ap 0 reg 16 xPSR (0x01000000)
w ap 0 @0x20001CA0 : 0x00000200 bytes, Data 0x00000000...
w ap 0 @0x20000000 : 0x00000004 bytes, Data 0x0000BE00...
w ap 0 @0x20000004 : 0x0000186C bytes, Data 0xDEC0ADDE...
Not sure why 0x20000500 is chosen as the SP, or what those 0x200 bytes written at 0x20001CA0 are, but I see that a bkpt instruction is written at the base of SRAM1 and then my object is written after that, which makes sense.
Then I see the registers written
w ap 0 reg 0 R0 0x00000001
...
w ap 0 reg 14 LR 0x20000001
w ap 0 reg 15 PC 0x200013F9
w ap 0 reg 16 xPSR 0x01000000
w ap 0 reg 17 MSP 0x20001C6C
...
Not sure why R0 is set to 1 unless it's there in case Init doesn't actually return a value it'll just default to success?
LR points back to the bkpt instruction, so that makes sense.
PC points to the start of Init()
MSP points to a high address, but not the top of my RAM segment or even the top of SRAM1, nor stack_size past the end of my object, and that address is not anything in my elf file; still there seems to be enough stack space of my code to work.
In the bad case, ie, when my object is >8K, the programmer does the first three writes above (ie PC, MSP, xPSR), but doesn't write the bkpt instruction, load any portion of my code, or write those unknown 0x200 bytes (or at least, doesn't log anything). Presumably some code in the CubeProgrammer decided this is an invalid object file (even though there really is 12K SRAM on chip). However, it does proceed to write all the registers and attempt to run the unloaded Init() with the MSP set to 0x0. When it halts it reads R0 which is still the success value it wrote itself, so it carries on and runs the unloaded SectorErase, again with MSP set to 0x0 and R0 set to the external address. Then it checks R0 for success, but it's still the external address and the programmer says the operation failed (with no useful diagnostic like "the sections were too big"). There was also a hardfault somewhere along the line not surprisingly.
If I edit the linker file to specify two separate memory areas (8K-4 and 4K) and place even one unused word in SRAM2, it's still the case that the programmer doesn't load any portion of my code (but goes ahead and tries to run an unloaded Init()).
Note that the bad cases described above assume that I did a power reset after running the good case; I saw some other broken behaviors which in retrospect I assume were due to the programmer does the wrong thing but there still being (now outdated) code in RAM from a previous run.
I haven't tried it yet, but I suspect that if I script the programmer CLI to do all the steps it does in the working case, but using my 12K object file and setting the correct MSP, everything will work fine.