HAL configuration
Since core version 1.6.0, a default STM32 HAL configuration is provided for each STM32 series. This avoids maintaining a separate configuration file for every variant in the series.
Each required STM32 HAL configuration file is in system/STM32YYxx/, where YY is the MCU series.
Choose a configuration method
Use the method that matches the scope of the change:
- Use
hal_conf_extra.hfor sketch-specific HAL module and configuration overrides. - Use
hal_conf_custom.hwhen the sketch must replace the complete default HAL configuration. - Use
build_opt.hfor preprocessor definitions that can be passed as compiler options. - Use
variant.honly for board-package or variant-specific defaults.
For general customization guidance, see Custom definitions and Customize build options with build_opt.h.
It allows to wrap to the correct HAL configurations. Example for a STM32F2: stm32f2xx_hal_conf.h
/* STM32F2xx specific HAL configuration options. */
#if __has_include("hal_conf_custom.h")
#include "hal_conf_custom.h"
#else
#if __has_include("hal_conf_extra.h")
#include "hal_conf_extra.h"
#endif
#include "stm32f2xx_hal_conf_default.h"
#endif
stm32yyxx_hal_conf_default.h file disables HAL modules that are not required by the core and includes the common stm32yyxx_hal_conf.h file available here: cores/arduino/stm32/stm32yyxx_hal_conf.h
This file handles:
- Mandatory HAL modules definition, including the default list of modules to be used in the HAL driver
- HAL modules enabled by default which can be disabled
- HAL modules not defined by default
Configuration file precedence
Place sketch-level configuration files beside the sketch .ino file:
MySketch/
|-- MySketch.ino
|-- hal_conf_extra.h
`-- hal_conf_custom.h
The series-specific wrapper applies the following precedence:
- If
hal_conf_custom.hexists, it replaces the default HAL configuration. - Otherwise, if
hal_conf_extra.hexists, it is included before the default configuration. - The default series configuration is used for the remaining settings.
hal_conf_custom.h is not an additive override. It must provide every definition required by the selected HAL configuration.
Customize HAL or variant definitions
Extra HAL configuration can also be enabled or disabled in variant.h when the setting belongs to a board package. For a sketch-level change, use:
hal_conf_extra.h
To replace the default configuration completely, use:
hal_conf_custom.h
After changing any of these files, force a clean rebuild. In Arduino IDE 2.3.10 and later, hold Shift while clicking Verify. With Arduino CLI, use arduino-cli compile --clean.
HAL modules configuration
Important
Below HAL modules or definitions are listed for convenience but may not be up to date. Refer to cores/arduino/stm32/stm32yyxx_hal_conf.h to make sure having up to date values.
HAL modules enabled by default
HAL_MODULE_ENABLEDHAL_CORTEX_MODULE_ENABLEDHAL_DMA_MODULE_ENABLED: Required by other modulesHAL_FLASH_MODULE_ENABLEDHAL_GPIO_MODULE_ENABLEDHAL_PWR_MODULE_ENABLEDHAL_RCC_MODULE_ENABLED
HAL modules enabled by default that can be disabled
HAL_ADC_MODULE_ENABLEDHAL_I2C_MODULE_ENABLEDHAL_RTC_MODULE_ENABLEDHAL_SPI_MODULE_ENABLEDHAL_TIM_MODULE_ENABLED
HAL modules not enabled by default
HAL_CAN_MODULE_ENABLEDHAL_DAC_MODULE_ENABLEDHAL_ETH_MODULE_ENABLEDHAL_SD_MODULE_ENABLEDHAL_QSPI_MODULE_ENABLED
HAL modules controlled by Arduino board menus
HAL_UART_MODULE_ENABLEDHAL_PCD_MODULE_ENABLED
List of HAL_*_MODULE_DISABLED definition
HAL_ADC_MODULE_DISABLEDHAL_I2C_MODULE_DISABLEDHAL_RTC_MODULE_DISABLEDHAL_SPI_MODULE_DISABLEDHAL_TIM_MODULE_DISABLEDHAL_DAC_MODULE_DISABLEDHAL_EXTI_MODULE_DISABLED: interrupt API does not used HAL EXTI module anyway API is cleaned with thisHAL_ETH_MODULE_DISABLEDHAL_SD_MODULE_DISABLEDHAL_QSPI_MODULE_DISABLED
Tip
Disabling unused modules can significantly reduce flash and RAM usage. Do not disable a module used by an Arduino API or another enabled library.
For example, these definitions disable unused modules in hal_conf_extra.h:
#define HAL_ADC_MODULE_DISABLED
#define HAL_I2C_MODULE_DISABLED
The equivalent build_opt.h entries are:
-DHAL_ADC_MODULE_DISABLED
-DHAL_I2C_MODULE_DISABLED
Historical size example
The following measurements were made with core 2.0.0 for a Nucleo-L031K6 with 32768 bytes of flash and 8192 bytes of RAM. They are indicative only; results depend on the core, compiler, optimization settings, board variant, and enabled Arduino APIs.
| Core 2.0.0 | Flash Size(%) | RAM Size(%) |
|---|---|---|
| Default (Serial enabled) | 11796 (35%) | 876 (10%) |
| HAL disabled* | 5340 (16%) | 60 (0%) |
| diff size(%) | -6456 (-19%) | -716 (-9%) |
*With all HAL_*_MODULE_DISABLED defined in hal_conf_extra.h and Serial disabled
Other HAL configuration
Important
Below HAL configurations are listed for convenience but may not be up to date. Refer to the required default STM32 HAL configuration file stm32yyxx_hal_conf_default.h in system/STM32YYxx/ (where YY is the MCU series) to make sure having up to date values.
Oscillator values
Override these values only when they match the actual clock sources fitted to the board. Incorrect values can affect system timing, baud rates, timers, RTC, USB, and delay functions.
HSE_VALUE: Value of the External oscillator in HzHSE_STARTUP_TIMEOUT: Time out for HSE start up, in msMSI_VALUE: Value of the Internal Multiple Speed oscillator in HzCSI_VALUE: Value of the Internal oscillator in HzHSI_VALUE: Value of the Internal High Speed oscillator in HzHSI_STARTUP_TIMEOUT: Time out for HSI start up, in msHSI14_VALUE: Value of the Internal High Speed oscillator for ADC in Hz. The real value may vary depending on the variations in voltage and temperature.HSI48_VALUE: Value of the Internal High Speed oscillator for USB in Hz. The real value may vary depending on the variations in voltage and temperature.LSI_VALUE: Value of the Internal Low Speed oscillator in Hz. The real value may vary depending on the variations in voltage and temperature.LSI1_VALUE: Value of the Internal Low Speed 1 oscillator in Hz. The real value may vary depending on the variations in voltage and temperature.LSI2_VALUE: Value of the Internal Low Speed 2 oscillator in Hz. The real value may vary depending on the variations in voltage and temperature.LSE_VALUE: Value of the External Low Speed oscillator in HzLSE_STARTUP_TIMEOUT: Time out for LSE start up, in msEXTERNAL_CLOCK_VALUE: External clock source for I2S peripheralEXTERNAL_SAI1_CLOCK_VALUE: Value of the SAI1 External clock source in HzEXTERNAL_SAI2_CLOCK_VALUE: Value of the SAI2 External clock source in Hz
HAL system configuration
The following HAL system configuration values can be redefined:
VDD_VALUE: Value of VDD in mVTICK_INT_PRIORITY: tick interrupt priorityPREFETCH_ENABLE: To enable prefetchINSTRUCTION_CACHE_ENABLE: Enable the instruction cacheDATA_CACHE_ENABLE: Enable the data cacheUSE_SPI_CRC: Enable the CRC feature in the HAL SPI driverART_ACCLERATOR_ENABLE: Enable the ART acceleratorUSE_SD_TRANSCEIVER: Enable the microSD transceiver
Use HAL modules without Arduino ownership
STM32 peripherals have many powerful features. Some of them are used by default by the Arduino API: I2C, SPI, TIM, U(S)ART, ... and take over IRQ Handlers (ex: TIMx_IRQHandler) and other HAL weaked functions (ex: HAL_XXX_MspInit()).
For advanced user applications, it could be useful to take control of those IRQ handlers.
Since core version 1.8.0, it is possible to disable the use of selected HAL modules by the Arduino API.
Defining HAL_PPP_MODULE_ONLY in build_opt.h or hal_conf_extra.h allows the application to use a HAL peripheral module without having the Arduino core use that peripheral.
For example, in hal_conf_extra.h:
#define HAL_UART_MODULE_ONLY
The application is then responsible for peripheral initialization, interrupt handlers, callbacks, and avoiding conflicts with Arduino libraries.
Hereafter list of possible definition:
HAL_UART_MODULE_ONLYHAL_TIM_MODULE_ONLYHAL_ADC_MODULE_ONLYHAL_DAC_MODULE_ONLYHAL_RTC_MODULE_ONLYHAL_PWR_MODULE_ONLY
I2C and SPI do not require a HAL_*_MODULE_ONLY definition because they are used by the core only through their built-in libraries. Do not include Wire.h or SPI.h when the application must use those HAL modules directly.
HAL assertion management
Note
Requires core version 2.8.0 or later.
HAL and LL include assertions which can be enabled by defining USE_FULL_ASSERT in build_opt.h. Assertions increase code size and are normally enabled only while debugging.
By default, assert_failed(uint8_t *file, uint32_t line) prints the assertion location and loops forever. The example below assumes that printf() is connected to an initialized output. The weak _Error_Handler(const char *msg, int val) function can also be redefined by the application when required.
Example at sketch level
extern "C" void assert_failed(uint8_t *file, uint32_t line) {
// Custom code
printf("Assert failed: %s (%lu)\n", (char *)file, line);
}
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
assert_param(LED_BUILTIN == 0);
pinMode(LED_BUILTIN, OUTPUT);
}
HAL FDCAN for STM32G0xx series
Note
Requires core version 2.8.0 or later.
The STM32G0xx series shares an IRQ with HardwareTimer, but the default IRQ handler did not forward the FDCAN interrupt because the core did not support FDCAN.
Since PR #2301, the handler forwards the interrupt to the correct FDCAN handler.
The application must declare the phfdcan1 and, when applicable, phfdcan2 handles before using FDCAN:
Example:
FDCAN_HandleTypeDef myhfdcan1;
FDCAN_HandleTypeDef *phfdcan1 = &myhfdcan1;
#if defined(FDCAN2_BASE)
FDCAN_HandleTypeDef *phfdcan2 = NULL;
#endif