Atomic configuration methods ¶
The concept ¶
HAL2 introduces several key updates to enhance flexibility and efficiency:
Unitary configuration APIs now allow configuring or retrieving a single item for a peripheral, such as setting the UART baud rate, without reapplying the full configuration.
The generic
__HAL_LINKDMAmacro has been replaced with dedicated DMA link APIs for clearer, more maintainable code.New APIs for setting and getting user data within HAL handles, supporting flexible application-specific data management.
The callback registration mechanism has been optimized by replacing the global register API with individual callback APIs, removing the “UnRegister” callback and reducing overhead.
Together, these enhancements improve the usability and performance of the HAL2 library.
Unitary configuration APIs ¶
In HAL 2, unitary configuration APIs enable configuring or retrieving a single item for a given peripheral, such as setting the UART baud rate. Depending on the peripheral, the unitary item can apply to the entire PPP instance, a specific PPP instance subblock, such as a TIM output compare subblock, or a PPP subinstance, like a TIM channel. These APIs are designed to dynamically modify or retrieve a unitary item, assuming that a global or subblock configuration has already been applied.
These functions allow the modification of a single configuration item without requiring the full configuration function to be called again. For certain HAL drivers, such as HAL I2C, these are new services. For other HAL drivers, like HAL TIM, these unitary APIs replace macros or functions previously used to dynamically modify a single item.
TIM example
|
HAL1 |
HAL2 |
|---|---|
TIM_HandleTypeDef htim;
/* Change the TIM Period */
__HAL_TIM_SET_AUTORELOAD(&htim, new_tim_period);
/* Change the TIM channel source */
HAL_TIMEx_TISelection(&htim,
TIM_TIM2_TI1_COMP2,
TIM_CHANNEL_1);
|
hal_tim_handle_t htim;
/* Change the TIM Period */
HAL_TIM_SetPeriod(&htim, new_tim_period);
/* Change the TIM channel source */
HAL_TIM_IC_SetChannelSource(&htim,
HAL_TIM_CHANNEL_1,
HAL_TIM_INPUT_TIM2_TI2_COMP2);
|
CRC example
|
HAL1 |
HAL2 |
|---|---|
/* X^8 + X^7 + X^4 + X^3 + X + 1 */
#define APP_CRC_POLYNOMIAL_8B 0x9B
CRC_HandleTypeDef hcrc;
/* Change the CRC Polynomial */
__HAL_CRC_POLYNOMIAL_CONFIG(&hcrc, APP_CRC_POLYNOMIAL_8B);
|
/* X^8 + X^7 + X^4 + X^3 + X + 1 */
#define APP_CRC_POLYNOMIAL_8B 0x9B
hal_crc_handle_t hcrc;
/* Change the CRC Polynomial */
HAL_CRC_SetConfigPolynomial(&hcrc, APP_CRC_POLYNOMIAL_8B,
HAL_CRC_POLY_SIZE_8B,
0xFFFFFFFF);
|
Dedicated DMA link APIs replace generic __HAL_LINKDMA macro ¶
In HAL1, the connection between a peripheral handle and its DMA handle was managed using the generic
__HAL_LINKDMA
macro within the MspInit function.
#define __HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD__, __DMA_HANDLE__) \
do{ \
(__HANDLE__)->__PPP_DMA_FIELD__ = &(__DMA_HANDLE__); \
(__DMA_HANDLE__).Parent = (__HANDLE__); \
} while(0)
Using this macro requires prior knowledge of the internal PPP handle DMA field (
__PPP_DMA_FIELD__), which is a private field of the handle.
In HAL2, this macro has been replaced by dedicated DMA link APIs, offering clearer and more maintainable code. For each HAL driver supporting DMA-based processes, dedicated DMA link APIs are provided with explicit naming and parameters.
UART example
|
HAL1 |
HAL2 |
|---|---|
/* Link the DMA handle to the UART handle for Rx processing */
__HAL_LINKDMA(huart, hdmarx, hdma_gpdma1_channel1);
|
/* Link the DMA handle to the UART handle for Rx processing */
HAL_UART_SetTxDMA(&huart, &hdma_gpdma1_channel1);
|
TIM example
|
HAL1 |
HAL2 |
|---|---|
/* Link the DMA handle to the TIM handle
for channel3 compare capture */
__HAL_LINKDMA(&htim, hdma[TIM_DMA_ID_CC3], &hdma_tim);
|
/* Link the DMA handle to the TIM handle
for channel3 compare capture */
HAL_TIM_SetDMA(&htim, HAL_TIM_DMA_ID_CC3, &hdma_tim);
|
Introduction of HAL user data set/get APIs ¶
HAL2 introduces new APIs that allow associating application-specific user data with the HAL PPP handle. This feature lets applications store and retrieve a user data pointer of any type within the handle. The pointer is defined as a void pointer for maximum flexibility. The HAL driver initializes this pointer as NULL during HAL_PPP_Init but does not manipulate or validate it thereafter. Ownership of the pointer fully belongs to the user and it is managed with the HAL_PPP_SetUserData and HAL_PPP_GetUserData functions. A common use case is setting the pointer before a process starts and retrieving it in the completion callback. These APIs are enabled by defining USE_HAL_PPP_USER_DATA as “1” in the stm32tnxx_hal_conf file.
Example
struct hal_tim_handle_s;
typedef struct hal_tim_handle_s hal_tim_handle_t;
struct hal_tim_handle_s
{
/* HAL TIM instance */
hal_tim_t instance;
...
#if defined (USE_HAL_TIM_USER_DATA) && (USE_HAL_TIM_USER_DATA == 1)
/* User Data Pointer */
const void *p_user_data;
#endif /* USE_HAL_TIM_USER_DATA */
};
#if defined (USE_HAL_TIM_USER_DATA) && (USE_HAL_TIM_USER_DATA == 1)
void HAL_TIM_SetUserData(hal_tim_handle_t *htim, const void *p_user_data);
const void *HAL_TIM_GetUserData(const hal_tim_handle_t *htim);
#endif /* USE_HAL_TIM_USER_DATA */
Individual callback registration APIs replace global register and unregister functions ¶
HAL2 optimizes the callback registration mechanism by replacing the global register callback API with separate registration functions for each callback, improving efficiency and reducing code footprint. The unregister callback API has been removed; users can restore default weak HAL PPP callbacks by re-registering them. Callback pointers remain stored in the HAL handle, and the feature is enabled with the USE_HAL_PPP_REGISTER_CALLBACK compilation define statement. Additionally, dedicated callback prototype types are introduced to enhance clarity and consistency.
UART example
|
HAL1 |
HAL2 |
|---|---|
UART_HandleTypeDef uart_handle;
void TxTransferCpltCallback(UART_HandleTypeDef *huart);
void RxTransferCpltCallback(UART_HandleTypeDef *huart,
uint16_t Size);
void TransferErrorCallback(UART_HandleTypeDef *huart);
/* Register Tx Complete Callback */
HAL_UART_RegisterCallback(&uart_handle,
HAL_UART_TX_COMPLETE_CB_ID,
TxTransferCpltCallback);
/* Register Rx Complete Callback */
HAL_UART_RegisterCallback(&uart_handle,
HAL_UART_RX_COMPLETE_CB_ID,
RxTransferCpltCallback);
/* Register Error Callback */
HAL_UART_RegisterCallback(&uart_handle,
HAL_UART_ERROR_CB_ID,
TransferErrorCallback);
/* UnRegister Tx Complete Callback */
HAL_UART_UnRegisterCallback(&uart_handle,
HAL_UART_TX_COMPLETE_CB_ID);
|
hal_uart_handle_t uart_handle;
void TxTransferCpltCallback(hal_uart_handle_t *huart);
void RxTransferCpltCallback(hal_uart_handle_t *huart,
uint16_t size_byte,
hal_uart_rx_event_types_t rx_event);
void TransferErrorCallback(hal_uart_handle_t *huart);
/* Register Tx Complete Callback */
HAL_UART_RegisterTxCpltCallback(&uart_handle,
TxTransferCpltCallback);
/* Register Rx Complete Callback */
HAL_UART_RegisterRxCpltCallback(&uart_handle,
RxTransferCpltCallback);
/* Register Error Callback */
HAL_UART_RegisterErrorCallback(&uart_handle,
TransferErrorCallback);
/* UnRegister Tx Complete Callback */
HAL_UART_RegisterTxCpltCallback(&uart_handle,
HAL_UART_TxCpltCallback);
|
TIM example
|
HAL1 |
HAL2 |
|---|---|
hal_tim_handle_t tim_handle;
void UpdateCallback(hal_tim_handle_t *htim);
void InputCaptureCallback(hal_tim_handle_t *htim);
/* Register Update Callback */
HAL_TIM_RegisterCallback(&tim_handle,
HAL_TIM_PERIOD_ELAPSED_CB_ID,
UpdateCallback);
/* Register Input Capture Callback */
HAL_TIM_RegisterCallback(&tim_handle,
HAL_TIM_IC_CAPTURE_CB_ID,
InputCaptureCallback);
/* UnRegister Update Callback */
HAL_TIM_UnRegisterCallback(&tim_handle,
HAL_TIM_PERIOD_ELAPSED_CB_ID);
|
hal_tim_handle_t tim_handle;
void UpdateCallback(hal_tim_handle_t *htim);
void InputCaptureCallback(hal_tim_handle_t *htim,
hal_tim_channel_t channel);
/* Register Update Callback */
HAL_TIM_RegisterUpdateCallback(&tim_handle,
UpdateCallback);
/* Register Input Capture Callback */
HAL_TIM_RegisterInputCaptureCallback(&tim_handle,
InputCaptureCallback);
/* UnRegister Update Callback */
HAL_TIM_RegisterUpdateCallback(&tim_handle,
HAL_TIM_UpdateCallback);
|