cancel
Showing results for 
Search instead for 
Did you mean: 

512 byte limit with HAL_UARTEx_ReceiveToIdle_DMA

Pincate
Associate III

Hello, I am having a issue with HAL_UARTEx_ReceiveToIdle_DMA on a NUCLEO-H7A3ZI-Q, when using the following code:

uint8_t rx_buffer [4096];
HAL_UARTEx_ReceiveToIdle_DMA(&huart3, rx_buffer, sizeof(rx_buffer));
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size){
    /*code*/
}

 My rx_buffer is only populating the first 512 bytes, with the remaining data remaining as 0.

__HAL_DMA_GET_COUNTER(huart3.hdmarx);

Provides the incorrect amount of data being passed over serial.

I have used serial plotter and CoolTerm to try and send packets but both hit this 512 byte limit.

Pincate_0-1771425939000.png

rx_buffer not populated past 512 bytes

Pincate_1-1771425954208.png

length correctly calculated as 640 bytes long

1 ACCEPTED SOLUTION

Accepted Solutions
Pincate
Associate III

My solution to this issue was using a resettable buffer to copy data from the dma buffer straight to memory before processing it separately. This was in circular mode with fifo disabled as this prevented idle bytes that didn't align to half time or full time events from populating the dma buffer.

for non aligned data I reconfigured the uart settings in stm32h7xx_it.c to manage idle events differently by clearing the idle flag and running a custom function that populates the memory from the rx_buffer.

View solution in original post

11 REPLIES 11
mfgkw
Senior III

I originally made that post and didn't find an answer, I cannot find any hardware or software limitations so thought rewording my post to focus on the DMA interrupt rather than the population of the LUT would be more successful as I have found this to be the route cause.

TDK
Super User

This looks like a cache issue. You will need to disable data cache or manage it appropriately. Invalidate after data is received but before reading it.

How many bytes are you expecting to receive? 640?

If you feel a post has answered your question, please click "Accept as Solution".
Pincate
Associate III

Thank you,

In the attached instance I was expecting 640 bytes + 5 confirmation bytes. However I want to send payloads up to 4096 bytes.

I have mapped the MPU to match the memory areas from the linker script

MEMORY
{
  ITCMRAM (xrw)  : ORIGIN = 0x00000000, LENGTH = 64K
  FLASH (rx)     : ORIGIN = 0x08000000, LENGTH = 2048K
  DTCMRAM1 (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
  DTCMRAM2 (xrw) : ORIGIN = 0x20010000, LENGTH = 64K
  RAM (xrw)      : ORIGIN = 0x24000000, LENGTH = 1024K
  RAM_CD (xrw)   : ORIGIN = 0x30000000, LENGTH = 128K
  RAM_SRD (xrw)  : ORIGIN = 0x38000000, LENGTH = 32K
}

Pincate_0-1771428459331.png

 

 Should I disable the MPU during hard faults? Is there anything else standing out.

This is how each region is configured.

Region memoryInstruction accessShareableCacheableBufferable
ITCM RAM (0x0000 0000, 64 KB)EnabledNot shareableNot cacheableNot bufferable
FLASH (0x0800 0000, 2 MB)EnabledNot shareableCacheableNot bufferable
DTCM RAM 1 (0x2000 0000, 64 KB)DisabledNot shareableNot cacheableNot bufferable
DTCM RAM 2 (0x2001 0000, 64 KB)DisabledNot shareableNot cacheableNot bufferable
AXI SRAM (0x2400 0000, 1 MB)DisabledNot shareableCacheableBufferable
SRAM_CD (0x3000 0000, 128 KB)DisabledNot shareableCacheableBufferable
SRAM_SRD (0x3800 0000, 32 KB)DisabledShareableNot cacheableNot bufferable
TDK
Super User

Initialize the array to something unique/nonzero so you can see if bytes 512-640 are actually written.

If you feel a post has answered your question, please click "Accept as Solution".
Pincate
Associate III

I added the following script to replace all of the rx_buffer values with 7:

for (uint16_t i = 0; i < 4096; ++i) {
	rx_buffer[i] = 7;
}

Pincate_0-1771501204458.png

Whilst rx_buffer is initially fully populated with 7's, by using breakpoints I can see that it is not updating to match the information sent over serial when the following interrupt is triggered.

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size){

it would appear my LUT, that has static memory allocation, is being populated by the first correct 512 bytes from somewhere else. (the first 5 bytes are the arbitration field which is why they are skipped in the for loop).

for (uint16_t k = 0, i = 5; i < length + 5; ++k, i += 2) {
  lut[k] = (rx_buffer[i+1] | rx_buffer[i] << 8);
  if (lut[k] >= 4095) {
      lut[k] = 4095;
  }
}

with the code bellow should the callback have a DMA specific function? is uint16_t size the correct value at the end.

 

Pincate
Associate III

Sorry, update to this; by changing the way I populated the rx_buffer in the while loop I have achieved the screenshots below. suggesting the issue still lies with how the rx_buffer is populated and not the transfer to the look up table.

while (1) {
	if (mode == 0) {
		if (rx_buffer[0] == 0) {
			for (uint16_t i = 0; i < 4096; ++i) {
					rx_buffer[i] = 7;
			}
		}
	}
    / code /
}

Pincate_0-1771504563558.png

payload had length 640, yet only the first 512 bytes of rx_buffer were populated (including [0]).

Pincate_2-1771504646324.png

The LUT is correctly populated from the rx_buffer with uint16_t based on the uint8_t captured in rx_buffer. this stops working at the 254 value as the 5 start bits account for the remaining values to reach 512 bytes. Each subsequent value is populated as 0x0707=1799 all the way to 319 as requested.

 

Pincate
Associate III

I have switched the DMA to circular mode to direct bytes into rx_buffer with the DMA before it becomes fully populated. This has fixed my rx_buffer issue, however caused some downstream issues that should be easier to fix. Thank you everyone for the continued support.

 

STM32 UART DMA Receive Example | Normal & Circular Mode

TDK
Super User

Hmm, I see no reason why it would stop at 512 bytes. There is no limitation that would explain this.

> __HAL_DMA_GET_COUNTER(huart3.hdmarx);
> Provides the incorrect amount of data being passed over serial.

Incorrect how? Does it suggest only 512 bytes have been transferred?

Does information in the huart handle and linked dma handles still appear valid?

If you feel a post has answered your question, please click "Accept as Solution".