2021-11-17 02:25 PM
Some Background:
MCU: STM32L4R9ZGJ6
SDK: STM32Cube_FW_L4_V1.14.0
Programmer: STM32CubeProgrammer v2.2.0
External Flash: OSPI (MT35XL512ABA1G12)
Application IDE: STM32Cube IDE 1.6.1
External Loader IDE: Keil uVision 5.16a
Project is was started on the STM32L4R9I-DISCO development kit. We have been on a custom board for over a year without issues.
Hello,
I encountered a strange issue today when loading data to an OSPI flash memory using a custom external loader (*.stldr). This external loader has been working fine for ~2 years when loading ~2MB of GUI assets to OSPI flash and has not changed during this time. Today, I attempted to write 32 bytes of data to a specific region in OSPI flash in addition to the GUI assets that are already written and the 32 bytes result in a write failure. If I write 16 bytes it works fine. Trial and error testing shows that if I write anything beyond 16 bytes in addition to the GUI assets, the write fails. The data being written is not contiguous and the 32 bytes are being written to an entirely different sector of OSPI flash. Below is code for both the failure case and passing case:
**** Failure Case -> Write 32 bytes ****
Linker:
flashTest:
{
*(flashTest flashTest.*)
*(.gnu.linkonce.r.*)
. = ALIGN(4);
KEEP(*(.flashTest)) /* Keep variable even if not referenced */
} >OCTOSPI_APP
App code:
const uint8_t testData[] __attribute__((section(".flashTest"))) =
{
0xAA, 0xBB, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xAA, 0xAB,
0xAA, 0xBB, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xAA, 0xAB,
};
STM32CubeProgrammer verbose error log (Level 3): 32ByteProgramFail.log (Attached)
**** Success Case -> Write <= 16 bytes ****
Linker (Same as above):
flashTest :
{
*(flashTest flashTest.*)
*(.gnu.linkonce.r.*)
. = ALIGN(4);
KEEP(*(.flashTest)) /* Keep variable even if not referenced */
} >OCTOSPI_APP
App code:
const uint8_t testData[] __attribute__((section(".flashTest"))) =
{
0xAA, 0xBB, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xAA, 0xAB,
};
STM32CubeProgrammer verbose error log (Level 3): 16ByteProgramSucceed.log (Attached)
For reference, here is how the linker places the GUI assets in OSPI flash:
/* Constant data into "OCTOSPI_GUI" Memory Mapped Flash type memory (TouchGFX GUI generated assets) */
ExtFlashSection :
{
*(ExtFlashSection ExtFlashSection.*)
*(.gnu.linkonce.r.*)
. = ALIGN(4);
} >OCTOSPI_GUI
Summary:
It baffles me how I can write 2 MB of GUI data to one location, but fail to write 32 bytes to another, yet writing anything less than 16 bytes works so long as it is 4-byte aligned. I thought maybe it was an alignment issue and tried 20 bytes, 24 bytes, 28 bytes, etc with the same failure. I even tried a different region of OSPI flash memory.
Questions:
1. Any clue to what may be causing this strange failure?
2. What is the best way to debug the external loader in real-time while STM32CubeProgrammer is using it? Is this even possible? The external loader project is built using Keil uVision.
Thanks,
Derek
Solved! Go to Solution.
2021-11-17 07:45 PM
You can't debug it in the single-step sense, but all the functionality of your board is at your disposal, so you can drive GPIO/LEDs, screens, etc and send loads of telemetry and reporting to a USART to display in a terminal application. You can instrument your code to understand internal status, errors and flow.
You can't really interact with it as the programmer software has expectations of responsiveness and has timeouts.
Not sure what's wrong here, but STM32 Cube Programmer isn't exactly something I'd describe as robust. And you're using a prehistoric version. The ST-LINK Utilities were better. Try also the GUI vs CLI invocation of Cube Programmer.
No caching on the L4, so not that. The H7 had some quirky end-of-memory issues in the last 32-bytes of QSPI space.
The OSPI switching in/out of memory-mapped mode and reseting the memory/interface can be problematic.
The write page size is 256-bytes (probably).
I'd probably double check the memory being written too is really blank.
For Keil you could create an equivalent .FLM and test that, the .STLDR is a rougher version
2021-11-17 07:45 PM
You can't debug it in the single-step sense, but all the functionality of your board is at your disposal, so you can drive GPIO/LEDs, screens, etc and send loads of telemetry and reporting to a USART to display in a terminal application. You can instrument your code to understand internal status, errors and flow.
You can't really interact with it as the programmer software has expectations of responsiveness and has timeouts.
Not sure what's wrong here, but STM32 Cube Programmer isn't exactly something I'd describe as robust. And you're using a prehistoric version. The ST-LINK Utilities were better. Try also the GUI vs CLI invocation of Cube Programmer.
No caching on the L4, so not that. The H7 had some quirky end-of-memory issues in the last 32-bytes of QSPI space.
The OSPI switching in/out of memory-mapped mode and reseting the memory/interface can be problematic.
The write page size is 256-bytes (probably).
I'd probably double check the memory being written too is really blank.
For Keil you could create an equivalent .FLM and test that, the .STLDR is a rougher version
2021-11-18 11:10 AM
Well darn, thank you kindly @Community member . I updated to STM32CubeProgrammer 2.8.0 and it worked first try. Must have been a bug in CubeProgrammer. I also program directly from CubeIDE 1.6.1 with the external loader, but CubeIDE comes with CubeProgrammer v2.7.0-RC1 so I am updating CubeIDE to 1.7 now to hopefully resolve the programming failure from within CubeIDE. I will update this thread after testing (It's taking forever to update).
Edit: Looks like CubeIDE 1.7 isn't compatible with our current TouchGFX framework. Now to determine if I can use the latest CubeProgrammer with CubeIDE 1.6.1.
Thanks,
Derek
2021-11-18 11:32 AM
Cool
In a real debug sense the typical approach would be to make an application framework to load/run the loader code within your normal build/test environment, and make test cases to run through normal use cases. This can be done for Keil .FLM and ST .STLDR approaches.
Creating and testing a BSP that both your app and loader can use interchangeably can also save a lot of time.
2021-11-18 02:33 PM
Doesn't look like I can easily replace the STM32CubeProgrammer 2.7 plugin in CubeIDE 1.6.1 with the STM32CubeProgrammer 2.8 plugin. CubeIDE doesn't seem to find the programmer tool in my failed attempt. I have resorted to fixing the build errors when updating to CubeIDE 1.7. The code compiles fine in CubeIDE 1.6.1 but generates the errors in the attached log in Cube 1.7. Is there some sort of TouchGFX migration guide for CubeIDE 1.7?
Thanks,
Derek
2021-11-18 03:08 PM
Can't say I've tried, can you just rename the file of the substitute EXE/DLL (best not to install into Program Files)
In Keil it was pretty easy to swap ST-LINK, J-LINK DLLs
2021-11-18 03:25 PM
@Community member I gave getting CubeProgrammer 2.8 working in CubeIDE 1.6.1 another shot. The STM32Cube plugin folder for CubeProgrammer has a dozen or so dll's. I initially tried replacing everything in the /bin folder to no avail. I managed to get it to work by replacing only the STM32_Programmer_CLI.exe file with the one included in CubeIDE 1.7. The external loader now works within CubeIDE 1.6.1. This is a much easier solution than figuring out the CubeIDE 1.7 TouchGFX build issues. Hopefully this doesn't lead to other programming issues down the road.
Full path for reference: C:\ST\STM32CubeIDE_1.6.1\STM32CubeIDE\plugins\com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.win32_1.6.0.202101291314\tools\bin\STM32_Programmer_CLI.exe
Thanks again for your help!
Derek