Skip to main content
Randy Nelson
Associate III
November 22, 2017
Solved

How to handle GPIO interrupts using StdPeriph_Lib

  • November 22, 2017
  • 2 replies
  • 3356 views
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.
This topic has been closed for replies.
Best answer by Tesla DeLorean
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

2 replies

waclawek.jan
Super User
November 22, 2017
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

Randy Nelson
Associate III
November 22, 2017
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 

waclawek.jan
Super User
November 22, 2017
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

Tesla DeLorean
Tesla DeLoreanBest answer
Guru
November 24, 2017
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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
Randy Nelson
Associate III
November 27, 2017
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

Tesla DeLorean
Guru
November 27, 2017
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 (See Profile) Up vote any posts that you find helpful, it shows what's working..