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 on Due with pinMode OUTPUT, and switching pinMode #1693

Closed
robinhedwards opened this issue Nov 20, 2013 · 5 comments
Closed

Interrupts on Due with pinMode OUTPUT, and switching pinMode #1693

robinhedwards opened this issue Nov 20, 2013 · 5 comments
Assignees
Labels
Board: Arduino Due Applies only to the Due

Comments

@robinhedwards
Copy link

There are two differences in the behaviour of interrupts on a Due, after comparison to an Uno (well actually a Duemilanove).

First - When I attachInterrupt() to FALLING on a digital pin, and drive the pin as an OUTPUT between HIGH and LOW, I would expect the interrupt to trigger each time the output pin is set low. This happens on the Uno, but NOT on the Due, where the interrupt only seems to fire once.

Test case:

// Interrupt comparison between Uno & Due
// Expected output (obtained on Uno)
// Pin high, count=0
// Pin low, count=1
// Pin high, count=1
// Pin low, count=2
// BUT...
// On due, count remains 1

int pin = 3;    // INT 1 on UNO
volatile int i = 0;

void test() { i++; }

void setup() {            
  Serial.begin(9600);   
  pinMode(pin, OUTPUT);
//  attachInterrupt(1, test, FALLING);    // Uno
  attachInterrupt(pin, test, FALLING);    // Due
}

void loop() {
  digitalWrite(pin, HIGH);
  Serial.print("Pin high, count="); Serial.println(i);
  delay(500);
  digitalWrite(pin, LOW);
  Serial.print("Pin low, count="); Serial.println(i);
  delay(500);
}

The expected behaviour can be obtained on the Due by replacing the digitalWrite() with digitalWriteDirect():

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

Now both Uno and Due count up as expected.

Second - Switching the pinMode() on a Due seems to detach the interrupts set up on the pin. You need to call attachInterrupt() again after changing e.g. from input to output mode. Again this is different behaviour from the Uno, where there is no need to do this.

Test case (replaces loop in first test case):

void loop() {
  static int secs = 3;
  digitalWriteDirect(pin, HIGH);
  Serial.print("Pin high, count=");
  Serial.println(i);
  delay(500);
  digitalWriteDirect(pin, LOW);
  Serial.print("Pin low, count=");
  Serial.println(i);
  delay(500);
  secs--;
  if (secs == 0) {
      pinMode(pin, INPUT);
      pinMode(pin, OUTPUT);
  }

More details on the forum:
http://forum.arduino.cc/index.php?topic=199320.0

Note that this difference in behaviour causes e.g. the PS2KeyboardExt2 library not to work on a Due, since the library relies on either the host or the keyboard being able to send data on the CLOCK & DATA lines. The call to pinMode() causes the interrupt on the CLOCK line to stop triggering.

@3esmit
Copy link

3esmit commented Jun 9, 2015

I've found out that executing pinMode is unattaching interrupts on DUE, maybe digitalWrite does that too.

@3esmit
Copy link

3esmit commented Jun 9, 2015

I used the following code to test it:

void setup()
{
  Serial.begin(9600);
}
void myFunc() {
  Serial.println(3);
}
void loop() {
  byte command;

  if (Serial.available()) {
    command = Serial.read();
    switch(command) {
    case '1':
      attachInterrupt(18, myFunc, CHANGE);
      Serial.println(1);
      break;
    case '2':
      pinMode(18, INPUT_PULLUP);
      Serial.println(2);
      break;
    }
  }
}

@facchinm facchinm assigned facchinm and unassigned cmaglie Jun 10, 2015
@ffissore ffissore modified the milestones: Release 1.6.5, Release 1.6.6 Jun 15, 2015
@ffissore ffissore modified the milestones: Release 1.6.6, 1.6.7 Nov 4, 2015
@ffissore ffissore modified the milestone: Release 1.6.7 Dec 14, 2015
@techpaul
Copy link
Contributor

techpaul commented Feb 1, 2016

Came across this issue on my PS2 keyboard libraries using V1.6.7 and Due board manager 1.6.6. My workaround for the library was put an architecture dependent detach and attach interrupt around the direction change for sending to the keyboard see PS2KeyAdvanced, this is then handled correctly and works seamlessly for me. Tested same library now on Uno/Mega/Due recently.

I expect some differences there are others as in AVR char is signed, SAM (Due) it is UNsigned so beware.

@iotmember
Copy link

Hello
I am using Arduino Due kit. I try to using external interrupt on Due but I met error
Program is crashed at line: attachInterrupt(8, ISR_TX_PIN, CHANGE);
Can you help me?

@agdl
Copy link
Member

agdl commented Feb 8, 2017

This issue was moved to arduino/ArduinoCore-sam#26

@agdl agdl closed this as completed Feb 8, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Board: Arduino Due Applies only to the Due
Projects
None yet
Development

No branches or pull requests

8 participants