cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L476RG UART TX proccess via DMA without UART interrupt

volkan
Associate II

Hello Friends,

I have a problem about Uart send via DMA. I had created a configuration via cube. the configuration has Uart2 Rx on DMA1 channel6 and Uart2 Tx on DMA1 channel7. Both of DMA channels are in normal mode. Uart2 interrupts are closed. My MCU platform is Nucleo-L476RG. I use hercules for uart tx rx tests. My aim is to send and receive messages with DMA without Uart Rx and Tx interrputs. I have to use HAL library but I don't like it, I'm used to using CMSIS library :(

I can receive messages many times from terminal without uart receive interrupt, but I can send message only once. When I try to send another message to terminal, there is no happen. I checked it in debug mode, I saw that HAL_UART_STATE_READY was busy in stm32l4xx_hal_uart.c file. I would like to point that message that was sent only once after reset can sent completely. HAL_UART_TxCpltCallback doesn't run when DMA send proccess is complete. But DMA1_Channel7_IRQHandler run two times (transfer half and full complete).

My second question is to receive message with DMA but I don't want to get interrupt half complete transfer. I want to get full trasfer interrupt only. I found HTIE flag in CCR register in datasheet and close it after HAL_UART_Receive_DMA function. Is it correct approach for this?

You can see my part of code in below.

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
 
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdio.h>
 
/* USER CODE END Includes */
 
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
 
/* USER CODE END PTD */
 
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define Uart_Print(__message)   HAL_UART_Transmit(&huart2,(uint8_t *)__message,strlen(__message),10)
/* USER CODE END PD */
 
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
 
/* USER CODE END PM */
 
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart2_rx;
DMA_HandleTypeDef hdma_usart2_tx;
 
/* USER CODE BEGIN PV */
uint8_t UART2_rxBuffer[12] = {0};
uint8_t UART2_txBuffer[] = {"volkan benzer\n\0"};
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */
 
/* USER CODE END PFP */
 
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
 
/* USER CODE END 0 */
 
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
	uint32_t waitTimer = 0;
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
	
	
 
	HAL_UART_Receive_DMA (&huart2, UART2_rxBuffer, 12);
	
	hdma_usart2_rx.Instance->CCR &= 0xFFFFFFFB;						//close half complete interrupt
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    if((HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 0) && (waitTimer == 0))
		{
			HAL_UART_Transmit_DMA (&huart2, UART2_txBuffer, strlen((char *)UART2_txBuffer));			
			waitTimer = HAL_GetTick();		
		}
		else
		{
			if(waitTimer != 0) 
			{
				if(HAL_GetTick() > (waitTimer + 100))
					waitTimer = 0;
			}
		}
		/* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	HAL_UART_Receive_DMA(&huart2, UART2_rxBuffer, 12);
	Uart_Print("Rx CallBack\n\0");
}
 
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
/* USER CODE END 4 */

void DMA1_Channel6_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel6_IRQn 0 */
 
  /* USER CODE END DMA1_Channel6_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart2_rx);
 
  /* USER CODE BEGIN DMA1_Channel6_IRQn 1 */
	hdma_usart2_rx.Instance->CCR &= 0xFFFFFFFB;
	Uart_Print("Rx Kesme geldi\n\0");
  /* USER CODE END DMA1_Channel6_IRQn 1 */
}
 
/**
  * @brief This function handles DMA1 channel7 global interrupt.
  */
void DMA1_Channel7_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel7_IRQn 0 */
  /* USER CODE END DMA1_Channel7_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart2_tx);	
  /* USER CODE BEGIN DMA1_Channel7_IRQn 1 */
	//HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
  /* USER CODE END DMA1_Channel7_IRQn 1 */
}

11 REPLIES 11

Dear @Guenael Cadier_O (ST Employee)​,

Thank you for your reply. I will test it asap.

Imen.D
ST Employee

Hello @volkan​ ,

Did you tested the suggestion provided by @Community member​ and @Guenael Cadier​ ? Does it work this time?

If one of these posts answers your question, please click the Best Answer ("Select as Best" button).

Thank you!

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen