Skip to main content
mantisrobot
Associate III
December 6, 2021
Question

DMA transmit/receive on lpuart1

  • December 6, 2021
  • 2 replies
  • 4033 views

I'm using the NUCLEO-H753ZI dev board and have been testing various tx/rx reception modes using HAL routines with RTOS for all the available uarts. I have them all working well except lpuart1. When I try to receive or transmit in DMA mode I get no interrupts and no data out from the tx pin.

Am I missing something? Does this uart support DMA transfers? I see it uses BDMA instead of DMA, bot I'm not sure what the difference is.

This is the auto generated init code:

static void MX_LPUART1_UART_Init(void)
{
 
 /* USER CODE BEGIN LPUART1_Init 0 */
 
 /* USER CODE END LPUART1_Init 0 */
 
 /* USER CODE BEGIN LPUART1_Init 1 */
 
 /* USER CODE END LPUART1_Init 1 */
 hlpuart1.Instance = LPUART1;
 hlpuart1.Init.BaudRate = 115200;
 hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
 hlpuart1.Init.StopBits = UART_STOPBITS_1;
 hlpuart1.Init.Parity = UART_PARITY_NONE;
 hlpuart1.Init.Mode = UART_MODE_TX_RX;
 hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
 hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
 hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
 hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
 hlpuart1.FifoMode = UART_FIFOMODE_DISABLE;
 if (HAL_UART_Init(&hlpuart1) != HAL_OK)
 {
 Error_Handler();
 }
 if (HAL_UARTEx_SetTxFifoThreshold(&hlpuart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
 {
 Error_Handler();
 }
 if (HAL_UARTEx_SetRxFifoThreshold(&hlpuart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
 {
 Error_Handler();
 }
 if (HAL_UARTEx_DisableFifoMode(&hlpuart1) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN LPUART1_Init 2 */
 
 /* USER CODE END LPUART1_Init 2 */
 
}
 
/**
 * Enable DMA controller clock
 */
static void MX_BDMA_Init(void)
{
 
 /* DMA controller clock enable */
 __HAL_RCC_BDMA_CLK_ENABLE();
 
 /* DMA interrupt init */
 /* BDMA_Channel0_IRQn interrupt configuration */
 HAL_NVIC_SetPriority(BDMA_Channel0_IRQn, 5, 0);
 HAL_NVIC_EnableIRQ(BDMA_Channel0_IRQn);
 /* BDMA_Channel1_IRQn interrupt configuration */
 HAL_NVIC_SetPriority(BDMA_Channel1_IRQn, 5, 0);
 HAL_NVIC_EnableIRQ(BDMA_Channel1_IRQn);
 
}

This topic has been closed for replies.

2 replies

mantisrobot
Associate III
December 6, 2021

UPDATE

When using lpuart1 in DMA mode I get continuous UART_DMAError() errors, tracking through the code it seems to be a transfer error:

hdma->ErrorCode = HAL_DMA_ERROR_TE;

Tesla DeLorean
Guru
December 6, 2021

0693W00000HnhZeQAJ.jpgI don't really see enough initialization here. CubeMX buries and obfuscates, so makes for bad examples.

Try using SRAM4 in the AHB4 / APB4 / D3 Domain for the memory buffering

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
mantisrobot
Associate III
December 6, 2021

Hi,

Thanks for your response.

I think you're probably correct in your answer and my DMA buffer should be in the SRAM4 ram. Unfortunately I have no idea how to place this in SRAM4 using CubeIDE.

Any thoughts?

Tesla DeLorean
Guru
December 6, 2021

Not my tools, but generally GNU/GCC would be via the linker script and __attribute__((section(".sram4"))) type construction

If it's not part of the memory visible to the linker, your could test with a simple pointer assignment.

uint8_t *Buffer4 = (uint8_t *)0x38000000; // 64KB at 0x38000000

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
mantisrobot
Associate III
December 6, 2021

Ok,

I found this article:

https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices

And now have the DMA working on lpuart1. I added the following to my linker script: STM32H753ZITX_FLASH.ld

 .dma_buffer :
 {
 	*(.dma_buffer)
 } >RAM_D3

Then added this definition in my code:

#if defined( __ICCARM__ )
 #define DMA_BUFFER \
 _Pragma("location=\".dma_buffer\"")
#else
 #define DMA_BUFFER \
 __attribute__((section(".dma_buffer")))
#endif

Then declared the DMA buffer as follows:

DMA_BUFFER uint8_t	dmaBuff[LPUART_RX_BUFFER];

Thanks for pointing me in the right direction!

Now I have a new issue, any overrun error on the UART never seems to get cleared. Any idea what I need to do to clear an overrun? I can ask a new question in the forum but thought you might have an idea.

Cheers.