cancel
Showing results for 
Search instead for 
Did you mean: 

DMA transfer in interrupt mode

FIann.2
Associate II

Hi, in the book i am reading there is an example about UART DMA trasnfer in interrupt mode. In this example i don t understand why the author enables the UART related interrupt.

I mean it is not the UART to generate the interrupt but the DMA when trasfer is completed, so why he needs to enable UART interrupts?

Another question:

if i want perform a DMA transfer in interrupt mode when a Timer expires, so i have to enable the timere interrupts also?

Many thanks

9 REPLIES 9
Pavel A.
Evangelist III

The book? which book?

Please see these good examples for UARTs with DMA.

https://github.com/MaJerle/stm32-usart-uart-dma-rx-tx/

Carmine Noviello book "Mastering STM32"

Do you know why he enables UART interruput when performing a DMA trasfer in interrupt mode?

He specially say not to forget to do it.

You would need to tell a bit more about the example.

There are several UART-related interrupts, for transmission (TxE), reception (RxNE), and errors.

Or perhaps he used an interrupt to manage DMA-based transmission for varying string length.

Hi the example is below.

In this example he is using the function HAL_UART_Receive_DMA which belongs to the HAL_UART module.

He specially raccomands to enable the UART related interrupt and call the HAL_UART_IRQHandler() routine from its ISR.

In a previous example he does the same job but using instead the HAL_DMA_Start_IT function(he is not using the HAL_UART module),

and he doesn t enable the UART related interrupt.

So i suppose he enables the UART interrupt when using the HAL UART module function HAL_UART_Receive_DMA.

But WHY?? i know the answer is here but is not clear to me.

Thank you very much for help!

uint8_t dataArrived = 0;

 

int main(void) {

HAL_Init();

Nucleo_BSP_Init(); //Configure the UART2

 

//Configure the DMA1 Channel 5, which is wired to the UART2_RX request line

hdma_usart2_rx.Instance = DMA1_Channel5;

hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;

hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;

hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

hdma_usart2_rx.Init.Mode = DMA_NORMAL;

hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW;

HAL_DMA_Init(&hdma_usart2_rx);

 

//Link the DMA descriptor to the UART2 one

__HAL_LINKDMA(&huart, hdmarx, hdma_usart2_rx);

 

/* DMA interrupt init */

HAL_NVIC_SetPriority(DMA1_Channel4_5_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(DMA1_Channel4_5_IRQn);

 

/* Peripheral interrupt init */

HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(USART2_IRQn);

 

//Receive three bytes from UART2 in DMA mode

uint8_t data[3];

HAL_UART_Receive_DMA(&huart2, &data, 3);

while(!dataArrived); //Wait for the arrival of data from UART Infinite loop */

while (1);

}

 

//This callback is automatically called by the HAL when the DMA transfer is completed

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {

dataArrived = 1;

}

 

void DMA1_Channel4_5_IRQHandler(void) {

HAL_DMA_IRQHandler(&hdma_usart2_rx); //This will automatically call the HAL_UART_RxCpltCallback()

}

The author writes:

when we use the HAL module for a given peripheral (HAL_UART in this case), we do

not need to provide our own callbacks: they are defined internally by the HAL, which uses them

to carry out its activities. The HAL offers us the ability to define our corresponding callback

functions (HAL_UART_RxCpltCallback() for UART_RX transfers in DMA mode), which will be

invoked automatically by the HAL, as shown in Figure 7. This rule applies to all HAL modules.

0693W000003ReNuQAK.png

FIann.2
Associate II

maybe he enables UART interrupt just for error menagement?

There is no UART interrupt in this example.

Only DMA TC interrupt, which notifies you when the buffer is full, i.e. the configured number of characters received.

Which you probably want, if you have just one DMA buffer.

I can't see where the DMA buffer size is configured. I am no Cube/HAL user (or friend), I don't know where this code is hidden.

I personally do never use DMA for UART reception, because one corrupted/lost character will throw the whole application logic off in a burst-mode protocol scenarion (short, isolated bursts/sentences, with longer idle phases).

It is fine for most transmission scenarios, though.

no, i think its becouse HAL_UART_RxCpltCallback is defined weak inside HAL_UART_IRQHandler

void USART2_IRQHandler(void)

{

 /* USER CODE BEGIN USART2_IRQn 0 */

 /* USER CODE END USART2_IRQn 0 */

 HAL_UART_IRQHandler(&huart2);

 /* USER CODE BEGIN USART2_IRQn 1 */

 /* USER CODE END USART2_IRQn 1 */

}

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)

{

………….

__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{

 /* Prevent unused argument(s) compilation warning */

 UNUSED(huart);

 /* NOTE: This function Should not be modified, when the callback is needed,

          the HAL_UART_TxCpltCallback could be implemented in the user file

  */

}

………..

}

FIann.2
Associate II

in HAL_UART_Receive_DMA:

/* Enable the UART Parity Error Interrupt */

SET_BIT(huart->Instance->CR1, USART_CR1_PEIE);

/* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */

SET_BIT(huart->Instance->CR3, USART_CR3_EIE);

no, you was right first:

The reason is that the HAL assumes that the “HAL_UART_IRQHandler()�? routine is properly called to setup internal HAL states. They are mostly related to UART error states (overrun, parity error, etc).