arduino / arduino/ArduinoCore-sam

Interrupts problem on Arduino Due

Open
#13 0 comments 0 reactions 0 assignees View on GitHub
Board: Arduino Due Type: Bug
Dominant language
HTML
Stars
91
Forks
112
PR merge metrics
No merged PRs in 30d

Description

_From @mvladic on January 22, 2017 0:11_

[Here](https://gist.github.com/mvladic/a1646b103e838df03e1483e9dfaf724d) is relatively small sketch that I extracted from [my much larger project](https://github.com/eez-open/psu-firmware).

In this sketch there are 2 interrupt handlers:

- ADC (Analog-to-Digital Converter) interrupt handler is running all the time, approx. 20 times per second.
- FAN interrupt handler is enabled for the brief period of time every 5 seconds when it should run 3 to 4 times. (In my project I use FAN interrupts to measure speed of the 3-wire fan.)

For the purpose of debugging, I'm counting, for both FAN and ADC, the number of interrupts occurred and print this counters to serial port every 1 second when I also reset them back to zero.

Here is what I get on serial port output when I run my sketch:

In the first 5 seconds, there is no FAN interrupts (as expected) and there are 20 ADC interrupts per second (also, as expected):

```
FAN interrupt counter = 0, ADC interrupt counter = 3
FAN interrupt counter = 0, ADC interrupt counter = 20
FAN interrupt counter = 0, ADC interrupt counter = 20
FAN interrupt counter = 0, ADC interrupt counter = 20
```

At this moment FAN interrupts are enabled for the brief period of time, and as expected now there are some FAN interrupts to process:

```
FAN interrupt counter = 1, ADC interrupt counter = 20
```

Now, FAN speed is measured (and printed on serial port) and FAN interrupts are again disabled:

```
RPM=4452
```

**But now, suddenly, we started to receive 20 FAN interrupts per second all the time, when we should receive no FAN interrupt because they should be disabled!?**

```
FAN interrupt counter = 22, ADC interrupt counter = 20
FAN interrupt counter = 20, ADC interrupt counter = 20
FAN interrupt counter = 20, ADC interrupt counter = 20
FAN interrupt counter = 20, ADC interrupt counter = 20
FAN interrupt counter = 21, ADC interrupt counter = 20
RPM=4419
FAN interrupt counter = 23, ADC interrupt counter = 20
FAN interrupt counter = 20, ADC interrupt counter = 20
FAN interrupt counter = 20, ADC interrupt counter = 20
FAN interrupt counter = 20, ADC interrupt counter = 20
FAN interrupt counter = 21, ADC interrupt counter = 20
RPM=4388
FAN interrupt counter = 23, ADC interrupt counter = 20
FAN interrupt counter = 20, ADC interrupt counter = 20
FAN interrupt counter = 19, ADC interrupt counter = 19
FAN interrupt counter = 20, ADC interrupt counter = 20
FAN interrupt counter = 21, ADC interrupt counter = 20
...
```

I checked the implementation of the functions attachInterrupt and detachInterrupt inside file WInterrupts.c from the Arduino library for the SEM boards. I have two observations/questions I think are interesting:

1) At the beginning of the file WInterrupts.c, there is initialization of the callbacksPioB (interrupt PIN's inside my sketch belongs to port B) for every pin (32 of them) to NULL:

```
int i;
for (i=0; i<32; i++) {
callbacksPioA[i] = NULL;
callbacksPioB[i] = NULL;
callbacksPioC[i] = NULL;
callbacksPioD[i] = NULL;
}
```

When attachInterrupt is called, callbacksPioB is set to given callback:

```
// Set callback function
if (pio == PIOA)
callbacksPioA[pos] = callback;
if (pio == PIOB)
callbacksPioB[pos] = callback;
if (pio == PIOC)
callbacksPioC[pos] = callback;
if (pio == PIOD)
callbacksPioD[pos] = callback;
```

**I was expecting, that in detachInterrupt, callbacksPioB will again be set to NULL, but there is no such code!?**

```
void detachInterrupt(uint32_t pin)
{
// Retrieve pin information
Pio *pio = g_APinDescription[pin].pPort;
uint32_t mask = g_APinDescription[pin].ulPin;

// Disable interrupt
pio->PIO_IDR = mask;
}
```

2) Interrupt handler for the port B looks like this:

```
void PIOB_Handler(void) {
uint32_t isr = PIOB->PIO_ISR;
uint8_t leading_zeros;
while((leading_zeros=__CLZ(isr))<32)
{
uint8_t pin=32-leading_zeros-1;
if(callbacksPioB[pin]) callbacksPioB[pin]();
isr=isr&(~(1<

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the behavior with the linked Arduino Due sketch, then inspect WInterrupts.c, especially attachInterrupt, detachInterrupt, and PIOB_Handler. Trace the PIO interrupt status and callback handling while the FAN interrupt is disabled. Done means identifying why the FAN ISR bit and callback remain active and documenting or correcting the behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
arduino, c
Domain
embedded-iot
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.