cstm32cortex-minfraredusart

Receiving IrDA message on STM32H7


I'm trying to receive some data using USART in IrDA mode on an STM32H7 board with HAL drivers.

I get the reply as I expect it on the gpio pin (baud rate, logic, and timing are ok) but for some reason the data is never moved to the RDR register of the USART and when I try to read it I just get zeroes on the first try and a timeout after that (polling mode).

After filling the IRDA handle structure I call HAL_IRDA_DeInit() and HAL_IRDA_Init(). I configure the GPIO in HAL_IRDA_MSP_Init() and send the first message that reaches the target (with HAL_IRDA_Transmit() ). The target then is sending a reply that I can check on the UART_RX pin. And here something happens.. or better doesn't happen. If I read the UART with HAL_IRDA_Receive() (1 byte at a time) I get only zero and then timeouts.

IRDA_HandleTypeDef hirda4;

void vIrdaInit(void)
{
    hirda.Instance = USART3;
    hirda.Init.BaudRate = 60100;
    hirda.Init.WordLength = IRDA_WORDLENGTH_9B;
    hirda.Init.Parity = IRDA_PARITY_NONE;
    hirda.Init.Mode = IRDA_MODE_TX_RX;
    hirda.Init.Prescaler = 1;
    hirda.Init.PowerMode = IRDA_POWERMODE_NORMAL;

    /* Initialize the IRDA registers. Here also HAL_IRDA_MspInit() will be called */
    if (HAL_IRDA_Init(&hirda4) != HAL_OK)
    {
        Error_Handler();
    }

}
/* Initialize IrDA low level resources. This function is called by HAL_IRDA_Init() */
void HAL_IRDA_MspInit(IRDA_HandleTypeDef* irdaHandle)
{

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if(irdaHandle->Instance==USART3)
    {
        /* UART4 clock enable */
        __HAL_RCC_USART3_CLK_ENABLE();
        __HAL_RCC_GPIOB_CLK_ENABLE();

        /**UART4 GPIO Configuration
        PB10     ------> USART3_RX
        PB11     ------> USART3_TX
        */
        GPIO_InitStruct.Pin = GPIO_PIN_10;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
        GPIO_InitStruct.Alternate = GPIO_AF7_UART3;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_11;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    }
}

here the call to HAL_IRDA_Transmit()/HAL_IRDA_Receive():

if(HAL_IRDA_Transmit(&hirda (uint8_t*)TxBuf, sizeof(RxBuf), 5000)!= HAL_OK)
{
    Error_Handler();
} 


memset(RxBuf, '\0', sizeof(RxBuf));
for (i = 0; i < 8; i++)
{
    // blocks here until timeout or data
    if(HAL_IRDA_Receive(&hirda, (uint8_t*)RxBuf, 1, 500)!= HAL_OK)
    {
        Error_Handler();
    } 
}

With the first time in the loop, I have the RXNE flag raised but in RDR there is only 0. The following iterations are resulting always in a timeout (from IRDA_WaitOnFlagUntilTimeout()). I have no idea where to look... The pulses I receive are bigger than the 3/16 of a period, the levels are ok but seem I cannot get the message through the SIR receive decoder and in the data register.

UPDATE: here a screenshot with the received signal: IrDA_RX

Baud rate is fine, start and stop bits are present and the message (9 bits) is what I am waiting for. But is not recognized by the decoder and passed to the UART.


Solution

  • Adding a dummy read of 1 byte just after calling the init function allowed me to successfully read once without Timeouts. The problem is that after that, the Receive() function starts again to return Timeouts. The only workaround I could find was to re-init the UART just before calling the Receive() function. This allows me to retrieve the full message. It is sloppy, but it works.

    I tried to find the registers that change but I was not able to isolate what is causing the problem.