Erik
Erik

Reputation: 84

DMA UART Buffer pointer

I'm using a STM32F4 for receiving data from a FPGA (now it only relays data from a PC) using DMA UART. The DMA UART is working as it should, but it can only give an interrupt when the buffer for the UART it is half full or full. The problem is that I want to know if I got new data in the buffer without it being half or full.

In short I am looking for a register which point to where the next byte from the UART should go in the DMA buffer. Does anyone know of a register like that.

Thank you!

Upvotes: 1

Views: 10305

Answers (5)

rohittheozzy
rohittheozzy

Reputation: 347

One way would be to poll and check the serial Rx buffer for data or check the value of hdmarx->Instance->CNDTR if changed from the default value of buffer size.

The second option would be to use an IDLE interrupt to know if data is received, this can be done by adding a few lines in HAL_UART_IRQHandler

if((__HAL_UART_GET_IT(huart, UART_IT_IDLE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE) != RESET))
{ 
    __HAL_UART_CLEAR_IT(huart, UART_CLEAR_IDLEF);
}

Upvotes: 0

Erik
Erik

Reputation: 84

Thanks for the help, I found what I was looking for.

uint32_t bytesRx DMA1_Stream1->NDTR;

and

UART_HandleTypeDef huart3;
uint32_t bytesRx = huart3.hdmarx->Instance->NDTR;

Both of them works for finding how many bytes that have been received, observe that NDTR counts down.

Upvotes: 3

Ben
Ben

Reputation: 21

The DMA has a CNDTR register (be aware that it counts down)

Upvotes: 2

JMA
JMA

Reputation: 494

Do you use HALs? We use this code to know how many bytes we've received:

UART_HandleTypeDef              *pHandleUart;
(...)
static uint8_t Uart_RxBufferPointerCheck(void)
{
    uint8_t returnValue = 0;

    rxUartBuffer.last = ( (uint16_t)UART_MAX_BUFFER_LENGTH - Uart_Dma_GetPeripheralNumberOfData() );

    if ( rxUartBuffer.last >= rxUartBuffer.first )
    {
        returnValue = 1;
    }

    return ( returnValue );
}

static uint16_t Uart_Dma_GetPeripheralNumberOfData(void)
{
    return (uint16_t) pHandleUart->hdmarx->Instance->NDTR;
}   

rxUartBuffer.first is modified when we read those bytes. This code is fo F7 uC, I hope it also works on F4.

Upvotes: 0

mevets
mevets

Reputation: 10445

I tried to look your part up, but only found marketing pages. To get what you want, disable the DMA. The purpose in the DMA is to lessen the interrupt load, and perhaps maintain a wire rate stream if your cpu can’t keep up with the interrupt rate. Since you want the interrupt for notification, the DMA is sorta pointless. Worse, it is keeping you from seeing the interrupt.

Often US?ARTs have an on-board fifo, which alleviates the interrupt rate somewhat, while letting you synchronize with the beginning of a burst or whatever your purpose is.

Upvotes: -2

Related Questions