Question
STM32F030 UART TX via DMA only works once
Posted on October 31, 2016 at 22:25
Hi,
I've seen similar questions to this but none seem to have helped. I'm transmitting on UART1 via DMA channel 2 and the first transmission works fine. I am unable to get anything out after receiving a DMA TC. None of the standard peripheral libraries examples show getting the DMA transmission to restart after a completion. Here are the basics(code is shown below.) 1) After pin/uart/dma initialization I wait for a send_string call. 2) Send_string() sets up DMA1 channel 2 descriptor and size, then enables DMA1_Channel2. 3) Upon DMA TC, clear DMA1_IT_TC2 flag. I have tried going to using the UART TC interrupt(as suggested in other threads) but it never seem to fire the interrupt. I'm sure it is something simple I need to clear/reset but I am unable to find it. Thanks, John C.#ifdef SERIAL
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_0);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_0);
// Configure the serial port on PB6(TX) and PB7(RX)
GPIO_InitStructure.GPIO_Pin = TX | RX;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
#endif
#ifdef SERIAL
USART_InitTypeDef USART_InitStructure;
// USART configuration
// BaudRate = 115200 baud, Word Length = 8 Bits
// One Stop Bit, No parity,
// Hardware flow control disabled (RTS and CTS signals)
//Receive and transmit enabled
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
/* Enable USART */
USART_Cmd(USART1, ENABLE);
/* Enable the USART1 Tx DMA1 requests */
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
// USe DMA to transmit the serial data
DMA_InitTypeDef DMA_InitStructure;
/* DMA1 Channel1 Config */
DMA_DeInit(DMA1_Channel2);
DMA_InitStructure.DMA_BufferSize = SERIAL_TX_SIZE;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)infoString;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->TDR);
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Channel2, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);
#endif
#ifdef SERIAL
/* Enable the USART Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
NVIC_SetPriority(DMA1_Channel2_3_IRQn,0);
#endif
void DMA1_Channel2_3_IRQHandler(void)
{
if ((DMA1->ISR & DMA_ISR_TCIF2) != 0) /* Test if transfer completed on DMA channel 2 */
{
txTail++;
txTail &= (MAX_SERIAL_TX_BUFFS-1);
// Clear the interrupt pending flag
DMA_ClearFlag(DMA1_FLAG_TC2);
DMA_ClearITPendingBit(DMA_ISR_TCIF2);
//DMA_ClearITPendingBit(DMA1_IT_GL2);
//USART_ClearFlag(USART1, USART_FLAG_IDLE);
//USART_ClearFlag(USART1, USART_ISR_TXE);
}
}
void uart1_send(const char *string_p)
{
size_t size;
size = strlen(string_p);
if (size)
{
uart1TX[txHead].txCount = 0;
strcpy(uart1TX[txHead].txBuffer, string_p);
DMA1_Channel2->CMAR = (uint32_t)uart1TX[txHead].txBuffer;
DMA1_Channel2->CNDTR = size;
uart1TX[txHead].txSize = size;
txHead++;
txHead &= (MAX_SERIAL_TX_BUFFS-1);
DMA_Cmd(DMA1_Channel2, ENABLE);
}
}