Use-case code

This section focuses on the code that implements the logic of the use-case. The configuration of the resources is covered in the Resources configuration section.

Overview

The STM32Cube Software Examples demonstrate the STM32Cube APIs to use the STM32 microcontrollers through meaningful use-cases. Nevertheless, this code is for demonstration purposes and not intended for direct use in production. The main priorities of the code are:

  • The code is meant to be educational and illustrative.

  • The code is structured for easy reuse and adaptation.

  • The functional code is designed to be hardware-agnostic and toolchains agnostic.

The benefits are:

  • Homogeneity: all examples are written the same way, with the same structure.

  • Education: the code is easy to read and understand, easy to link to the documentation.

  • Diversity: the code enables reuse and adaptation across all STM32 series.

The examples are preconfigured IDE projects created with STM32CubeMX2. It is easy to reconfigure them with STM32CubeMX2 and generate the configuration code for customized use-cases.

The use-case code is gathered in the application/ folder of the project.

The main entry-points of the use-case are located in the example.c file. The infrastructure of the example is centralized in the main.c file.

Infrastructure

main.c implements the infrastructure of the example. This code is almost the same for all examples. It is only a basic infrastructure to schedule the functional code implemented in example.c and manage the termination of the example.

main.c entry points

Function

Description

main.c/main()

The main entry point of the example:

  • This is where the system initialization takes place with mx_system_init().

  • main() is also the scheduler of the functional code implemented in example.c:

    • It calls app_init() to initialize the example and app_process() to run the example.

    • It can implement a loop to run app_process() in an infinite loop.

    • It can also implement a one-shot mode to run app_process() once and stop with app_deinit().

main.c/success_handler()

This function is entered when the example is successfully completed. It is used to report the success when the example terminates. For examples running in an infinite loop, this function is not implemented.

main.c/error_handler()

This function is entered when an unrecoverable error occurs. It is used to report the error and to stop the execution of the example. Out of the box, this code does not execute because all examples are verified as functional.

main.c/HardFault_Handler()

This function is entered when a fault occurs. It is used to report the fault and to stop the execution of the example. Out of the box, this code does not execute because all examples are verified as functional.

Processing

example.c is the file implementing the example scenario logic with the HAL APIs:

  1. Each scenario step is implemented here, and identified with a tag ########## Step X ##########

  2. The example code is structured in app_xxx() functions and app_process() is the functional part of the use-case.

  3. This code can leverage the PRINTF service to write application logs to the console. These logs are enabled by setting the USE_TRACE compiler switch to 1.

This file also contains the user callbacks, and all local functions used to implement the example scenario. Local functions are used to implement some helpers that are not at the core of the example scenario. This keeps app_process() focused on the HAL calls, and the code snippets to copy/paste in custom applications.

The system and resource configuration code is not located in example.c. Refer to the Resources configuration page. This is where the clocks, pins, and peripherals are configured:

  • The system initialization code is called from main() in main.c.

  • The resources configuration services are called from app_init() in example.c.

Conventions

Admonitions

The comments use admonitions such as the @user tag to highlight possible modifications (see How to port an example). Additional admonitions are used to highlight important information.

Admonitions

Type

Description

Example

Attention

Highlights a particularly important note that must not be overlooked.

Attention: the resistors values condition the data rate that can be achieved.

Warning

Used when there may be negative consequences to consider if a recommendation is not obeyed.

Warning: this variable must be 32-bit aligned.

Note

Notes have the lowest importance.

Note: no callback is associated with this interrupt as it is only used to wake the system up.

Naming rules

In the example code, the naming rules aim at identifying easily:

  • The portions of code which are related to the internal design of the example.

  • The code snippets which can be reused in custom applications.

These rules apply to the code located in example.c.

Naming conventions

Element

Naming Rule

Description

Global variables

Global variables are written in CamelCase . For example: RxBuffer is a global variable to store some bytes received from a peripheral.

The example code requires global variables to operate and connect all services, but they are likely to be replaced by application-specific ones.

Local variables

Local variables are written in snake_case . For example: i2c_error_code is a local variable to handle an I2C error.

Functions like app_process() use local variables, and these code snippets may be reused in custom applications.

Main functions

The major functions implementing the example are written in snake_case . For example: app_process().

These functions implement the use-case with the functional APIs being demonstrated. They are designed as code to be reused in other applications.

Helper functions

Helper functions are written in CamelCase . For example: TransferCompleteCallback() is a user callback.

Helper functions are used to implement some services that are not at the core of the example scenario. This code is specific to the example and is not intended for reuse in other applications.

In a nutshell:

  • Elements written in CamelCase are specific to the example.

  • Elements written in snake_case can be of interest as code snippets for custom applications.