Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interrupts problem on Arduino Due #13

Open
agdl opened this issue Feb 8, 2017 · 0 comments
Open

Interrupts problem on Arduino Due #13

agdl opened this issue Feb 8, 2017 · 0 comments

Comments

@agdl
Copy link
Member

agdl commented Feb 8, 2017

From @mvladic on January 22, 2017 0:11

Here is relatively small sketch that I extracted from my much larger project.

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;
}
  1. 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<<pin));
  }
}

So, depending of PIO_ISR, multiple callbacks (given with attachInterrupt) could be called during single port B interrupt handler.

And indeed, in my case, after first 5 seconds, every time when ADC interrupt has been triggered, both ADC bit and FAN bit of PIO_ISR are set to 1 (I repeat, at this point FAN interrupts should be disabled).

Consequently, both (FAN and ADC) interrupt handlers that are set with attachIntterupt are called.

If detachInterrupt had reset callback to NULL (see point 1) FAN interrupt handler wouldn't be called. But still, the question is why ISR bit for the FAN pin is marked when FAN interrupts should be disabled?

Copied from original issue: arduino/Arduino#5897

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant