cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with STM32H743ZI2 USART Rx DMA

Manu Abraham
Senior

Hi,

Can someone help me identify what I am doing wrong ?

Still having issues with the DMA, but with Rx DMA instead. The issue with Tx DMA is fixed.

I am trying to send 4 chars from a terminal to the H743 rxbuf array using DMA.

In the debugger window, the sent chars can be seen in USART2->RDR

But DMA Rx does not happen (Transfer Complete/Transfer ERROR)

Any thoughts ?

Thanks,

Manu

/**
 * UART3 DMA Rx test application over ST Link Virtual COM Port
 * LED1 Blinks after DMA Transfer Complete
 * LED2 Blinks in case of DMA Transfer Error
 */
 
#include "stm32h7xx_ll_bus.h"
#include "stm32h7xx_ll_cortex.h"
#include "stm32h7xx_ll_dma.h"
#include "stm32h7xx_ll_gpio.h"
#include "stm32h7xx_ll_pwr.h"
#include "stm32h7xx_ll_rcc.h"
#include "stm32h7xx_ll_system.h"
#include "stm32h7xx_ll_usart.h"
#include "stm32h7xx_ll_utils.h"
 
#define APB_Div			4
 
__IO uint8_t tx_done = 0;
__IO uint8_t rx_done = 0;
 
 
const uint8_t txstr[] = "STM32H743 USART DMA TxRx Test: \r\n Type something! Look at LED status\r\n";
uint8_t txlen = sizeof (txstr);
 
#define RXBUFLEN			16
uint8_t rxbuf[RXBUFLEN] = { 0 };
uint8_t rxlen = 4;
 
 
/**
 * System Clock Configuration
 * The system Clock is configured as follow :
 * 	System Clock source	= PLL1 (HSE BYPASS)
 *	SYSCLK(Hz)		= 400000000 (CPU Clock)
 *	HCLK(Hz)		= 200000000 (AXI and AHBs Clock)
 *	AHB Prescaler		= 2
 *	D1 APB3 Prescaler	= 2 (APB3 Clock  100MHz)
 *	D2 APB1 Prescaler	= 2 (APB1 Clock  100MHz)
 *	D2 APB2 Prescaler	= 2 (APB2 Clock  100MHz)
 *	D3 APB4 Prescaler	= 2 (APB4 Clock  100MHz)
 *	HSE Frequency(Hz)	= 8000000
 *	PLL_M			= 4
 *	PLL_N			= 400
 *	PLL_P			= 2
 *	PLL_Q			= 4
 *	PLL_R			= 2
 *	VDD(V)			= 3.3
 *	Flash Latency(WS)	= 4
 */
static void SystemClock_Config(void)
{
	/* Power Configuration */
	LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY);
	LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
	while (LL_PWR_IsActiveFlag_VOS() == 0) { }
 
	LL_RCC_HSE_EnableBypass();
	LL_RCC_HSE_Enable();
	while (LL_RCC_HSE_IsReady() != 1) { }
 
	LL_FLASH_SetLatency(LL_FLASH_LATENCY_4);
 
	/* Main PLL configuration and activation */
	LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSE);
	LL_RCC_PLL1P_Enable();
	LL_RCC_PLL1Q_Enable();
	LL_RCC_PLL1R_Enable();
	LL_RCC_PLL1FRACN_Disable();
	LL_RCC_PLL1_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_2_4);
	LL_RCC_PLL1_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
	LL_RCC_PLL1_SetM(4);
	LL_RCC_PLL1_SetN(400);
	LL_RCC_PLL1_SetP(2);
	LL_RCC_PLL1_SetQ(4);
	LL_RCC_PLL1_SetR(2);
	LL_RCC_PLL1_Enable();
	while (LL_RCC_PLL1_IsReady() != 1) { }
 
	LL_RCC_SetSysPrescaler(LL_RCC_SYSCLK_DIV_1);
	LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
	LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
	LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2);
	LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_2);
	LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1);	/* PLL1 as System Clock Source */
	while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) { }
 
	SysTick_Config(400000000 / 1000);			/* 1ms Systick */
	SystemCoreClock = 400000000;
}
 
void led_init(void)
{
	LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOB);	/* GPIO Clk */
	LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOE);
 
	LL_GPIO_SetPinMode(GPIOB,
			   LL_GPIO_PIN_0,
			   LL_GPIO_MODE_OUTPUT);		/* PB.0 -> LED1 */
 
	LL_GPIO_SetPinMode(GPIOE,
			   LL_GPIO_PIN_1,
			   LL_GPIO_MODE_OUTPUT);		/* PE.1 -> LED2 */
 
	LL_GPIO_SetPinMode(GPIOB,
			   LL_GPIO_PIN_14,
			   LL_GPIO_MODE_OUTPUT);		/* PB.14 -> LED3 */
}
 
void config_usart(void)
{
	LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOD);	/* GPIO Clk */
 
	LL_GPIO_SetPinMode(GPIOD, LL_GPIO_PIN_8, LL_GPIO_MODE_ALTERNATE);
	LL_GPIO_SetAFPin_8_15(GPIOD, LL_GPIO_PIN_8, LL_GPIO_AF_7);
	LL_GPIO_SetPinSpeed(GPIOD, LL_GPIO_PIN_8, LL_GPIO_SPEED_FREQ_HIGH);
	LL_GPIO_SetPinOutputType(GPIOD, LL_GPIO_PIN_8, LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinPull(GPIOD, LL_GPIO_PIN_8, LL_GPIO_PULL_UP);
 
	LL_GPIO_SetPinMode(GPIOD, LL_GPIO_PIN_9, LL_GPIO_MODE_ALTERNATE);
	LL_GPIO_SetAFPin_8_15(GPIOD, LL_GPIO_PIN_9, LL_GPIO_AF_7);
	LL_GPIO_SetPinSpeed(GPIOD, LL_GPIO_PIN_9, LL_GPIO_SPEED_FREQ_HIGH);
	LL_GPIO_SetPinOutputType(GPIOD, LL_GPIO_PIN_9, LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinPull(GPIOD, LL_GPIO_PIN_9, LL_GPIO_PULL_UP);
 
	LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART3);	/* USART3 Clk */
	LL_RCC_SetUSARTClockSource(LL_RCC_USART234578_CLKSOURCE_PCLK1);		/* Clk source */
 
	LL_USART_SetTransferDirection(USART3, LL_USART_DIRECTION_TX_RX);
	LL_USART_ConfigCharacter(USART3,
				 LL_USART_DATAWIDTH_8B,
				 LL_USART_PARITY_NONE,
				 LL_USART_STOPBITS_1);
 
	LL_USART_SetBaudRate(USART3,
			     (SystemCoreClock / APB_Div),
			     LL_USART_PRESCALER_DIV1,
			     LL_USART_OVERSAMPLING_16,
			     115200);
 
	LL_USART_Enable(USART3);
 
	while ((!(LL_USART_IsActiveFlag_TEACK(USART3))) ||
	       (!(LL_USART_IsActiveFlag_REACK(USART3)))) { }
}
 
/**
 * Bugfix!
 * 2.3.1 DMA stream locked when transferring UART data
 *
 * Description:
 * When a USART/UART is issuing a DMA request to transfer data,
 * if a concurrent transfer occurs, the requested transfer
 * may not be served and the DMA stream may stay locked.
 *
 * Workaround:
 * Use the alternative peripheral DMA channel protocol
 * by setting bit 20 of the DMA_SxCR register.
 */
__STATIC_INLINE void LL_DMA_EnablePeriphDMA(DMA_TypeDef *DMAx, uint32_t Stream)
{
	register uint32_t dma_base_addr = (uint32_t)DMAx;
 
	SET_BIT(((DMA_Stream_TypeDef *)(dma_base_addr + LL_DMA_STR_OFFSET_TAB[Stream]))->CR, DMA_SxCR_TRBUFF);
}
 
//__STATIC_INLINE void LL_DMA_DisablePeriphDMA(DMA_TypeDef *DMAx, uint32_t Stream)
//{
//	register uint32_t dma_base_addr = (uint32_t)DMAx;
 
//	CLEAR_BIT(((DMA_Stream_TypeDef *)(dma_base_addr + LL_DMA_STR_OFFSET_TAB[Stream]))->CR, DMA_SxCR_TRBUFF);
//}
 
void config_dma(void)
{
	LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);	/* enable DMA1 clock */
 
	/* Rx DMA */
	LL_DMA_SetPeriphRequest(DMA1,
				LL_DMA_STREAM_1,		/* Request DMA stream 1 */
				LL_DMAMUX1_REQ_USART3_RX);	/* for DMAMUX1 USART3 Rx */
 
	LL_DMA_SetDataTransferDirection(DMA1,
					LL_DMA_STREAM_1,
					LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
 
	LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_1, LL_DMA_PRIORITY_HIGH);
	LL_DMA_SetMode(DMA1, LL_DMA_STREAM_1, LL_DMA_MODE_NORMAL);
 
	LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_STREAM_1, LL_DMA_PERIPH_NOINCREMENT);
	LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_STREAM_1, LL_DMA_MEMORY_INCREMENT);
	LL_DMA_SetPeriphSize(DMA1, LL_DMA_STREAM_1, LL_DMA_PDATAALIGN_BYTE);
	LL_DMA_SetMemorySize(DMA1, LL_DMA_STREAM_1, LL_DMA_PDATAALIGN_BYTE);
 
	/* DMA IRQ */
	LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_1);		/* Rx Transfer Complete */
	LL_DMA_EnableIT_TE(DMA1, LL_DMA_STREAM_1);		/* Rx Transfer Error */
 
	NVIC_SetPriority(DMA1_Stream1_IRQn, 0);			/* Rx Stream Priority */
	NVIC_EnableIRQ(DMA1_Stream1_IRQn);			/* Rx Global IRQ */
	LL_USART_EnableDMAReq_RX(USART3);			/* Enable Rx DMARQ */
 
	LL_DMA_ConfigAddresses(DMA1,
			       LL_DMA_STREAM_1,
			       LL_USART_DMA_GetRegAddr(USART3, LL_USART_DMA_REG_DATA_RECEIVE),
			       (uint32_t)rxbuf,
			       LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_STREAM_1));
 
	LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_1, rxlen);
 
	LL_DMA_EnablePeriphDMA(DMA1, LL_DMA_STREAM_1);		/* Enable USART Rx DMA */
	LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_1);		/* Enable DMA Channel Rx */
}
 
void led_blink(uint8_t led, uint32_t Period)
{
	while (1) {
		switch (led) {
		case 1:
			LL_GPIO_TogglePin(GPIOB, LL_GPIO_PIN_0);
			break;
		case 2:
			LL_GPIO_TogglePin(GPIOE, LL_GPIO_PIN_1);
			break;
		case 3:
			LL_GPIO_TogglePin(GPIOB, LL_GPIO_PIN_14);
			break;
		}
		LL_mDelay(Period);
	}
}
 
void DMA1_Stream1_IRQHandler(void)
{
	if (LL_DMA_IsActiveFlag_TC1(DMA1)) {
		LL_DMA_ClearFlag_TC1(DMA1);
		rx_done = 1;
//		LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_0);		/* Done: LED ON */
		led_blink(1, 100);
	} else if (LL_DMA_IsActiveFlag_TE1(DMA1)) {
//		LL_DMA_DisablePeriphDMA(DMA1, LL_DMA_STREAM_1);		/* Disable USART Rx DMA */
		led_blink(2, 1000);					/* loop in here */
	}
}
 
int main(void)
{
	SystemClock_Config();
	led_init();
	config_dma();
	config_usart();
 
	while (1) {
 
	}
}

4 REPLIES 4
Pavel A.
Evangelist III

It seems to be missing files "lwrb/lwrb.h"

So, I tried the usart_init() and SystemClock_Config() functions;

But that gives me a DMA TEIF0, trying to read data from a terminal.

The code's working at your end ?

Identified the issue as the buffer is placed in DTCM ?

Moving it to AXI SRAM did fix the issue.

Ttian.3
Associate

i just use hal not LL, and uart with dma makes sense.