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.
1 ACCEPTED SOLUTION

Accepted Solutions
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..

View solution in original post

16 REPLIES 16
Posted on November 22, 2017 at 14:12

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

No, you want to unmask *interrupt* so use IMR rather than EMR.

I won't check the MUX setting in SYSCFG. A common error is forgetting to enable SYSCFG clock. Also the pin may need to be set as digital input in GPIO (it should work also when digital output or AF, but this is the simplest setting).

Also,

        EXTI_PR1 |= BIT4 ; //clears interrupt

don't use RMW here, write directly 1, the PR register is rc_w1 for a good reason (RMW may inadvertently clear other bits - not relevant for your test case but it's a bad practice which may backfire later when the application grows or code is reused).

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

  GPIOB_ODR &= ~BIT3; 

Better use BSRR.

JW

Posted on November 22, 2017 at 14:33

Thanks JW.

My code is:.

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

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

Your comment 'use IMR rather than EMR.' indicates my code should be (???):

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

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

     <--- commented out

I tried this but my 'void EXTI4_IRQHandler(void) {' is still not getting hit.

Also the pin is setup as digital input. I can poll it and model its input level to another output pin. So I feel the pin is okay. 

Thanks for your comments on BSSR. This is on my list once I get the interrupt working.

Randy 

Posted on November 22, 2017 at 14:52

Check and confirm the setting in SYSCFG. Note my comment above. Registers readout in debugger is often helpful.

JW

Posted on November 22, 2017 at 15:15

Make sure SYSCFG clock is enabled

Enable in NVIC

Make sure you have correct linkage with the vector table

If using C++ use extern 'C' void EXTI4_IRQHandler(void) { }

Look at the SPL examples, then convert to register level

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 22, 2017 at 15:20

JW,

Thanks. The SYSCFG  was not set. Once enabled the 

SYSCFG_EXTICR2, 

EXTI_IMR1, and 

EXTI_FTSR1 are now set.

I'm toggling the pin and the handler is still not getting set. I've even tried 'EXTI_SWIER1 |= BIT4;' (verified set using viewer) to force an interrupt. Again the handler is not getting hit. When I say hit I'm running in the normal mode AND in in single step mode and the handler code is not getting hit.

Any more ideas?

Thanks...

Randy

Posted on November 22, 2017 at 15:23

Clive's above.

JW

Posted on November 22, 2017 at 15:24

Look at the SPL examples, then convert to register level

Would have been my recommendation, too.

The initialization of the user push button for the discovery examples (SPL) uses an Exti interrupt.

Posted on November 22, 2017 at 15:27

Clive,

Thanks for the suggestions. Totally missed the SYSCFG clock until JW mentioned it.

I'm using Keil Uvision and a simple 'C' project. You mention the NVIC. While reading the docs I've seen this mentioned. To setup/use and interrupt do I have to configure the registers I've mentioned plus registers in the NVIC?

I'm assuming the linkage in the vector table statement refers to my handler code. If yes then I'm to sure WHERE to look to find the 'correct' handler. I'm using the Standard Lib. 

Thanks for answering with the suggestions.

Randy

Posted on November 22, 2017 at 15:34

Everyone,

I'm using the STM32F303K8 part and looking at the EXTI example code in STM32F30x_StdPeriph_Examples. I see 'void EXTI15_10_IRQHandler(void)' and 'void EXTI9_5_IRQHandler(void)'. Is there some documentation that explains these? Is there one for EXTI4? What headers/c files do I need in my project to have access to the handler for EXTI4.

Thanks for any direction.

Randy