InterruptIn Bug?

24 Aug 2016

Hello all,

I think I've found a bug in the implementation of InterruptIn for STM32F411. I wrote a simple encoder class that uses InterruptIn. When I use a single implementation of my class, it works fine. When I use two of them, only the second one that is instantiated works. My guess is that it has to do with the way that InterruptIn enables interrupts in the STM32 hal. I tried looking at the hal code, but wasn't able to figure it out. Can anyone find a bug in the STM32 hal related to this? Am I missing something obvious in my code??? My code is below:

#ifndef ENCODER_H
#define ENCODER_H

#include "mbed.h"

typedef void (*voidfunc)(void);

class Encoder
{
  public:
    Encoder(PinName chA, PinName chB): chanA(chA), chanB(chB), state(0), pulses(0), notifyFunc(0) { enable(); }

    void reset(void) { pulses = 0; }
    int getCount(void) { return(pulses); }
    void setNotifyFunc(voidfunc func) { notifyFunc = func; }
    void enable(void)
    {
      state = (chanB.read() << 1) | (chanA.read());
      chanA.rise(this, &Encoder::p1up);
      chanA.fall(this, &Encoder::p1dn);
      chanB.rise(this, &Encoder::p2up);
      chanB.fall(this, &Encoder::p2dn);
    }
    void disable(void)
    {
      chanA.rise(0);
      chanA.fall(0);
      chanB.rise(0);
      chanB.fall(0);
    }

  private:
    void p1up(void)
    {
      state|=1;
      if(state&2)
        pulses--;
      else
        pulses++;
      if(notifyFunc)
        notifyFunc();
    }

    void p1dn(void)
    {
      state&=~1;
      if(state&2)
        pulses++;
      else
        pulses--;
      if(notifyFunc)
        notifyFunc();
    }

    void p2up(void)
    {
      state|=2;
      if(state&1)
        pulses++;
      else
        pulses--;
      if(notifyFunc)
        notifyFunc();
    }

    void p2dn(void)
    {
      state&=~2;
      if(state&1)
        pulses--;
      else
        pulses++;
      if(notifyFunc)
        notifyFunc();
    }

    InterruptIn chanA;
    InterruptIn chanB;

    int state;
    int pulses;
    voidfunc notifyFunc;
};
  
#endif

Then in my main function, I have:

Encoder enc2(PC_12, PC_11);
Encoder enc1(PC_10, PA_12);

I use the two classes. Whichever encoder I put first, doesn't work. If I switch the order of the above two lines, the other one works...

25 Aug 2016

I just read that you can't have an InterruptIn pin on two pins with same pin number. So PA_12 and PC_12 conflict. Can anyone confirm or deny this? Is this indeed a hardware limitation???

Souce: https://developer.mbed.org/questions/3393/Nucleo-401-Multiple-InterruptIn-Pins

19 Sep 2016

I wrote some code for the F446 and have the same results as you. The most recent declaration of Interrupt In overrides the first. I can get PA12 or PC12 to work but not both. That's really bad...

<edit> I looked in the reference manual for the STM32F446RE and it shows that all GPIO pins of the same numeric offset from PAx to PHx are routed to a multiplexer which only allows one of the pins to generate the interrupt for input "12" in this case.

So it's not a bug but a feature. Sorry!