Hi,
I'm using Keil MDK-ARM 4.22a RTX OS on a STM3220G Eval board.
I added RTX and FS to the "Memory" example and everything is working fine. I have tasks that read a file while another one is blinking leds.
I tried to add and external interrupt on the KEY button (PG15 pin) and to do so I integrated the ST StdPeriph library (which is used mainly for setting up the interruption).
But if the button is working, I can't clear the Interrupt Pending bit in the IRQ handler. So when I send a semaphore from it, the OS raises quickly an overflow error.
Here is the code for the interruption setup :
void EXTI_User_Button_Config(void) { EXTI_InitTypeDef EXTI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; /* Enable GPIOG clock */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); /* Enable SYSCFG clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); /* Configure PG15 pin as input floating */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; GPIO_Init(GPIOG, &GPIO_InitStructure); /* Connect EXTI Line0 to PG15 pin */ SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOG, EXTI_PinSource15); /* Configure EXTI Line0 */ EXTI_InitStructure.EXTI_Line = EXTI_Line15; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_ClearITPendingBit(EXTI_Line15); EXTI_Init(&EXTI_InitStructure); /* Enable and set EXTI Line15 Interrupt to the lowest priority */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }
And the IRQ handler :
void EXTI15_10_IRQHandler (void) __irq { if(EXTI_GetITStatus(EXTI_Line15) != RESET) { /* Clear the EXTI line 15 pending bit */ EXTI_ClearITPendingBit(EXTI_Line15); /* Toggle LED1 */ STM_EVAL_LEDToggle(LED1); /*Send Semaphore */ isr_sem_send (semaphore1); cpt++; } }
The 'cpt' variable is only for debugging purpose, as it's decremented by the task that handles semaphore1. When it's reaching 32 (the ISR FIFO size I defined), the OS raises the overflow error.
The code from the Std library to reset the pending bit :
void EXTI_ClearITPendingBit(uint32_t EXTI_Line) { /* Check the parameters */ assert_param(IS_EXTI_LINE(EXTI_Line)); EXTI->PR = EXTI_Line; }
The interrupt setup is done before launching the OS.
Am I doing something wrong ? Is there another way to clear the interrupt bit ?
I modified the IRQ handler like suggested on the other topic :
void EXTI15_10_IRQHandler (void) __irq { if(EXTI_GetITStatus(EXTI_Line15) != RESET) { /* Clear the EXTI line 15 pending bit */ EXTI_ClearITPendingBit(EXTI_Line15); /*Send Semaphore */ isr_sem_send (semaphore1); /* Re-clears the interrupt NVIC_ClearPendingIRQ(EXTI15_10_IRQn); } }
and there is no more overflow, the semaphore is only set once.
Hi Per,
When I keep the button pressed, I get no interrupts. But sometimes they occur when I release it. This is not a big issue, because we probably put a task polling for buttons (and use very different ones on our final hardware), as we want to implement some debounce on them. This was just for testing the external interrupts.
Any mechanical button in my experience will cause several edge interrupts on both edges on a press and release. That is the whole point of debouncing.
A very rough method I use is to use task events.
If I get an interrupt on say the rising edge the ISR disables the interrupt and raises an event.
A task is waiting for the event and when it receives the event it checks the state of the pin for X amount of time to make sure it is a press and not a bounce.
If it's a press handle the press otherwise re-enable the interrupt and wait for the event again.