cancel
Showing results for 
Search instead for 
Did you mean: 

Restart DMA - STM32F767

Pilous Droip
Senior
Posted on January 30, 2018 at 11:35

Hello.

I have question. How to restart DMA?

I have this init function:

&sharpdefine DMA_RX_BUFF_SIZE            64         

uint8_t dma_rx_buff[DMA_RX_BUFF_SIZE];

void MX_UART5_Init(void)

{

/* Enable CLOCK for GPIO */

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOC);

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOD);

/* Enable Clock for UART5 */

LL_RCC_SetUARTClockSource(LL_RCC_UART5_CLKSOURCE_HSI);

/* Peripheral clock enable */

LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_UART5);

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);

/* create structure */

LL_USART_InitTypeDef USART_InitStruct;

LL_GPIO_InitTypeDef GPIO_InitStruct;

/**

* UART5 GPIO Configuration

* PC12 ------> UART5_TX

* PD2 ------> UART5_RX

*/

GPIO_InitStruct.Pin = LL_GPIO_PIN_12;

GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;

GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;

GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;

GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;

GPIO_InitStruct.Alternate = LL_GPIO_AF_8;

LL_GPIO_Init(GPIOC, &GPIO_InitStruct);

GPIO_InitStruct.Pin = LL_GPIO_PIN_2;

GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;

GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;

GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;

GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;

GPIO_InitStruct.Alternate = LL_GPIO_AF_8;

LL_GPIO_Init(GPIOD, &GPIO_InitStruct);

/* Init DMA */

/* For UART5 -> STREAM - 0, CHANNEL = 4 */

LL_DMA_SetChannelSelection(DMA1, LL_DMA_STREAM_0, LL_DMA_CHANNEL_4);

LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_STREAM_0, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);

LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_0, LL_DMA_PRIORITY_LOW);

LL_DMA_SetMode(DMA1, LL_DMA_STREAM_0, LL_DMA_MODE_NORMAL);

LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_STREAM_0, LL_DMA_PERIPH_NOINCREMENT);

LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_STREAM_0, LL_DMA_MEMORY_INCREMENT);

LL_DMA_SetPeriphSize(DMA1, LL_DMA_STREAM_0, LL_DMA_PDATAALIGN_BYTE);

LL_DMA_SetMemorySize(DMA1, LL_DMA_STREAM_0, LL_DMA_MDATAALIGN_BYTE);

LL_DMA_DisableFifoMode(DMA1, LL_DMA_STREAM_0);

LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_0, (uint32_t)dma_rx_buff);

LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_0, sizeof(dma_rx_buff));

LL_DMA_SetPeriphAddress(DMA1, LL_DMA_STREAM_0, (uint32_t)&UART5->RDR);

//LL_DMA_EnableIT_HT(DMA1, LL_DMA_STREAM_0);

//LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_0);

LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_0);

/* init for UART5 */

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(UART5, &USART_InitStruct);

LL_USART_Init(UART5, &USART_InitStruct);

LL_USART_ConfigAsyncMode(UART5);

LL_USART_EnableDMAReq_RX(UART5);

//LL_USART_EnableIT_IDLE(UART5);

LL_USART_EnableRxTimeout(UART5);

LL_USART_SetRxTimeout(UART5, 115);

LL_USART_EnableIT_RTO(UART5);

LL_USART_Enable(UART5);

NVIC_SetPriority(UART5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));

NVIC_EnableIRQ(UART5_IRQn);

}

And this funtion:

void UART5_IRQHandler(void) {

uint16_t pos;

/**

* Check for idle line detection on USART

*/

if (LL_USART_IsActiveFlag_RTO(UART5)) //kontrola, zda je preruseni od TIMER Rx uartu

{

LL_USART_ClearFlag_RTO(UART5); //smazu priznak

prijatych_znaku=DMA_RX_BUFF_SIZE-LL_DMA_GetDataLength(DMA1, LL_DMA_STREAM_0);

itoa(prijatych_znaku, buffer, 10);

process_usart_data(buffer, strlen(prijatych_znaku));

LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_0);

LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_0, (uint32_t)dma_rx_buff);

LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_0, sizeof(dma_rx_buff));

LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_0);

}

}

And when I receive data I print lenght of receive data. And my receive data show as:

  • --> Send from PC
    • Hello\r\n
  • <-- Return to PC
    • 7
  • -->Send from PC
    • Hello\r\n
  • <-- Return to PC
    • 0

I would expect 7, not 0.

#uart-dma #stm32f767
6 REPLIES 6
Pilous Droip
Senior
Posted on January 30, 2018 at 12:41

I modificate this function:

void UART5_IRQHandler(void)

{

if (LL_USART_IsActiveFlag_RTO(UART5)) //check RTO uart

{

LL_USART_ClearFlag_RTO(UART5); //delete flag

receive_char=DMA_RX_BUFF_SIZE-LL_DMA_GetDataLength(DMA1, LL_DMA_STREAM_0);

itoa(

receive_char

, buffer, 10);

usart_puts(buffer);

usart_puts(''\r\nNEW:'');

LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_0);

LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_0, sizeof(dma_rx_buff));

LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_0, (uint32_t)dma_rx_buff);

LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_0);

}

}

And when I send first string, MCU return good value (7), but after this it is return only 0. And it is wrong value. Any idea, what is wrong?

Yellow: data from PC

Black: data from MCU

0690X00000604H1QAI.jpg
Posted on January 30, 2018 at 13:11

Read out and check/post the content of relevant DMA registers (including status) at the beginning of ISR.

JW

Posted on January 30, 2018 at 13:12

Sorry, but I don't understand. How do you think? 

Posted on January 30, 2018 at 13:27

The simplest way is to put a breakpoint at the beginning of the ISR and read out the registers using the registers view of debugger.

If you don't use a debugger, you can write code to do that at the beginning of ISR and then send the result to PC or visualize in any other way you prefer.

JW

Posted on January 30, 2018 at 17:43

Ok. So I look on register of DMA1 and I see one problem. Register: 

DMA_SxCR_EN 

isn't set to 1, when I restart my DMA. But I don't know why.

void UART5_IRQHandler(void)

{

if (LL_USART_IsActiveFlag_RTO(UART5)) 

LL_USART_ClearFlag_RTO(UART5); 

prijatych_znaku=DMA_RX_BUFF_SIZE-LL_DMA_GetDataLength(DMA1, LL_DMA_STREAM_0);

itoa(prijatych_znaku, buffer, 10);

usart_puts(buffer);

usart_puts(''\r\nNEW:'');

LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_0);

LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_0, (uint32_t)dma_rx_buff);

LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_0, sizeof(dma_rx_buff));

LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_0); // this set 

DMA_SxCR_EN  (problem!!!?)

LL_GPIO_TogglePin(GPIOB, LL_GPIO_PIN_14);

asm(''NOP'');   //only for debugging

}

}

But you can see in function, that I set this register.

0690X00000609YLQAY.png
Posted on January 30, 2018 at 18:44

Ok. Problem was solved.

Here is init:

void MX_UART5_Init(void)

{

/* Enable CLOCK for GPIO */

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOC);

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOD);

/* Enable Clock for UART5 */

LL_RCC_SetUARTClockSource(LL_RCC_UART5_CLKSOURCE_HSI);

/* Peripheral clock enable */

LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_UART5);

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);

/* create structure */

LL_USART_InitTypeDef USART_InitStruct;

LL_GPIO_InitTypeDef GPIO_InitStruct;

/**

* UART5 GPIO Configuration

* PC12 ------> UART5_TX

* PD2 ------> UART5_RX

*/

GPIO_InitStruct.Pin = LL_GPIO_PIN_12;

GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;

GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;

GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;

GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;

GPIO_InitStruct.Alternate = LL_GPIO_AF_8;

LL_GPIO_Init(GPIOC, &GPIO_InitStruct);

GPIO_InitStruct.Pin = LL_GPIO_PIN_2;

GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;

GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;

GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;

GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;

GPIO_InitStruct.Alternate = LL_GPIO_AF_8;

LL_GPIO_Init(GPIOD, &GPIO_InitStruct);

/* Init DMA */

/* For UART5 -> STREAM - 0, CHANNEL = 4 */

LL_DMA_SetChannelSelection(DMA1, LL_DMA_STREAM_0, LL_DMA_CHANNEL_4);

LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_STREAM_0, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);

LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_0, LL_DMA_PRIORITY_LOW);

LL_DMA_SetMode(DMA1, LL_DMA_STREAM_0, LL_DMA_MODE_NORMAL);

LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_STREAM_0, LL_DMA_PERIPH_NOINCREMENT);

LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_STREAM_0, LL_DMA_MEMORY_INCREMENT);

LL_DMA_SetPeriphSize(DMA1, LL_DMA_STREAM_0, LL_DMA_PDATAALIGN_BYTE);

LL_DMA_SetMemorySize(DMA1, LL_DMA_STREAM_0, LL_DMA_MDATAALIGN_BYTE);

LL_DMA_DisableFifoMode(DMA1, LL_DMA_STREAM_0);

LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_0, (uint32_t)dma_rx_buff);

LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_0, sizeof(dma_rx_buff));

LL_DMA_SetPeriphAddress(DMA1, LL_DMA_STREAM_0, (uint32_t)&UART5->RDR);

LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_0);

/* init for UART5 */

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(UART5, &USART_InitStruct);

LL_USART_ConfigAsyncMode(UART5);

LL_USART_EnableDMAReq_RX(UART5);

LL_USART_EnableRxTimeout(UART5);

LL_USART_SetRxTimeout(UART5, 115);

LL_USART_EnableIT_RTO(UART5);

LL_USART_Enable(UART5);

NVIC_SetPriority(UART5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));

NVIC_EnableIRQ(UART5_IRQn);

}

And interrupt is here.

void UART5_IRQHandler(void)

{

if (LL_USART_IsActiveFlag_RTO(UART5)) //kontrola, zda je preruseni od TIMER Rx uartu

{

LL_USART_ClearFlag_RTO(UART5); //smazu priznak

prijatych_znaku=DMA_RX_BUFF_SIZE-LL_DMA_GetDataLength(DMA1, LL_DMA_STREAM_0);

itoa(prijatych_znaku, buffer, 10);

usart_puts(buffer);

usart_puts('\r\nNEW:');

LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_0);

LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_0, (uint32_t)dma_rx_buff);

LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_0, sizeof(dma_rx_buff));

LL_DMA_ClearFlag_TE0(DMA1);

LL_DMA_ClearFlag_TC0(DMA1);

LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_0);

LL_GPIO_TogglePin(GPIOB, LL_GPIO_PIN_14);

asm('NOP');

}

}

And problem was: 

  1. Clear FLAG TCIF
  2. Clear FLAG TEIF

It is ALL.

🙂

 

🙂

 

🙂