Interrupt on WKP with class method as an ISR

I originally posted this in the troubleshooting section a few weeks ago and never got a response- the more I think about it, I think that I’ve either made a very simple mistake, or stumbled on some sort of firmware issue, so I figured I’d try posting it here. Any help would be greatly appreciated.

I’m trying to attach an interrupt to the WKP/A7 pin so that I can put a Photon into a deep sleep after being idle for a few minutes, but can have it function normally when its awake.

I’m trying to use a library that I wrote, and I’ve included the ISR as a method in the library (it sets a pending bit to true for the service loop to handle), but I get the dreaded blinky oragne light as soon as the attachInterrupt() function is called. I put together a simplified version of what I’m trying to do, and I still run into the same issue:

WKP_Test.ino:

#include "ints.h"
#include "application.h"

//ints::Ints intTest(D2);     // I work if I'm uncommented
ints::Ints intTest(WKP);

void setup() {
  Serial.begin(9600);
  intTest.begin();
}

void loop() {
  if(intTest.intPending){
    Serial.println("Interrupted!");
    intTest.intPending = false;
  }
  delay(100);
}

ints.cpp:


ints::Ints::Ints(int pin){
    intPin = pin;
}

void ints::Ints::handleInt(void){
    intPending = true;
}

void ints::Ints::begin(void){
    Serial.println("I'll get printed");
    delay(500);
    pinMode(intPin, INPUT_PULLDOWN);
    Serial.println("I will too.");
    delay(500);
    attachInterrupt(intPin, &Ints::handleInt, this, RISING);
    Serial.println("I'll never be seen by anyone if intPin is WKP :(");
    delay(500);
}

void ints::Ints::resetInt(void){
    intPending = false;
}

ints.h

#include "application.h"

namespace ints {
    class Ints {
        public:
            int intPin;
            bool intPending;
        
            Ints(int pin);
            void begin(void);
            void handleInt(void);
            void resetInt(void);
    };
}

Since the above works when using pin D2, but not WKP, I’m really stumped. Any ideas?

HI @pcfens

There was a bug fixed in this area in 0.4.8 so it makes a difference which version of the system firmware you are running.

Here is the changelog entry: https://github.com/spark/firmware/issues/443#issuecomment-114389744

You can find out which version you are running by hooking your Photon to a USB port and a terminal emulator and with the device in listening mode, you type “v” to get the version info.

So how are you compiling? If you are using Particle DEV, the Atom-based editor, it does not automatically update your Photon. If you are using the web IDE, then you get to choose which version to compile against (but your device is never automatically downgraded, only upgraded). It can make a big difference.

Can you make sure you have v0.4.8 system firmware and try that?

2 Likes

I have tried 0.4.8-rc6 and I still see SOS on A6, A7 and TX.

But I tried from Build, so app FW is still 0.4.7.


Edit: Now I’ve built application firmware for 0.4.8-rc6 too and now it works for A7 (at least :wink: - not tried the others). (Meaning no SOS anymore, but the interrupt doesn’t seem to fire, now)

Sorry for that, no it still doesn’t work!
So this is something for @mdma then - I guess.

For further investigation, what do A6, A7 and TX have in common that makes all three SOS with this code?

Hi @bko - Thanks for such a quick response.

I’m running 0.4.7 since I’ve been flashing from the web (on a Linux box, so no atom based dev, but I haven’t looked hard for it yet either, if there’s something in development I’m happy to run an alpha/beta/nightly)

Though it sounds like @ScruffR has beat me to it, I’m happy to test with v0.4.8 if you can point me to the flashing instructions and files. The rc releases all list the electron as the target - am I correct in assuming they’re different firmwares?

Thanks again.


I found how to build firmwares and can probably get it all figured out if needed now.

Edit:

I am going to take back what I said about it being fixed in 0.4.8, that was due to a search showing me too little detail. It looks like it was supposed to have been fixed last Summer in 0.4.3.

Can you try the test code in that issue? This will avoid any C++ vs C funny business.

volatile bool interrupt = false;
static int INTERRUPT_PIN = WKP;
static int LED = D0;

void setup() {
  pinMode(INTERRUPT_PIN,INPUT_PULLUP);
  attachInterrupt(INTERRUPT_PIN,ISR,FALLING);
}

void loop() {
  if (interrupt) {
    blinkLED();
    interrupt = false;
  }
}

void ISR() {
  interrupt = true;
}

void blinkLED() {
  pinMode(LED,OUTPUT);
  digitalWrite(LED, HIGH);
  delay(50);
  digitalWrite(LED, LOW);
  delay(50);
}

There is only one repository for all platforms, hence you have to state the platform you want to build against.
But in order to test these, you need a local toolchain installed and then you can run this build command from the modules folder

make PARTICLE_DEVELOP=1 APP=<yourapp> PLATFORM=photon

where the sources for your app have to be located in .../firmware/user/applications/<yourapp>/

I'm not sure if this was directed to me or not, but the code example flashed and ran without any issues via the web IDE.

1 Like

I’ve confirmed the same problem on 0.4.8-rc.6 as well. Including that it works fine when the ISR isn’t a class method.

Thanks for the help in getting started compiling at the command line.

@pcfens, I have to ask. Are you trying to attach an interrupt to WKP so you can wake the processor from deep sleep? If so, this is not necessary since a RISING edge on WKP when in (the STM32’s) standby mode (deep sleep) will cause the processor to come out of deep sleep and reset.

The docs show one mode for deep sleep: System.sleep(SLEEP_MODE_DEEP, long seconds) which will wake the processor after N seconds or a RISING edge on WKP is applied. There is also the undocumented System.sleep(SLEEP_MODE_DEEP) which will deep sleep forever until a RISING edge on the WKP pin is applied.

I am using this mode in a battery operated photon device. Once the photon completes its task, it goes to deep sleep. I have a physical button used for menu selection connected to WKP. On first press, it wakes the photon and resets. After that, I set the WKP as a regular GPIO input pin for button input (I use the clickButton library). Works very well!

There’s a fix for this which will be released in 0.4.9

1 Like

@mdma, which branch could we test this with, as in current develop it’s not fixed.

@peekay123, no OP wants to use WKP after wake as normal interrupt pin in his running application.

@ScruffR, I asked because this is really not clear.

1 Like

Sorry for the confusion @peekay123-
I’m working on a lightning sensor interface (for the AS3935), that I’d like to put to sleep after a few minutes of inactivity, but wake up when the interrupt pin goes high (because something was detected). However during a storm, I’d rather not wait for the wakeup/wifi handshake.

Luckily, the pin stays high until a particular register is read, so I can tell on wakeup if there’s a pending event to handle or not, so in this case I’d like for the wakeup pin to also handle interrupts, and digital reads.

Thanks all for the help on this - I’ll keep an eye out for 0.4.9

1 Like

@pcfens, I understand now:

  • Photon in deep sleep, AS3935 sees lightning and puts rising edge on WKP, waking the Photon and causing a reset.
  • Photon is awake and uses WKP interrupts to signal lightning data available which Photon handles
  • Photon is bored, not getting any lightning activity for a while, goes back to deep sleep.

Super! :wink:

1 Like