HAL and LL standalone templates

 hal/
   └── stm32tnxx/
       ├── _htmresc/
       ├── .config/
       ├── deprecated/
       ├── doc/
       ├── hal/
       ├── ll/
       ├── os_port/
       ├── templates/
       │   ├── common/
       │   │   ├── stm32_assert.h
       │   │   ├── stm32_ll.h
       │   │   └── stm32tnxx_hal_conf.h
       │   ├── os_port/
       │   │   ├── stm32_hal_os.c
       │   │   └── stm32_hal_os.h
       │   ├── timebases/
       │   │   ├── mx_rtc.c
       │   │   ├── mx_rtc.h
       │   │   ├── mx_timx.c
       │   │   ├── mx_timx.h
       │   │   └── stm32_hal_timebase.h
       ├── timebases/
       ├── utils/
       ├── .gitignore
       ├── license.md
       ├── README.md
       ├── Release_Notes.html
       └── STMicroelectronics.stm32tnxx_hal.pdsc

The STM32 HAL drivers provide templates necessary for user applications when using the HAL in standalone mode (without code generation). When using code generation, these files will be automatically generated by the STM32 Tool according to the project configuration. Thus, these template files are intended for direct use of the HAL in standalone mode without code generation. These templates should be copied to the user application and customized according to the user’s needs.

  • Templates that can be directly used with default behavior:

    • stm32tnxx_hal_conf.h: The STM32 HAL configuration file, intended to customize the HAL modules’ behavior.

    • stm32_ll.h: The STM32 LL entry inclusion file, including the LL driver header files.

    • stm32_assert.h: The STM32 HAL and LL assert header file, providing assert macros for HAL and LL parameters and for HAL state.

  • Templates that may need to be customized by the user according to their application:

    • mx_rtc.c / mx_rtc.h: Provides an implementation of the RTC initialization when the RTC is intended to be used as a HAL time base.

    • mx_timx.c / mx_timx.h: Provides an implementation of a Timer (TIMx) initialization when the given TIMER is intended to be used as a HAL time base. Note that the exact TIM instance (TIMx) depends on the given STM32 series.

    • stm32_hal_timebase.h: Provides an entry inclusion point for the above mx_rtc.h and mx_timx.h. It also provides aliases to the user timer or RTC “init” and “get handles” functions.

    • stm32_hal_os.c / stm32_hal_os.h: Templates providing a skeleton for a custom HAL OSAL implementation.

  • Other templates: stm32_external_env.h header file is a template provided by the DFP pack and should be copied and updated per platform specifications for standalone users (not using STM32CubeMX2 code generation). It is not part of the HAL pack. This file allows users to define external oscillator values and other board-specific values such as the VDD value, the presence of a transceiver, etc. When using STM32CubeMX2 with code generation, this file is generated according to the user choices.

Common templates

HAL configuration file

templates/
├── common/
│   ├── stm32_assert.h
│   ├── stm32_ll.h
│   └── stm32tnxx_hal_conf.h
├── os_port/
└── timebases/

The STM32 HAL configuration file, stm32tnxx_hal_conf.h, is designed to customize the behavior of the HAL modules. Users can utilize the provided file as-is, where all HAL modules are enabled with their default settings. Alternatively, users have the flexibility to customize the file based on their application’s requirements. For example, they can enable only the necessary HAL modules or modify the predefined settings to achieve the desired functionality.

/** @file    stm32tnxx_hal_conf.h */
/* ############## system/timebase config ##################### */

#define USE_HAL_TICK_INT_PRIORITY  HAL_TICK_INT_LOWEST_PRIORITY /*!< tick interrupt priority (lowest by default) */
#define USE_HAL_FLASH_PREFETCH 1U               /*!< Enable Flash prefetch */
/* ############### HAL MUTEX usage activation ################# */
/* Used by the HAL PPP Acquire/Release APIs when the define USE_HAL_MUTEX is set to 1 */
#define USE_HAL_MUTEX 0U

/* ############### Run time parameter check activation ######## */
#define USE_HAL_CHECK_PARAM 0U
#define USE_HAL_SECURE_CHECK_PARAM 0U

/* ################ protection of state transition in thread safe activation ######## */
#define USE_HAL_CHECK_PROCESS_STATE 0U

/* ########################## PPP Config ############################## */
#define USE_HAL_PPP_MODULE 1U
#define USE_HAL_PPP_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO
#define USE_HAL_PPP_REGISTER_CALLBACKS 0U
#define USE_HAL_PPP_USER_DATA 0U
#define USE_HAL_PPP_GET_LAST_ERRORS 0U
#define USE_HAL_PPP_DMA 1U
#define USE_HAL_PPP_FEATURE1 1U
#define USE_HAL_PPP_FEATURE2 1U
#define USE_HAL_PPP_FEATURE3 1U

/* ex : */
/* ########################## ADC Config ############################## */

#define USE_HAL_ADC_MODULE 1U
#define USE_HAL_ADC_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO
#define USE_HAL_ADC_REGISTER_CALLBACKS 0U
#define USE_HAL_ADC_USER_DATA 0U
#define USE_HAL_ADC_GET_LAST_ERRORS 0U
#define USE_HAL_ADC_DMA 1U

/* ########################## SPI Config ############################## */
#define USE_HAL_SPI_MODULE 1U
#define USE_HAL_SPI_CLK_ENABLE_MODEL HAL_CLK_ENABLE_NO
#define USE_HAL_SPI_REGISTER_CALLBACKS 0U
#define USE_HAL_SPI_USER_DATA 0U
#define USE_HAL_SPI_GET_LAST_ERRORS 0U
#define USE_HAL_SPI_DMA 1U
#define USE_HAL_SPI_CRC 1U

(...)

The stm32tnxx_hal_conf.h contains the following sections:

Section

Configuration defines

Default value

Description

System/Timebase Configuration

USE_HAL_TICK_INT_PRIORITY

HAL_TICK_INT_LOWEST_PRIORITY

Configures system tick interrupt priority.

USE_HAL_FLASH_PREFETCH

1

Configures flash prefetch settings.

Note: the feature availability depends on the given STM32 series.

HAL Mutex Usage Activation

USE_HAL_MUTEX

0

Enables or disables the use of mutexes in HAL PPP Acquire/Release APIs.

Runtime Parameter Check Activation

USE_HAL_CHECK_PARAM

0

Enables or disables runtime parameter checks.

USE_HAL_SECURE_CHECK_PARAM

0

Enables or disables secure parameter checks.

State Transition Protection in Thread Safe Activation

USE_HAL_CHECK_PROCESS_STATE

0

Enables or disables protection of state transitions in a thread-safe manner.

HAL PPP Configuration

USE_HAL_PPP_MODULE

1

Enables or disables the PPP module.

USE_HAL_PPP_CLK_ENABLE_MODEL

HAL_CLK_ENABLE_NO

Configures the clock enable model for PPP.

USE_HAL_PPP_REGISTER_CALLBACKS

0

Enables or disables callback registration for PPP.

USE_HAL_PPP_USER_DATA

0

Enables or disables user data for PPP.

USE_HAL_PPP_GET_LAST_ERRORS

0

Enables or disables error retrieval for PPP.

USE_HAL_PPP_DMA

1

Enables or disables DMA for PPP.

USE_HAL_PPP_FEATUREn

x

0: for enable/disable features Ex: USE_HAL_WWDG_HARDWARE_START

Or a default value for multichoices features Ex: USE_HAL_WWDG_TIME_UNIT feature default value is HAL_WWDG_TIME_UNIT_MS

Enables or disables feature n for PPP. Or set the feature value.

stm32_ll.h header file

templates/
├── common/
│   ├── stm32_assert.h
│   ├── stm32_ll.h
│   └── stm32tnxx_hal_conf.h
├── os_port/
└── timebases/

This file provides a single inclusion entry point to all the LL driver header files of a given series. The file name is agnostic, i.e., without the name of the series.

In the case of standalone usage, the stm32_ll.h includes all the LL driver header files of the given series. In the case of code generation, this file contains only the selected LL driver components. Users can utilize the copied file as is, where all LL drivers of the given STM32 family are included, or customize it to keep only the required LL driver’s inclusion.

This flexibility allows users to optimize their application by including only the necessary LL drivers, thereby improving maintainability.

/*** @file    stm32_ll.h */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef STM32_LL_H
#define STM32_LL_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "stm32tnxx_ll_adc.h"
#include "stm32tnxx_ll_bus.h"
#include "stm32tnxx_ll_comp.h"
#include "stm32tnxx_ll_cordic.h"
(...)
#include "stm32tnxx_ll_gtzc.h"
#include "stm32tnxx_ll_i2c.h"
#include "stm32tnxx_ll_icache.h"
#include "stm32tnxx_ll_iwdg.h"

#endif /* STM32_LL_H */

stm32_assert.h header file

templates/
├── common/
│   ├── stm32_assert.h
│   ├── stm32_ll.h
│   └── stm32tnxx_hal_conf.h
├── os_port/
└── timebases/

The STM32 assert header file provides assert macros for HAL parameters and HAL state. Users can use the copied file as is, which provides an implementation of the ASSERT_DBG_PARAM and ASSERT_DBG_STATE macros. However, they must provide an implementation of the assert_dbg_param_failed and assert_dbg_state_failed functions within their application.

Users also have the option to provide a custom implementation of the ASSERT macros, but they need to keep the parameters as is. This ensures that the assert functionality is correctly integrated and can handle parameter and state validation appropriately.

/** @file    stm32_assert.h
 (...)

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef STM32_ASSERT_H
#define STM32_ASSERT_H

#ifdef __cplusplus
extern "C" {
#endif

/* Exported macro ------------------------------------------------------------*/
#if defined(USE_ASSERT_DBG_PARAM)
#define ASSERT_DBG_PARAM(expr) ((expr) ? (void)0U : assert_dbg_param_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_dbg_param_failed(uint8_t *file, uint32_t line);
#else
#define ASSERT_DBG_PARAM(expr) ((void)0U)
#endif /* USE_ASSERT_DBG_PARAM */

#if defined(USE_ASSERT_DBG_STATE)
#define ASSERT_DBG_STATE(state,val) (((((uint32_t)(state)) &  ((uint32_t)(val))) != 0U) ?  \
                                               (void)0U :                                                     \
                                               assert_dbg_state_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_dbg_state_failed(uint8_t *file, uint32_t line);
#else
#define ASSERT_DBG_STATE(state,val) ((void)0U)
#endif /* USE_ASSERT_DBG_STATE  */

#ifdef __cplusplus
}
#endif

#endif /* STM32_ASSERT_H */

HAL OS templates

stm32_hal_os.c/h

templates/
├── common/
├── os_port/
│   ├── stm32_hal_os.c
│   └── stm32_hal_os.h
└── timebases/

The stm32_hal_os.c / stm32_hal_os.h files provide an empty implementation of the HAL OS abstraction. These files serve as a skeleton of the required HAL OS APIs that should be implemented by users who need to customize the HAL OSAL (Operating System Abstraction Layer) implementation. This customization is necessary for users who are implementing a custom OS or require a custom implementation of the HAL OSAL. By providing this skeleton, users have a structured starting point to develop their own OS abstraction, ensuring compatibility and integration with the HAL.

HAL time base templates

mx_timx.c/h

templates/
├── common/
├── os_port/
└── timebases/
    ├── mx_rtc.c
    ├── mx_rtc.h
    ├── mx_timx.c
    ├── mx_timx.h
    └── stm32_hal_timebase.h

The mx_timx.c and mx_timx.h files are template files containing the HAL TIM X timebase configuration function. These templates are to be used when the application needs to use the TIM “X” as a time base for HAL (instead of the SysTick). When STM32CubeMX2 code generation is not used, these files should be copied into the user space, and X should be replaced according to the TIM used by the application as the HAL time base.

The mx_timx.c and mx_timx.h template file structure and offered functions should be identical to the corresponding code generation for the TIM. They contain:

  • The init function: mx_timx_hal_init.

  • The de-init function: mx_timx_hal_deinit.

  • The “get handle” function: mx_timx_hal_gethandle.

  • The IRQHandler: TIMx_IRQHandler.

//mx_timx.h

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef STM32_TIMx_H
#define STM32_TIMx_H

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* Includes ------------------------------------------------------------------*/
#include "stm32_hal.h"

hal_tim_handle_t *mx_timx_hal_init(void);

void mx_timx_hal_deinit(void);

hal_tim_handle_t *mx_timx_hal_gethandle(void);

void TIMx_IRQHandler(void);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* STM32_TIMx_H */

// mx_timx.c

#include "mx_timx.h"

static hal_tim_handle_t hTIMx;

hal_tim_handle_t *mx_timx_hal_init(void)
{

   if (HAL_TIM_Init(&hTIMx, HAL_TIMx) != HAL_OK)
   {
     return NULL;
   }

   HAL_RCC_TIMx_EnableClock();

   /* Enable Timer update interrupt */
   HAL_CORTEX_NVIC_SetPriority(TIMx_IRQn,
                                  HAL_CORTEX_NVIC_PREEMP_PRIORITY_0,
                                  HAL_CORTEX_NVIC_SUB_PRIORITY_0);

   HAL_CORTEX_NVIC_EnableIRQ(TIMx_IRQn);

   return &hTIMx;
}

void mx_timx_hal_deinit(void)
{
   HAL_TIM_DeInit(&hTIMx);

   HAL_RCC_TIMx_DisableClock();

   HAL_CORTEX_NVIC_DisableIRQ(TIMx_IRQn);
}

hal_tim_handle_t *mx_timx_hal_gethandle(void)
{
   return &hTIMx;
}

void TIMx_IRQHandler(void)
{
   HAL_TIM_IRQHandler(&hTIMx);
}

Note

The mx_timx_hal_init function is limited to calling HAL_TIM_Init, enabling the TIM clock, and enabling and setting the TIM NVIC priority. The mx_timx_hal_init function does not configure the timer; this is handled by the overridden HAL_InitTick function implemented in the ready-to-use pattern stm32_hal_timebase_tim.c.

A standalone user (not using code generation) copies these template files ( mx_timx.c / mx_timx.h) and customizes them according to their needs, replacing the x in timx with the timer instance used (for example, TIM2).

Users utilizing code generation will have the mx_timx.c / mx_timx.h files generated automatically and do not need to copy or update these templates.

mx_rtcx.c/h

templates/
├── common/
├── os_port/
└── timebases/
    ├── mx_rtc.c
    ├── mx_rtc.h
    ├── mx_timx.c
    ├── mx_timx.h
    └── stm32_hal_timebase.h

Like the mx_timx.c and mx_timx.h files, the mx_rtc.c and mx_rtc.h files are provided as template files containing the HAL RTC initialization to be used when needed and RTC alarm or wakeup as a HAL time base.

stm32_hal_timebase.h

The stm32_hal_timebase.h is a template file to be used when customizing the HAL “time base” to use a TIMER or the RTC as a HAL time base. It is designed to include the required files, either mx_timx.h or mx_rtc.h. It also contains redirection aliases to the TIMER “init” and “get handle” functions.

It is to be used by standalone users only (not using STM32CubeMX2). In case of using STM32CubeMX2 with code generation, this file is generated according to the user choices.

/**
  ******************************************************************************
  * @file    stm32_hal_timebase.h
  * @brief   HAL time base template header file.
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef STM32_HAL_TIMEBASE_H
#define STM32_HAL_TIMEBASE_H

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* Includes ------------------------------------------------------------------*/
/* When using a TIMER as a timebase:
   Update this line to include the header file of the corresponding TIMx,
   for example: mx_tim6.h.
   Remove this include when using the RTC as time base. */
#include "mx_timx.h"

/* Keep this include when using RTC ALARM or WAKEUP as a HAL timebase.
   Remove this include when using a TIMER as a HAL time base. */
#include "mx_rtc.h"

/******************************************************************************/
/*   TIMEBASE ALIASES   (private aliases)                                     */
/******************************************************************************/

/*
When using a TIMER as a timebase: these aliases shall be updated to point to the corresponding timx,
for example: #define timebase_gethandle   mx_tim6_hal_gethandle

Remove these defines if not using a TIMER as timebase.
*/
#define timebase_gethandle   mx_timx_hal_gethandle
#define timebase_init        mx_timx_hal_init
#define timebase_deinit      mx_timx_hal_deinit
#define TIMEBASE_IRQ         TIMx_IRQn

/*
When using RTC (Alarm or Wakeup) as a timebase: these aliases shall be kept.
Remove these defines if not using RTC as timebase.
*/
#define timebase_init        mx_rtc_hal_init
#define timebase_deinit      mx_rtc_hal_deinit
#define TIMEBASE_IRQ         RTC_IRQn

/* Exported functions ------------------------------------------------------- */

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* STM32_HAL_TIMEBASE_H */

Other templates impacting the HAL and LL behavior: stm32_external_env.h header file

Several defines are provided for adapting internal and external oscillator values, as well as system configurations. These include:

  • Internal Oscillator Values: Adaptations like HSI, MSI, etc.

  • External Oscillator Values: Adaptations like HSE, LSE, etc.

  • System Configuration: Values like VDD_VALUE.

The purpose of the stm32_external_env.h file is to provide the defines specific to the hardware platform or board, such as external oscillators and board-dependent values. This file is provided as a template in the DFP pack and should be copied and updated per platform specifications for standalone users (not using STM32CubeMX2 code generation). If using STM32CubeMX2 code generation, the file is generated automatically based on user selections.

This file is included in stm32tnxx.h under the switch USE_EXTERNAL_ENV . The USE_EXTERNAL_ENV define, when needed, should be set in the project preprocessor.

#if defined(USE_EXTERNAL_ENV)
   #include "stm32_external_env.h"
#endif /* USE_EXTERNAL_ENV */

To streamline the configuration, all internal oscillator values should be placed in the CMSIS device file such as the stm32c562xx.h file. The stm32tnxx_hal_conf.h contains only the configuration defines used by HAL. In stm32tnxx_hal_rcc.c and stm32tnxx_hal_rcc.h, all the code linked to external clocks are handled under the <OSC_VALUE> preprocessor define.

  • Example

#if defined(HSE_VALUE)
typedef enum
{
  HAL_RCC_HSE_ON             = RCC_CR_HSEON,                                   /*!< HSE clock activation                        */
  HAL_RCC_HSE_BYPASS         = (RCC_CR_HSEBYP | RCC_CR_HSEON),                 /*!< External Analog clock source for HSE clock  */
  HAL_RCC_HSE_BYPASS_DIGITAL = (RCC_CR_HSEEXT | RCC_CR_HSEBYP | RCC_CR_HSEON), /*!< External Digital clock source for HSE clock */
} hal_rcc_hse_t;
#endif /* HSE_VALUE */

Note

As oscillator values move inside the CMSIS file and stm32_external_env.h, these defines are defined in HAL and LL files such as stm32tnxx_ll_rcc.h. This ensures a cleaner separation of platform-specific configurations and HAL-specific settings, improving maintainability and clarity.

Note

IMPORTANT NOTE: The stm32_external_env.h file is not part of the HAL driver files; it is provided as a template in the DFP pack. It should be copied once to the user example or application and updated according to the platform specifications. When using STM32CubeMX2 with code generation, this file is generated automatically based on user selections.

Note

The implementation of the internal and external defines should use conditional defines as follows:

  • For internal oscillator this allows users to define the required value at the compiler preprocessor in case it needs to be adjusted.

    /* file:  stm32tnxxyy.h */
    #if !defined(HSI_VALUE)
    #define HSI_VALUE   144000000UL /*!< Value of the Internal oscillator in Hz*/
    #endif
    
  • For external oscillator and board-dependent values, this allows users to define the required values at the compiler preprocessor if the stm32_external_env.h file is not used (the define USE_EXTERNAL_ENV is not set in the compiler preprocessor).

    /* file: stm32_external_env.h */
    #if !defined(HSE_VALUE)
    #define HSE_VALUE   8000000U  /*!< Value of the External oscillator in Hz*/
    #endif