//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
}
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.
I know about interrupts C and C++ incompatibility, but i couldn’t understand why i need to use only the attachinterrupt command.
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.
It works fine.
Can you post your working code. I’m interested in this type of stuff.
Thanks.
f0: https://github.com/dannyf00/My-MCU-Libr … er/STM32F0
f1: https://github.com/dannyf00/My-MCU-Libr … /STM32F1xx
f4: https://github.com/dannyf00/My-MCU-Libr … er/STM32F4
// 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
}
[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.
I am not familiar with “weak ” definition.
Can you explain me, what have you done?
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.
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 – 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”.. ![]()
I hate auto correct on phones and tablets.

