1

I'm using the HAL with an STM32F3xx, implementing UART receive with circular DMA. The data should continually be received into the huart->pRxBuffPtr buffer, overwriting old data as new data arrives, and the HAL_UARTEx_RxEventCallback() function gets called regularly to copy out the data before it gets overwritten. The HAL_UARTEx_RxEventCallback() function receives a size parameter and of course a pointer huart, but no direct indication of where in the huart->pRxBuffPtr the freshly arrived data was DMA'd to.

How do I know whereabouts in huart->pRxBuffPtr the freshly arrived data starts?

Captain Normal
  • 441
  • 4
  • 14
  • Look at the DMA stream data number register (called NDTR or something like that) it counts down the number of items remaining and then gets reset to the count of items when the buffer wraps. Subtract the value you initially wrote from the current value to get the number of items stored. Obviously this number is out of date as soon as you read it, but the DMA will only be accessing items after where it points to. – Tom V Feb 08 '22 at 20:53

1 Answers1

2

Thank you to Tom V for the hint. For future generations, here is the solution code - a function which returns true and gets the next available byte, otherwise returns false:

bool uart_receiveByte(uint8_t *pData) {
  static size_t dmaTail = 0u;

  bool isByteReceived = false;

  // dmaHead is the next position in the buffer the DMA will write to.
  // dmaTail is the next position in the buffer to be read from.
  const size_t dmaHead = huart->RxXferSize - huart->hdmarx->Instance->CNDTR;

  if (dmaTail != dmaHead) {
    isByteReceived = true;
    *pData = pRxDmaBuffer[dmaTail];
    if (++dmaTail >= huart->RxXferSize) {
      dmaTail = 0u;
    }
  }

  return isByteReceived;
}
Captain Normal
  • 441
  • 4
  • 14