2017-11-22 04:48 AM
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 edgeIf 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.Solved! Go to Solution.
2017-11-24 10:23 AM
// 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) { }}#endif2017-11-22 05:12 AM
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
2017-11-22 06:33 AM
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
2017-11-22 06:52 AM
Check and confirm the setting in SYSCFG. Note my comment above. Registers readout in debugger is often helpful.
JW
2017-11-22 07:15 AM
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
2017-11-22 07:20 AM
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
2017-11-22 07:23 AM
Clive's above.
JW
2017-11-22 07:24 AM
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.
2017-11-22 07:27 AM
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
2017-11-22 07:34 AM
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