Skip to main content
MSuhe
Associate III
April 10, 2019
Question

STM32F4: EXTI: Fails to capture rising edge interrupt sometimes

  • April 10, 2019
  • 4 replies
  • 3651 views

In out project we are making use of EXTI for interfacing a radio (RF) ASIC with STM32F411. Whenever, the radio has some data to be sent host it interrupts the host using the I/O line (drives the line high). This I/O line stays high till data is read by STM32 over SPI.

Now, we have configured this line to be external interrupt line with EXTI. And the functionality works as expected most of the time. But, we do see some scenarios where, EXTI controller does not raise an interrupt even though the I/O line is high.

To overcome this issue, we are monitoring the state of the I/O line to check if it is high and if true, try and read the data from radio over SPI.

A quick check at the state of the EXTI registers whenever this happens shows PR (pending register) set to 0 (no interrupt pending) and IMR (interrupt mask register) set to 0x400, which mean the associated interrupt being enabled.

Is there any reason why the EXTI might fail to capture a rising edge on the I/O line? STM32F4 does not support level sensitive interrupts, otherwise we could have configured the external interrupt as level sensitive.

Please do share your inputs.

This topic has been closed for replies.

4 replies

waclawek.jan
Super User
April 10, 2019

This typically happens if the external device can generate two edges consecutively and you clear the pending register *after* the second edge arrives.

JW

MSuhe
MSuheAuthor
Associate III
April 10, 2019

Thanks for your response. As far as i am know,

  • The external device we have generates an edge everytime it has some data for host.
  • And we clear the pending register right at the beginning of the ISR handler before we start reading data from external device.
  • We clear the pending register as a first step, so that EXTI can capture any new triggers/edges generated on the I/O line, while executing the ISR handler.
  • Also, we are not masking the interrupts at all, as edges are not captured if masked. by clearing "interrupt mask register".

Am i missing anything else? Please so share your inputs.

waclawek.jan
Super User
April 10, 2019

> The external device we have generates an edge everytime it has some data for host.

How often that can be? Is your total interrupt latency, ie. worst-case time from the physical edge to the point where the pending register is cleared, guaranteed to be faster than the closest two edges from the external device?

How do you notify the external device that you've accepted the data? Do you notify after clearing the pending register? Will the external device generate an edge if notification comes after it has more data?

JW

MSuhe
MSuheAuthor
Associate III
April 11, 2019

Thanks again for your quick response. Please find some important aspects regarding how/when the external device drives the I/O line and when the I/O line is cleared.

  • From the STM32 side, we have configured the I/O line as input and set the pull-up to PULL-DOWN.
  • Now, whenever the external device has some data it generates a rising edge on the I/O line and leaves the I/O state high as long as the data is not fully read by the host MCU.
  • Now on getting the ISR, we clear the Pending register as a first step. At this point I/O line will still be high.
  • Next MCU reads the data/status from external device over SPI.
  • External device will drive the I/O line low, once all the data is read.
  • Continue with ISR execution.

External device will only generate a second edge only after it is driven low. As the I/O line stays high until all the data is read by host MCU. Now, if there is more data accumulated from the point I/O line goes high to MCU reading it, it is fine. As, MCU will no do a partial read.

Now, with above said external device behaviour and handling from MCU. I don't understand how the host can still miss an edge?

Bob S
Super User
April 11, 2019

What happens if:

  • Device has 1 set of data and drives I/O line high
  • You get the interrupt, ISR clears pending bit
  • While ISR is reading 1 set of data, device receives a 2nd set of data

Does your ISR always only read 1 set of data and then exit? Or does it check to see if more data is available before exiting? Does it check the state of the I/O line before exiting (i.e. does it keep reading data as long as the I/O line is high)?

waclawek.jan
Super User
April 11, 2019

> No, we just read the data when the I/O line is high and exit. And do not check for the status of the I/O line. Probably a good thing to do.

It's *necessary* to do so. This is the very root of your problem. There can't be a rising edge, if the signal remains high...

JW

MSuhe
MSuheAuthor
Associate III
April 12, 2019

Thanks for your response. Now i have added a check to verify if the I/O line is still high. And if true, attempt reading the data from the external device. This has definitely brought improvements, but has not fully fixed the issue.

Because, till now the workaround what we had for identifying missing edge interrupts and mitigating lock-up was with an API "radio_isr_kick()". This will be called from the FreeRTOS thread. And all "radio_isr_kick()" API does is,

  1. Check if the external I/O line is high.
  2. If yes, execute the external interrupt ISR handler.

And with the help of some flags i still see that, ISR handler gets executed from within "radio_isr_kick()". Which means the I/O line was high and EXTI somehow did not capture the edge.

Bob S
Super User
April 12, 2019

Can you post the code from your interrupt function? You can remove the radio-specific code and replace it with a "radio stuff here" comment. And how are you "executing" the ISR handler from your kick function - using the EXTI_SWIER register? The status/interrupt output from your radio is not really an edge sensitive interrupt signal, it is a level sensitive signal. It appears that somehow your ISR is somehow exiting with the signal still asserted.

Vangelis Fortounas
Associate II
April 16, 2019

Hello!

A concept behind these Atmel radios is to have fast enough code to take the received data primarily and other necessary information from it before next IRQ occurs.

IRq pin from this device is cleared (LO) only if you read all four (4) interrupt status registers using the SPI. So, supposing that code reads first of all these rfic registers to take action , you must ensure that you use fast code to take all the data before next IRQ occurs, else what? overwritten? lose data?

A practice is to configure the rfic not to generate interrupts in IRQ pin for everything but for some absolute necessary reasons eg "Receiver Frame End" and not e.g. for "Receiver Frame Start".

And to solve this ambiguity about lost edges, configure a timer as an external input counter counting on rising edges with zero prescaller and full ARR value and connect the input pin to IRQ pin (EXTI_GPIO input, TIm_Input an IRQ pin tied together)

Timer will count the rise edges. Define a global integer variable, initialize it to zero and increase it by one inside the radio_irq. Compare the values of timer's counter with this variable to see if finaly EXTI Fails to capture rising edges sometimes. HW timers tell always the truth.