2025-08-25 7:36 AM
Dear STM32 Community,
We believe that the example projects provided for the STM32Cube embedded software are a valuable resource when developing projects.
We would like to better understand how developers use these examples in their workflow and explore ways to improve them. Therefore, we have a few questions we would like to ask:
From where do you obtain the examples, and why?
How do you use the examples in your work with STM32 embedded software?
What is working well, and what can we do to improve the examples and/or your experience working with them?
You can either reply directly in this thread or feel free to send me a private message.
Best regards,
Emil
2025-09-02 10:37 AM
I'll agree. Perhaps a different example code schema would be to write your code, then in a specific section do something like:
//*********************************************************************************
// Code here to write one character to the USART, assuming that the USART is already initialized
// example for HAL and CUBEMX using blocking send:
result = HAL_UART_Transmit(huart, dataptr, data_count, 20);
if (LF) result = HAL_UART_Transmit(huart, (uint8_t*)&terminate[0], sizeof(terminate), 20);
// ********************************************************************************
Using a usart send as an example.
Your BSP packages are so specific to a board as to limit them only to running a demo on your specific hardware.
You have experts in BSP packages, experts in LL packages, and experts in HAL packages. Simple #ifdef statements can control which gets used, and each expert can contribute their own connection to the driver.
2025-09-15 11:03 PM
Hello,
As other mentioned BSP package can be a nightmare.
When you devlopp a custom PCB you can spend a lot of time debugging code !!!
Other when using DMA2D on STM32N6 after one week of debugging i had the not pleasant surpise to discover that the example had code put in the USER CODE section to make it work .
I think that examples should mention when code for driver other than cube MX is used !!!!!
2025-09-16 11:06 AM - edited 2025-09-16 11:07 AM
Hello @Harvey White,
Sorry for my late replies, but to me it sounds more like an issue with how HAL is working with FreeRTOS rather than the examples. This type of feedback is also really appreciated.
For HAL and RTOS it is issue we are aware and are trying to solve in the future. Maybe you have seen the preview of HAL2 (https://community.st.com/t5/developer-news/get-a-preview-of-the-latest-stm32cube-hal-update-for-stm32u5-on/ba-p/821784) where the HAL is redesigned to work better with a RTOS
Just a FYI regarding AZURE, we have realized that this is not the solution we thought it would be and have therefore pivoted back to FreeRTOS (https://community.st.com/t5/developer-news/new-strategic-directions-for-stm32cube/ba-p/799537)
Best Regards,
Emil
2025-09-16 11:21 AM
Hello @Harvey White, @chornbeck, @Hamady and @john37
How would I fit with your way of work, if we changed the BSP code with code generated from STM32CubeMX and application code with a clear separation between the two, by having MX generated code in one set of files that the application code calls, in a structure like this?:
Best Regards,
Emil
2025-09-16 11:25 AM
@john37, for references could it be referring some of our own documentation?
We are putting in place new type of online doc, and could therefore make references like this one to our ADC (https://dev.st.com/stm32cube-docs/stm32u5-hal2/2.0.0-beta.1.1/docs/drivers/hal_drivers/adc/hal_adc_overview.html#hal-adc-overview) as an example. Also to the relevant API description e.g. ADC START (https://dev.st.com/stm32cube-docs/stm32u5-hal2/2.0.0-beta.1.1/docs/drivers/hal_drivers/adc/api/hal_adc_exported_functions.html#_CPPv413HAL_ADC_StartP16hal_adc_handle_t)
Best Regards,
Emil
2025-09-16 7:19 PM
No problem with the late replies.
2025-09-16 7:39 PM
I'd be concerned that as long as I have to go through and rewrite all the low level calls, that I need to do this only one time and let the driver (or a global) figure out which driver to call.
From what I can see, the only use for a BSP package is to run pre packaged demos that do not (IMHO) contribute to learning much, if anything. The problem is that you do not generate BSP code anywhere. I have to dig the code out of the examples, and IIRC, the examples are not well documented, and are not written to play nice with other code. The HAL2 drivers at least allow you to make a choice between the LL and the HAL level drivers.
Given that choice. I really don't care whether or not when I call a HAL2 driver if it uses LL drivers or higher level HAL2 drivers, as long as it works. If you shifted to BSP drivers, I wouldn't notice as long as they were more or less compatible with the HAL drivers (in terms of function).
I tend to be far more interested in the "get it done" approach to drivers, as long as they do what I need to do. I generally don't care what's under the hood.
My software uses a lot of #ifdef to control operation. Want a serial port, change the #ifdef (uncomment it), and so on. You may consider the same approach.
What I'd like to see, given that you support more than one OS, is a definition that switches that OS in and out as needed.
I do like the idea of a mode on a driver to use DMA or not, IRQ or not, blocking or not, and if an OS is defined, a queue or not. These choices are not useful for all driver situations (SPI, I2C, Serial are all I use), but a good HAL2 driver should address these (and quite frankly, if you use the IOC file, then please put in the callbacks as needed).
2025-09-19 1:46 PM
I liked the idea so much that I decided to see if it would work. I have a partial implementation using embOS and FreeRTOS. Full testing of emBOS is going to require a lot of work, but the implementation should be more or less straight forward. For how to do the actual substitutions, I'm using the instructions from Segger: https://www.segger.com/products/rtos/embos/
File wise, OS_MACROS.h contains the main data, and HAL_I2C shows how to paste in the definitions of the OS handles, and the part in HAL_I2C.cpp shows how to insert the code. It's still in progress, though. The normal FreeRTOS views do show the proper creation of the semaphore.
For the macros:
/*******************************************************************************************************************
* MACRO SUBSTITUTIONS
* INCLUDE FILES
*
******************************************************************************************************************/
// SEMAPHORES
//
// all FreeRTOS macros
#ifdef _FREERTOS
// semaphore:
// _WHICH is SemaphoreHandle_t, _DELAY not implemented since this is blocked
// semaphore is created and given, so that the next _SEMAPHORE_GET will work automatically
// this is a binary semaphore, non-counting
#define _SEMAPHORE_CREATE(_WHICH) _WHICH = xSemaphoreCreateMutex(); xSemaphoreGive(_WHICH);
#define _SEMAPHORE_GET (_WHICH, _DELAY) xSemaphoreTake(_WHICH, DELAY);
#define _SEMAPHORE_RELEASE (_WHICH) xSemaphoreGive(_WHICH);
#endif
which is how the FreeRTOS would work. Note that this and the embOS implementations make significant compromises because of the different way the two OS treat a semaphore.
#ifdef _EMBOS
// semaphore:
// _WHICH is OS_SEMAPHORE*, _DELAY in macro is ignored
// _WHICH is a pointer to OS_MUTEX
#define _FOREVER 0
#define _SEMAPHORE_CREATE(_WHICH) OS_SEMAPHORE_Create(_WHICH); OS_SEMAPHORE_GiveMax(_WHICH,1); // uses macro for zero count
#define _SEMAPHORE_GET (_WHICH, _DELAY) OS_SEMAPHORE_TakeBlocked(_WHICH); // delay is ignored
#define _SEMAPHORE_RELEASE (_WHICH) OS_SEMAPHORE_Give(_WHICH);
#endif
and to illustrate the creation of the semaphore:
_SEMAPHORE_CREATE(busy);
//#ifdef _FREERTOS_STATIC
// busy = xSemaphoreCreateBinaryStatic( &static_map.I2C_STATIC[(uint8_t)which].BSemaphoreBuffer );
//#else
// busy = xSemaphoreCreateBinary();
//#endif
//
and for the .hpp file, which is made from a template.
// *********************************************** SEMAPHORE ******************************************************
#ifdef _FREERTOS
SemaphoreHandle_t busy;
#endif
#ifdef _EMBOS
OS_SEMAPHORE busy;
#endif
Design notes:
Names of the macros are chosen to (hopefully) conflict with no existing names. Note that enabling _EMBOS and disabling _FREERTOS should take care of everything.
Some of the arguments are ignored, which might give flexibility from OS to OS. See the notes in the OS_MACRO.h file for the reasoning
Looks as if it might work well, as long as the differences between OS can be ironed out.
2025-09-19 3:36 PM
Concept seems to work just fine.
However..........
embOS and FreeRTOS are apparently determined to be very different from each other, number of arguments, and what is returned.
Time for Plan B,
Replace the macros by functional programming.
More to come.
2025-09-25 1:43 PM
Primarily, I usually like to get the examples from the latest MCU packages so I can also use that folder to "grep" through when I am looking for something. Never tried the STM32CubeMX Example selector. I may have accessed them through github a couple of times. I like the idea of being able to see the rev history for them in github.
I usually run the examples first as-is to learn how the HAL calls work together, then I use it as a reference for writing what I need (which will differ).
I feel like the examples usually work, but If I could pick an area where I would like more examples it would definitely be "low power" (sleep, stop, etc, and multiple modes here). This area seems to have the most variation when jumping from different stm32 mcus (lots of nuances and differences).