Timer 2 interrupt using low level programming

billys7
Thu Apr 05, 2018 10:28 pm
Do i miss something?
//Toggling the onboard led on PC13 every 1 sec.

volatile boolean led ;
volatile unsigned long x ;

void setup()
{
Serial.begin(250000);
Serial.println("Start");

RCC_BASE->APB1ENR |= (1 << RCC_APB1ENR_TIM2EN); // Enable Timer2. p147
RCC_BASE->APB2ENR |= (1 << RCC_APB2ENR_IOPCEN); // Enable PC. p145

GPIOC->regs->CRH = GPIOC->regs->CRH | 0x00300000; // Set output mode on PC13 @ max freq 50MHz (MODE13[1:0] = 11) p158, p171
GPIOC->regs->CRH = GPIOC->regs->CRH & 0xFF3FFFFF; // Set output mode on PC13 as general push-pull output (cnf8[1:0] = 00)

asm volatile("cpsie i"); // Enables interrupts and configurable fault handlers. p99 C

TIMER2_BASE->CR1 = 0;
TIMER2_BASE->CR2 = 0;
TIMER2_BASE->SMCR = 0;
TIMER2_BASE->DIER = 0;
TIMER2_BASE->SR= 0;
TIMER2_BASE->EGR= 0;
TIMER2_BASE->CCMR1= 0;
TIMER2_BASE->CCMR2= 0;
TIMER2_BASE->CCER= 0;
TIMER2_BASE->CNT= 0;
TIMER2_BASE->PSC= 0;
TIMER2_BASE->ARR = 65535;
TIMER2_BASE->CCR1= 0;
TIMER2_BASE->CCR2= 0;
TIMER2_BASE->CCR3= 0;
TIMER2_BASE->CCR4= 0;
TIMER2_BASE->DCR= 0;
TIMER2_BASE->DMAR= 0;

TIMER2_BASE->PSC = 23999; // Set prescaler to 24.000 (PSC + 1) Means 72.000.000 / 24.000 = 3.000 per second. p417
TIMER2_BASE->ARR = 3000; // Auto reload value 3000. The update event is sent when the counter reaches the overflow. p418
TIMER2_BASE->DIER |= (1 << 0); // Enable update interrupt TIM_DIER_UIE = 1 . p408
TIMER2_BASE->CR1 |= (1 << 0); // Enable timer TIM_CR1_CEN = 1 . p403

NVIC_BASE->IP[28] = 15<< 4; // Set Priority, 0 = highest, 15 = lowest. From the table on page 197 TIM2 = 28. Move it to the left 4 positions. p125 C
TIMER2_BASE->SR &= ~(1 << 0); // clear pending interrupt UIF flag TIM_SR_UIF=0. p409
NVIC_BASE->ISER[0]|= (1 << 28); // Enable interrupt TIM2. From page 197 on the table TIM2 = 28. ISER = 0. p119 C & p120 C.
}

void loop()
{
GPIOC->regs->BSRR |= (1 << (13 + (led * 16))); // Lower 16 bits setting while higher bits clearing. p172
Serial.println(x); // Show me how many interrupts has occurred
}


edogaldo
Fri Apr 06, 2018 5:09 am
The short answer is that you cannot redefine the irqs already defined in the core.
In these cases you have to use the attachInterrupt hooks provided by the core or directly change the irqs in the core.

There have been several threads on this in the past, you can search for “weak” and “interrupt” for further details.

Cheers, E.


billys7
Fri Apr 06, 2018 11:06 am
To be honest, i read them, before posting, but i really couldn’t understand them.
I know about interrupts C and C++ incompatibility, but i couldn’t understand why i need to use only the attachinterrupt command.

edogaldo
Fri Apr 06, 2018 11:58 am
When you use a core then you rely on a framework that offers you some advantages but also forces some constraints.
The libmaple core already implements several interrupt handlers and offers you a framework to bind your code which is based on the “attachInterrupt” hooks.
Consider this: you already have __irq_tim2() defined here; if you redefine __irq_tim2() in your sketch then you end up with 2 definitions for it and then the linker complains because it doesn’t know which one to use..
In order to be able to use your definition you should remove the core’s one.
Anyway consider that the attachInterrupt approach also performs some other tasks (like enabling the interrupt) required to correctly set up the interrupt management; if you decide to bypass it, you have to take care also of the other stuff.

Hope this clarifies a little better..

Cheers, E.


billys7
Fri Apr 06, 2018 3:00 pm
Thank you Edogaldo.
It works fine.

cyberheater
Mon Apr 09, 2018 8:47 am
Hi Billys7

Can you post your working code. I’m interested in this type of stuff.

Thanks.



billys7
Mon Apr 09, 2018 2:55 pm
Here is the working code.

// Toggling the onboard led on PC13 every 1 sec.
// I must exempt - delete the corresponding timer from STM32F1/cores/maple/libmaple/timer.c
// For this example the corresponding timer is described on lines 506 to 508 of timer.c.

volatile boolean led =0;
volatile unsigned long x ;

void setup()
{
Serial.begin(57600);
Serial.println("Start");

RCC_BASE->APB1ENR |= (1 << RCC_APB1ENR_TIM2EN); // Enable Timer2. p147
RCC_BASE->APB2ENR |= (1 << RCC_APB2ENR_IOPCEN); // Enable PC. p145

GPIOC->regs->CRH = GPIOC->regs->CRH | 0x00300000; // Set output mode on PC13 @ max freq 50MHz (MODE13[1:0] = 11) p158, p171
GPIOC->regs->CRH = GPIOC->regs->CRH & 0xFF3FFFFF; // Set output mode on PC13 as general push-pull output (cnf8[1:0] = 00)

asm volatile("cpsie i"); // Enables interrupts and configurable fault handlers. p99 C
/* Reset all the registers */
TIMER2_BASE->CR1 = 0;
TIMER2_BASE->CR2 = 0;
TIMER2_BASE->SMCR = 0;
TIMER2_BASE->DIER = 0;
TIMER2_BASE->SR= 0;
TIMER2_BASE->EGR= 0;
TIMER2_BASE->CCMR1= 0;
TIMER2_BASE->CCMR2= 0;
TIMER2_BASE->CCER= 0;
TIMER2_BASE->CNT= 0;
TIMER2_BASE->PSC= 0;
TIMER2_BASE->ARR = 65535;
TIMER2_BASE->CCR1= 0;
TIMER2_BASE->CCR2= 0;
TIMER2_BASE->CCR3= 0;
TIMER2_BASE->CCR4= 0;
TIMER2_BASE->DCR= 0;
TIMER2_BASE->DMAR= 0;

TIMER2_BASE->PSC = 23999; // Set prescaler to 24.000 (PSC + 1) Means 72.000.000 / 24.000 = 3.000 counts per second. p417
TIMER2_BASE->ARR = 3000; // Auto reload value 3000. The update event is sent when the counter reaches the overflow. p418
TIMER2_BASE->DIER |= (1 << 0); // Enable update interrupt TIM_DIER_UIE = 1 (timer level). p408
TIMER2_BASE->CR1 |= (1 << 0); // TIM_CR1_CEN = 1 Enable timer. p403

NVIC_BASE->IP[28] = 15<< 4; // Set Priority, 0 = highest, 15 = lowest. From the table on page 197 TIM2 = 28. Move it to the left 4 positions. p125 C
TIMER2_BASE->SR &= ~(1 << 0); // clear pending interrupt UIF flag TIM_SR_UIF=0. p409
NVIC_BASE->ISER[0]|= (1 << 28); // Enable interrupt TIM2. From page 197 on the table TIM2 = 28. ISER = 0. p119 C & p120 C.
}

void loop()
{
GPIOC->regs->BSRR |= (1 << (13 + (led * 16))); // Lower 16 bits setting while higher bits clearing. p172
Serial.println(x); Serial.println(led); // Show me how many interrupts has occurred
}

extern "C" void __irq_tim2(void) // https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/master/STM32F1/cores/maple/libmaple/stm32f1/performance/vector_table.S
{ /* Remember, never try to clear the pending interrupt flag as the last instruction in the ISR itself. It causes the ISR to reenter immediately.*/
led = !led; // Reverse state
TIMER2_BASE->SR &= ~(1 << 0); // clear pending interrupt UIF flag TIM_SR_UIF=0. p409
x++; // Count the interrupts
}


cyberheater
Wed Apr 11, 2018 6:25 am
Thanks Billys7.

edogaldo
Wed Apr 11, 2018 7:33 am
[billys7 – Fri Apr 06, 2018 3:00 pm] –
Thank you Edogaldo.
It works fine.

@billys7: maybe you can be interested in this thread: here I proposed a possible core change to allow overriding of any IRQ without having to remove the ones defined in the core; I tested the change and implemented it for all core IRQs in my personal core variant with no issues (so far) anyway the core maintainers didn’t consider it worth the possible risks.

Hope this helps.

Best, E.


billys7
Mon Apr 16, 2018 8:44 am
Hi edogaldo,

I am not familiar with “weak ” definition.
Can you explain me, what have you done?


edogaldo
Mon Apr 16, 2018 9:11 am
https://en.wikipedia.org/wiki/Weak_symbol

What I proposed is a method to mark the Core IRQs as “weak” so that they can be overridden with a “strong” definition provided in the sketch (if desided).
This way one can either define his own IRQ implementation or use the default core one as preferred without conflicts (this would avoid the need to remove the Core IRQ as you did).

In the thread I proposed the solution for IRQ “__irq_usart1()” but this could apply to any IRQ..

Cheers, E.


RogerClark
Mon Apr 16, 2018 9:18 pm
Is there a PR for this, as it defiantly has merit

edogaldo
Tue Apr 17, 2018 7:41 am
Hello Roger, glad to read that this can be interesting.
In this post I explain the approach.
As you prefer I can provide either a “big bang” PR (for all IRQs) or a trial one with only some IRQs so that you can test and confirm everthing is fine.
let me know.

Best, E.


RogerClark
Tue Apr 17, 2018 8:07 am
May as well do them all in one go

edogaldo
Tue Apr 17, 2018 11:52 am
[RogerClark – Mon Apr 16, 2018 9:18 pm] –
Is there a PR for this, as it defiantly has merit

By the way, hope it was a “definitely”.. :)


RogerClark
Tue Apr 17, 2018 9:29 pm
Aargghhh

I hate auto correct on phones and tablets.


Leave a Reply

Your email address will not be published. Required fields are marked *