2022-11-06 04:00 AM
Im trying some bare Metal programming on the NUCLEO - H743ZI2.
Im stuck on creating a Button Interrupt on EXTI line 13.
The User Button 1 is located on PC13, im trying to toggle LED2 on PE1.
LED and Button configuration must be correct, since it works with polling. I think im missing something in the Register configuration for the EXTI, but i cant find the problem. I found no "bare metal" examples for the board im using.
The PR1 register is always at 0x2000 after configuration(bit 13 is set to 1), but only if i activate any of the trigger edge settings. I commented out the RCC and SYSCFG lines in the setup_ISR function and it didnt change the behaviour, so i think im missing something in@ these lines to correctly setup the EXTI. I have tried to find a solution without any succes.
#include <main.h>
volatile unsigned char led_on = 1;
uint32_t interrupt = 0;
void setup_usrled_2(void)
{
//LED_PIN = PE1
// peripheral clock enable
RCC -> AHB4ENR |= RCC_AHB4ENR_GPIOEEN;
// 00 overwrite
GPIOE -> MODER &= ~(0b11 << (LED_PIN*2));
// 01 output
GPIOE -> MODER |= (0b01 << (LED_PIN*2));
// 0 Open Drain
GPIOE -> OTYPER &= ~(0b1 << LED_PIN);
GPIOE -> PUPDR &= ~(0b11 << LED_PIN*2);
}
void setup_usrbttn_1(void)
{
//BUTTON_PIN = PC13
// peripheral clock enable
RCC -> AHB4ENR |= RCC_AHB4ENR_GPIOCEN;
// 00overwrite == input mode
GPIOC -> MODER &= ~(0b11 << (BUTTON_PIN*2));
// 00 overwrite
GPIOC -> PUPDR &= ~(0b11 << (BUTTON_PIN*2));
// 10 Pull Down, since USER_B1 is connected to VDD (inactive high)
GPIOC -> PUPDR |= (0b10 << (BUTTON_PIN*2));
}
void setup_bttn1_ISR(void)
{
//BUTTON_PIN = PC13
// peripheral clock enable
RCC -> APB4ENR |= RCC_APB4ENR_SYSCFGEN;
// reset EXTI line 13
SYSCFG -> EXTICR[0] &= ~(SYSCFG_EXTICR4_EXTI13_Msk);
// activate EXTI line 13 for GPIO Port C (PC13)
SYSCFG -> EXTICR[0] |= (SYSCFG_EXTICR4_EXTI13_PC);
// unmask Interrupt for line/interrupt 13
EXTI -> IMR1 |= (0x01 << EXTI_IMR1_IM13_Pos);
// deactivate rising trigger (do not react on release of btn)
EXTI -> RTSR1 &= ~(0x01 << EXTI_RTSR1_TR13_Pos);
// activate falling trigger (react on press of button)
EXTI -> FTSR1 |= (0x01 << EXTI_FTSR1_TR13_Pos);
//activate NVIC
NVIC_SetPriority(EXTI15_10_IRQn, 0x03);
NVIC_EnableIRQ(EXTI15_10_IRQn);
}
void EXTI15_10_IRQHandler(void)
{
if (EXTI->PR1 & (1 << BUTTON_PIN))
{
// clear EXTI status flag
EXTI->PR1 |= (1 << BUTTON_PIN);
led_on = !led_on;
}
NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
}
int main(void)
{
setup_usrbttn_1();
setup_usrled_2();
setup_bttn1_ISR();
interrupt = EXTI->PR1;
while (1)
{
if (led_on)
{
GPIOE->ODR |= (1 << LED_PIN);
}
else
{
GPIOE->ODR &= ~(1 << LED_PIN);
}
}
}
2022-11-06 07:05 AM
Read out and check/post content of registers you are trying to work with.
> SYSCFG -> EXTICR[0] &= ~(SYSCFG_EXTICR4_EXTI13_Msk);
> SYSCFG -> EXTICR[0] |= (SYSCFG_EXTICR4_EXTI13_PC);
Are you sure with the [0]?
JW
2022-11-07 03:39 AM
Sorry for the late response.
First, the registers directly after the setup:
Peripheral Clock for EXTI: RCC->APB4ENR = 0x2 SYSCFG peripheral on
EXTICR4 Register for EXTI line 13: SYSCFG -> EXTICR[4] = 0x2000 line 13 active?
Interrupt Mask Register 1: EXTI -> IMR1 = 0x2000 Interrupt line 13 unmasked
Rising Trigger Register 1: EXTI -> RTSR1 = 0x0 0 Rising off
Falling Trigger Register 1: EXTI -> FTRS1 = 0x2000 Falling Trigger on at line 13
I have also tried replacing the [0] with [4], and changing the GPI/O PIN to PC14 with no change in behaviour. I hope this information helps.
2022-11-07 03:40 AM
Sorry for the late response.
First, the registers directly after the setup:
Peripheral Clock for EXTI: RCC->APB4ENR = 0x2 SYSCFG peripheral on
EXTICR4 Register for EXTI line 13: SYSCFG -> EXTICR[4] = 0x2000 line 13 active?
Interrupt Mask Register 1: EXTI -> IMR1 = 0x2000 Interrupt line 13 unmasked
Rising Trigger Register 1: EXTI -> RTSR1 = 0x0 0 Rising off
Falling Trigger Register 1: EXTI -> FTRS1 = 0x2000 Falling Trigger on at line 13
I have also tried replacing the [0] with [4] and changing the GPI/O PIN to PC14 with no change in behaviour. I hope this information helps.
2022-11-07 04:23 AM
__IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */
You want to use SYSCFG -> EXTICR[3] - in RM, EXTICR are 1-based numbered, while in C the array is 0-based.
JW
2022-11-07 06:30 AM
What a stupid mistake.
I set it to [3] as you told me and it works as intended.
Makes me wonder, why is the EXTICR 1-based. I hope i am not the only one who got confused by it.
2022-11-07 10:12 AM
> Makes me wonder, why is the EXTICR 1-based.
Because typically the hardware guys do not understand the software and vice versa. Though in ST's case even the software guys do not understand the software. And on top of that the company is too large for the departments to be able to communicate with each other.
By the way, the Julian/Gregorian numbering of years is also 1-based and mathematically flawed:
2022-11-07 10:53 AM
> hardware guys do not understand the software
This is compounded by the fact that the 32-bitters these days are not designed in some consistent way, but are slapped together from components (IPs) bought from various vendors.
JW