Curious if there are any STM32 guys using the CubeMX HAL. I'm having an issue that I can work around, but want to know the details of this issue. The part is an STM32F042, using CubeMX ver 4.23, GNU compiler and CooCox IDE.
The problem is this, I have PA4 setup as external interrupt for a falling edge detection (only external interrupt):
I do not have this signal debounced in hardware (for a reason). Therefore, in the ISR I disable the interrupt immediately, then re-enable later in the the code:
ISR:
You'll notice the handler calls HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4) which resides in hal_gpio.c:
Now, I thought that __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin) clears the interrupt pending bit. With the external interrupts disabled (beginning of ISR), I should be free to activate the IRQ at a later time. However, when I do this, the interrupt routine executes again immediately (once, like it was previously triggered). So I tried calling HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4) , right before re-enabling the interrupt:
No Difference. So I dug deeper. What I found was that the interrupt is able to be triggered when the IRQ is disabled (makes sense given no debounce), and the HAL routine for clearing the pending interrupt does not seem to work. I also found, during debugging, after the initial run through the ISR, that ICPR and ISPR are triggered, which seems to cause the second (erroneous) run through the ISR. These seem to be the "interrupt clear pending register" and "interrupt set pending registers" although I do not find these in the Reference Manual for this chip. The documentation I happened to find on Keil seemed inconsistent with my debugger findings.
Reading through the reference manual, it seems that writing a 1 to the EXT1_PR is the way to clear a pending register, and I see this actually happening while debugging, but does not prevent the double fire of my ISR. I see no mention of the ICPR and ISPR in the reference manual which seem to be the registers allowing this double fire to happen. Is this a peripheral vs NVIC issue? Does the HAL support a solution? This would seem like a fairly common problem to want to overcome.
Thanks
The problem is this, I have PA4 setup as external interrupt for a falling edge detection (only external interrupt):
Code:
/*Configure GPIO pin : PA4 */
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/snip
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI4_15_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
ISR:
Code:
void EXTI4_15_IRQHandler(void)
{
/* USER CODE BEGIN EXTI4_15_IRQn 0 */
HAL_NVIC_DisableIRQ(EXTI4_15_IRQn);//Disable external IRQs
SenseTime[EventSlot]=__HAL_TIM_GET_COUNTER(&htim2); //Get sense time from timer 2
if(TriggerTime<9) //index where the time even happened.
TriggerTime++;
else
TriggerTime=0;
/* USER CODE END EXTI4_15_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
/* USER CODE BEGIN EXTI4_15_IRQn 1 */
/* USER CODE END EXTI4_15_IRQn 1 */
}
Code:
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin);
}
}
Code:
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);//Enable IRQ for sensing next pulse
Reading through the reference manual, it seems that writing a 1 to the EXT1_PR is the way to clear a pending register, and I see this actually happening while debugging, but does not prevent the double fire of my ISR. I see no mention of the ICPR and ISPR in the reference manual which seem to be the registers allowing this double fire to happen. Is this a peripheral vs NVIC issue? Does the HAL support a solution? This would seem like a fairly common problem to want to overcome.
Thanks