cancel
Showing results for 
Search instead for 
Did you mean: 

Tim1 & Tim15 in Assembly

markjohnson9
Associate II
Posted on January 20, 2016 at 14:09

My application requires to input capture a pulse to trigger TIM1 & TIM15. The trigger pulse is present on both input capture pins and channels. Both timers are to turn on at the same time but have different counts to be outputted on different pins. I was able to get TIM1 working but not TIM15. The code is below. Can anyone identify where the problem resides?

Main.c Function

void configureGPIO (void){ 

RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // Enable TIM3 clk

RCC->APB2ENR |= RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM15EN; // Enable TIM1,15 clk

RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIODEN;  // Enable peripheral ckls GPIO A,B,C,D

GPIOA->AFR[0] |= 0x02 << (2*4); // Select TIM15_CH1 on PA2 by enabling AF0 on GPIOA AFRL register

GPIOA->AFR[0] |= 0x02 << (3*4); // Select TIM15_CH2 on PA3 by enabling AF0 on GPIOA AFRL register

GPIOA->AFR[1] |= 0x02 << ((9-8)*4); // Select TIM1_CH2 on PA9 by enabling AF2 on GPIOA AFRH register

GPIOA->AFR[1] |= 0x02 << ((10-8)*4); // Select TIM1_CH3 on PA10 by enabling AF2 on GPIOA AFRH register

GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER2 | GPIO_MODER_MODER3 | GPIO_MODER_MODER9 | GPIO_MODER_MODER10)) | (GPIO_MODER_MODER2_1  | GPIO_MODER_MODER3_1 | GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1); // Alt Function PA2,3,9,10

}

;Main.s Function

;TIM1 CONFIG

LDR R1,=0x40012C00 ;MOVE TIM1_CR1 ADDRESS TO R1

LDR R0,=2_0000000010001000 ;MOVE TIM1_CR1 DATA TO R0

STR R0,[R1] ;MOVE TIM1_CR1 DATA TO TIM1_CR1 LOCATION

LDR R1,=0x40012C08 ;MOVE TIM1_SMCR ADDRESS TO R1

LDR R0,=2_0000000001100110 ;MOVE TIM1_SMCR DATA TO R0

STR R0,[R1] ;MOVE TIM1_SMCR DATA TO TIM1_SMCR LOC

LDR R1,=0x40012C18 ;MOVE TIM1_CCMR1 ADDRESS TO R1

LDR R0,=2_0000000100000000 ;MOVE TIM1_CCMR1 DATA TO R0

STR R0,[R1] ;MOVE TIM1_CCMR1 LOCATION

LDR R1,=0x40012C1C ;MOVE TIM1_CCMR2 ADDRESS TO R1

LDR R0,=2_0000000001110000 ;MOVE TIM1_CCMR2 DATA TO R0

STR R0,[R1] ;MOVE TIM1_CCMR2 DATA TIM1_CCMR2 LOC

LDR R1,=0X40012C20 ;MOVE TIM1_CCER ADDRESS TO R1

LDR R0,=2_0000101100000000 ;MOVE TIM1_CCER DATA TO R0

STR R0,[R1] ;MOVE TIM1_CCER DATA TO TIM1_CCER LOC

LDR R1,=0x40012C2C ;MOVE TIM1_ARR ADDRESS TO R1

LDR R0,=4000 ;LOAD AUTO-RELOAD WITH 100uS

STR R0,[R1] ;MOVE TIM_1ARR DATA TO TIM1-ARR LOCATION

LDR R1,=0x40012C44 ;Move TIM1_BDTR ADDRESS TO R1

LDR R0,=2_1000000000000000 ;MOVE TIM1_CR1 DATA

STR R0,[R1] ;MOVE TIM1_BDTR DATA TO LOC

;TIM15 CONFIG

LDR R1,=0x40014000 ;MOVE TIM15_CR1 ADDRESS TO R1

LDR R0,=2_0010001000 ;OPM = 1, ARPE = 1, CKD = 00

STR R0,[R1] ;MOVE DATA TO TIM15_CR1 REGISTER

LDR R1,=0x40014004; MOVE TIM15_CR2 ADDRESS TO R1

LDR R0,=2_00001010000 ;MMS = 101

STR R0,[R1]; MMS = 101 PUTS OC2REF ON TRIG0

LDR R1,=0x40014008; MOVE TIM15_SMCR ADDRESS TO R1

LDR R0,=2_01010110 ;TS = 101, SMS = 110

STR R0,[R1] ;TS = 101 (TI1FP1), SMS = 110 (TRIGGER MODE)

LDR R1,=0x40014018 ;MOVE TIM15_CCMR1 ADDRESS TO R1

LDR R0,=2_0001000000000001 ;CC1S = 01 (CHANNEL 1 INPUT)

STR R0,[R1] ;OC2M = 001 (OC2REF IS COMPARE ACTIVE)

LDR R1,=0x40014038 ;MOVE TIM15_CCR2 ADDRESS TO R1

LDR R0,=0x438 ;DECIMAL 1080

STR R0,[R1] ;1080*25nS = 27uS DELAY TO START SMP

LDR R1,=0X40014020 ;MOVE TIM15_CCER ADDRESS TO R1

LDR R0,=2_0000000010110000 ;MOVE TIM15_CCER DATA TO R0 

STR R0,[R1] ;MOVE TIM15_CCER DATA TO TIM15_CCER LOC

LDR R1,=0x4001402C ;MOVE TIM15_ARR ADDRESS TO R1

LDR R0,=0xFA0 ;DECIMAL 4000 = 100uS

STR R0,[R1] ;TIMEOUT PERIOD WHEN TIM15 RESETS

LDR R1,=0x40014044 ;Move TIM15_BDTR ADDRESS TO R1

LDR R0,=2_1000000000000000; MOVE TIM15_CR1 DATA

STR R0,[R1] ;MOVE TIM15_BDTR DATA TO LOCATION

#tim1-tim15
4 REPLIES 4
Posted on January 20, 2016 at 15:01

Can anyone identify where the problem resides?

It's probably quite a small subset of anyone, further diminished by those that think register level programmers need to do there own debugging.

Couldn't you make this more consistent/efficient if you just loaded the base address of the peripheral once, and used an immediate offset version of the STR?

TIM1 is a full feature timer, not sure if TIM15 is on the part you are using, but it's not clear what that is.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
markjohnson9
Associate II
Posted on January 20, 2016 at 15:12

Part is STM32F030R08 and the part has Tim15

markjohnson9
Associate II
Posted on January 20, 2016 at 17:17

I agree, however I exhausted my troubleshooting ideas after days of debugging so I am reaching out to see if I am overlooked something obvious.

Posted on January 20, 2016 at 17:35

The basic debugging method is to read back the content of relevant registers and check, in doubt post here.

Also, I am not aware of any STM32F030R08 ...

Also, and probably this is what you are looking for, according to the datasheet, TIM15_CH1 on PA2 and TIM15_CH2 on PA3 are AF0 rather than AF2, so the following is wrong:

> GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER2 | GPIO_MODER_MODER3 | GPIO_MODER_MODER9 | GPIO_MODER_MODER10)) | (GPIO_MODER_MODER2_1  | GPIO_MODER_MODER3_1 | GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1); // Alt Function PA2,3,9,10

JW