cancel
Showing results for 
Search instead for 
Did you mean: 

Half duplex DMA Uart

Posted on December 15, 2015 at 16:22

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 rs4

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!

5 REPLIES 5
Posted on December 15, 2015 at 17:13

I think I am on a good track of debugging this... What I cant find in documentation of HAL is either I have to intentionaly clear the DMA uart RX buffers. For example lets say I send a command and now I am waiting for answer but it doesnt come. I want to send another command then, but before I do that i need to clear everything with DMA rx procedures so i can start clean again. Is there a way?

Posted on December 16, 2015 at 10:17

What happens If I set the DMA, but no data will come. Can I simply reconfigure it or do I need to clear some flags before, like transfer flag? Is it a good direction? Please help.

Posted on March 07, 2018 at 21:07

Did you ever find an answer?

Posted on March 07, 2018 at 22:09

I'll link in Allen's more recent thread here for completeness, especially if anyone else is looking for this type of functionality or support within HAL

https://community.st.com/0D50X00009XkXRGSA3

DAHMEN.IMEN

st.mcu

‌ perhaps you can see if there is any interest among the HAL dev team to review these use cases and perhaps provide some direction or implementation in the F2/F4 libraries.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on March 07, 2018 at 22:40

And, specifically, what the details were in the change right after 1.1.2 - were any app-level code changes required?

  • HAL UART

     

    update

    • Several update on HAL UART driver to implement the new UART state machine: 

      • Add new field in UART_HandleTypeDef structure:

        'rxState',

        UART

        state information related to Rx Operations
      • Rename 'state' field in UART_HandleTypeDef structure by 'gstate':

        UART

        state information related to global Handle management and Tx Operations
      • Update UART process to manage the new UART states.

      • Update __HAL_UART_RESET_HANDLE_STATE() macro to handle the new UART state parameters (gState, rxState)

    • Update UART_BRR_SAMPLING16() and UART_BRR_SAMPLING8() Macros to fix wrong baudrate calculation.

    • Update Polling management:

      • The user Timeout value must be estimated for the overall process duration: the Timeout measurement is cumulative

    • Update DMA process:

      • Update the m

        anagement of UART peripheral errors during DMA process. This requires the following updates in user application:

        • Configure and enable the UART IRQ in HAL_UART_MspInit() function

        • In stm32f2xx_it.c file, UART_IRQHandler() function: add a call to HAL_UART_IRQHandler() function

        • Add and customize the Error Callback API: HAL_UART_ErrorCallback()