[HAL][LL][IRDA] Fix various bugs identified in IRDA driver
- Add a check on the IRDA parity before enabling the parity error interrupt
- Fix wrong cast when computing the USARTDIV value in IRDA_SetConfig()
- Optimize HAL IRDA to avoid using macros as argument of function calls
- Optimized stack usage for multiple APIs
- Improve header description of IRDA_WaitOnFlagUntilTimeout() function
diff --git a/Inc/stm32l5xx_hal_irda.h b/Inc/stm32l5xx_hal_irda.h
index cb7a5d7..cda5efe 100644
--- a/Inc/stm32l5xx_hal_irda.h
+++ b/Inc/stm32l5xx_hal_irda.h
@@ -143,7 +143,7 @@
IRDA_InitTypeDef Init; /*!< IRDA communication parameters */
- uint8_t *pTxBuffPtr; /*!< Pointer to IRDA Tx transfer Buffer */
+ const uint8_t *pTxBuffPtr; /*!< Pointer to IRDA Tx transfer Buffer */
uint16_t TxXferSize; /*!< IRDA Tx Transfer size */
@@ -261,15 +261,15 @@
/** @defgroup IRDA_Error_Definition IRDA Error Code Definition
* @{
*/
-#define HAL_IRDA_ERROR_NONE ((uint32_t)0x00000000U) /*!< No error */
-#define HAL_IRDA_ERROR_PE ((uint32_t)0x00000001U) /*!< Parity error */
-#define HAL_IRDA_ERROR_NE ((uint32_t)0x00000002U) /*!< Noise error */
-#define HAL_IRDA_ERROR_FE ((uint32_t)0x00000004U) /*!< frame error */
-#define HAL_IRDA_ERROR_ORE ((uint32_t)0x00000008U) /*!< Overrun error */
-#define HAL_IRDA_ERROR_DMA ((uint32_t)0x00000010U) /*!< DMA transfer error */
-#define HAL_IRDA_ERROR_BUSY ((uint32_t)0x00000020U) /*!< Busy Error */
+#define HAL_IRDA_ERROR_NONE (0x00000000U) /*!< No error */
+#define HAL_IRDA_ERROR_PE (0x00000001U) /*!< Parity error */
+#define HAL_IRDA_ERROR_NE (0x00000002U) /*!< Noise error */
+#define HAL_IRDA_ERROR_FE (0x00000004U) /*!< frame error */
+#define HAL_IRDA_ERROR_ORE (0x00000008U) /*!< Overrun error */
+#define HAL_IRDA_ERROR_DMA (0x00000010U) /*!< DMA transfer error */
+#define HAL_IRDA_ERROR_BUSY (0x00000020U) /*!< Busy Error */
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
-#define HAL_IRDA_ERROR_INVALID_CALLBACK ((uint32_t)0x00000040U) /*!< Invalid Callback error */
+#define HAL_IRDA_ERROR_INVALID_CALLBACK (0x00000040U) /*!< Invalid Callback error */
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
/**
* @}
@@ -573,12 +573,12 @@
* @retval None
*/
#define __HAL_IRDA_ENABLE_IT(__HANDLE__, __INTERRUPT__) (((((__INTERRUPT__) & IRDA_CR_MASK) >> IRDA_CR_POS) == 1U)? \
- ((__HANDLE__)->Instance->CR1 |= ((uint32_t)1U << \
+ ((__HANDLE__)->Instance->CR1 |= (1U << \
((__INTERRUPT__) & IRDA_IT_MASK))):\
((((__INTERRUPT__) & IRDA_CR_MASK) >> IRDA_CR_POS) == 2U)? \
- ((__HANDLE__)->Instance->CR2 |= ((uint32_t)1U << \
+ ((__HANDLE__)->Instance->CR2 |= (1U << \
((__INTERRUPT__) & IRDA_IT_MASK))):\
- ((__HANDLE__)->Instance->CR3 |= ((uint32_t)1U << \
+ ((__HANDLE__)->Instance->CR3 |= (1U << \
((__INTERRUPT__) & IRDA_IT_MASK))))
/** @brief Disable the specified IRDA interrupt.
@@ -594,12 +594,12 @@
* @retval None
*/
#define __HAL_IRDA_DISABLE_IT(__HANDLE__, __INTERRUPT__) (((((__INTERRUPT__) & IRDA_CR_MASK) >> IRDA_CR_POS) == 1U)? \
- ((__HANDLE__)->Instance->CR1 &= ~ ((uint32_t)1U << \
+ ((__HANDLE__)->Instance->CR1 &= ~ (1U << \
((__INTERRUPT__) & IRDA_IT_MASK))): \
((((__INTERRUPT__) & IRDA_CR_MASK) >> IRDA_CR_POS) == 2U)? \
- ((__HANDLE__)->Instance->CR2 &= ~ ((uint32_t)1U << \
+ ((__HANDLE__)->Instance->CR2 &= ~ (1U << \
((__INTERRUPT__) & IRDA_IT_MASK))): \
- ((__HANDLE__)->Instance->CR3 &= ~ ((uint32_t)1U << \
+ ((__HANDLE__)->Instance->CR3 &= ~ (1U << \
((__INTERRUPT__) & IRDA_IT_MASK))))
/** @brief Check whether the specified IRDA interrupt has occurred or not.
@@ -634,7 +634,7 @@
#define __HAL_IRDA_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) \
((((((((__INTERRUPT__) & IRDA_CR_MASK) >>IRDA_CR_POS) == 0x01U)? (__HANDLE__)->Instance->CR1 :(((((__INTERRUPT__) \
& IRDA_CR_MASK) >> IRDA_CR_POS)== 0x02U)? (__HANDLE__)->Instance->CR2 :(__HANDLE__)->Instance->CR3)) \
- & ((uint32_t)0x01U <<(((uint16_t)(__INTERRUPT__)) & IRDA_IT_MASK))) != 0U) ? SET : RESET)
+ & (0x01U <<(((uint16_t)(__INTERRUPT__)) & IRDA_IT_MASK))) != 0U) ? SET : RESET)
/** @brief Clear the specified IRDA ISR flag, in setting the proper ICR register flag.
* @param __HANDLE__ specifies the IRDA Handle.
@@ -827,11 +827,11 @@
*/
/* IO operation functions *****************************************************/
-HAL_StatusTypeDef HAL_IRDA_Transmit(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size, uint32_t Timeout);
+HAL_StatusTypeDef HAL_IRDA_Transmit(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_IRDA_Receive(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size, uint32_t Timeout);
-HAL_StatusTypeDef HAL_IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size);
+HAL_StatusTypeDef HAL_IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_IRDA_Receive_IT(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size);
-HAL_StatusTypeDef HAL_IRDA_Transmit_DMA(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size);
+HAL_StatusTypeDef HAL_IRDA_Transmit_DMA(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_IRDA_Receive_DMA(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_IRDA_DMAPause(IRDA_HandleTypeDef *hirda);
HAL_StatusTypeDef HAL_IRDA_DMAResume(IRDA_HandleTypeDef *hirda);
@@ -889,3 +889,4 @@
#endif
#endif /* STM32L5xx_HAL_IRDA_H */
+
diff --git a/Inc/stm32l5xx_hal_irda_ex.h b/Inc/stm32l5xx_hal_irda_ex.h
index 1c25cca..9c98f69 100644
--- a/Inc/stm32l5xx_hal_irda_ex.h
+++ b/Inc/stm32l5xx_hal_irda_ex.h
@@ -254,3 +254,4 @@
#endif
#endif /* STM32L5xx_HAL_IRDA_EX_H */
+
diff --git a/Src/stm32l5xx_hal_irda.c b/Src/stm32l5xx_hal_irda.c
index 473522b..7591af8 100644
--- a/Src/stm32l5xx_hal_irda.c
+++ b/Src/stm32l5xx_hal_irda.c
@@ -125,8 +125,8 @@
allows the user to configure dynamically the driver callbacks.
[..]
- Use Function @ref HAL_IRDA_RegisterCallback() to register a user callback.
- Function @ref HAL_IRDA_RegisterCallback() allows to register following callbacks:
+ Use Function HAL_IRDA_RegisterCallback() to register a user callback.
+ Function HAL_IRDA_RegisterCallback() allows to register following callbacks:
(+) TxHalfCpltCallback : Tx Half Complete Callback.
(+) TxCpltCallback : Tx Complete Callback.
(+) RxHalfCpltCallback : Rx Half Complete Callback.
@@ -141,9 +141,9 @@
and a pointer to the user callback function.
[..]
- Use function @ref HAL_IRDA_UnRegisterCallback() to reset a callback to the default
+ Use function HAL_IRDA_UnRegisterCallback() to reset a callback to the default
weak (surcharged) function.
- @ref HAL_IRDA_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ HAL_IRDA_UnRegisterCallback() takes as parameters the HAL peripheral handle,
and the Callback ID.
This function allows to reset following callbacks:
(+) TxHalfCpltCallback : Tx Half Complete Callback.
@@ -158,13 +158,13 @@
(+) MspDeInitCallback : IRDA MspDeInit.
[..]
- By default, after the @ref HAL_IRDA_Init() and when the state is HAL_IRDA_STATE_RESET
+ By default, after the HAL_IRDA_Init() and when the state is HAL_IRDA_STATE_RESET
all callbacks are set to the corresponding weak (surcharged) functions:
- examples @ref HAL_IRDA_TxCpltCallback(), @ref HAL_IRDA_RxHalfCpltCallback().
+ examples HAL_IRDA_TxCpltCallback(), HAL_IRDA_RxHalfCpltCallback().
Exception done for MspInit and MspDeInit functions that are respectively
- reset to the legacy weak (surcharged) functions in the @ref HAL_IRDA_Init()
- and @ref HAL_IRDA_DeInit() only when these callbacks are null (not registered beforehand).
- If not, MspInit or MspDeInit are not null, the @ref HAL_IRDA_Init() and @ref HAL_IRDA_DeInit()
+ reset to the legacy weak (surcharged) functions in the HAL_IRDA_Init()
+ and HAL_IRDA_DeInit() only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the HAL_IRDA_Init() and HAL_IRDA_DeInit()
keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
[..]
@@ -173,8 +173,8 @@
in HAL_IRDA_STATE_READY or HAL_IRDA_STATE_RESET state, thus registered (user)
MspInit/DeInit callbacks can be used during the Init/DeInit.
In that case first register the MspInit/MspDeInit user callbacks
- using @ref HAL_IRDA_RegisterCallback() before calling @ref HAL_IRDA_DeInit()
- or @ref HAL_IRDA_Init() function.
+ using HAL_IRDA_RegisterCallback() before calling HAL_IRDA_DeInit()
+ or HAL_IRDA_Init() function.
[..]
When The compilation define USE_HAL_IRDA_REGISTER_CALLBACKS is set to 0 or
@@ -801,10 +801,10 @@
* @param Timeout Specify timeout value.
* @retval HAL status
*/
-HAL_StatusTypeDef HAL_IRDA_Transmit(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+HAL_StatusTypeDef HAL_IRDA_Transmit(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
- uint8_t *pdata8bits;
- uint16_t *pdata16bits;
+ const uint8_t *pdata8bits;
+ const uint16_t *pdata16bits;
uint32_t tickstart;
/* Check that a Tx process is not already ongoing */
@@ -831,7 +831,7 @@
if ((hirda->Init.WordLength == IRDA_WORDLENGTH_9B) && (hirda->Init.Parity == IRDA_PARITY_NONE))
{
pdata8bits = NULL;
- pdata16bits = (uint16_t *) pData; /* Derogation R.11.3 */
+ pdata16bits = (const uint16_t *) pData; /* Derogation R.11.3 */
}
else
{
@@ -980,7 +980,7 @@
* @param Size Amount of data elements (u8 or u16) to be sent.
* @retval HAL status
*/
-HAL_StatusTypeDef HAL_IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size)
+HAL_StatusTypeDef HAL_IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size)
{
/* Check that a Tx process is not already ongoing */
if (hirda->gState == HAL_IRDA_STATE_READY)
@@ -1052,8 +1052,16 @@
/* Process Unlocked */
__HAL_UNLOCK(hirda);
- /* Enable the IRDA Parity Error and Data Register not empty Interrupts */
- SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE);
+ if (hirda->Init.Parity != IRDA_PARITY_NONE)
+ {
+ /* Enable the IRDA Parity Error and Data Register not empty Interrupts */
+ SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE);
+ }
+ else
+ {
+ /* Enable the IRDA Data Register not empty Interrupts */
+ SET_BIT(hirda->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE);
+ }
/* Enable the IRDA Error Interrupt: (Frame error, noise error, overrun error) */
SET_BIT(hirda->Instance->CR3, USART_CR3_EIE);
@@ -1077,7 +1085,7 @@
* @param Size Amount of data elements (u8 or u16) to be sent.
* @retval HAL status
*/
-HAL_StatusTypeDef HAL_IRDA_Transmit_DMA(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size)
+HAL_StatusTypeDef HAL_IRDA_Transmit_DMA(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size)
{
/* Check that a Tx process is not already ongoing */
if (hirda->gState == HAL_IRDA_STATE_READY)
@@ -1194,8 +1202,11 @@
/* Process Unlocked */
__HAL_UNLOCK(hirda);
- /* Enable the UART Parity Error Interrupt */
- SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
+ if (hirda->Init.Parity != IRDA_PARITY_NONE)
+ {
+ /* Enable the UART Parity Error Interrupt */
+ SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
+ }
/* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
SET_BIT(hirda->Instance->CR3, USART_CR3_EIE);
@@ -1287,7 +1298,10 @@
__HAL_IRDA_CLEAR_OREFLAG(hirda);
/* Re-enable PE and ERR (Frame error, noise error, overrun error) interrupts */
- SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
+ if (hirda->Init.Parity != IRDA_PARITY_NONE)
+ {
+ SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
+ }
SET_BIT(hirda->Instance->CR3, USART_CR3_EIE);
/* Enable the IRDA DMA Rx request */
@@ -2283,21 +2297,21 @@
{
case IRDA_CLOCKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
- tmpreg = (uint16_t)(IRDA_DIV_SAMPLING16(pclk, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
+ tmpreg = (uint32_t)(IRDA_DIV_SAMPLING16(pclk, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
break;
case IRDA_CLOCKSOURCE_PCLK2:
pclk = HAL_RCC_GetPCLK2Freq();
- tmpreg = (uint16_t)(IRDA_DIV_SAMPLING16(pclk, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
+ tmpreg = (uint32_t)(IRDA_DIV_SAMPLING16(pclk, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
break;
case IRDA_CLOCKSOURCE_HSI:
- tmpreg = (uint16_t)(IRDA_DIV_SAMPLING16(HSI_VALUE, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
+ tmpreg = (uint32_t)(IRDA_DIV_SAMPLING16(HSI_VALUE, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
break;
case IRDA_CLOCKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
- tmpreg = (uint16_t)(IRDA_DIV_SAMPLING16(pclk, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
+ tmpreg = (uint32_t)(IRDA_DIV_SAMPLING16(pclk, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
break;
case IRDA_CLOCKSOURCE_LSE:
- tmpreg = (uint16_t)(IRDA_DIV_SAMPLING16((uint32_t)LSE_VALUE, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
+ tmpreg = (uint32_t)(IRDA_DIV_SAMPLING16((uint32_t)LSE_VALUE, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
break;
default:
ret = HAL_ERROR;
@@ -2307,7 +2321,7 @@
/* USARTDIV must be greater than or equal to 0d16 */
if ((tmpreg >= USART_BRR_MIN) && (tmpreg <= USART_BRR_MAX))
{
- hirda->Instance->BRR = tmpreg;
+ hirda->Instance->BRR = (uint16_t)tmpreg;
}
else
{
@@ -2365,11 +2379,12 @@
}
/**
- * @brief Handle IRDA Communication Timeout.
+ * @brief Handle IRDA Communication Timeout. It waits
+ * until a flag is no longer in the specified status.
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
* the configuration information for the specified IRDA module.
* @param Flag Specifies the IRDA flag to check.
- * @param Status Flag status (SET or RESET)
+ * @param Status The actual Flag status (SET or RESET)
* @param Tickstart Tick start value
* @param Timeout Timeout duration
* @retval HAL status
@@ -2770,7 +2785,7 @@
*/
static void IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda)
{
- uint16_t *tmp;
+ const uint16_t *tmp;
/* Check that a Tx process is ongoing */
if (hirda->gState == HAL_IRDA_STATE_BUSY_TX)
@@ -2787,7 +2802,7 @@
{
if ((hirda->Init.WordLength == IRDA_WORDLENGTH_9B) && (hirda->Init.Parity == IRDA_PARITY_NONE))
{
- tmp = (uint16_t *) hirda->pTxBuffPtr; /* Derogation R.11.3 */
+ tmp = (const uint16_t *) hirda->pTxBuffPtr; /* Derogation R.11.3 */
hirda->Instance->TDR = (uint16_t)(*tmp & 0x01FFU);
hirda->pTxBuffPtr += 2U;
}
@@ -2894,3 +2909,5 @@
/**
* @}
*/
+
+