2024-03-14 07:47 AM - edited 2024-03-14 07:48 AM
Hi
I am trying to get a custom external loader working on a STM32L562VET with a MT25QL128ABA attached over QuadSPI. I have followed this tutorial: https://www.st.com/content/st_com/en/support/learning/stm32-education/stm32-moocs/external_QSPI_loader.html
and after some modifications, I managed to successfully run the main_test code and everything seems to work fine. I can also see the data in the memory viewer in the STM32CubeIDE.
I then continued to build the *.stldr which also seem to work fine. However when I import it in STMCubeProgrammer v2.15.0, I can erase certain sectors or the whole chip. But if I try to download a .bin file (256Bytes random ASCII), I get the following error messages:
15:39:48 : Error: failed to download Segment[0]
15:39:48 : Error: failed to download the File
If I go back to the memory viewer, I can see that the data was successfully written to the flash despite the error message. What could be the problem here?
I already tried with STMCubeProgrammer v2.6.0 but get the same error message.
This is the log I get:
15:43:24:265 : Memory Programming ...
15:43:24:265 : Opening and parsing file: output-onlinefiletools.bin
15:43:24:266 : File : output-onlinefiletools.bin
15:43:24:266 : Size : 256.00 B
15:43:24:266 : Address : 0x90000000
15:43:24:266 : Erasing Segment <0> Address <0x90000000> Size <256>Bytes
15:43:24:266 : Erasing memory corresponding to segment 0:
15:43:24:266 : Memory Erase via FlashLoader!
15:43:24:266 : Memory erase...
15:43:24:272 : halt ap 0
15:43:24:272 : w ap 0 reg 15 PC (0x20000000)
15:43:24:272 : w ap 0 reg 17 MSP (0x20000500)
15:43:24:272 : w ap 0 reg 16 xPSR (0x01000000)
15:43:24:276 : w ap 0 @0x20012B60 : 0x00000200 bytes, Data 0x00000000...
15:43:24:276 : w ap 0 @0x20000000 : 0x00000004 bytes, Data 0x0000BE00...
15:43:24:778 : w ap 0 @0x20000004 : 0x00012728 bytes, Data 0x00000000...
15:43:24:778 : Erasing external memory sector 0
15:43:24:778 : Init flashloader...
15:43:24:778 : halt ap 0
15:43:24:778 : w ap 0 reg 0 R0 0x00000001
15:43:24:779 : w ap 0 reg 1 R1 0x00000000
15:43:24:779 : w ap 0 reg 2 R2 0x00000000
15:43:24:779 : w ap 0 reg 3 R3 0x00000000
15:43:24:779 : w ap 0 reg 4 R4 0x00000000
15:43:24:779 : w ap 0 reg 5 R5 0x00000000
15:43:24:779 : w ap 0 reg 6 R6 0x00000000
15:43:24:779 : w ap 0 reg 7 R7 0x00000000
15:43:24:779 : w ap 0 reg 8 R8 0x00000000
15:43:24:779 : w ap 0 reg 9 R9 0x00000000
15:43:24:779 : w ap 0 reg 10 R10 0x00000000
15:43:24:779 : w ap 0 reg 11 R11 0x00000000
15:43:24:779 : w ap 0 reg 12 R12 0x00000000
15:43:24:779 : w ap 0 reg 13 SP 0x00000000
15:43:24:779 : w ap 0 reg 14 LR 0x20000001
15:43:24:779 : w ap 0 reg 15 PC 0x20000731
15:43:24:779 : w ap 0 reg 16 xPSR 0x01000000
15:43:24:779 : w ap 0 reg 17 MSP 0x20012B28
15:43:24:779 : w ap 0 reg 18 PSP 0x00000000
15:43:24:779 : run ap 0
15:43:24:779 : halt ap 0
15:43:24:779 : r ap 0 reg 0 R0 0x00000001
15:43:24:779 : Loader sector erase...
15:43:24:779 : w ap 0 reg 0 R0 0x90000000
15:43:24:779 : w ap 0 reg 1 R1 0x90000000
15:43:24:780 : w ap 0 reg 2 R2 0x00000002
15:43:24:796 : w ap 0 reg 3 R3 0x00000000
15:43:24:799 : w ap 0 reg 4 R4 0x00000000
15:43:24:801 : w ap 0 reg 5 R5 0x00000000
15:43:24:801 : w ap 0 reg 6 R6 0x00000000
15:43:24:802 : w ap 0 reg 7 R7 0x00000000
15:43:24:802 : w ap 0 reg 8 R8 0x00000000
15:43:24:802 : w ap 0 reg 9 R9 0x00000000
15:43:24:802 : w ap 0 reg 10 R10 0x00000000
15:43:24:802 : w ap 0 reg 11 R11 0x00000000
15:43:24:802 : w ap 0 reg 12 R12 0x00000000
15:43:24:802 : w ap 0 reg 13 SP 0x00000000
15:43:24:802 : w ap 0 reg 14 LR 0x20000001
15:43:24:802 : w ap 0 reg 15 PC 0x200007CD
15:43:24:802 : w ap 0 reg 16 xPSR 0x01000000
15:43:24:802 : w ap 0 reg 17 MSP 0x20012B28
15:43:24:802 : w ap 0 reg 18 PSP 0x00000000
15:43:24:802 : run ap 0
15:43:24:903 : halt ap 0
15:43:24:903 : r ap 0 reg 0 R0 0x00000001
15:43:24:903 : erase: 0638ms
15:43:24:903 : Download in Progress:
15:43:24:904 : Size : 256 Bytes
15:43:24:904 : Address : 0x90000000
15:43:24:904 : Buffer program...
15:43:24:912 : halt ap 0
15:43:24:912 : w ap 0 reg 15 PC (0x20000000)
15:43:24:912 : w ap 0 reg 17 MSP (0x20000500)
15:43:24:912 : w ap 0 reg 16 xPSR (0x01000000)
15:43:24:916 : w ap 0 @0x20012B60 : 0x00000200 bytes, Data 0x00000000...
15:43:24:916 : w ap 0 @0x20000000 : 0x00000004 bytes, Data 0x0000BE00...
15:43:25:407 : w ap 0 @0x20000004 : 0x00012728 bytes, Data 0x00000000...
15:43:25:408 : Loader write range...
15:43:25:409 : w ap 0 @0x20012B60 : 0x00000100 bytes, Data 0x6A7D2670...
15:43:25:409 : W B1 in RAM @0x20012B60 size 0x00000100 : 0002ms
15:43:25:409 : Init flashloader...
15:43:25:411 : halt ap 0
15:43:25:411 : w ap 0 reg 0 R0 0x00000001
15:43:25:411 : w ap 0 reg 1 R1 0x00000000
15:43:25:412 : w ap 0 reg 2 R2 0x00000000
15:43:25:412 : w ap 0 reg 3 R3 0x00000000
15:43:25:412 : w ap 0 reg 4 R4 0x00000000
15:43:25:412 : w ap 0 reg 5 R5 0x00000000
15:43:25:413 : w ap 0 reg 6 R6 0x00000000
15:43:25:413 : w ap 0 reg 7 R7 0x00000000
15:43:25:414 : w ap 0 reg 8 R8 0x00000000
15:43:25:414 : w ap 0 reg 9 R9 0x00000000
15:43:25:415 : w ap 0 reg 10 R10 0x00000000
15:43:25:415 : w ap 0 reg 11 R11 0x00000000
15:43:25:416 : w ap 0 reg 12 R12 0x00000000
15:43:25:416 : w ap 0 reg 13 SP 0x00000000
15:43:25:416 : w ap 0 reg 14 LR 0x20000001
15:43:25:417 : w ap 0 reg 15 PC 0x20000731
15:43:25:417 : w ap 0 reg 16 xPSR 0x01000000
15:43:25:417 : w ap 0 reg 17 MSP 0x20012B28
15:43:25:418 : w ap 0 reg 18 PSP 0x00000000
15:43:25:418 : run ap 0
15:43:25:421 : halt ap 0
15:43:25:421 : r ap 0 reg 0 R0 0x00000001
15:43:25:421 : w ap 0 reg 0 R0 0x90000000
15:43:25:421 : w ap 0 reg 1 R1 0x00000100
15:43:25:421 : w ap 0 reg 2 R2 0x20012B60
15:43:25:421 : w ap 0 reg 3 R3 0x00000002
15:43:25:422 : w ap 0 reg 4 R4 0x00000000
15:43:25:423 : w ap 0 reg 5 R5 0x00000000
15:43:25:423 : w ap 0 reg 6 R6 0x00000000
15:43:25:425 : w ap 0 reg 7 R7 0x00000000
15:43:25:425 : w ap 0 reg 8 R8 0x00000000
15:43:25:426 : w ap 0 reg 9 R9 0x00000000
15:43:25:426 : w ap 0 reg 10 R10 0x00000000
15:43:25:426 : w ap 0 reg 11 R11 0x00000000
15:43:25:426 : w ap 0 reg 12 R12 0x00000000
15:43:25:426 : w ap 0 reg 13 SP 0x00000000
15:43:25:426 : w ap 0 reg 14 LR 0x20000001
15:43:25:427 : w ap 0 reg 15 PC 0x20000789
15:43:25:428 : w ap 0 reg 16 xPSR 0x01000000
15:43:25:429 : w ap 0 reg 17 MSP 0x20012B28
15:43:25:429 : w ap 0 reg 18 PSP 0x00000000
15:43:25:429 : run ap 0
15:43:25:433 : w ap 0 @0x20012B60 : 0x00000100 bytes, Data 0x6A7D2670...
15:43:25:433 : W B2 in RAM @0x20029460 size 0x00000100: 0020ms
15:43:25:433 : r ap 0 reg 0 R0 0x00000001
15:43:25:433 : Wait W B1 in Flash @0x90000000 size 0x00000100: 0001ms
15:43:25:433 : w ap 0 reg 0 R0 0x90000000
15:43:25:433 : w ap 0 reg 1 R1 0x00000100
15:43:25:433 : w ap 0 reg 2 R2 0x20012B60
15:43:25:433 : w ap 0 reg 3 R3 0x00000002
15:43:25:433 : w ap 0 reg 4 R4 0x00000000
15:43:25:433 : w ap 0 reg 5 R5 0x00000000
15:43:25:435 : w ap 0 reg 6 R6 0x00000000
15:43:25:436 : w ap 0 reg 7 R7 0x00000000
15:43:25:436 : w ap 0 reg 8 R8 0x00000000
15:43:25:436 : w ap 0 reg 9 R9 0x00000000
15:43:25:445 : w ap 0 reg 10 R10 0x00000000
15:43:25:446 : w ap 0 reg 11 R11 0x00000000
15:43:25:446 : w ap 0 reg 12 R12 0x00000000
15:43:25:447 : w ap 0 reg 13 SP 0x00000000
15:43:25:447 : w ap 0 reg 14 LR 0x20000001
15:43:25:448 : w ap 0 reg 15 PC 0x20000789
15:43:25:448 : w ap 0 reg 16 xPSR 0x01000000
15:43:25:448 : w ap 0 reg 17 MSP 0x20012B28
15:43:25:448 : w ap 0 reg 18 PSP 0x00000000
15:43:25:448 : run ap 0
15:43:25:448 : r ap 0 reg 0 R0 0x00000000
15:43:25:448 : halt ap 0
15:43:25:448 : w ap 0 reg 15 PC (0x20000000)
15:43:25:448 : w ap 0 reg 17 MSP (0x20000500)
15:43:25:448 : w ap 0 reg 16 xPSR (0x01000000)
15:43:25:448 : Loader write range...
15:43:25:448 : w ap 0 @0x20012B60 : 0x00000100 bytes, Data 0x6A7D2670...
15:43:25:448 : W B1 in RAM @0x20012B60 size 0x00000100 : 0002ms
15:43:25:449 : halt ap 0
15:43:25:449 : r ap 0 reg 0 R0 0x00000000
15:43:25:449 : Error: failed to download Segment[0]
15:43:25:449 : Error: failed to download the File
2024-03-14 11:59 AM - edited 2024-03-14 12:00 PM
Hello @Marcus1
Please check this FAQ: Custom external loader "failed to download segment... - STMicroelectronics Community
I hope this will help.
Please keep me informed about your progress on this issue.
2024-03-14 04:21 PM
Hi @Imen.D,
Thanks for your answer. I already saw that post and tried the suggested modifications but they didn't help. That's also the reason why I switched back to CubeProgrammer v2.6.0.
Maybe the template I used from the following repository is not compatible anymore since it seems outdated? Last change to the repo was 4years ago:
2024-03-14 05:09 PM
Doesn't look an unreasonable starting point.
The log seems to indicate it tries to write twice, failing the second time. You can instrument you loader to use any hardware on your board. You can output diagnostic information via an available UART
BTW what's you pin utilization here?
2024-03-14 06:19 PM - edited 2024-03-14 06:27 PM
@Imen.D Why won't ST implement "universal" QSPI/OSPI loader like Segger did?
If I understand correctly, they've split the loader to MCU specific part (which supports all QSPI pinout variants) and flash memory specific logic that sits on the host. The MCU part reads the standard flash chip info, then the host decides which commands and parameters to use, etc. This way the flash specific algorithm is done only once for all MCUs. As soon as a new flash chip is made known to the host library, all MCUs and boards automatically support it.
There's no more N*M proliferation of loaders, where N are boards/pinouts and M are flash chips. Users won't have to roll their own.
2024-03-15 06:42 AM
I made some more experiments and it seems like the data is not correctly written to the flash from CubeProgrammer. When I write a bin file containing 16bytes "0123456789abcdef", it actually works and I get the message "file download complete" and the memory looks right:
However, when I download a bin file containing 17bytes "0123456789abcdefg", I get the mentioned error message and the 17bytes get correctly written including 3 garbage bytes (randomly):
Here's my pin Cube config:
I also ran this piece of code to fill every sector with the corresponding sector number:
for (var = 0; var < SECTORS_COUNT; var++) {
if (CSP_QSPI_EraseSector(var * MEMORY_SECTOR_SIZE,(var + 1) * MEMORY_SECTOR_SIZE - 1) != HAL_OK) {
while(1); //breakpoint - error detected
}
for (int i = 0; i < MEMORY_SECTOR_SIZE; i++) {
buffer_test[i] = (var & 0xff);
}
if (CSP_QSPI_WriteMemory(buffer_test, var * MEMORY_SECTOR_SIZE, sizeof(buffer_test)) != HAL_OK) {
while(1); //breakpoint - error detected
}
}
That runs fine and I can see the sectors get correctly filled. However I somehow don't manage to erase sectors 128...255. MEMORY_SECTOR_SIZE is 0x10000
next, I will try to print some debug messages over UART as you suggested
2024-03-15 10:30 AM
IAR had a scripting method.
A start at the .STLDR level might be for the tools to dynamically query the StorageInfo.
Say another exported function, which takes as input a pin table, defining GPIO Bank, Pin and AF#, and returns a StorageInfo structure.
There's a couple of things that could be done quite easily without breaking backward compatibility.
2024-03-15 12:30 PM
Tentative L5 build from my OSPI forks.
PA3:AF10 CLK
PA4:AF3 NCS
PB1:AF10 D0
PB0:AF10 D1
PA7:AF10 D2
PA6:AF10 D3
2024-03-18 12:00 PM - edited 2024-03-18 12:08 PM
Hi @Pavel A.,
Now, ST is providing a new solution to customize and generate the external loaders based on two Middlewares: "STM32_ExtMem_Manager" & "STM32_ExtMem_Loader" that are integrated in CubeMX in order to develop the external memory loaders using CubeMX.
This will allow you to develop your external loaders in all IDEs (Keil MDK-ARM, IAR & CubeIDE) for all the same IDEs.
This solution is deployed on STM32H7RS series for the moment and will be used for the next products.
You can find the template under this new package STM32CubeH7RS and used it for your product:
"STM32Cube_FW_H7RS_V1.0.0\Projects\STM32H7S78-DK\Templates\Template_XIP".
Note that this solution supports NOR, SDcard & PSRAM memories.
PS: For the moment, no plan to deploy this in legacy products.
2024-03-19 01:25 AM
Unfortunately, this did not work. However, thanks to the debug UART output, I managed to find the issue. There was something wrong with the de-initialisation of the OSPI in the write function. No idea why this only happened when writing the second time.
However the behavior of CubeProgrammer is still a bit mysterious to me. Like mentioned above, writing a 16byte bin file worked correctly because it was written only once. Here the log of my UART output:
Initialisation
LOADER_OK
Write: 0x90000000 0x10 0123456789abcdef
LOADER_OK
(Write: [Address][length][data])
However a 17byte bin file gets written twice and the length transmitted is not correct and thus there is some garbage data:
Initialisation
LOADER_OK
Write: 0x90000000 0x14 0123456789abcdefg▒▒▒
LOADER_OK
Write: 0x90000000 0x14 0123456789abcdefg▒▒▒
LOADER_OK
Is this a bug or a feature?