AnsweredAssumed Answered

Dual USART DMA configuration issue on STM32F722

Question asked by David Pekin on Feb 16, 2018
Latest reply on Feb 17, 2018 by David Pekin

Hello,

 

I have a single USART (USART_6) working correctly with the STM32F722 Nucleo board.  It is DMA interrupt driven and the callback complete functions are getting called correctly.  Now I'm working on bringing up a second UART (USART_2) and I'm having considerable trouble getting the DMA to work with it.  The call back function never gets calles and I do'nt see any activity on the lines.  I've debugged all the HAL DMA setup calls and have no errors (that I can find).   The callbacks are set correctly in the UartHandle when Transmit_DMA is called and the program is waiting for the callback to be called...

 

I'm wondering what restrictions there are for what DMA channels I can use.  For the working USART I'm using DMA2, Channel 5 and streams 1 & 7 (I don't know why these are used as they came from the sample code).  For the second not working USART, I'm using DMA2, Channel 6 and streams 5 & 6.  Can I share the same DMA2 between the two?  Is there some logic to choosing the channel and stream numbers?  

 

Below is my configuration from main.h and MSP initialization code from STM32f7xx_hal_msp.c.    Any suggestions or idea of why the DMA is failing would be appreciated.

 

Thanks in advance.

 

 

From main.h

/* User can use this section to tailor USARTx/UARTx instance used and associated
resources */
/* Definition for USARTx clock resources */
// configuration for RS-422 using dedicated pins and driver chip

#define USARTx USART6
#define USARTx_CLK_ENABLE() __HAL_RCC_USART6_CLK_ENABLE()
#define DMAx_CLK_ENABLE() __HAL_RCC_DMA2_CLK_ENABLE()
#define USARTx_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
#define USARTx_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()

#define USARTx_FORCE_RESET() __HAL_RCC_USART6_FORCE_RESET()
#define USARTx_RELEASE_RESET() __HAL_RCC_USART6_RELEASE_RESET()

/* Definition for USARTx Pins */
#define USARTx_TX_PIN GPIO_PIN_6
#define USARTx_TX_GPIO_PORT GPIOC
#define USARTx_TX_AF GPIO_AF8_USART6
#define USARTx_RX_PIN GPIO_PIN_7
#define USARTx_RX_GPIO_PORT GPIOC
#define USARTx_RX_AF GPIO_AF8_USART6

/* Definition for USARTx's DMA */
#define USARTx_TX_DMA_STREAM DMA2_Stream7
#define USARTx_RX_DMA_STREAM DMA2_Stream1
#define USARTx_TX_DMA_CHANNEL DMA_CHANNEL_5
#define USARTx_RX_DMA_CHANNEL DMA_CHANNEL_5


/* Definition for USARTx's NVIC */
#define USARTx_DMA_TX_IRQn DMA2_Stream7_IRQn
#define USARTx_DMA_RX_IRQn DMA2_Stream1_IRQn
#define USARTx_DMA_TX_IRQHandler DMA2_Stream7_IRQHandler
#define USARTx_DMA_RX_IRQHandler DMA2_Stream1_IRQHandler

/* Definition for USARTx's NVIC */
#define USARTx_IRQn USART6_IRQn
#define USARTx_IRQHandler USART6_IRQHandler

/* Size of Trasmission buffer */
#define UART_TXBUFFERSIZE (UART_COUNTOF(UART_aTxBuffer) - 1)
/* Size of Reception buffer */
#define UART_RXBUFFERSIZE sizeof(api_msg_t)

/* Exported macro ------------------------------------------------------------*/
#define UART_COUNTOF(__BUFFER__) (sizeof(__BUFFER__) / sizeof(*(__BUFFER__)))
/* Exported functions ------------------------------------------------------- */

 

 

#if DUALUART
// 2nd uart definitions
#define USART2x USART2
#define USART2x_CLK_ENABLE() __HAL_RCC_USART2_CLK_ENABLE()
#define DMA2x_CLK_ENABLE() __HAL_RCC_DMA2_CLK_ENABLE()
#define USART2x_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
#define USART2x_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()

#define USART2x_FORCE_RESET() __HAL_RCC_USART2_FORCE_RESET()
#define USART2x_RELEASE_RESET() __HAL_RCC_USART2_RELEASE_RESET()

/* Definition for USARTx Pins */
#define USART2x_TX_PIN GPIO_PIN_5
#define USART2x_TX_GPIO_PORT GPIOD
#define USART2x_TX_AF GPIO_AF7_USART2
#define USART2x_RX_PIN GPIO_PIN_6
#define USART2x_RX_GPIO_PORT GPIOD
#define USART2x_RX_AF GPIO_AF7_USART2

/* Definition for USARTx's DMA */
#define USART2x_TX_DMA_STREAM DMA2_Stream6
#define USART2x_RX_DMA_STREAM DMA2_Stream5
#define USART2x_TX_DMA_CHANNEL DMA_CHANNEL_6
#define USART2x_RX_DMA_CHANNEL DMA_CHANNEL_6


/* Definition for USARTx's NVIC */
#define USART2x_DMA_TX_IRQn DMA2_Stream6_IRQn
#define USART2x_DMA_RX_IRQn DMA2_Stream5_IRQn
#define USART2x_DMA_TX_IRQHandler DMA2_Stream6_IRQHandler
#define USART2x_DMA_RX_IRQHandler DMA2_Stream5_IRQHandler

/* Definition for USARTx's NVIC */
#define USART2x_IRQn USART2_IRQn
#define USART2x_IRQHandler USART2_IRQHandler

/* Size of Trasmission buffer */
#define UART2_TXBUFFERSIZE (UART_COUNTOF(UART_aTxBuffer) - 1)
/* Size of Reception buffer */
#define UART2_RXBUFFERSIZE sizeof(api_msg_t)

/* Exported macro ------------------------------------------------------------*/
#define UART2_COUNTOF(__BUFFER__) (sizeof(__BUFFER__) / sizeof(*(__BUFFER__)))
#endif

 

 

 

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
static DMA_HandleTypeDef hdma_tx;
static DMA_HandleTypeDef hdma_rx;
static DMA_HandleTypeDef hdma2_tx;
static DMA_HandleTypeDef hdma2_rx;

GPIO_InitTypeDef GPIO_InitStruct;

if (huart == &UartHandle)
{

/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO TX/RX clock */
USARTx_TX_GPIO_CLK_ENABLE();
USARTx_RX_GPIO_CLK_ENABLE();

/* Enable USARTx clock */
USARTx_CLK_ENABLE();

/* Enable DMA clock */
DMAx_CLK_ENABLE();

/*##-2- Configure peripheral GPIO ##########################################*/
/* UART TX GPIO pin configuration */
GPIO_InitStruct.Pin = USARTx_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = USARTx_TX_AF;

HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);

/* UART RX GPIO pin configuration */
GPIO_InitStruct.Pin = USARTx_RX_PIN;
GPIO_InitStruct.Alternate = USARTx_RX_AF;

HAL_GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStruct);

/*##-3- Configure the DMA ##################################################*/
/* Configure the DMA handler for Transmission process */
hdma_tx.Instance = USARTx_TX_DMA_STREAM;
hdma_tx.Init.Channel = USARTx_TX_DMA_CHANNEL;
hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_tx.Init.Mode = DMA_NORMAL;
hdma_tx.Init.Priority = DMA_PRIORITY_LOW;

HAL_DMA_Init(&hdma_tx);

/* Associate the initialized DMA handle to the UART handle */
__HAL_LINKDMA(huart, hdmatx, hdma_tx);

/* Configure the DMA handler for reception process */
hdma_rx.Instance = USARTx_RX_DMA_STREAM;
hdma_rx.Init.Channel = USARTx_RX_DMA_CHANNEL;
hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_rx.Init.Mode = DMA_NORMAL;
hdma_rx.Init.Priority = DMA_PRIORITY_HIGH;

HAL_DMA_Init(&hdma_rx);

/* Associate the initialized DMA handle to the the UART handle */
__HAL_LINKDMA(huart, hdmarx, hdma_rx);

/*##-4- Configure the NVIC for DMA #########################################*/
/* NVIC configuration for DMA transfer complete interrupt (USART6_TX) */
HAL_NVIC_SetPriority(USARTx_DMA_TX_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(USARTx_DMA_TX_IRQn);

/* NVIC configuration for DMA transfer complete interrupt (USART6_RX) */
HAL_NVIC_SetPriority(USARTx_DMA_RX_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USARTx_DMA_RX_IRQn);

/* NVIC for USART, to catch the TX complete */
HAL_NVIC_SetPriority(USARTx_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(USARTx_IRQn);
}
#if DUALUART
else // then it's the 2nd uart handle
{
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO TX/RX clock */
USART2x_TX_GPIO_CLK_ENABLE();
USART2x_RX_GPIO_CLK_ENABLE();

/* Enable USARTx clock */
USART2x_CLK_ENABLE();

/* Enable DMA clock */
DMA2x_CLK_ENABLE();

/*##-2- Configure peripheral GPIO ##########################################*/
/* UART TX GPIO pin configuration */
GPIO_InitStruct.Pin = USART2x_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = USART2x_TX_AF;

HAL_GPIO_Init(USART2x_TX_GPIO_PORT, &GPIO_InitStruct);

/* UART RX GPIO pin configuration */
GPIO_InitStruct.Pin = USART2x_RX_PIN;
GPIO_InitStruct.Alternate = USART2x_RX_AF;

HAL_GPIO_Init(USART2x_RX_GPIO_PORT, &GPIO_InitStruct);

/*##-3- Configure the DMA ##################################################*/
/* Configure the DMA handler for Transmission process */
hdma2_tx.Instance = USART2x_TX_DMA_STREAM;
hdma2_tx.Init.Channel = USART2x_TX_DMA_CHANNEL;
hdma2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma2_tx.Init.Mode = DMA_NORMAL;
hdma2_tx.Init.Priority = DMA_PRIORITY_LOW;

HAL_DMA_Init(&hdma2_tx);

/* Associate the initialized DMA handle to the UART handle */
__HAL_LINKDMA(huart, hdmatx, hdma2_tx);

/* Configure the DMA handler for reception process */
hdma2_rx.Instance = USART2x_RX_DMA_STREAM;
hdma2_rx.Init.Channel = USART2x_RX_DMA_CHANNEL;
hdma2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma2_rx.Init.Mode = DMA_NORMAL;
hdma2_rx.Init.Priority = DMA_PRIORITY_HIGH;

HAL_DMA_Init(&hdma2_rx);

/* Associate the initialized DMA handle to the the UART handle */
__HAL_LINKDMA(huart, hdmarx, hdma2_rx);

/*##-4- Configure the NVIC for DMA #########################################*/
/* NVIC configuration for DMA transfer complete interrupt (USART6_TX) */
HAL_NVIC_SetPriority(USART2x_DMA_TX_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(USART2x_DMA_TX_IRQn);

/* NVIC configuration for DMA transfer complete interrupt (USART6_RX) */
HAL_NVIC_SetPriority(USART2x_DMA_RX_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART2x_DMA_RX_IRQn);

/* NVIC for USART, to catch the TX complete */
HAL_NVIC_SetPriority(USART2x_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(USART2x_IRQn);
}
#endif
}

Outcomes