External interrupt HIFIVE REV B

Good evening, hope everyone is safe out there. I am trying to initialize the external interrupt for the falling edge for pin 0 to 7 in HIFIVE revB. When I push the push button the external interrupt handler is executed. however, it is stuck in the handler even though I wrote back to the claim_commplite register. Also, to break out of the loop I cleared bit number 11 in mie register. however, when I enabled the mie later in main(), CPU started to execute the external_interrupt even without pushing the push button. If any one could spot what I am missing, I will be so gratfull.
memory map
extern 3
interrupt.h


interrupt.c

main.c

interesting.
you might try only x=claim_complete reading the register, not claim_complete=x writing it. Section 10.7 of the Manual says that “… can perform an interrupt claim by reading the claim/complete register.” maybe the hardware store operation has something to do with the troubles seen?
supposedly, the interrupt source(s) are also [atomically] cleared but you might try clearing them explicitly either before or after (not sure which) your claim operation.
not sure those delays are really needed but probably not bad for debugging.
aside from that, wonder if there is some insane switch bounce going on. not sure if the i/o pins have schmitt trigger features, figuring in some firmware hysteresis might not be a bad idea. try configuring either pull-up or open-drain mode of the gpio’s PUE setting, or either the 1ma or 20ma mode of the gpio’s DS setting. on the pcba schematic, what kind of pull-up resistor and/or filter cap does the switch input have?

Good evening, thanks very much for your response. I did enable pull up the GPIO register for the input pin. I do not have experience with HIFIVE So I do not really know what “drain mode of the gpio’s PUE setting, or either the 1ma or 20ma mode of the gpio’s DS setting” means. Also, from HIfive data sheet it mentions that I could wright to claim/complete register.


However, when I tried your way and enabled 4 pins to be used as fall interrupt. it was interesting that every pin could fire the interrupt only one time, so I was able to go to an external interrupt handler four times, and then the interrupt stop working. One the other hand, if I wrote to the complete/claim register the interrupt will be called infinite time. Hopefully, you can explain the reason for that. Thank you again.

It seems like you’re trying to trigger this on the falling edge, so my guess is that you’re shorting the pins to ground?

I think @pds is right that this sounds like it needs denouncing and/or a pull up resistor.

For pull-up resistors there are internal latches that can do that for you, but they need to be enabled, this is the PUE pds mentioned. See offset 0x10 in the gpio memory map. This is likely why the interrupt triggers once as you’ve grounded the pin, and on disconnect it remains floating. Enabling the pull-up resistor will “pull up” the signal to high when it’s floating.

Debouncing is a different problem due to the nature of buttons and contacts https://learn.adafruit.com/make-it-switch/debouncing

I’d think the delays would help with that, but maybe delaying after claiming the interrupt is the problem here, as reading the claim/complete register is supposed to atomically clear it as well, which could queue another interrupt while you’re delaying if the switch is bouncing.

Thanks for your response. I did enable the pull-up register. Then I connect the pin to the push button and the other side of the push button is connected to the ground.
debug interrupt
I did debug the code. And when the interrupt occurred the crossing interrupt pending bit is set. However, this bit never cleared. so after I pushed the two push-button two pending bits are set and never cleared. After the interrupt handler is served my code inside the while(1) work fine. Do you know the reason for that.Thanks very much.
debug interrupt2

good tips here from @tincman and nice progress so far.
Section 17.4 of the Manual is interesting: “Once the interrupt is pending, it will remain set until a 1 is written to the *_ip register at that bit.”

after interrupt is detected, in the handler, try writing 0x00030000 with your fall_ip = 0x00030000 function. Apparently, one would think that the gpio _ip fields (0x1C, 0x24, 0x2C, 0x34) are read-only registers but it could be the case these latches are reset when 1’s are written to their RO addresses.

Suggestion: to do this in a generic way, after reading the _ip value write same value back to _ip. might want to mask off only the bit of the interrupt input your servicing, if handling more than one source, but that’s for later work. for example,
x = fall_ip; // read pending status
fall_ip = x; // clear pending bit(s)

I would have assumed that the claim/complete process would have done this atomically, but maybe not?

Thanks for both of you. Thanks, Paul Sherman I didn’t read that part of the manual since I wrote the GPIO module. This was the missing two lines that cause my code to misbehave. Also, still, I need to write to the complete register at the end of the function handler in order for the code to work. Otherwise, the interrupt will be executed only once.
image
Thanks, Scott Tincman, for mentioning the debouncing issue.