cancel
Showing results for 
Search instead for 
Did you mean: 

[STM32F103] USART1 TX DMA only fires once

zhausq
Associate III
Posted on August 06, 2016 at 15:06

I have a problem, I wrote some code based of https://github.com/g4lvanix/STM32F1-workarea/tree/master/Project/STM32F10x_StdPeriph_Examples/USART/DMA_Polling and it only fires the USART1 TX DMA once for some reason, I tried to get smarter from the datasheet and reference manual but couldnt for the life of me figure out how to do it correctly.

The code is the following

 //RCC config
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);
//GPIO config
#define USART1_PORT GPIOA
#define USART1_PIN_TX GPIO_Pin_9
#define USART1_PIN_RX GPIO_Pin_10
//initialize tx pin
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = USART1_PIN_TX;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(USART1_PORT, &GPIO_InitStructure);
//DMA config
DMA_InitTypeDef DMA_InitStructure;
#define USART1_TX_DMA_CHANNEL DMA1_Channel4
#define USART1_RX_DMA_CHANNEL DMA1_Channel5
/* USARTy TX DMA1 Channel (triggered by USARTy Tx event) Config */
DMA_DeInit(USART1_TX_DMA_CHANNEL);
DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_BASE + 0x04;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)txbuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = BUFFERSIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(USART1_TX_DMA_CHANNEL, &DMA_InitStructure);
//usart config
USART_InitTypeDef USART_InitStructure;
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_Tx;
USART_Init(USART1, &USART_InitStructure);

 //tx buffer for the first time
//disable spi and dma
USART_DMACmd(USART1, USART_DMAReq_Tx, DISABLE);
USART_Cmd(USART1, DISABLE);
DMA_Cmd(USART1_TX_DMA_CHANNEL, DISABLE);
//reconfigure dma
USART1_TX_DMA_CHANNEL->CMAR = (uint32_t)txbuffer;
DMA_SetCurrDataCounter(USART1_TX_DMA_CHANNEL, 4);
//tx dma
DMA_Cmd(USART1_TX_DMA_CHANNEL, ENABLE);
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
USART_Cmd(USART1, ENABLE);
while (DMA_GetFlagStatus((int)USART1_TX_DMA_CHANNEL) == RESET);
delay_ms(1000);
 //tx buffer again
//disable spi and dma
USART_DMACmd(USART1, USART_DMAReq_Tx, DISABLE);
USART_Cmd(USART1, DISABLE);
DMA_Cmd(USART1_TX_DMA_CHANNEL, DISABLE);
//reconfigure dma
USART1_TX_DMA_CHANNEL->CMAR = (uint32_t)txbuffer;
DMA_SetCurrDataCounter(USART1_TX_DMA_CHANNEL, 4);
//tx dma
DMA_Cmd(USART1_TX_DMA_CHANNEL, ENABLE);
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
USART_Cmd(USART1, ENABLE);
while (DMA_GetFlagStatus((int)USART1_TX_DMA_CHANNEL) == RESET);
delay_ms(1000);

It correctly transmits the buffer one time but fails to do it for a second time. As I said I couldn't get smart from the documentation and would appreciate a pointer to ether my mistake and/or a reference to the documentation about it. Thank you in advance. #stm32-f1-usart-tx-dma
4 REPLIES 4
stm322399
Senior
Posted on August 06, 2016 at 16:07

I can't tell exactely what's wrong, but I have a few remarks:

* DMA must be started after USART

* no need to stop DMA as it is automatically disabled at end of transfer

* keeping dma mode of TX enabled all time should make no harm

* keeping USART enabled all time sb. harmless as well

* in doubt, check status register of USART and DMA before the second run

Posted on August 06, 2016 at 16:10

Not sure I have an F1 example to hand, but this is how I would demonstrate this.

[DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Java/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Java/Failing%20to%20set%20up%20USART%20DMA%20TX&FolderCTID=0x01200200770978C69A1141439FE559EB459D758000F9A0E3A95BA69146A17C2E80209ADC21&currentviews=48]https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Java/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2FSTM32Java%2FFailing%20to%20set%20up%20USART%20DMA%20TX&FolderCTID=0x01200200770978C69A1141439FE559EB459D758000F9A0E3A95BA69146A17C2E80209ADC21¤tviews=48

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
zhausq
Associate III
Posted on August 06, 2016 at 22:25

That you for the suggestions.

zhausq
Associate III
Posted on August 06, 2016 at 22:26

That you for that link! I didn't realize I had to reconfigure the DMA after every use, it works now.