cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 DMA1 Trigger Issue

zd9797
Associate II

Hi Folks,

I'm working on pattern generation on GPIO pins and I've done it successfully using bare-metal programming approach. I used TIM1 to trigger DMA2 to take data from a buffer and send it GPIOA->BSRR. 

But when I try to change the timer from TIM1 to TIM2 and change the respective DMA stream, the same code does not work.

code:

 

uint32_t signal1[6]; //pattern no included

// Enable clocks for GPIOA, TIM2, and DMA1
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;

// Configure GPIOA Pins 0-5 as output
GPIOA->MODER &= ~0x00000FFF; // Clear mode for PA0-PA5
GPIOA->MODER |= 0x00000555;  // Set PA0-PA5 as General Purpose Output

// Configure TIM2 for DMA requests on update event
TIM2->PSC = 0;               // Set prescaler to 0
TIM2->ARR = 999;             // Set auto-reload value (adjust for timing)
TIM2->DIER |= TIM_DIER_UDE;  // Enable update DMA request
TIM2->CR1 |= TIM_CR1_CEN;    // Enable TIM2

// Configure DMA1 Stream 5 for TIM2 Update
DMA1_Stream5->CR &= ~DMA_SxCR_EN; // Disable stream to configure
DMA1_Stream5->PAR = (uint32_t)&GPIOA->ODR;  // Peripheral address (GPIOA ODR)
DMA1_Stream5->M0AR = (uint32_t)signal1;     // Memory address (signal1 array)
DMA1_Stream5->NDTR = 6;                     // Number of data items

// Configure DMA control register
DMA1_Stream5->CR = (3 << DMA_SxCR_CHSEL_Pos) |  // Channel 3 for TIM2_UP
                   (0 << DMA_SxCR_DIR_Pos)   |  // Memory-to-Peripheral
                   (2 << DMA_SxCR_MSIZE_Pos) |  // Memory size: 32-bit
                   (2 << DMA_SxCR_PSIZE_Pos) |  // Peripheral size: 32-bit
                   DMA_SxCR_MINC             |  // Memory increment mode
                   DMA_SxCR_CIRC;               // Circular mode

// Enable DMA1 Stream 5
DMA1_Stream5->CR |= DMA_SxCR_EN;

// TIM2 will now trigger DMA transfers to output the pattern on GPIOA pins 0-5

 

 This code does not work but if you change it to TIM1 and respective DMA stream it works. I checked and i get transfer error interrupt flag. Any help or direction is appreciated. 

1 ACCEPTED SOLUTION

Accepted Solutions

>>So is there a way to know what can the DMA1 access and what it cannot?

There's a bus matrix diagram

DMA1 associates with peripherals on the APB1, ie access to registers, source of triggers

DMA2 associates with peripherals on the APB2, ie access to registers, source of triggers

DMA2 can also do memory-to-memory, basically a two step process, a read, then a write, rather than simple flow-thru mechanics.

This functionality has been repeatedly stated for F2 / F4 designs for well over a decade.

My correction to the earlier statement

"DMA1 does not have direct access to the AHB1 bus, which is why the transfer is failing"

>>Is this intentional or a flaw?

It's a function of the design, to simplify the implementation.

APB1/DMA1 has internal connectivity, think points on a rail system, and can connect peripherals to/from memory. It doesn't inter-stage, so it can't go memory-to-memory, bus-to-bus,or APB1-to-APB2

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

4 REPLIES 4
Sarra.S
ST Employee

Hello @zd9797

  • TIM1 is on APB2 
  • TIM2 is on APB1 
  • GPIOA is on AHB1 

As you can see from the system architecture: 

SarraS_0-1726069376235.png

DMA1 does not have direct access to the APB1 bus, which is why the transfer is failing

Using TIM1, DMA2 has access to both AHB1 and APB2 buses that's why it works. 

You either use a timer that's on APB2 bus, or use a different DMA stream that has access to to APB1 bus 

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

zd9797
Associate II

Oh is that why it was failing! I brought up this issue with my senior and I was afraid of this answer. 

DMA1 does not have direct access to the APB1 bus, which is why the transfer is failing - Is this intentional or a flaw?

 So is there a way to know what can the DMA1 access and what it cannot?

 

>>So is there a way to know what can the DMA1 access and what it cannot?

There's a bus matrix diagram

DMA1 associates with peripherals on the APB1, ie access to registers, source of triggers

DMA2 associates with peripherals on the APB2, ie access to registers, source of triggers

DMA2 can also do memory-to-memory, basically a two step process, a read, then a write, rather than simple flow-thru mechanics.

This functionality has been repeatedly stated for F2 / F4 designs for well over a decade.

My correction to the earlier statement

"DMA1 does not have direct access to the AHB1 bus, which is why the transfer is failing"

>>Is this intentional or a flaw?

It's a function of the design, to simplify the implementation.

APB1/DMA1 has internal connectivity, think points on a rail system, and can connect peripherals to/from memory. It doesn't inter-stage, so it can't go memory-to-memory, bus-to-bus,or APB1-to-APB2

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

That makes sense. Thank you so much!