Optimized input checks ¶
Input validation is optimized by avoiding systematic parameter and state checks during normal operation, relying instead on debug assertions for parameters, pointers, and states.
Assertion implementation and usage in HAL1 ¶
In HAL1, the
assert_param
macro is used exclusively within the
HAL_PPP_Init
function to validate initialization parameters. Its default implementation is provided in the
stm32_assert.h
template file as follows:
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t *file, uint32_t line);
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
To activate the assertion:
Add the
USE_FULL_ASSERTcompilation switch to the IDE preprocessor settings.Implement the
assert_failedfunction.
Several HAL1 examples provide the following implementation of the
assert_failed
function:
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add their own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
/* USER CODE END 6 */
}
Additionally, state validity checks in HAL1 APIs are performed at runtime, as demonstrated below:
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
{
...
/* Check that a Tx process is not already ongoing */
if (huart->gState == HAL_UART_STATE_READY)
{
huart->gState = HAL_UART_STATE_BUSY_TX;
..
}
}
Assertion implementation and usage in HAL2 ¶
In HAL2, all HAL APIs validate input parameters using the
ASSERT_DBG_PARAM
macro, extending beyond just the Init or Config functions. Additionally, HAL2 APIs verify the validity of the current state for operations, such as configuration, feature setting, and processes, through assertions using the
ASSERT_DBG_STATE
macro.
The code snippet below shows an example of the use of the
ASSERT_DBG_PARAM
and
ASSERT_DBG_STATE
macros.
hal_status_t HAL_UART_Transmit_DMA(hal_uart_handle_t *huart, const void *p_data, uint32_t size_byte)
{
ASSERT_DBG_PARAM(huart != NULL);
ASSERT_DBG_PARAM(p_data != NULL);
ASSERT_DBG_PARAM(size_byte != 0);
ASSERT_DBG_PARAM(huart->hdma_tx != NULL);
ASSERT_DBG_STATE(huart->global_state, HAL_UART_STATE_CONFIGURED);
ASSERT_DBG_STATE(huart->tx_state, HAL_UART_TX_STATE_IDLE);
..
}
The
stm32_assert.h
template file provides a default implementation of the
ASSERT_DBG_PARAM
and
ASSERT_DBG_STATE
macros, as shown below:
#if defined(USE_ASSERT_DBG_PARAM)
/**
* @brief The ASSERT_DBG_PARAM macro is used for function's parameters check.
* @param expr If expr is false, it calls assert_dbg_param_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#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)
/**
* @brief The ASSERT_DBG_STATE macro is used for function's states check.
* @param __STATE__ the state field within the PPP handle
* @param __VAL__ the authorized states value(s) to be checked
* can be a combination of states
* @note if __STATE__ & __VAL__ is zero (unauthorized state) then
* @note assert_dbg_state_failed function is called which reports
* the name of the source file and the source line number of the call that failed.
* if __STATE__ & __VAL__ is zero (unauthorized state) then, the ASSERT_DBG_STATE macro returns no value.
*/
#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 */
To activate the assertion:
Add the
USE_ASSERT_DBG_PARAMcompilation switch to the IDE pre-processor settings to activate assertion on parameters. In this case, provide an implementation of theassert_dbg_param_failedfunction as per HAL1.Add the
USE_ASSERT_DBG_STATEcompilation switch to the IDE pre-processor settings to activate assertion on states. In this case, provide an implementation of theassert_dbg_state_failedfunction, similar toassert_dbg_param_failed.
Summary ¶
|
Aspect |
HAL1 |
HAL2 |
|---|---|---|
|
Macro for parameter check |
|
|
|
Macro for state check |
Unavailable |
|
|
Scope of parameter check |
Used exclusively within
|
Used in all HAL APIs. |
|
Scope of state check |
State validity checks done at runtime within specific functions. |
State validity checks are performed using
|
|
Default implementation Ffile |
|
|
|
Default implementation for assertion parameter macros |
#ifdef USE_FULL_ASSERT
#define assert_param(expr) ((expr) ? \
(void)0U : \
assert_failed((uint8_t *)__FILE__, __LINE__))
void assert_failed(uint8_t *file, uint32_t line);
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
|
#if defined(USE_ASSERT_DBG_PARAM)
#define ASSERT_DBG_PARAM(expr) ((expr) ? \
(void)0U : \
assert_dbg_param_failed((uint8_t *)__FILE__, __LINE__))
void assert_dbg_param_failed(uint8_t *file, uint32_t line);
#else
#define ASSERT_DBG_PARAM(expr) ((void)0U)
#endif /* USE_ASSERT_DBG_PARAM */
|
|
Default implementation for assertion state macros |
Unavailable |
#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__))
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 */
|
|
Assertion activation |
Add
|
Add
|
|
Implementation of failed user application function |
User provides
|
User provides
|
|
Example of HAL checks |
HAL_StatusTypeDef HAL_UART_Transmit_DMA(
UART_HandleTypeDef *huart,
const uint8_t *pData,
uint16_t Size)
{
if (huart->gState == HAL_UART_STATE_READY)
{
huart->gState = HAL_UART_STATE_BUSY_TX;
/..
}
}
|
hal_status_t HAL_UART_Transmit_DMA(
hal_uart_handle_t *huart,
const void *p_data,
uint32_t size_byte) {
ASSERT_DBG_PARAM(huart != NULL);
ASSERT_DBG_PARAM(p_data != NULL);
ASSERT_DBG_PARAM(size_byte != 0);
ASSERT_DBG_PARAM(huart->hdma_tx != NULL);
ASSERT_DBG_STATE(huart->global_state, HAL_UART_STATE_CONFIGURED);
ASSERT_DBG_STATE(huart->tx_state, HAL_UART_TX_STATE_IDLE);
..
}
|