cancel
Showing results for 
Search instead for 
Did you mean: 

How to handle GPIO interrupts using StdPeriph_Lib

Randy Nelson
Associate III
Posted on November 22, 2017 at 13:48

Working with STM32F303K8 at the lowest level where I'm writing to the registers directly. Try to follow generic statements in STM documents to handle a high2low transition on a GPIO PB4 input pin. These are the instructions I feel I need to do for the docs.

//interrupts

//EXTI registers. Only set ones that are needed.

SYSCFG_EXTICR2 |= BIT0; //select source pin PB4 for the EXTI4 external interrupt

EXTI_IMR1 |= BIT4; //assumming MR4 is EXTI4. Set to not mask

EXTI_EMR1 |= BIT4; //assumming MR4 is EXTI4. Unmask event

EXTI_FTSR1 |= BIT4; //assumming TR4 is EXTI4. Failing edge

If this code all I need and correct?

I also need an interrupt handler. Again from examples and online searches this is my handler.

void EXTI4_IRQHandler(void) {

if((EXTI_PR1 & BIT4) != 0) {

EXTI_PR1 |= BIT4 ; //clears interrupt

} //determines if set

GPIOB_ODR |= BIT3; //toggle test points for scope

GPIOB_ODR &= ~BIT3;

}

When running and PB4 going high2low at ~1K rate the handler does not appear to be hit. Even putting a breakpoint at the 'if(EXTI..' does not get hit.

Any suggestions or directions to get a low level GPIO handler working.

Thanks,

Randy

#gpio-interrupts-using-stdperiph_lib

Note: this post was migrated and contained many threaded conversations, some content may be missing.
16 REPLIES 16
Posted on November 22, 2017 at 15:37

In the examples it indicates these are listed in my startup file. For me this is startup_stm32f303x8.s .

In this file there is:

Default_Handler PROC

EXPORT WWDG_IRQHandler [WEAK]

EXPORT PVD_IRQHandler [WEAK]

EXPORT TAMP_STAMP_IRQHandler [WEAK]

EXPORT RTC_WKUP_IRQHandler [WEAK]

EXPORT FLASH_IRQHandler [WEAK]

EXPORT RCC_IRQHandler [WEAK]

EXPORT EXTI0_IRQHandler [WEAK]

EXPORT EXTI1_IRQHandler [WEAK]

EXPORT EXTI2_TSC_IRQHandler [WEAK]

EXPORT EXTI3_IRQHandler [WEAK]

EXPORT EXTI4_IRQHandler [WEAK]                        <<<<<<<<<<< this is the one I've defined in my main.c

Randy

Posted on November 22, 2017 at 15:44

NVIC_EnableIRQ(EXTI4_IRQn) you have?

JW

Posted on November 22, 2017 at 15:50

JW,

Am trying to find this in the reference manuals.

Randy

Posted on November 24, 2017 at 19:23

// Example in SPL

#include 'stm32f30x.h'

void GPIO_Config(void)

{

  GPIO_InitTypeDef   GPIO_InitStructure;

  /* Enable GPIOB clock */

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

  /* Configure PB3 pin as output */

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

}

void EXTI4_Config(void)

{

  EXTI_InitTypeDef   EXTI_InitStructure;

  GPIO_InitTypeDef   GPIO_InitStructure;

  NVIC_InitTypeDef   NVIC_InitStructure;

  /* Enable GPIOB clock */

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

  /* Configure PB4 pin as input floating */

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

  /* Enable SYSCFG clock */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

  /* Connect EXTI4 Line to PB4 pin */

  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource4);

  /* Configure EXTI4 line */

  EXTI_InitStructure.EXTI_Line = EXTI_Line4;

  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;

  EXTI_InitStructure.EXTI_LineCmd = ENABLE;

  EXTI_Init(&EXTI_InitStructure);

  /* Enable and set EXTI4 Interrupt to the lowest priority */

  NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

void EXTI4_IRQHandler(void)

{

  if (EXTI_GetITStatus(EXTI_Line4) == SET)

  {

    /* Clear the EXTI line 4 pending bit */

    EXTI_ClearITPendingBit(EXTI_Line4);

        GPIOB->ODR |= GPIO_Pin_3; // Pulse PB3

        GPIOB->ODR &= ~GPIO_Pin_3;

  }

}

int main(void)

{

    /* Configure PB3 as an output */

    GPIO_Config();

  /* Configure PB4 in interrupt mode */

  EXTI4_Config();

  /* Infinite loop */

  while (1)

  {

  }

}

#ifdef  USE_FULL_ASSERT

/**

  * @brief  Reports the name of the source file and the source line number

  *         where the assert_param error has occurred.

  * @param  file: pointer to the source file name

  * @param  line: assert_param error line source number

  * @retval None

  */

void assert_failed(uint8_t* file, uint32_t line)

{

  /* User can add his own implementation to report the file name and line number,

     ex: printf('Wrong parameters value: file %s on line %d\r\n', file, line) */

  /* Infinite loop */

  while (1)

  {

  }

}

#endif
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on November 27, 2017 at 16:44

Clive,

Thanks you very much. Got the example included in my project and I can see the interrupt happening. Getting this code included also has helped me understand my Keil environment better (a big plus). Now that I have something working I can study how the interrupts work.

Thanks again.

Randy

Posted on November 27, 2017 at 17:24

The modular nature of the ARM designs tends to mean there are more ducks to line up when it comes to configuration compared to tighter or more integrated designs. Once done you can enable/disable at the peripheral level quite simply.

There can be a lot of similar/replicated code for initialization, this can be reduced with the use of functions or configuration tables, but that would tend to obfuscate the examples. You should also watch register level coding, the registers are treated as volatile so the compiler can't fold multiple operations, so if you write 1000 lines of RMW code you'll get 1000 LDR/STR operations.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on November 27, 2017 at 18:05

the registers are treated as volatile so the compiler can't fold multiple operations, so if you write 1000 lines of RMW code you'll get 1000 LDR/STR operations.

This is IMO obvious to anybody who did some asm programming on the 8-bitters; I believe it's the kids churned out by schools teaching exclusively high level languages why we see so many of this lately.

JW