Page 1 of 1

Interrupts call not working

Posted: Mon Mar 07, 2022 4:01 pm
by vas_
Hello all,

Could anyone explain me what's wrong with this code in a C++ library:

.h file

Code: Select all

class PSM
{
public:
    PSM(uint32_t sensePin, uint32_t mode = RISING);
    
    static void onInterrupt();
    
    unsigned int cps();
    
private:
	void calculateSkip();
    
	volatile unsigned int _a;
};
.cpp file

Code: Select all

static PSM * _thePSM;

PSM::PSM(uint32_t sensePin, uint32_t mode)
{
    _thePSM = this;

    pinMode(sensePin, INPUT_PULLUP);

    attachInterrupt(digitalPinToInterrupt(sensePin), onInterrupt, mode);
}

void PSM::onInterrupt(void)
{    
    _thePSM->calculateSkip();
}

void PSM::calculateSkip(void)
{
    PSM::_a++;
}

unsigned int PSM::cps()
{
    return PSM::_a
}
The point is obviously to count impulses on a sensePin.

This code works on AVR, but doesn't work on STM32F411.

attachInterrupt for the same pin and mode works if placed directly in .ino.

What could be wrong with the code? I'm not a C++ pro, maybe it's something obvious.

Re: Interrupts call not working

Posted: Mon Mar 07, 2022 8:12 pm
by fpiSTM

Code: Select all

static PSM * _thePSM;
You declare it as as pointer ?

Re: Interrupts call not working

Posted: Mon Mar 07, 2022 8:36 pm
by vas_
Yes, it's a pointer.

I tried to rewrite it the following way but the static method still isn't called

Code: Select all

extern "C" {
void _onInterrupt(void)
{    
    digitalWrite(PC13, LOW);
    //_thePSM->calculateSkip();
}
}

PSM::PSM(uint32_t sensePin, uint32_t mode)
{
    _thePSM = this;

    pinMode(sensePin, INPUT_PULLUP);

    attachInterrupt(digitalPinToInterrupt(sensePin), _onInterrupt, mode);
}

Re: Interrupts call not working

Posted: Tue Mar 08, 2022 1:10 am
by ag123
you need

Code: Select all

static PSM g_PSM(pin, mode);
you can omit 'static' if this is a global variable after all.

Re: Interrupts call not working

Posted: Tue Mar 08, 2022 4:07 am
by vas_
This will effectively make the class static, right? So there will be only one instance possible.

Re: Interrupts call not working

Posted: Tue Mar 08, 2022 6:40 am
by vas_
UPDATE: The original piece of code works in PlatformIO. Looks like Arduino IDE is a problem here.

Re: Interrupts call not working

Posted: Wed Apr 06, 2022 4:13 pm
by davetcc
EDIT - I've gone in a lot more depth now, and evaluated all the libraries that are even potentially included, even if not used. I found that the major difference between the two is the inclusion of stm32duino/STM32Duino FreeRTOS. As soon as I remove this dependency it starts working. I assume it is the overriding of the new operator that is not working because this particular test sketch did not initialize free rtos, even though it was on the build path.

----

I've been trying to track down a very strange issue in attachInterrupt, so strange that I didn't even want to post it until I could reliably recreate it. It seems that in some conditions attachInterrupt does not register and it seems to matter that other classes are present in the sketch. It seems very localized to the build environment. I am also a platformIO user, and have one project where this is a problem, one where it is not.

Problem is, I cannot fully isolate it. I post the code below as the closest I have got to isolating, but I have to say, it does not reliably recreate the issue, it may be there is a particular configuration of compiler / settings that creates this problem. But I can't understand how more people would not have seen this?

Unless you think there's some benefit in investigating further I was going to delete the faulty project and configuration and just start over in the working project (and hope it doesn't come back).

Code: Select all

/**
 * My environment is platformIO (CLion IDE), I've tried this on various versions of the Stm32Duino platform back to 
 * about a year ago. In one project it reliably fails, in the other it works perfectly.
 * 
 * Unfortunately, I cannot run the sketch in Arduino as I'd have to add the board I'm using to the boards file there.
 * I know the board is working properly when the marked line below is commented out.
 *
 */

#include <Arduino.h>

// First we create an interface that we will use later - to create a virtual table.
class MyAbstraction {
public:
    virtual void pinDirection(uint8_t pin, uint8_t mode)=0;
};

// Then we create the implementation that has the pinDirection method implementation.
class MyAbstractionImpl : public MyAbstraction {
public:
    void pinDirection(uint8_t pin, uint8_t mode) override {
        pinMode(pin, mode);
    }
};

volatile int counter;

void interruptCallback() {
    // in the interrupt we just increment the counter
    counter++;
}

void setup() {
    // commenting out this line makes the sketch work in the environment that fails.
    auto* digitalIo = new MyAbstractionImpl();
    Serial.begin(115200);

    pinMode(PC8, INPUT_PULLUP);

    // here we register the interrupt
    ::attachInterrupt(digitalPinToInterrupt(PC8), interruptCallback, CHANGE);
}

void loop() {
    // we just print out the contents of the counter every second.
    Serial.print("Counter is ");
    Serial.println(counter);
    delay(1000);
}