Examples architecture

Examples illustrate how to use HAL/LL drivers, middleware, utilities and parts in a target project. They are intended as learning material and quick-start code snippets rather than reusable libraries.

Example categories

The STM32Cube Software Examples are organized in different categories, each of them illustrating a specific part of the STM32Cube embedded software.

Example categories

Category

Description

advanced

Examples combining several STM32 peripherals to achieve a complex use-case.

hal

Examples demonstrating the use of the STM32 HAL (Hardware Abstraction Layer). HAL examples can use LL APIs for some specific needs and part drivers for LED and user button handling.

ll

Examples demonstrating the use of the STM32 LL (Low Layer) drivers.

middleware

Examples demonstrating the use of the STM32 middleware. Middleware uses both the HAL and part drivers.

parts

Examples demonstrating the use of the part drivers with the STM32 evaluation boards and Discovery kits. Part drivers leverage the HAL drivers too.

templates

Project templates to start developing an STM32 application compliant with the STM32Cube architecture. A template project has the same structure as any example, but with no configuration nor use-case code.

utilities

Examples demonstrating the use of the STM32 utilities.

Programming model

Examples follow simple, application-oriented programming patterns. They typically present a small set of functions that the user can adapt to their project.

Common conventions used across examples:

Common example functions

Function

Description

Code scope

app_init()

Performs board and peripheral initialization.

This code is generated with STM32CubeMX2 and demonstrates how to configure and initialize hardware resources.

app_process()

Application main processing (invoked from the main loop or integrated in FreeRTOS tasks).

This code exercises the use-case logic and demonstrates how to use the software components to achieve the example scenario.

app_deinit()

Optional de-initialization and resource cleanup.

This code is not called in all examples. It demonstrates how to properly release resources.

Execution model

Examples follow a simple infrastructure/use-case separation:

  • main.c implements the example infrastructure (system initialization and scheduler)

  • while example.c implements the use-case logic.

Typical behavior:

  1. main.c calls the system initializer (for example mx_system_init()), then calls app_init() to configure resources required by the scenario.

  2. After initialization, the scheduler in main.c either:

  • repeatedly calls app_process() in a bare-metal infinite loop, or

  • executes app_process() once and then calls app_deinit() and success_handler(), or

  • starts a FreeRTOS task that runs application processing for OS-based examples.

This separation makes examples easy to re-use:

  • the minimal infrastructure in main.c remains stable across examples

  • while example.c contains the portable, copy-paste-worthy code snippets.

State management

Examples follow a two-level state management approach:

Application use-case state

The application use-case code ( example.c ) typically keeps state handling minimal. By default, examples are structured by their three main functions ( app_init() , app_process() , app_deinit() ) and do not implement a complex state machine.

Important

Examples are not intended to provide a full use-case implementation. They offer a starting point and reference for users to build upon, mostly with code-snippets, but they are not meant to be a complete framework. Their main focus is to demonstrate the usage of STM32Cube embedded software and STM32 microcontrollers in a clear and concise way.

Infrastructure state machine

The infrastructure in main.c tracks the example lifecycle and ensures proper execution flow. The ExecStatus state variable guides the execution sequence through:

  1. System and peripheral initialization status

  2. Application processing result (success, error, or unknown)

  3. Optional de-initialization: this can be used to demonstrate resource cleanup and proper shutdown of the example scenario.

  4. Final status reporting

Note

All examples run successfully the intended sequence out of the box. Users can modify the example code to explore different execution paths. This is where the error handling and state management helps identify and understand the impact of changes on the example behavior.

Error handling and user interaction model

The error handling is designed to be simple and lightweight rather than comprehensive. It is meant to identify quickly and visually the success or failure of the example scenario.

It allows identifying two main steps in the example execution:

  1. System and peripheral initialization success or failure: this validates that the hardware resources are correctly configured and ready for use

  2. Application processing success or failure: this indicates whether the main use-case logic executed as expected

Errors are routed to handlers ( error_handler(), success_handler(), HardFault_Handler()) which provide visual feedback through the user LED.

Status reporting

The user LED provides visual feedback of the example execution status:

  • Success: LED remains turned on (example scenario completed successfully)

  • Error: LED flashing (50 ms on, 2 sec off) when error_handler() is active

  • Fault: LED tentatively turned off when a system fault occurs (HardFault_Handler())

User interactions

Examples support typical user interactions to demonstrate scenarios and observe results:

  • User button: triggers events (short or long press, with debouncing handled in hardware or software)

  • Console logs: enabled via the USE_TRACE compiler switch; output is transmitted over the ST-LINK virtual COM port (managed by the Basic STDIO utility)

  • Pinout connections: signals are routed to Arduino® UNO R3, STM32 Zio, or fanout connectors for observation with an oscilloscope or logic analyzer

  • Debugger: examples include debug symbols. The debugger can be used to set breakpoints, inspect variables, and step through code

How to use examples

The typical workflow to use examples is:

  1. Read the example README before running the code.

  2. Use examples as a reference or a starting point: adapt them for your board and map resources using STM32CubeMX2 when appropriate.

  3. Do not treat examples as production-ready modules: re-use the code-snippets in your own application framework.

Documentation and further reading

Each example includes its own README and source-level comments.

For more extensive documentation, refer to the STM32Cube Software Examples documentation.

For the full catalog of examples, refer to the STM32 Example Library.