AnsweredAssumed Answered

Half duplex DMA Uart

Question asked by Lukasz Przenioslo on Dec 15, 2015
Latest reply on Mar 7, 2018 by Allen Huffman
Hello there,
I am experiencing a weird behaviour in my application. I am using HAL library. I am using STM32F407 and usart2 to send and receive using DMA in half-duplex mode.
Everything is working fine, until I decide to send a message with different lenght and wait for an answer with different length. What I mean is, if i send and receive same length frames it is working. If I change it, it skips the first reception packet and after that everything is shifted somehow in the reception buffer.

This is my procedure. First of I send:
HAL_StatusTypeDef rs485_sendData(uint8_t* buffer, size_t len)
{
    HAL_StatusTypeDef ret = HAL_OK;
 
    ret |= HAL_HalfDuplex_EnableTransmitter(p_rs485_usartHandle);
    rs485_SetTransmissionMode();
 
    while (HAL_UART_GetState(p_rs485_usartHandle) != HAL_UART_STATE_READY);
    ret |= HAL_UART_Transmit_DMA(p_rs485_usartHandle, buffer, len);
 
    return ret;
}

rs485_SetTransmissionMode(); sets DE pin High because this is rs485.
After I send i get Tx interrupt:
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    assert_param(huart);
 
    if (huart == p_rs485_usartHandle)
    {
        assert_param(p_rs485_msgInfo);
 
        rs485_SetReceptionMode();
        HAL_HalfDuplex_EnableReceiver(p_rs485_usartHandle);
 
        HAL_UART_Receive_DMA(p_rs485_usartHandle, rs485_rxBuffer,
                p_rs485_msgInfo->rxDataLen + RS485_PAYLOADS_SIZE);
    }
}

HAL_UART_Receive_DMA I specify for how many bytes I am waiting. WHen they come i get rx interrupt:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    assert_param(huart);
 
    if (huart == p_rs485_usartHandle)
    {
        // -1 because crc byte is not taken
        uint8_t crc = rs485_getCRC(rs485_rxBuffer, p_rs485_msgInfo->rxDataLen + RS485_PAYLOADS_SIZE - 1);
 
        // check CRC (-1 because its index)
        if (rs485_rxBuffer[p_rs485_msgInfo->rxDataLen + RS485_PAYLOADS_SIZE - 1] == crc)
        {
            // CRC OK
            Led_Toggle(2);
            if (osOK != osMessagePut(msgQId_rs485Frame, (uint32_t)rs485_rxBuffer, 0))
                log_PushLine(e_logLevel_Critical, "Unable to put rs485 rx message in the queue");
        }
        else
        {
            log_PushLine(e_logLevel_Warning, "Received command %u with bad crc!", rs485_rxBuffer[1]);
        }
    }
}

And this works quite fine if from the begining of code I send the same message all the time. But lets say after a while i start to send a bit different message, that also receives answer with different amount of bytes. I specify that and while debuging I see that for the first different message I send I dont get any answer at all and on my rs485 sniffer i see that the answer is sent. I just dont receive it in code and I have no idea why. Im on this for all day now. I tried doing DMA init before each send but that didnt change anything...

Is there something I am missing in the confifuration? I would really apreciate all help!

Outcomes