cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 DMA2 Repeated Disable and Enable Fails

Josh Yu
Associate II
Posted on April 12, 2018 at 03:22

Hi,

I'm using STM32F407 in my project and I use DMA2 on USART1 RX/TX. Since my TX packet length changes almost every time, I'd have to disable DMA, reconfigure it to the correct data length, and enable DMA. I'm doing this at least 100Hz if not more. And I don't know if it's because of that, the DMA would fail to enable after random periods of time. I write 1 to the EN bit in the control register and poll it to make sure it actually becomes 1, but it never does. I'm not sure what the problem is, since it always works for a few minutes then stops working. Another interesting point is that the DMA2 RX doesn't stop working at all. If anyone has any pointers I highly appreciate it. Thanks!

Here's my USART1 TX and DMA reconfigure code: (by the way, the printf statements printed out the same values when the DMA is working and when it's not)

void USART1_DMA2_Send_Array(u8 * data_to_send_addr, u16 send_length)
{
static int i = 0;
// Make sure that the UART TX DMA is disabled (which should already be disabled by hardware if
// the previous transfer is completed)
uint16_t remaining = DMA_GetCurrDataCounter(DMA2_Stream7);
if (remaining != 0) {
printf('Remaining DMA transfer = %u', remaining);
}
i = 0;
DMA_Cmd(DMA2_Stream7,DISABLE);
while(DMA_GetCmdStatus(DMA2_Stream7) != DISABLE) {
DMA_Cmd(DMA2_Stream7,DISABLE);
printf('Disabling DMA... %d\n', i);
i++;
if (i > 1000) {
System_Failure();
}
}
DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_TCIF7|DMA_FLAG_HTIF7|DMA_FLAG_TEIF7|DMA_FLAG_DMEIF7|DMA_FLAG_FEIF7);
USART_ClearFlag(USART1, USART_FLAG_TC);
DMA_InitTypeDef DMA_InitStructure;
 // common configuration
 DMA_StructInit(&DMA_InitStructure);
 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
 DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
 DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
 DMA_InitStructure.DMA_Priority = DMA_Priority_High;
 // Configure TX DMA: DMA2_Stream7 Channel 4
 DMA_InitStructure.DMA_Channel = DMA_Channel_4;
 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(USART1->DR);
 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
 DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
 DMA_InitStructure.DMA_BufferSize = send_length;
 DMA_InitStructure.DMA_Memory0BaseAddr = (u32)data_to_send_addr;
 DMA_Init(DMA2_Stream7,&DMA_InitStructure);
//DMA_SetCurrDataCounter(DMA2_Stream7, send_length);
// printf('Enabling DMA... %d\n', i);
//printf('Buffer size = %u\n', send_length);
//printf('USART1->SR = 0x%x\n', USART1->SR);
//printf('USART1->CR1 = 0x%x\n', USART1->CR1);
//printf('USART1->CR3 = 0x%x\n', USART1->CR3);
//printf('DMA2->HISR = 0x%x\n', DMA2->HISR);
//printf('DMA2->S7CR = 0x%x\n\n', DMA2_Stream7->CR);
 // started to transmit
 i = 0;
 DMA_Cmd(DMA2_Stream7,ENABLE);
 while(DMA_GetCmdStatus(DMA2_Stream7) != ENABLE) {
 DMA_Cmd(DMA2_Stream7,ENABLE);
//printf('Enabling DMA... %d\n', i);
//printf('Buffer size = %u\n', send_length);
//printf('USART1->SR = 0x%x\n', USART1->SR);
//printf('USART1->CR1 = 0x%x\n', USART1->CR1);
//printf('USART1->CR3 = 0x%x\n', USART1->CR3);
//printf('DMA2->HISR = 0x%x\n', DMA2->HISR);
//printf('DMA2->S7CR = 0x%x\n', DMA2_Stream7->CR);
i++;
vTaskDelay(pdMS_TO_TICKS(1));
if (i > 1000) {
System_Failure();
}
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

#stm32f4 #dma #usart #usart-tx-issue
11 REPLIES 11
Posted on April 13, 2018 at 09:16

So the status flags are cleared, and still the EN bit won't be set... humm.

Can you please tell us about how do you handle the reception? Do you reconfigure its DMA?

I see you have transfer-error interrupt enabled. How is it handled? Does it happen? Doesn't it happen just before the problem?

Can you please make a copy of the HTIF before you clear it, into a local variable, and then print it out when the problem happens?

You don't enable/disable or reset the UART, do you?

You don't observe the USART and/or DMA registers in a debugger while the application is running, do you? If you do, please disconnect the debugger and try to run the application without it.

JW

Posted on April 13, 2018 at 10:07

Not even closely. As I've said, it's three register writes, or maybe four.

For you, yes.

Pretty sure Cube generates much noise about those simple register writes...