2024-03-23 03:31 AM
Hello,
I'm trying to develop a custom external loader for STM32WL5 device, in a custom board using SPI flash memory Winbond W25Q80DV.
In the past I've already developed external loaders successfully for other MCUs and boards.
I again followed the steps described by official documentation, hints on this forum, examples in folder bin/ExternalLoader of CubeProgrammer: I set up a new project with CubeIDE, compiled, created .stldr file and copied it in ExternalLoader folder. If I debug the project everything is ok. Besides, opening CubeProgrammer, I correctly see my new external loader in external loader list and information provided are correct.
The problem is that when I try to read from the SPI flash mapped address (set to 0x9000 0000 in this case) using CubeProgrammer, the procedure fails. Selecting Verbosity level 3, I can see these messages:
11:11:37:994 : UR connection mode is defined with the HWrst reset mode
11:11:38:061 : ST-LINK SN : 54FF69066685495419301687
11:11:38:062 : ST-LINK FW : V2J43S7
11:11:38:062 : Board : --
11:11:38:062 : Voltage : 3.22V
11:11:38:062 : SWD freq : 4000 KHz
11:11:38:062 : Connect mode: Normal
11:11:38:062 : Reset mode : Hardware reset
11:11:38:062 : Device ID : 0x497
11:11:38:063 : Revision ID : Rev Y
11:11:38:063 : Reading data...
11:11:38:063 : r ap 0 @0x1FFF7550 0x00000004 bytes Data 0x0000FFFF
11:11:38:063 : Reading data...
11:11:38:063 : r ap 0 @0x1FFF7550 0x00000004 bytes Data 0x0000FFFF
11:11:38:063 : Database: Config 1 is active.
11:11:38:063 : r ap 0 @0x1FFF73F8 0x00000004 bytes Data 0x38100002
11:11:38:064 : r ap 0 @0x1FFF73FC 0x00000004 bytes Data 0x46AFDBD1
11:11:38:064 : flash loader C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer3\bin/FlashLoader/0x497.stldr is loaded
11:11:38:064 : Debug in Low Power mode is not supported for this device.
11:11:38:064 : r ap 0 @0x1FFF73F8 0x00000004 bytes Data 0x38100002
11:11:38:064 : r ap 0 @0x1FFF73FC 0x00000004 bytes Data 0x46AFDBD1
11:11:38:064 : Reading data...
11:11:38:064 : r ap 0 @0x1FFF75E0 0x00000004 bytes Data 0xFFFF0100
11:11:38:064 : r ap 0 @0x1FFF3EFE 0x00000004 bytes Data 0x008800C4
11:11:38:333 : r ap 0 @0x1FFF73F8 0x00000004 bytes Data 0x38100002
11:11:38:334 : r ap 0 @0x1FFF73FC 0x00000004 bytes Data 0x46AFDBD1
11:11:38:334 : r ap 0 @0x1FFF3EFE 0x00000004 bytes Data 0x008800C4
11:11:38:334 : Selected loader: C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer3\bin/ExternalLoader/W25Q80DV_Term_Redox.stldr
11:11:38:334 : Selected loader: C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer3\bin/ExternalLoader/W25Q80DV_Term_Redox.stldr
11:11:38:334 : External loader C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer3\bin/ExternalLoader/W25Q80DV_Term_Redox.stldr is loaded
11:11:38:334 : UPLOADING OPTION BYTES DATA ...
11:11:38:334 : Bank : 0x00
11:11:38:334 : Address : 0x58004020
11:11:38:334 : Size : 96 Bytes
11:11:38:334 : Reading data...
11:11:38:334 : r ap 0 @0x58004020 0x00000060 bytes Data 0x3BFFF0AA
11:11:38:335 : Bank : 0x01
11:11:38:335 : Address : 0x58004080
11:11:38:335 : Size : 8 Bytes
11:11:38:335 : Reading data...
11:11:38:335 : r ap 0 @0x58004080 0x00000008 bytes Data 0x80FF00FF
11:11:38:335 : UPLOADING OPTION BYTES DATA ...
11:11:38:336 : Bank : 0x00
11:11:38:336 : Address : 0x58004020
11:11:38:336 : Size : 96 Bytes
11:11:38:336 : Reading data...
11:11:38:336 : r ap 0 @0x58004020 0x00000060 bytes Data 0x3BFFF0AA
11:11:38:336 : Bank : 0x01
11:11:38:336 : Address : 0x58004080
11:11:38:336 : Size : 8 Bytes
11:11:38:336 : Reading data...
11:11:38:337 : r ap 0 @0x58004080 0x00000008 bytes Data 0x80FF00FF
11:11:38:337 : r ap 0 @0x1FFF73F8 0x00000004 bytes Data 0x38100002
11:11:38:337 : r ap 0 @0x1FFF73FC 0x00000004 bytes Data 0x46AFDBD1
11:11:38:337 : r ap 0 @0x1FFF3EFE 0x00000004 bytes Data 0x008800C4
11:11:38:337 : UPLOADING ...
11:11:38:337 : Size : 1024 Bytes
11:11:38:337 : Address : 0x90000000
11:11:38:337 : Read progress:
11:11:38:337 : Reading data...
11:11:38:337 : halt ap 0
11:11:38:338 : w ap 0 reg 15 PC (0x20000000)
11:11:38:338 : w ap 0 reg 17 MSP (0x20000500)
11:11:38:338 : w ap 0 reg 16 xPSR (0x01000000)
11:11:38:339 : Loader read...
11:11:38:339 : Init flashloader...
11:11:38:340 : halt ap 0
11:11:38:340 : w ap 0 reg 0 R0 0x00000000
11:11:38:340 : w ap 0 reg 1 R1 0x00000000
11:11:38:341 : w ap 0 reg 2 R2 0x00000000
11:11:38:341 : w ap 0 reg 3 R3 0x00000000
11:11:38:342 : w ap 0 reg 4 R4 0x00000000
11:11:38:342 : w ap 0 reg 5 R5 0x00000000
11:11:38:343 : w ap 0 reg 6 R6 0x00000000
11:11:38:343 : w ap 0 reg 7 R7 0x00000000
11:11:38:343 : w ap 0 reg 8 R8 0x00000000
11:11:38:343 : w ap 0 reg 9 R9 0x00000000
11:11:38:343 : w ap 0 reg 10 R10 0x00000000
11:11:38:343 : w ap 0 reg 11 R11 0x00000000
11:11:38:343 : w ap 0 reg 12 R12 0x00000000
11:11:38:344 : w ap 0 reg 13 SP 0x00000000
11:11:38:344 : w ap 0 reg 14 LR 0x00000000
11:11:38:344 : w ap 0 reg 15 PC 0x20000009
11:11:38:344 : w ap 0 reg 16 xPSR 0x01000000
11:11:38:344 : w ap 0 reg 17 MSP 0x00000000
11:11:38:344 : w ap 0 reg 18 PSP 0x00000000
As you can see, after the step
11:11:38:338 : w ap 0 reg 15 PC (0x20000000)
11:11:38:338 : w ap 0 reg 17 MSP (0x20000500)
11:11:38:338 : w ap 0 reg 16 xPSR (0x01000000)
a step is missing where the code is actually loaded in MCU ram at address 0x2000 0004.
If I try to select other external loaders in the list, those, for example, developed for STM32H7 MCUs, the result is the same.
Instead, for a few other loaders, for example N25Q256A_STM32L476G-EVAL loader, the code loading step is actually done (in red):
11:20:26:349 : w ap 0 reg 15 PC (0x20000000)
11:20:26:349 : w ap 0 reg 17 MSP (0x20000500)
11:20:26:349 : w ap 0 reg 16 xPSR (0x01000000)
11:20:26:354 : w ap 0 @0x20001680 : 0x00000200 bytes, Data 0x00000000...
11:20:26:354 : w ap 0 @0x20000000 : 0x00000004 bytes, Data 0x0000BE00...
11:20:26:392 : w ap 0 @0x20000004 : 0x00001258 bytes, Data 0xB085B500...
11:20:26:392 : Loader read...
11:20:26:392 : Init flashloader...
I've done another test: if I try to use the CubeProgrammer software with another board equipped with STM32H735 MCU, regardless of the external loader selected, the code is ALWAYS loaded in ram.
I'm asking for your help and hints.
Anybody knows the reason of this weird behaviour?
Am I missing anything or making some mistakes?
Thank you very much.
Solved! Go to Solution.
2024-03-24 12:57 PM
Previously I forgot to mention that I've already tested all the functions in debug in user space and everything worked correctly, sorry.
Anyway in the meantime I've done other tests and actually I confirm that it seems a stack overflow issue.
Infact I've drastically simplified the spif driver, trying to reduce the nested calls of the functions and so it works also from CubeProgrammer: I've been able to read the correct data and to erase the chip.
Now I will do deeper tests and, above all, I'll set up an IDE project with objects allocated in the memory mapped space of the spi flash memory (0x9000 0000) to verify the write functionality of the external loader also from the debug launcher of the IDE.
I will let you know.
Thank you very much in the meantime.
2024-03-23 05:46 AM
Likely related to the structuring of the .ELF file (STLDR), could perhaps review with things like OBJCOPY or FROMELF
MX25L4006E_STM32WL5M-SUBG.stldr loads at 0x20000004, but only takes about 11 KB
2024-03-24 05:43 AM
Hello Tesla DeLorean,
thank you very much. I followed your suggestion: actually bin files obtained with objcopy were very different. In .bin file from MX25L4006E_STM32WL5M-SUBG.stldr at the beginning there is the devInfo struct and then, after 0x2000 0000 bytes (all zero), there is the code. Then I tried to use your .ld file (ExternalLoader.ld) and magically also the .bin file obtained from my .elf file had that structure and finally was loaded in ram by CubeProgrammer.
Now I have another weird problem: yesterday I was working with an external loader code reduced for the sake of testing the procedure (the only thing Init function did was returning 1); then, after adding the whole code, the program is not loaded again anymore in ram. Why this?
It seems that if the .prog section is small ( about 4 kB) CubeProgrammer loads to ram, instead if .prog section is bigger (about 12 kB) CubeProgrammer doesn't load it (also if MCU ram is 32kB big).
I did this test with different sizes and I actually observed this behaviour.
Do you agree?
Finally another question: How msp is set by the CubeProgrammer? I noticed that msp is assigned an address if the load is successfull but I can't understand the logic of this assignment.
Thank you very much again.
2024-03-24 08:06 AM
Fresh update: refactoring and reducing at the maximum the code, I've been able to make it load by the CubeProgrammer, but now I have a problem with the Read function.
If the code of the function is like this:
int __attribute__((section(".text.Read"))) Read (uint32_t Address, uint32_t Size, uint8_t* buffer)
{
for( uint32_t i=0; i < Size; i++ )
{
*buffer = 0xAE;
buffer++;
}
return 1;
}
Ok, I see in the Device memory window the bytes filled with 0xAE.
But if the code is like this:
int __attribute__((section(".text.Read"))) Read (uint32_t Address, uint32_t Size, uint8_t* buffer)
{
SPIF_ReadAddress(&spif, Address, buffer, Size);
return 1;
}
I don't read the content of the flash memory (erased so all at 0xFF) but I read all ZERO.
Also if the code is like that:
int __attribute__((section(".text.Read"))) Read (uint32_t Address, uint32_t Size, uint8_t* buffer)
{
SPIF_ReadAddress(&spif, Address, buffer, Size);
for( uint32_t i=0; i < Size; i++ )
{
*buffer = 0xAE;
buffer++;
}
return 1;
}
I read all ZERO and not 0xAE.
It seems a problem of stack pointer that exceeds. I noticed from the log window of the CubeProgrammer that it is set to a strange value 0x2000 2C80 , instead of being set to the upper limit of the memory (0x2000 7FFC).
16:00:48:829 : w ap 0 reg 14 LR 0x20000001
16:00:48:830 : w ap 0 reg 15 PC 0x2000006D
16:00:48:834 : w ap 0 reg 16 xPSR 0x01000000
16:00:48:835 : w ap 0 reg 17 MSP 0x20002C80
Is there a reason for this?
Thank you again
2024-03-24 09:55 AM
You can output diagnostic and telemetry data out of a serial port.
The stack pointer is determines by how much space the loader takes up. It doesn't have to be at the end of RAM, and in fact the remainder of RAM is used as a transfer buffer, or pair of them, for the Read,Write and Verify actions.
I can't explain why the last 0xAE example didn't work as expected. Are you sure the loader was copied over to the directory, and Cube Programmer was restarted.
If you can test the code in user space, as an application or framework, it will be easier to debug. You want to be sure the SPI/FLASH functions are working correctly.
2024-03-24 12:57 PM
Previously I forgot to mention that I've already tested all the functions in debug in user space and everything worked correctly, sorry.
Anyway in the meantime I've done other tests and actually I confirm that it seems a stack overflow issue.
Infact I've drastically simplified the spif driver, trying to reduce the nested calls of the functions and so it works also from CubeProgrammer: I've been able to read the correct data and to erase the chip.
Now I will do deeper tests and, above all, I'll set up an IDE project with objects allocated in the memory mapped space of the spi flash memory (0x9000 0000) to verify the write functionality of the external loader also from the debug launcher of the IDE.
I will let you know.
Thank you very much in the meantime.
2024-03-30 08:04 AM
Hello,
I've done deep tests and I can say that now it works. It definitively was a problem of stack and ram too big.
Thank you very much for your very useful and appreciated help.