6 STM32CubeMX C Code generation overview

6.1          STM32Cube code generation using only HAL drivers

(default mode)

During the C code generation process, STM32CubeMX performs the following actions:

1.      If it is missing, it downloads the relevant STM32Cube MCU package from the user repository. STM32CubeMX repository folder is specified in the Help > Updater settings menu.

2.      It copies from the firmware package, the relevant files in Drivers/CMSIS and Drivers/STM32F4_HAL_Driver folders and in the Middleware folder if a middleware was selected.

3.      It generates the initialization C code ( .c/.h files) corresponding to the user MCU configuration and stores it in the Inc and Src folders. By default, the following files are included:

stm32f4xx_hal_conf.h file: this file defines the enabled HAL modules and sets some parameters (e.g. External High Speed oscillator frequency) to predefined default values or according to user configuration (clock tree).

stm32f4xx_hal_msp.c (MSP = MCU Support package): this file defines all initialization functions to configure the peripheral instances according to the user configuration (pin allocation, enabling of clock, use of DMA and Interrupts).

main.c is in charge of:

Resetting the MCU to a known state by calling the HAL_init() function that resets all peripherals, initializes the flash memory interface and the SysTick.

Configuring and initializing the system clock.

Configuring and initializing the GPIOs that are not used by peripherals.

Defining and calling, for each configured peripheral, a peripheral initialization function that defines a handle structure that will be passed to the corresponding peripheral HAL init function which in turn will call the peripheral HAL MSP initialization function. Note that when LwIP (respectively USB) middleware is used, the initialization C code for the underlying Ethernet (respectively USB peripheral) is moved from main.c to LwIP (respectively USB) initialization C code itself.

main.h file:

This file contains the define statements corresponding to the pin labels set from

the Pinout tab, as well as the user project constants added from the Configuration tab (refer to Figure 564 and Figure 565 for examples):

#define MyTimeOut       10

#define LD4_Pin       GPIO_PIN_12 #define LD4_GPIO_Port  GPIOD

#define LD3_Pin          GPIO_PIN_13

#define LD3_GPIO_Port   GPIOD

#define LD5_Pin         GPIO_PIN_14

#define LD5_GPIO_Port GPIOD

#define LD6_Pin         GPIO_PIN_15

#define LD6_GPIO_Port GPIOD

Figure 564. Labels for pins generating define statements

image501

In case of duplicate labels, a unique suffix, consisting of the pin port letter and the pin index number, is added and used for the generation of the associated define statements.

In the example of a duplicate I2C1 labels shown in Figure 566, the code generation produces the following code, keeping the I2C1 label on the original port B pin 6 define statements and adding B7 suffix on pin 7 define statements:

#define I2C1_Pin           GPIO_PIN_6

#define I2C1_GPIO_Port     GPIOB

#define I2C1B7_Pin        GPIO_PIN_7

#define I2C1B7_GPIO_Port GPIOB

Figure 566. Duplicate labels

image502

In order for the generated project to compile, define statements shall follow strict naming conventions. They shall start with a letter or an underscore as well as the corresponding label. In addition, they shall not include any special character such as minus sign, parenthesis or brackets. Any special character within the label is replaced by an underscore in the define name.

If the label contains character strings between “[]” or “()”, only the first string listed

is used for the define name. As an example, the label “ LD6 [Blue Led]” corresponds the following define statements:

#define LD6_Pin   GPIO_PIN_15

#define LD6_GPIO_Port   GPIOD

The define statements are used to configure the GPIOs in the generated initialization code. In the following example, the initialization of the pins labeled

Audio_RST_Pin and LD4_Pin is done using the corresponding define statements:

/*Configure GPIO pins : LD4_Pin Audio_RST_Pin */

GPIO_InitStruct.Pin = LD4_Pin | Audio_RST_Pin;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_LOW;

HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  1. Finally it generates a Projects folder that contains the toolchain specific files that match the user project settings. Double-clicking the IDE specific project file launches the IDE and loads the project ready to be edited, built and debugged.

6.2          STM32Cube code generation using Low Layer drivers

STM32CubeMX allows the user to generate peripheral initialization code based either on the peripheral HAL driver or on the peripheral Low Layer (LL) driver.

The choice is made through the Project Manager view (see Section 4.11.3: Advanced Settings tab).

The LL drivers are available only for the peripherals which require an optimized access and do not have a complex software configuration. The LL services allow performing atomic operations by changing the relevant peripheral registers content:

•        Examples of supported peripherals: RCC, ADC, GPIO, I2C, SPI, TIM, USART,… •  Examples of peripherals not supported by LL drivers: USB, SDMMC, FSMC.

The LL drivers are available within the STM32CubeL4 package:

•        They are located next to the HAL drivers ( stm32l4_hal_<peripheral_name>) within the Inc and Src directory of the

STM32Cube_FW_L4_V1.6\Drivers\STM32L4xx_HAL_Driver folder. - They can be easily recognizable by their naming convention:

stm32l4_ll_<peripheral_name>

For more details on HAL and LL drivers refer to the STM32L4 HAL and Low-layer drivers user manual (UM1884).

As the decision to use LL or HAL drivers is made on a peripheral basis, the user can mix both HAL and LL drivers within the same project.

The following tables show the main differences between the three possible STM32CubeMX project generation options: HAL-only, LL-only, and mix of HAL and LL code.

Table 24. LL versus HAL code generation: drivers included in STM32CubeMX projects

Project configuration and drivers to be included

HAL only

LL only

Mix of HAL and LL

Comments

CMSIS

Yes

Yes

Yes

STM32xxx_HAL_Driver

Only HAL

driver files

Only LL

driver files

Mix of HAL and LL driver files

Only the driver files required for a given configuration (selection of peripherals) are copied when the project settings option is set to “Copy only the necessary files”. Otherwise (“all used libraries” option) the complete set of driver files is copied.

Table 25. LL versus HAL code generation: STM32CubeMX generated header files

Generated header files

HAL only

LL only

Mix of HAL and LL

Comments

main.h

Yes

Yes

Yes

This file contains the include statements and the generated define statements for user constants (GPIO labels and user constants).

stm32xxx_hal_conf.h

Yes

No

Yes

This file enables the HAL modules necessary to the project.

stm32xxx_it.h

Yes

Yes

Yes

Header file for interrupt handlers

stm32xx_assert.h

No

Yes

Yes

This file contains the assert macros and the functions used for checking function parameters.

Table 26. LL versus HAL: STM32CubeMX generated source files

Generated source files

HAL only

LL only

Mix of HAL and LL

Comments

main.c

Yes

Yes

Yes

Contains the main functions and, optionally, STM32CubeMX generated functions.

stm32xxx_hal_msp.c

Yes

No

Yes

Contains the following functions:

–  HAL_MspInit

–  for peripherals using HAL drivers: HAL_<Peripheral>_MspInit,

HAL_<Peripheral>_MspDeInit,

These functions are available only for the peripherals that use HAL drivers.

stm32xxx_it.c

Yes

Yes

Yes

Source file for interrupt handlers

Table 27. LL versus HAL: STM32CubeMX generated functions and function calls

Generated source files

HAL only

LL only

Mix of HAL and LL

Comments

HAL_init()

Called in main.c

Not used

Called in main.c

This file performs the following functions:

  • Configuration of flash memory prefetch and instruction and data caches

  • Selection of the SysTick timer as timebase source

  • Setting of NVIC group priority

  • MCU low-level initialization

HAL_msp_init()

Generated in stm32xxx_hal_msp.c and called by HAL_init()

Not used

Generated in stm32xxx_hal_msp.c and called by HAL_init()

This function performs the peripheral resources configuration (1) .

MX_<Peripheral>_Init()

[1]: Peripheral configuration and call to HAL_<Peripheral>_Init()

[2]: Peripheral and peripheral resource configuration (1) using LL functions. Call to LL_Peripheral_Init()

When HAL driver is selected for the <Peripheral>, follows [1]: Peripheral configuration and call to HAL_<Peripheral>_Init(). When LL driver is selected, follows [2]: Peripheral and peripheral resource configuration using LL functions

This file takes care of the peripherals configuration. When the LL driver is selected for the <Peripheral>, it also performs the peripheral resources configuration (1) .

HAL_<Peripheral>_MspInit()

[3]: Generated in stm32xxx_hal_msp.c when HAL driver selected for the <Peripheral>

Not used

Only HAL driver can be selected for the <Peripheral>: function generation and calls done following [3]: Generated in stm32xxx_hal_msp.c when HAL driver selected for the <Peripheral>

Peripheral resources configuration (1)

HAL_<Peripheral>_MspDeInit()

[4]: Generated in stm32xxx_hal_msp.c when HAL driver selected for the <Peripheral>

Not used

Only HAL driver can be selected for the <Peripheral>: function generation and calls done following [4]: Generated in stm32xxx_hal_msp.c when HAL driver selected for the <Peripheral>

This function can be used to free peripheral resources.

(1) Peripheral resources include: peripheral clock, pinout configuration (GPIOs), peripheral DMA requests, peripheral interrupt requests and priorities. .. rubric:: Figure 567. HAL-based peripheral initialization: usart.c code snippet

image503

Figure 568. LL-based peripheral initialization: usart.c code snippet

image504

6.3          Custom code generation

STM32CubeMX supports custom code generation by means of a FreeMarker template engine (see http://www.freemarker.org).

6.3.1           STM32CubeMX data model for FreeMarker user templates

STM32CubeMX can generate a custom code based on a FreeMarker template file (.ftl extension) for any of the following MCU configuration information:

•        List of MCU peripherals used by the user configuration

•        List of parameters values for those peripherals

•        List of resources used by these peripherals: GPIO, DMA requests and interrupts.

The user template file must be compatible with STM32CubeMX data model. This means that the template must start with the following lines:

[#ftl]

[#list configs as dt]

[#assign data = dt]

[#assign peripheralParams =dt.peripheralParams]

[#assign peripheralGPIOParams =dt.peripheralGPIOParams]

[#assign usedIPs =dt.usedIPs] and end with

[/#list]

A sample template file is provided for guidance (see Figure 570).

STM32CubeMX will also generate user-specific code if any is available within the template.

As shown in the example below, when the sample template is used, the ftl commands are provided as comments next to the data they have generated:

FreeMarker command in template:

${peripheralParams.get(“RCC”).get(“LSI_VALUE”)} Resulting generated code:

LSI_VALUE :  32000       [peripheralParams.get(“RCC”).get(“LSI_VALUE”)]

Figure 570. Default content of the extra_templates folder

image505

6.3.2          Saving and selecting user templates

The user can either place the FreeMarker template files under STM32CubeMX installation path within the db/extra_templates folder or in any other folder.

Then for a given project, the user will select the template files relevant for its project via the Template Settings window accessible from the Code Generator Tab in the Project Manager view menu (see Section 4.11)

6.3.3          Custom code generation

To generate custom code, the user must place the FreeMarker template file under STM32CubeMX installation path within the db/extra_templates folder (see Figure 571).

The template filename must follow the naming convention <user filename>_<file extension>.ftl in order to generate the corresponding custom file as <user filename>.<file extension>.

By default, the custom file is generated in the user project root folder, next to the .ioc file (see Figure 572).

To generate the custom code in a different folder, the user shall match the destination folder tree structure in the extra_template folder (see Figure 573).

Figure 571. extra_templates folder with user templates

image506

Figure 572. Project root folder with corresponding custom generated files

image507

Figure 574. Custom folder with corresponding custom generated files

image508

6.4          Additional settings for C project generation

STM32CubeMX allows specifying additional project settings through the .extSettings file. This file must be placed in the same project folder and at the same level as the .ioc file.

As an example, additional settings can be used when external tools call STM32CubeMX to generate the project and require specific project settings.

Possible entries and syntax

All entries are optional. They are organized under the followings three categories: ProjectFiles, Groups or Others.

[ProjectFiles]: section where to specify additional include directories

Syntax

HeaderPath = <include directory 1 path>;< include directory 2 path >

Example

HeaderPath=../../IIR_Filter_int32/Inc ;

[Groups]: section where to create new groups of files and/or add files to a group Syntax

<Group name> = <file pathname1>;< file pathname2>

Example

Doc=$ PROJ_DIR$\..\readme.txt

Lib=C:\libraries\mylib1.lib; C:\libraries\mylib2.lib;

Drivers/BSP/MyRefBoard = C:\MyRefBoard\BSP\board_init.c; C:\MyRefBoard\BSP\board_init.h;

[Others]: section where to enable HAL modules and/or specify preprocessor define statements

–     Enabling preprocessor define statements

Preprocessor define statements can be specified using the following syntax after the [Others] line:

Syntax

Define = <define1_name>;<define2_name>

Example

Define= USE_STM32F429I_DISCO

–     Enabling HAL modules in generated stm32f4xx_hal_conf.h

HAL modules can be enabled using the following syntax after the [Others] line:

Syntax

HALModule = <ModuleName1>; <ModuleName1>;

Example

HALModule=I2S;I2C

.extSettings file example and generated outcomes

For the purpose of the example, a new project is created by selecting the

STM32F429I-DISCO board from STM32CubeMX board selector. The EWARM toolchain is selected in the Project tab of the Project Manager view. The project is saved as

MyF429IDiscoProject. In the project folder, next to the generated .ioc file, a .extSettings text file is placed with the following contents:

[Groups]

Drivers/BSP/STM32F429IDISCO=C:\Users\frq09031\STM32Cube\Repository\STM3

2Cube_FW_F4_V1.14.0\Drivers\BSP\STM32F429I-

Discovery\stm32f429i_discovery.c;

C:\Users\frq09031\STM32Cube\Repository\STM32Cube_FW_F4_V1.14.0\Drivers\

BSP\STM32F429I-Discovery\stm32f429i_discovery.h

Lib=C:\Users\frq09031\STM32Cube\Repository\STM32Cube_FW_F4_V1.14.0\

Middlewares\Third_Party\FreeRTOS\Source\portable\IAR\ARM_CM4F\portasm.s

Doc=$PROJ_DIR$\..\readme.txt

[Others]

Define = USE_ STM32F429I_DISCO

HALModule = UART;SPI

Upon project generation, the presence of this .extSettings file triggers the update of:

•        the project MyF429IDiscoProject.ewp file in EWARM folder (see Figure 575)

•        the stm32f4xx_hal_conf.h file in the project Inc folder (see Figure 576)

•        the project view within EWARM user interface as shown in Figure 577 and Figure 578.

Figure 575. Update of the project .ewp file (EWARM IDE) for preprocessor define statements