cancel
Showing results for 
Search instead for 
Did you mean: 

DMA uart XferCpltCallback problem

Tanaz Javanmardi
Associate
Posted on June 09, 2018 at 08:55

Hi

I use DMA in Interrupt mode to receive data from UART Periph to memory. data is transfered (my destination memory is occupied correctly)but my DMAReceiptComplete() callback function is never called.

/*--------------------------------------------------------------------------main.c------------------------------------------------------------------------*/

/* Includes ------------------------------------------------------------------*/

&sharpinclude 'stm32f1xx_hal.h'

&sharpinclude <myboard_hal_bsp.h>

&sharpinclude 'string.h'

/* Private variables ---------------------------------------------------------*/

extern UART_HandleTypeDef huart2;

extern UART_HandleTypeDef huart1;

DMA_HandleTypeDef hdma_usart1_rx;

DMA_HandleTypeDef hdma_usart2_tx;

char *msg = 'HI Hello STM32 Lovers! This message is transferred in DMA Mode.\r\n';

uint8_t buf[2] = '';

void DMAReceiptComplete(DMA_HandleTypeDef *hdma);

int main(void){

    HAL_Init();

    MyBoard_BSP_Init();

    //USART1

    hdma_usart1_rx.Instance = DMA1_Channel5;

    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;

    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;

    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;

    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

    hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;

    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;

    hdma_usart1_rx.XferCpltCallback = &DMAReceiptComplete;

    HAL_DMA_Init(&hdma_usart1_rx);

    /* DMA interrupt init */

    HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);

    HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);

    HAL_DMA_Start_IT(&hdma_usart1_rx, (uint32_t)&huart1.Instance->DR, (uint32_t)buf, 2);

    //Enable UART in DMA mode

    huart1.Instance->CR3 |= USART_CR3_DMAR;

    //USART2

    hdma_usart2_tx.Instance = DMA1_Channel7;

    hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;

    hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE;

    hdma_usart2_tx.Init.MemInc = DMA_MINC_DISABLE;

    hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;

    hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

    hdma_usart2_tx.Init.Mode = DMA_NORMAL;

    hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW;

    HAL_DMA_Init(&hdma_usart2_tx);

    __HAL_LINKDMA(&huart2, hdmatx, hdma_usart2_tx);

    /* DMA interrupt init */

    HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0);

    HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);

    /* Peripheral interrupt init */

    HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);

    HAL_NVIC_EnableIRQ(USART2_IRQn);

    //Enable UART in DMA mode ( receive or transmit DMAR DMAT)

    huart2.Instance->CR3 |= USART_CR3_DMAT;

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

    while(1);

     return 0;

}

void DMAReceiptComplete(DMA_HandleTypeDef *hdma) {

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

    if (hdma->Instance == DMA1_Channel5){ //now we should enable usart2 i think

        HAL_UART_Transmit_DMA(&huart2, (uint8_t*)buf, 2);

    }

}

void DMA1_Channel5_IRQHandler(void){

    HAL_DMA_IRQHandler(&hdma_usart1_rx);

}

void USART1_IRQHandler (void){

    HAL_UART_IRQHandler(&huart1);

}

void DMA1_Channel7_IRQHandler(void){

    HAL_DMA_IRQHandler(&hdma_usart2_tx);

}

void USART2_IRQHandler (void){

    HAL_UART_IRQHandler(&huart2);

}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){

    ;

}

Is it a bug or I made mistake somewhere?

#dma-uart #xfercpltcallback
3 REPLIES 3
T J
Lead
Posted on June 11, 2018 at 01:10

did you fix it ?

did you use the cube ?

I use the Uart  DMA in Circular mode.

I just calculate the buffer size from the DMA counter.

Posted on June 11, 2018 at 10:47

no I haven't fixed it.

yes I used cube

the problem is with dmauart1_rx , I used it in circular mode too. but

what's the point?

Posted on June 11, 2018 at 10:56

why do you need DMAReceiptComplete() ?

I poll this function every mS,   RxBufSize = readableU1();  // unread length

void initUart1RxDMABuffer(void) {

    if (HAL_UART_Receive_DMA(&huart1, (uint8_t *)Usart1RxDMABuffer, U1RxBufSize) != HAL_OK)

 

        printf(string, 'initUart1RxDMABuffer Failed\n');

    else

        printf(string, 'initUart1RxDMABuffer OK!\n');

}

char readableU1(void) {

    U1RxBufferPtrIN =  U1RxBufSize - huart1.hdmarx->Instance->CNDTR;

    return U1RxBufferPtrIN - U1RxBufferPtrOUT;  // length of unread characters

}

char getc1(void) {

    char Rxbyte = Usart1RxDMABuffer[U1RxBufferPtrOUT++];

    if (U1RxBufferPtrOUT >= U1RxBufSize) U1RxBufferPtrOUT = 0;

    return Rxbyte;

}