Bluepill Uart DMA W/Callback

Post here first, or if you can't find a relevant section!
Post Reply
PeteS
Posts: 2
Joined: Wed Mar 30, 2022 8:29 pm

Bluepill Uart DMA W/Callback

Post by PeteS »

Hello, I am trying to get DMA working with Serial 2(ideally) for sending data with on a Bluepill. I don't need to read anything, its just needs to be able to send the message. After a great deal of searching for an example using DMA with serial I decided to turn to GPT and spent most of the day attempting to come up with a working example.... and while I've had a number of programs that would compile with out errors and would not cause the processor to lock up, I have not been able to get a message sent or and I have not been able to get any of the interrupt handlers/callbacks for DMA to to work.

I know that working with DMA is a rather technical process but I had no idea it would be so hard to find something as simple as a basic example that would work with the stm32duino core in the Arduino IDE. The code I have below is what I feel like would be the closest to working that I was able to come up with using GPT but it's clearly missing something important or may even just be formatted totally wrong....I honestly have no idea at this point. I have not included any of my debug prints or pin toggles so keep the code here as focused as possible, but trust me when I say I've checked this code all over the place with debug messages to see what's happening.

This code is called in my setup

Code: Select all

Serial2.begin(921600); 
 DMA1_Channel7->CPAR = (uint32_t) & (USART2->DR);// where DMA will sending the array values
 DMA1_Channel7->CMAR = (uint32_t) buffer;// the array data source DMA will use
 DMA1_Channel7->CNDTR = sizeof(buffer);// number of bytes to send with DMA
 DMA1_Channel7->CCR = DMA_CCR_MINC | DMA_CCR_DIR; // Enable memory increment and memory-to-peripheral mode 
 DMA1_Channel7->CCR |= DMA_CCR_TCIE;// Enable DMA interrupt for channel 7
 USART2->CR1 = USART_CR1_TE | USART_CR1_UE; // Enable USART2 for TX 

  /* DMA interrupt init */
  /* DMA1_Channel7_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);


The following line is what I believe should begin the transfer based on what I came up with using GPT. I have tried using this line at the end of the code used in the setup routine as well as calling it directly in the main loop and it doesn't do anything from what I can tell.

Code: Select all

 DMA1_Channel7->CCR |= DMA_CCR_EN;// begins the DMA transfer


This is the callback handler that I would have expected should be called when the transfer was completed but this also does not work.

Code: Select all

// DMA1 Channel 7 interrupt handler
void DMA1_Channel7_IRQHandler()
{ 
  if (DMA1->ISR & DMA_ISR_TCIF7)
  { 
    DMA1->IFCR |= DMA_IFCR_CTCIF7; // Clear the transfer complete flag   
  }
}

I'm really hoping someone can tell me what I'm doing wrong or what I'm missing in order to get this working.....or maybe someone has a working example that uses DMA for sending message using a hardware serial ports they would be willing to share?
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Bluepill Uart DMA W/Callback

Post by fpiSTM »

Add extern "C" before the handler function
User avatar
Bakisha
Posts: 139
Joined: Fri Dec 20, 2019 6:50 pm
Answers: 5
Contact:

Re: Bluepill Uart DMA W/Callback

Post by Bakisha »

I am not familiar with UART and DMA, but i did some experiments with SPI and DMA.
Anyway, quick look in RM0008, i noticed DMAT (DMA enable transmitter) bit in CR3 register need to be set.
Try

Code: Select all

USART2->CR3 |= USART_CR3_DMAT ;
Also, i think DMA clock needs to be enabled:

Code: Select all

RCC->AHBENR = ( RCC->AHBENR ) | (RCC_AHBENR_DMA1EN); // enable DMA1 clock
Post Reply

Return to “General discussion”