cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H750 read USART Rx data via DMA

CBrom.1
Associate II

Dear ST Community,

I would like to set up the USART1 and DMA2 in a way, so that the DMA automatically stores the data received by the USART to a buffer variable.

To achieve that I used STM32CubeMX to generate the configuration code utilizing the Low Level- library and added some necessary commands.

Without DMA request enabled the USART1_IRQHandler is entered and via the debugger I can read the expected data within the USART1->RDR register. With the DMA request enabled neither the USART nor the DMA IRQHandler are accessed. Therefore, I suspect that my problem is that with the DMA Request enabled no interrupt is issued when sending data.

If you can find problems with my code I would really appreciate your answers.

The compiler otimization flag is set to -O0. The code is as follows:

 Declaration of the buffer variable:

__attribute__ ((section(".buffers"), used))
uint8_t usart1_rx_buffer[10];

with the key .buffers is mapped to the SRAM memory address 0x38000000 in the linker script according to https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices:

   .buffers(NOLOAD) : {
   . = ALIGN(4);
   *(.buffers*)
 } > RAM_D3

Commands within the main function:

  LL_APB4_GRP1_EnableClock(LL_APB4_GRP1_PERIPH_SYSCFG);
 
  NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
 
  while (1)
  {
	  __asm("nop");
  }

SystemClock_Config():

  LL_FLASH_SetLatency(LL_FLASH_LATENCY_4);
  while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_4)
  {
  }
  LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY);
  LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0);
  LL_RCC_HSI_Enable();
 
   /* Wait till HSI is ready */
  while(LL_RCC_HSI_IsReady() != 1)
  {
 
  }
  LL_RCC_HSI_SetCalibTrimming(32);
  LL_RCC_HSI_SetDivider(LL_RCC_HSI_DIV1);
  LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSI);
  LL_RCC_PLL1P_Enable();
  LL_RCC_PLL1_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_8_16);
  LL_RCC_PLL1_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
  LL_RCC_PLL1_SetM(4);
  LL_RCC_PLL1_SetN(60);
  LL_RCC_PLL1_SetP(2);
  LL_RCC_PLL1_SetQ(2);
  LL_RCC_PLL1_SetR(2);
  LL_RCC_PLL1_Enable();
 
   /* Wait till PLL is ready */
  while(LL_RCC_PLL1_IsReady() != 1)
  {
  }
 
   /* Intermediate AHB prescaler 2 when target frequency clock is higher than 80 MHz */
   LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
 
  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1);
  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_SetAPB3Prescaler(LL_RCC_APB3_DIV_2);
  LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_2);
 
  LL_Init1msTick(480000000);
 
  LL_SetSystemCoreClock(480000000);
  LL_RCC_SetUSARTClockSource(LL_RCC_USART16_CLKSOURCE_PCLK2);

MX_GPIO_Init():

/* GPIO Ports Clock Enable */
  LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOB);

 MX_DMA_Init():

/* DMA controller clock enable */
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2);
 
  NVIC_SetPriority(DMA2_Stream0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(DMA2_Stream0_IRQn);
 
  NVIC_SetPriority(DMA2_Stream1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(DMA2_Stream1_IRQn);

 MX_USART1_UART_Init():

   LL_USART_InitTypeDef USART_InitStruct = {0};
   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
 
  /* Peripheral clock enable */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);
   LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOB);
 
  /**USART1 GPIO Configuration
  PB14   ------> USART1_TX
  PB15   ------> USART1_RX  */
  GPIO_InitStruct.Pin 			= LL_GPIO_PIN_14|LL_GPIO_PIN_15;
  GPIO_InitStruct.Mode 			= LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed 		= LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType 	= LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull 			= LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate 	= LL_GPIO_AF_4;
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
  /* USART1 interrupt Init */
  NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(USART1_IRQn);
 
  USART_InitStruct.PrescalerValue 		= LL_USART_PRESCALER_DIV1;
  USART_InitStruct.BaudRate 			= 115200;
  USART_InitStruct.DataWidth 			= LL_USART_DATAWIDTH_8B;
  USART_InitStruct.StopBits 			= LL_USART_STOPBITS_1;
  USART_InitStruct.Parity 				= LL_USART_PARITY_NONE;
  USART_InitStruct.TransferDirection 	= LL_USART_DIRECTION_TX_RX;
  USART_InitStruct.HardwareFlowControl 	= LL_USART_HWCONTROL_NONE;
  USART_InitStruct.OverSampling 		= LL_USART_OVERSAMPLING_16;
  LL_USART_Init(USART1, &USART_InitStruct);
  
  LL_USART_SetTXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_2);
  LL_USART_SetRXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_2);
  LL_USART_DisableFIFO(USART1);
 
  LL_USART_ConfigAsyncMode(USART1);
  LL_USART_EnableDMAReq_RX(USART1);
  LL_USART_DisableOneBitSamp(USART1);
  LL_USART_DisableIT_TC(USART1);
  LL_USART_ClearFlag_TC(USART1);
 
  LL_USART_EnableIT_RXNE_RXFNE(USART1);
  LL_USART_Enable(USART1);
   /* Polling USART1 initialisation */
  while((!(LL_USART_IsActiveFlag_REACK(USART1))))
  {
  }
 
  /* USART1_RX Init */
   LL_DMA_SetPeriphRequest(DMA2, LL_DMA_STREAM_0, LL_DMAMUX1_REQ_USART1_RX);
  LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_STREAM_0, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
  LL_DMA_SetStreamPriorityLevel(DMA2, LL_DMA_STREAM_0, LL_DMA_PRIORITY_LOW);
  LL_DMA_SetMode(DMA2, LL_DMA_STREAM_0, LL_DMA_MODE_CIRCULAR);
  LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_STREAM_0, LL_DMA_PERIPH_NOINCREMENT);
  LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_STREAM_0, LL_DMA_MEMORY_INCREMENT);
  LL_DMA_SetPeriphSize(DMA2, LL_DMA_STREAM_0, LL_DMA_PDATAALIGN_BYTE);
  LL_DMA_SetMemorySize(DMA2, LL_DMA_STREAM_0, LL_DMA_MDATAALIGN_BYTE);
  LL_DMA_DisableFifoMode(DMA2, LL_DMA_STREAM_0);
 
  /* USART1_TX Init */
  LL_DMA_SetPeriphRequest(DMA2, LL_DMA_STREAM_1, LL_DMAMUX1_REQ_USART1_TX);
  LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_STREAM_1, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
  LL_DMA_SetStreamPriorityLevel(DMA2, LL_DMA_STREAM_1, LL_DMA_PRIORITY_LOW);
  LL_DMA_SetMode(DMA2, LL_DMA_STREAM_1, LL_DMA_MODE_NORMAL);
  LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_STREAM_1, LL_DMA_PERIPH_NOINCREMENT);
  LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_STREAM_1, LL_DMA_MEMORY_INCREMENT);
  LL_DMA_SetPeriphSize(DMA2, LL_DMA_STREAM_1, LL_DMA_PDATAALIGN_BYTE);
  LL_DMA_SetMemorySize(DMA2, LL_DMA_STREAM_1, LL_DMA_MDATAALIGN_BYTE);
  LL_DMA_DisableFifoMode(DMA2, LL_DMA_STREAM_1);
 
  LL_DMA_SetPeriphAddress(DMA2, LL_DMA_STREAM_0, (uint32_t)(&(USART1->RDR)));
  LL_DMA_SetMemoryAddress(DMA2, LL_DMA_STREAM_0, (uint32_t)(&usart1_rx_buffer));
  LL_DMA_SetDataLength(DMA2, LL_DMA_STREAM_0, 4);
  LL_DMA_SetMemoryBurstxfer(DMA2, LL_DMA_STREAM_0, LL_DMA_MBURST_SINGLE);
  LL_DMA_SetStreamPriorityLevel(DMA2, LL_DMA_STREAM_0, LL_DMA_PRIORITY_HIGH);
  LL_DMA_EnableIT_TC(DMA2, LL_DMA_STREAM_0);
  LL_DMA_EnableStream(DMA2, LL_DMA_STREAM_0);
 
  LL_DMA_SetPeriphAddress(DMA2, LL_DMA_STREAM_1, (uint32_t)(&(USART1->TDR)));
  LL_DMA_SetMemoryAddress(DMA2, LL_DMA_STREAM_1, (uint32_t)(&usart1_tx_buffer));
  LL_DMA_SetDataLength(DMA2, LL_DMA_STREAM_1, 1);
  LL_DMA_SetMemoryBurstxfer(DMA2, LL_DMA_STREAM_1, LL_DMA_MBURST_SINGLE);
  LL_DMA_EnableIT_TC(DMA2, LL_DMA_STREAM_1);
  LL_DMA_EnableStream(DMA2, LL_DMA_STREAM_1);
 
  LL_USART_DisableDirectionTx(USART1);
  LL_USART_EnableDirectionRx(USART1);

USART1_IRQHandler():

if(LL_USART_IsActiveFlag_RXNE_RXFNE(USART1)) 
      LL_USART_ClearFlag_NE(USART1);
   if(LL_USART_IsActiveFlag_FE(USART1))
      LL_USART_ClearFlag_FE(USART1);
   if(LL_USART_IsActiveFlag_ORE(USART1))
      LL_USART_ClearFlag_ORE(USART1);
   if(LL_USART_IsActiveFlag_TC(USART1))
      LL_USART_ClearFlag_TC(USART1);

 DMA2_Stream0_IRQHandler():

if(LL_DMA_IsActiveFlag_HT0(DMA2))
      LL_DMA_ClearFlag_HT0(DMA2);
   if(LL_DMA_IsActiveFlag_TC0(DMA2))
      LL_DMA_ClearFlag_TC0(DMA2);

DMA2_Stream1_IRQHandler():

if(LL_DMA_IsActiveFlag_HT1(DMA2))
         LL_DMA_ClearFlag_HT1(DMA2);
   if(LL_DMA_IsActiveFlag_TC1(DMA2))
         LL_DMA_ClearFlag_TC1(DMA2);

0 REPLIES 0