The project is, an interrupt connected on the PB12 will change the state of the onboard led.
I read the reference manual and other documents, i also search on google but i couldn’t find detailed documentation. I also tried to decode the libraries but I couldn’t make to work the following code.
Any help will be welcome.
volatile int state = LOW;
volatile unsigned long x = 0;
void setup()
{
Serial.begin(57600);
RCC_BASE->APB2ENR |= (1 << RCC_APB2ENR_IOPBEN); // Enable PB
RCC_BASE->APB2ENR |= (1 << RCC_APB2ENR_IOPCEN); // Enable PC
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)
GPIOB->regs->CRH = 0x44484444; // Set input mode on PB12 P/U or P/D p158, p171
GPIOB->regs->ODR |= 0b0001000000000000; // Pull up on PB12 is enabled
RCC_BASE->APB2ENR |= (1 << RCC_APB2ENR_AFIOEN); // Enable AFIO
RCC_BASE->APB2RSTR |= (1 << RCC_APB2RSTR_AFIORST);
asm volatile("cpsie i"); // Enable interrupts
EXTI_BASE->FTSR |= (1 << 12); // Falling on 12
EXTI_BASE->RTSR |= (1 << 12); // Rising on 12
EXTI_BASE->IMR |= (1 << 12); // Interrupt mask register
AFIO_BASE->EXTICR4 |= (1 << 0); // On PB12
NVIC_BASE->ISER[1] |= (1 << (NVIC_EXTI_15_10 & 0x1F)); // enable interrupt EXTI 10..15
}
void loop()
{
digitalWrite(PC13, state);
Serial.println(x);
}
void EXTI15_10_IRQHandler(void)
{
x++;
state = !state;
EXTI_BASE->PR |= (1 << 12);
}
So you have to use the same name for the needed ISR as listed in that file.
void __irq_exti2(void)
//void blink()
{
x++;
state = !state;
EXTI_BASE->PR |= (1 << 12);
}
extern "C" <interrupt_handler_name>() {
...
}
It crashes when it enter in the interrupt.
volatile int state = LOW;
volatile unsigned long x = 0;
void setup()
{
Serial.begin(57600);
Serial.println("Start");
RCC_BASE->APB2ENR |= (1 << RCC_APB2ENR_IOPBEN);
RCC_BASE->APB2ENR |= (1 << RCC_APB2ENR_IOPCEN);
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)
GPIOB->regs->CRH = 0x44484444; // Set input mode on PB12 P/U or P/D p158, p171
GPIOB->regs->ODR |= 0b0001000000000000; // Pull up on PB12 is enabled
RCC_BASE->APB2ENR |= (1 << RCC_APB2ENR_AFIOEN);
RCC_BASE->APB2RSTR |= (1 << RCC_APB2RSTR_AFIORST);
asm volatile("cpsie i");
EXTI_BASE->FTSR |= (1 << 12);
EXTI_BASE->RTSR |= (1 << 12);
EXTI_BASE->IMR |= (1 << 12);
AFIO_BASE->EXTICR4 |= (1 << 0);
NVIC_BASE->ISER[1] |= (1 << (NVIC_EXTI_15_10 & 0x1F));// enable interrupt EXTI 10..15
}
void loop()
{
digitalWrite(PC13, state);
Serial.println(x);
}
void __irq_exti15_10()
{
x++;
state = !state;
EXTI_BASE->PR |= (1 << 12);
}
What is your final goal, what do you want to implement?
[edogaldo – Sun Apr 01, 2018 3:54 pm] –
extern "C" <interrupt_handler_name>() {
...
}
[stevestrong – Sun Apr 01, 2018 9:51 pm] –
Why don’t you use the Arduino_STM32 core with Arduino IDE?
What is your final goal, what do you want to implement?
First of all, i want to learn everything from the beginning.
From my experience, (i am not an expert) using the arduino libraries makes the executing slower. Using arduino libraries is very easy but sometimes, if you don’t know their limits, becomes more complex.
RCC_BASE->APB2RSTR |= (1 << RCC_APB2RSTR_AFIORST);
You will eventually save some flash space, of which however plenty is available (128kB).
The libmaple core allows you to use low level functions which are really thin and speed optimized.
But of course is finally your choice which way to go.
For libmaple core you will most probably get support here.
But it is not sure that you will get support for your low level programming.
[stevestrong – Sun Apr 01, 2018 10:26 pm] –
I am not sure that speed is really what you gain, specially when you sometimes add a “delay(…);”
The code you have seen is just a test for me. The goal is to learn how external interrupt works.
//Toggling the onboard led on PC13 after the occurred interrupt.
//The interrupt occurred when you connect PB12 to the ground.
volatile boolean led ;
volatile unsigned long x ;
void setup()
{
Serial.begin(250000);
Serial.println("Start");
RCC_BASE->APB2ENR |= (1 << RCC_APB2ENR_IOPBEN); // Enable PB. p145
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)
GPIOB->regs->CRH = 0x44484444; // Set input mode on PB12 P/U or P/D p158, p171
GPIOB->regs->ODR |= 0b0001000000000000; // Pull up on PB12 is enabled
RCC_BASE->APB2ENR |= (1 << RCC_APB2ENR_AFIOEN); // Enable AFIO. p145
RCC_BASE->APB2RSTR |= (1 << RCC_APB2RSTR_AFIORST); // Reset the AFIO registers. p105
asm volatile("cpsie i"); // Enables interrupts and configurable fault handlers. p99 C
EXTI_BASE->FTSR |= (1 << 12); // Falling on 12. p211
EXTI_BASE->IMR |= (1 << 12); // Interrupt mask register. p210
AFIO_BASE->EXTICR4 |= (1 << 0); // On PB12. p191
NVIC_BASE->IP[40] = 0 << 4; // Priority to set, 0 being highest priority and 15 being lowest. From the table NVIC_EXTI_15_10 = 40. Move it to the left 4 positions. p125 C
EXTI_BASE->PR |= (1 << 12); // Clear pending interrupt on that pin. p212
NVIC_BASE->ISER[1] |= (1 << 8); // Enable interrupt EXTI 10..15. From the table NVIC_EXTI_15_10 = 40. p119 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
}
extern "C" void __irq_exti15_10(void)
{
led = !led; // Reverse state
EXTI_BASE->PR |= (1 << 12); // Clear pending interrupt on that pin. p212
x++; // Count the interrupts. Remember, never try and clear the flag that caused the interrupt as the last instruction in the ISR itself. It causes the ISR to reenter immediately.
}
I think that everybody coming to this business/hobby, should learn the fundamentals in the way you have demonstrated. Most users do ignore the manuals and are trying to use the high level constructs that are hiding the fundamentals. Then when things are not working, it will be hard to find out what went wrong. In that analysis, you must use a low level debugger and look the bits in the registers.
On other side, as you can see the programming at register level is very difficult to read. Personally, I left that style and replaced it with CubeMX and have no regrets. The biggest gain is that now there is a wide audience who can fluently read my code – even without comments.
Cheers, Ollie

![[Pending Enhancement] RTC values resetting](https://sparklogic.ru/wp-content/uploads/2019/11/nucleo-l476rg-zestaw-startowy-z-mikrokontrolerem-z-rodziny-stm32-stm32l476-90x90.jpg)