STMicroelectronics / STM32CubeL0

STM32Cube MCU Full Package for the STM32L0 series - (HAL + LL Drivers, CMSIS Core, CMSIS Device, MW libraries plus a set of Projects running on all boards provided by ST (Nucleo, Evaluation and Discovery Kits))
Other
103 stars 57 forks source link

Passing interrupt reason to RxEventCallback #28

Closed hippiefm closed 1 year ago

hippiefm commented 1 year ago

Hello,

for now, RxEventCallback does not allow to distinguish interrupt reason, in DMA mode this could be RX half transfer, RX transfer complete or RX line idle. Adding information about interrupt reason would allow end user to react only on certain situations, eg. RX line idle interrupt is really helpful in communication with GSM modems.

Proposed solution

Changes inside stm32l0xx_hal_uart.h contain adding meaningful information about DMA specific interrupts (not covered by UART status register) and extending RxEventCallback with interrupt reason.

/** @defgroup UART_RX_DMA_INTERRUPT_TYPE_Values  UART RX DMA interrupt type values
  * @{
  */
#define HAL_UART_RX_DMA_INTERRUPT_HALF_TRANSFER          (0xFFFFFFFEU)             /*!< RX DMA half transfer interrupt                       */
#define HAL_UART_RX_DMA_INTERRUPT_TRANSFER_COMPLETE      (0xFFFFFFFFU)             /*!< RX DMA transfer complete interrupt  */
/**
  * @}
  */

typedef  void (*pUART_RxEventCallbackTypeDef)(struct __UART_HandleTypeDef *huart, uint16_t Pos, uint32_t Interrupt);   /*!< pointer to a UART Rx Event specific callback function */

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size, uint32_t Interrupt);

Changes inside stm32l0xx_hal_uart.c

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart) 
{
...
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /*Call registered Rx Event callback*/
        huart->RxEventCallback(huart, (huart->RxXferSize - huart->RxXferCount), isrflags);
#else
        /*Call legacy weak Rx Event callback*/
        HAL_UARTEx_RxEventCallback(huart, (huart->RxXferSize - huart->RxXferCount), isrflags);
#endif
...
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /*Call registered Rx complete callback*/
        huart->RxEventCallback(huart, nb_rx_data, isrflags);
#else
        /*Call legacy weak Rx Event callback*/
        HAL_UARTEx_RxEventCallback(huart, nb_rx_data, isrflags);
#endif
}

__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size, uint32_t Interrupt)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
  UNUSED(Size);
  UNUSED(Interrupt);

  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_UARTEx_RxEventCallback can be implemented in the user file.
   */
}

static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
{
...
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
    /*Call registered Rx Event callback*/
    huart->RxEventCallback(huart, huart->RxXferSize, HAL_UART_RX_DMA_INTERRUPT_TRANSFER_COMPLETE);
#else
    /*Call legacy weak Rx Event callback*/
    HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize, HAL_UART_RX_DMA_INTERRUPT_TRANSFER_COMPLETE);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}

static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
{
...
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
    /*Call registered Rx Event callback*/
    huart->RxEventCallback(huart, huart->RxXferSize/2U, HAL_UART_RX_DMA_INTERRUPT_HALF_TRANSFER);
#else
    /*Call legacy weak Rx Event callback*/
    HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize/2U, HAL_UART_RX_DMA_INTERRUPT_HALF_TRANSFER);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}

static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
...
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /*Call registered Rx Event callback*/
        huart->RxEventCallback(huart, huart->RxXferSize, isrflags);
#else
        /*Call legacy weak Rx Event callback*/
        HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize, isrflags);
#endif
}

Rationale

Adding above changes will allow end user to distinguish various interrupt reasons, either by checking SR flags or checking predefined values for DMA interrupts.

ASELSTM commented 1 year ago

Hi @hippiefm,

Thank you for this report. We have actually performed some fixes related to this issue. Please check this commit available in the stm32l0xx_hal_driver repository.

As several types of events could occur (IDLE event, Half Transfer event, or Transfer Complete event), a new function HAL_UARTEx_GetRxEventType() has been added to retrieve the Rx Event type that has lead to Rx Event callback execution. This allows thus to provide the Rx Event type that has lead to RxEvent callback execution.

With regards,

RJMSTM commented 1 year ago

Hi @cnxiaochun,

I hope you are fine.

The issue you reported has been fixed in the frame of version v1.12.2 of the STM32CubeL0 published recently on GitHub.

Thank you again for having reported.

BeST Regards, Rania