Skip to main content
esukh
Associate II
August 6, 2018
Question

How to properly configure DMA for TIM2 timer?

  • August 6, 2018
  • 4 replies
  • 1081 views

TIM2 Timer initialization:

static void my_TIM2_initInputCaptureTimer(void) {
 
 // enable clock source for timer
 RCC->APB1LENR |= (0x1 << 0);
 // set prescaler to 1
 TIM2->PSC = 200 - 1;
 
 // choose TIM2_CH1 input
 TIM2->TISEL |= (0x0 << 0);
 // set channel 1 as input mapped on TI1
 TIM2->CCMR1 |= (0x1 << 0);
 // digital filter length (0)
 TIM2->CCMR1 |= (0x0 << 4);
 // rising edge
 TIM2->CCER |= (0x1 << 1);
 TIM2->CCER |= (0x1 << 3);
 // prescaler to (0)
 TIM2->CCMR1 |= (0x0 << 2);
 // enable DMA interrupt
 TIM2->DIER |= (0x1 << 9) | (0x1 << 1);
 // enable timer
 TIM2->CCER |= (0x1 << 0);
 // reset registers WARNING: need for preloading PSC 
 TIM2->EGR |= (0x1 << 0);
 
 // enable TIM3 timer
 TIM2->CR1 |= TIM_CR1_CEN;
 // enable interrupt request
 NVIC_EnableIRQ(TIM2_IRQn);
 // set priority
 NVIC_SetPriority(TIM2_IRQn, 1);
 
}

DMA with DMAMUX initialization:

static void my_DMA_init(void) {
 // enable DMA1 clocking
 RCC->AHB1ENR |= (0x1 << 0);
 // clear EN bit to 0
 DMA1_Stream0->CR &= ~(0x1 << 0);
 // safeguard EN bit reset
 while (DMA1_Stream0->CR & 0x1);
 // check LISR HISR registers
 if ((DMA1->HISR == 0) && (DMA1->LISR == 0))
 printf("status registers is clear\r\n");
 else
 printf("status register is not clear -- DMA wont start\r\n");
 // set peripheral addres
 DMA1_Stream0->PAR = TIM2_CCR1_Address;
 // set memory addres
 DMA1_Stream0->M0AR = (unsigned int)buffer;
 // set total number of data items
 DMA1_Stream0->NDTR = DMA_BUFFER_SIZE;
 
 // NOTE: configurate TIM2_CH1 interrupt route
 // set DMAMUX to route request (TIM2_CH1)
 DMAMUX1_Channel0->CCR |= 18U;
 
 // set DMA priority (very high)
 DMA1_Stream0->CR |= (0x3 << 16);
 // set memory data size (32)
 DMA1_Stream0->CR |= (0x2 << 13);
 // set peripheral data size (32)
 DMA1_Stream0->CR |= (0x2 << 11);
 // set memory addres increment (enable)
 DMA1_Stream0->CR |= (0x1 << 10);
 // set peripheral addres increment (disable)
 DMA1_Stream0->CR |= (0x0 << 9);
 // set circular buffer mode (enable)
 DMA1_Stream0->CR |= (0x1 << 8);
 // set data transfer direction (peripheral to memory)
 DMA1_Stream0->CR |= (0x0 << 6);
 // set transfer complete interrupt
 DMA1_Stream0->CR |= (0x1 << 4);
 // enable DMA1
 DMA1_Stream0->CR |= (0x1 << 0);
 // enable IRQ
 NVIC_EnableIRQ(DMA1_Stream0_IRQn);
 printf("DMA1_Stream0 %u \r\n", (DMA1_Stream0->CR & 0x1));
}

DMA interrupt routine (code never reach this part even once)

void DMA1_Stream0_IRQHandler(void) {
 
 flag = 2;
 printf("within\r\n");
 // clear interrupt flag
 //DMA1->IFCR |= (0x1 << 0);
 
}

My bet is wrong DMAMUX configuration, but I have no idea what else I got to configure to make this work. In case you interested in full project: (stm32h743zi-nucleo -- gcc-arm\make -- .bin .hex files attached)

https://drive.google.com/open?id=1fwns5fKexGWJl64UDeYfDyFmSFA9BURZ

expected behavior (when you press user button (the blue one) ->PG0 pin get SET (1) state -> so input capture pin (PA5, they should be connected via jumper) get low-high transition and capture first value and send it in COM port, when you unpress button, input capture pin get high-low transition and capture another value and sent it via COM port, but none of this events do not kickstart DMA request.

Data will be outputted via com port with 115200 speed.

Thanks in advance

This topic has been closed for replies.

4 replies

Tesla DeLorean
Guru
August 6, 2018

The number of people wanting to wade through register level H7 code is pretty limited. You'll need to use the debugger, and probing into the Peripheral View windows and inspect the registers, and status/error bit that might be flagging.

The IRQ Handler won't enter if the transactions aren't occurring, and this should be apparent from the address/count not advancing.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
waclawek.jan
Super User
August 6, 2018

I don't 'H7, but can't this be the problem?

0690X0000060S0aQAE.png

// NOTE: configurate TIM2_CH1 interrupt route

// set DMAMUX to route request (TIM2_CH1)

DMAMUX1_Channel0->CCR |= 18U;

I also am not fan of using magic values; instead, I recommend using the symbols from the CMSIS-mandated device header.

JW

esukh
esukhAuthor
Associate II
August 7, 2018

0690X000006Br6rQAC.png

(RM0433 Reference manual STM32H743/753 advanced ARM ® -based 32-bit MCUs) 4th Revision (but it's looks like your document is different from mine, i should look into it too)

I'm totally agree about magic numbers but this is some kind of testing\fluent code I just poke into registers and trying to understand documentation.

The most interesting thing that there are few another question about dmamux configuration (one from stackoverflow, another from local resource) and none of them were answered.

waclawek.jan
Super User
August 7, 2018

Indeed. I have an old copy of the RM.

I don't know then.

0690X000006BrBwQAK.png