1
votes
    /* Configure EXTI interupt PB4 */
    SYSCFG->EXTICR[0] &= ~SYSCFG_EXTICR2_EXTI4_PB; 
    EXTI->IMR |= EXTI_IMR_IM4;                                                                          //Interrupt Mask on line 2  */
    EXTI->RTSR |= EXTI_RTSR_RT4;                                                                        
    EXTI->FTSR |= EXTI_FTSR_FT4;                                                                        
    NVIC_EnableIRQ(EXTI4_15_IRQn);                                                                          //Załączenie przerwania na pinie zasilania
    NVIC_SetPriority(EXTI4_15_IRQn,1); 

This is how I configure the EXTI

    GPIOB->MODER =      (0U << GPIO_MODER_MODE4_Pos);
    GPIOB->PUPDR =      (1U << GPIO_PUPDR_PUPD4_Pos);

This is how I manage the pins

    while(1)
    {
        if(state == 0){
            ServoToggle(0, 100, 255);
            delay(1000);
        } else {
            ServoToggle(0, 115, 255);
            delay(1000);
            ServoToggle(0, 60, 255);
            delay(1000);
        }
        delay(1);
    }

This is what my program does after stand-up

void EXTI4_15_IRQHandler(void)
{
    if(!(GPIOB->IDR & GPIO_IDR_ID4)){
        state = 0;
    } else {
        state = 1;
    } 
    EXTI->PR = EXTI_PR_PR4;
}

This is how I'm trying to handle the interrupt.

And this thing does not work. Idk why but for PA0 it works like a charm but changing to PB4 stops poping up interrupt event.

I've got a button connected to the pin that changed the IDR register on press.

What am I missing?

I'm using STM32L052 family

2

2 Answers

1
votes

An EXTI IRQ from 4-15 is quite uncommon. Maybe you could add the exakt controller you are using?

On an STM32F415 for example it would be EXTI4_IRQHandler for the IRQ handler.

1
votes

For PA0, I believe it has to to with this line:

SYSCFG->EXTICR[0] &= ~SYSCFG_EXTICR2_EXTI4_PB;

According to the reference manual, PB[x] (where x is 4) is mapped to bit 0-3 of SYSCFG_EXTICR2. So in your case it should be:

SYSCFG->EXTICR[2] &= ~SYSCFG_EXTICR2_EXTI4;
SYSCFG->EXTICR[2] |= SYSCFG_EXTICR2_EXTI4_PB;

PA0 is mapped to SYSCFG->EXTICR[0]. SYSCFG->EXTICR[0] &= ~SYSCFG_EXTICR2_EXTI4_PB; means that AND the contents of SYSCFG->EXTICR[0] with inverse of SYSCFG_EXTICR2_EXTI4_PB which is 0xFE. Assuming SYSCFG->EXTICR[0] was all zeros then you are essentially just AND bunch of zeros together hence why PA0 works.

Just another thing I noticed is that in your interrupt handler, I would check the external interrupt handler flags not the GPIO IDR register to check if the button was pushed. From my understanding of the question, you want to push the button to toggle the variable state. Pushing the button triggers the interrupt so you sort of defeat the purpose by checking IDR register anyways.In the EXTI interrupt handler you check that it is the correct interrupt via the Pending Register/PR. Other EXTI interrupts looks like they share the same handler so you would want to use the EXTR->PR register to check the right pending bit.

Here is some STM32F407 code I have as an example:

#define PORTD_ALL 0x0000F000
void EXTI0_IRQHandler(void){

  // Check for EXTI 0 flag
  if((EXTI->PR & EXTI_PR_PR0) == EXTI_PR_PR0){

    // Toggle all LED on board
    GPIOD->ODR ^= PORTD_ALL;

    // Clear interupt pending request
    EXTI->PR = EXTI_PR_PR0;
  }
}

Every time I press a button it toggles the LED on the board

For the state variable use XOR operation. It is quite useful.

To answer this question I used STM32L052 reference manual and the STM32L052.h file from ST website. Just look for the STM32CubeL0 download