Need Help with NVIC Pending Register Not Reflecting Button Press on STM32L476RG

@Umesh Lokhande @Edison_ngunjiri @ZacckOsiemo just saw this question in another forum and thought you might be able to troubleshoot for the dev: Subject: Need Help with NVIC Pending Register Not Reflecting Button Press on STM32L476RG Message: I'm currently working on a project where I'm writing a driver for my STM32 Nucleo L476RG board. I’m trying to test an interrupt using the user button on the board. Here's what I’ve done so far: * Button Configuration: * Configured the user button to trigger on the falling edge. * Verified the GPIO pin is set as an input with the correct pull-up/pull-down configuration. * EXTI Configuration: * Mapped the EXTI line to the correct GPIO pin for the button. * Set the trigger condition to the falling edge. * NVIC Configuration: * Enabled the NVIC interrupt line associated with the EXTI. * Verified the interrupt priority is set correctly. * Clock Setup: * Enabled the clock for all required peripherals, including GPIO and SYSCFG. * Issue: * Despite all the configurations being correct, the NVIC pending register doesn’t reflect the button press when I check it. All other relevant registers seem to be correctly configured. * Debugging Attempts: * Cross checked every register. * Physically checked the button’s connection and signal output. And also tried with internal button and internal led * I’ve been stuck on this for days now and would really appreciate any insights or suggestions on what else I should check or do to resolve this issue.
13 Replies
techielew
techielew3mo ago
Reference for those interested: https://www.youtube.com/watch?v=4C0tJ5Itnvo
DevHeads
YouTube
DevHeads Engineering Hour REHEAT: Interrupts and the NVIC Controlle...
Interrupts allow a processor to halt program execution to handle events such as state changes, which is essential for systems that rely on streaming sensor data inputs. They're also the foundation of any multi-tasking systems that does not use an operating system. Learn how hardware interrupts work and how to implement an interrupt service rout...
Edison_ngunjiri
Edison_ngunjiri3mo ago
Hi @techielew I have gone through his setup description.seems okay. He may have created the function to setup and maybe forgot to call them . I think we can help him well enough if we can get to see the code.
Umesh Lokhande
Umesh Lokhande3mo ago
We must ask him to try the code from DevHeads Github repo. This external interrupt example project uses an onboard LED (PA5) and onboard Button switch (PC13) https://github.com/DevHeadsCommunity/EP-11-Explore-Interrupt-and-NVIC-Controller-in-Cortex-M-MCU/tree/main/EXTINT
GitHub
EP-11-Explore-Interrupt-and-NVIC-Controller-in-Cortex-M-MCU/EXTINT ...
Contribute to DevHeadsCommunity/EP-11-Explore-Interrupt-and-NVIC-Controller-in-Cortex-M-MCU development by creating an account on GitHub.
techielew
techielew3mo ago
@Edison_ngunjiri @Umesh Lokhande , meet @lokii. He is the one with the referenced problem above. Here is his code: https://github.com/lokii2310/GPIO_INTERRUPT_DRIVER
GitHub
GitHub - lokii2310/GPIO_INTERRUPT_DRIVER
Contribute to lokii2310/GPIO_INTERRUPT_DRIVER development by creating an account on GitHub.
Edison_ngunjiri
Edison_ngunjiri3mo ago
Hi, @lokii ,in the repository, I have seen 4 different .c files. Which one you need help on?
lokii
lokii3mo ago
The button_interrupt one
Umesh Lokhande
Umesh Lokhande3mo ago
Hi @lokii, just checked your repo and button_interrupt.c file. I saw you've commented the entire while(1) loop. I mean line number 50...54. You must keep the empty while loop even when you use interrupt. As you wrote GPIO drivers seperately stm32nul476rg_gpio_driver.h Due to lack of time at my end to test for STM32L4. I suggest use my code (register level code) to do the necessory changes in your gpio driver file.
lokii
lokii3mo ago
Thank you so much for your time and help But still it didn't turn out well actually. The led won't toggle yet. In the file I had an error that NVIC_EableIRQ(EXTI15_10_IRQn); Is undefined So added these lines instead of that #define NVIC_BASE (0xE000E100UL) #define NVIC_ISER1 (*(volatile uint32 *) (NVIC_BASE+0x004)) NVIC_ISER1 = (1<<(EXTI15_10_IRQn-32)); Still not led toggle
Enthernet Code
Enthernet Code3mo ago
@lokii first try trouble shooting to make sure everything works and is on the right places then try this code
#include "stm32f4xx.h"

void EXTI15_10_IRQHandler(void) {
// Check if EXTI line 13 triggered the interrupt
if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_13) != RESET) {
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_13); // Clear the interrupt flag
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_5); // Toggle the LED pin
}
}

int main(void) {
HAL_Init();

// Enable the GPIOC clock for the LED
__HAL_RCC_GPIOC_CLK_ENABLE();

// Configure LED pin (PC5) as output
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

// Enable the SYSCFG clock for EXTI
__HAL_RCC_SYSCFG_CLK_ENABLE();

// Configure button pin (PC13) as input with EXTI
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

// Set priority and enable EXTI line 15-10 interrupt in NVIC
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

while (1) {
// Main loop
}
}
#include "stm32f4xx.h"

void EXTI15_10_IRQHandler(void) {
// Check if EXTI line 13 triggered the interrupt
if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_13) != RESET) {
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_13); // Clear the interrupt flag
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_5); // Toggle the LED pin
}
}

int main(void) {
HAL_Init();

// Enable the GPIOC clock for the LED
__HAL_RCC_GPIOC_CLK_ENABLE();

// Configure LED pin (PC5) as output
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

// Enable the SYSCFG clock for EXTI
__HAL_RCC_SYSCFG_CLK_ENABLE();

// Configure button pin (PC13) as input with EXTI
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

// Set priority and enable EXTI line 15-10 interrupt in NVIC
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

while (1) {
// Main loop
}
}
The code sets up the LED on GPIOC pin 5 and configures an interrupt on GPIOC pin 13, using HAL functions to ensure proper setup of the NVIC and EXTI. The interrupt handler toggles the LED and clears the interrupt flag when triggered.
lokii
lokii3mo ago
Actually trying to implement using my own driver files I have created. I'm not using hal drivers
Marvee Amasi
Marvee Amasi3mo ago
I hope you have correctly mapped the EXTI line to the GPIO pin and that the NVIC configuration aligns with your EXTI settings. If everything is set up correctly, the NVIC pending register should reflect your button presses as expected @lokii
lokii
lokii3mo ago
#include "stm32l4xx.h"

void EXTI15_10_IRQHandler(void) {
// Check if EXTI line 13 triggered the interrupt
if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_13) != RESET) {
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_13); // Clear the interrupt flag
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Toggle the LED pin
}
}

int main(void) {
HAL_Init();

// Enable the GPIOC clock for the LED
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

// Configure LED pin (PA5) as output
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

// Enable the SYSCFG clock for EXTI
__HAL_RCC_SYSCFG_CLK_ENABLE();

// Configure button pin (PC13) as input with EXTI
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

// Set priority and enable EXTI line 15-10 interrupt in NVIC
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

while (1) {
// Main loop
}
}
#include "stm32l4xx.h"

void EXTI15_10_IRQHandler(void) {
// Check if EXTI line 13 triggered the interrupt
if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_13) != RESET) {
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_13); // Clear the interrupt flag
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Toggle the LED pin
}
}

int main(void) {
HAL_Init();

// Enable the GPIOC clock for the LED
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

// Configure LED pin (PA5) as output
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

// Enable the SYSCFG clock for EXTI
__HAL_RCC_SYSCFG_CLK_ENABLE();

// Configure button pin (PC13) as input with EXTI
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

// Set priority and enable EXTI line 15-10 interrupt in NVIC
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

while (1) {
// Main loop
}
}
` This code actually works but here i have used the hal drivers but when i try it with it the driver files i created it doesn't work
#include "stm32nul476rg.h"
#include "string.h"

void delay(void)
{
for(uint32_t i = 0; i < 50000/2; i++);
}

#define LOW 1
#define BTN_PRESSED LOW

int main(void)
{
GPIO_Handle_t GpioLed, GpioBtn;

memset(&GpioLed, 0, sizeof(GpioLed));
memset(&GpioBtn, 0, sizeof(GpioBtn));

// LED GPIO configuration
GpioLed.pGPIOx = GPIOA;
GpioLed.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NO_5;
GpioLed.GPIO_PinConfig.GPIO_PinMode = GPIO_MODE_OUT;
GpioLed.GPIO_PinConfig.GPIO_PinSpeed = GPIO_SPEED_LOW;
// GpioLed.GPIO_PinConfig.GPIO_PinOPType = GPIO_OP_TYPE_PP;
GpioLed.GPIO_PinConfig.GPIO_PinPuPdContol = GPIO_NO_PUPD;

// GPIO_PeriClockControl(GPIOA, ENABLE);
GPIO_Init(&GpioLed);

// Button GPIO configuration
GpioBtn.pGPIOx = GPIOC;
GpioBtn.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NO_13;
GpioBtn.GPIO_PinConfig.GPIO_PinMode = GPIO_MODE_IT_FT; // Interrupt mode, falling edge
// GpioBtn.GPIO_PinConfig.GPIO_PinSpeed = GPIO_SPEED_FAST;
GpioBtn.GPIO_PinConfig.GPIO_PinPuPdContol = GPIO_NO_PUPD;

// GPIO_PeriClockControl(GPIOC, ENABLE);
GPIO_Init(&GpioBtn);

// IRQ configuration
GPIO_IRQPriorityConfig(IRQ_NO_EXTI15_10, NVIC_IRQ_PRI15);
GPIO_IRQInterruptConfig(IRQ_NO_EXTI15_10, ENABLE);
while(1);
// while(1){
// delay();
// GPIO_ToggleOutputPin(GPIOA, GPIO_PIN_NO_5); // Toggle the LED
//
// }

return 0;
}

void EXTI15_10_IRQHandler(void)
{
if(GPIO_ReadFromInputPin(GPIOC, 13) != BTN_PRESSED)
{
GPIO_IRQHandling(GPIO_PIN_NO_13); // Clear the interrupt flag
GPIO_ToggleOutputPin(GPIOA, GPIO_PIN_NO_5); // Toggle the LED
}
}
#include "stm32nul476rg.h"
#include "string.h"

void delay(void)
{
for(uint32_t i = 0; i < 50000/2; i++);
}

#define LOW 1
#define BTN_PRESSED LOW

int main(void)
{
GPIO_Handle_t GpioLed, GpioBtn;

memset(&GpioLed, 0, sizeof(GpioLed));
memset(&GpioBtn, 0, sizeof(GpioBtn));

// LED GPIO configuration
GpioLed.pGPIOx = GPIOA;
GpioLed.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NO_5;
GpioLed.GPIO_PinConfig.GPIO_PinMode = GPIO_MODE_OUT;
GpioLed.GPIO_PinConfig.GPIO_PinSpeed = GPIO_SPEED_LOW;
// GpioLed.GPIO_PinConfig.GPIO_PinOPType = GPIO_OP_TYPE_PP;
GpioLed.GPIO_PinConfig.GPIO_PinPuPdContol = GPIO_NO_PUPD;

// GPIO_PeriClockControl(GPIOA, ENABLE);
GPIO_Init(&GpioLed);

// Button GPIO configuration
GpioBtn.pGPIOx = GPIOC;
GpioBtn.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NO_13;
GpioBtn.GPIO_PinConfig.GPIO_PinMode = GPIO_MODE_IT_FT; // Interrupt mode, falling edge
// GpioBtn.GPIO_PinConfig.GPIO_PinSpeed = GPIO_SPEED_FAST;
GpioBtn.GPIO_PinConfig.GPIO_PinPuPdContol = GPIO_NO_PUPD;

// GPIO_PeriClockControl(GPIOC, ENABLE);
GPIO_Init(&GpioBtn);

// IRQ configuration
GPIO_IRQPriorityConfig(IRQ_NO_EXTI15_10, NVIC_IRQ_PRI15);
GPIO_IRQInterruptConfig(IRQ_NO_EXTI15_10, ENABLE);
while(1);
// while(1){
// delay();
// GPIO_ToggleOutputPin(GPIOA, GPIO_PIN_NO_5); // Toggle the LED
//
// }

return 0;
}

void EXTI15_10_IRQHandler(void)
{
if(GPIO_ReadFromInputPin(GPIOC, 13) != BTN_PRESSED)
{
GPIO_IRQHandling(GPIO_PIN_NO_13); // Clear the interrupt flag
GPIO_ToggleOutputPin(GPIOA, GPIO_PIN_NO_5); // Toggle the LED
}
}
void GPIO_IRQPriorityConfig(uint8_t IRQNumber, uint32_t IRQPriority)
{
//1. First find the ipr register
uint8_t iprx = IRQNumber/4;
uint8_t iprx_section = IRQNumber%4;

uint8_t shift_amount = (8 * iprx_section) + (8 - NO_PR_BITS_IMPLEMENTED);
*(NVIC_PR_BASE_ADDR + iprx ) |= ( IRQPriority << shift_amount);
}

void GPIO_IRQInterruptConfig(uint8_t IRQNumber, uint8_t EnorDi)
{
if(EnorDi == ENABLE)
{
if(IRQNumber <=31)
{
// program ISER0 register
*NVIC_ISER0 |= (1<< IRQNumber);
}
else if(IRQNumber >31 && IRQNumber<64 )
{
// program ISER1 register
*NVIC_ISER1 |= (1<< IRQNumber%32);
}
else if(IRQNumber>= 64 && IRQNumber<96)
{
// program ISER2 register
*NVIC_ISER2 |= (1<< IRQNumber%64);
}
}
else
{
if(IRQNumber <=31)
{
// program ICER0 register
*NVIC_ICER0 |= (1<< IRQNumber);
}
else if(IRQNumber >31 && IRQNumber<64 )
{
// program ICER1 register
*NVIC_ICER1 |= (1<< IRQNumber%32);

}
else if(IRQNumber>= 64 && IRQNumber<96)
{
// program ICER2 register
*NVIC_ICER2 |= (1<< IRQNumber%64);
}

}
}
void GPIO_IRQPriorityConfig(uint8_t IRQNumber, uint32_t IRQPriority)
{
//1. First find the ipr register
uint8_t iprx = IRQNumber/4;
uint8_t iprx_section = IRQNumber%4;

uint8_t shift_amount = (8 * iprx_section) + (8 - NO_PR_BITS_IMPLEMENTED);
*(NVIC_PR_BASE_ADDR + iprx ) |= ( IRQPriority << shift_amount);
}

void GPIO_IRQInterruptConfig(uint8_t IRQNumber, uint8_t EnorDi)
{
if(EnorDi == ENABLE)
{
if(IRQNumber <=31)
{
// program ISER0 register
*NVIC_ISER0 |= (1<< IRQNumber);
}
else if(IRQNumber >31 && IRQNumber<64 )
{
// program ISER1 register
*NVIC_ISER1 |= (1<< IRQNumber%32);
}
else if(IRQNumber>= 64 && IRQNumber<96)
{
// program ISER2 register
*NVIC_ISER2 |= (1<< IRQNumber%64);
}
}
else
{
if(IRQNumber <=31)
{
// program ICER0 register
*NVIC_ICER0 |= (1<< IRQNumber);
}
else if(IRQNumber >31 && IRQNumber<64 )
{
// program ICER1 register
*NVIC_ICER1 |= (1<< IRQNumber%32);

}
else if(IRQNumber>= 64 && IRQNumber<96)
{
// program ICER2 register
*NVIC_ICER2 |= (1<< IRQNumber%64);
}

}
}
Want results from more Discord servers?
Add your server