C++ ISR using class method?

2019-07-15 06:41发布

Is it possible to use a class method as the Interrupt Service Routine?

I have an ISR written and working in C using a function:

    static void interrupt far ISR(...) {}

I've tried in C++ to create a method (prototype):

    void interrupt far ISR(...);

Then the implementation:

    #pragma interrupt
    void interrupt far MyClass::ISR(...) {
    ...
    }

But I get all sorts of errors when I try to use this with 'setvect':

    setvect(muint16Vector, &ISR);

I'm trying to write a class to service a serial port, the ISR would service the Rx of data from the port. The ISR would then use instance specific members.

I have 3 serial ports, so I would like to create 3 instances of the class.

4条回答
爷、活的狠高调
2楼-- · 2019-07-15 06:54

The real answer is 'No' it is not possible in C++ to use a method as the ISR handler directly.

You have to resort to standard C functions and then with glue in the ISR function, reference the required object.

It ends up as quite a messy solution.

查看更多
趁早两清
3楼-- · 2019-07-15 07:06

There's an old Dr. Dobbs article that covers this well, along with a good explanation of the issues involved: Implementing Interrupt Service Routines in C++

查看更多
可以哭但决不认输i
4楼-- · 2019-07-15 07:14

You just need to create a global variable which is the instance to invoke upon:

class Handler {
  void ISR(...) {}
};

static unique_ptr<Handler> g_handler;

#pragma interrupt
extern "C" static void interrupt far ISR(...) {
  if (g_handler)
    g_handler->ISR(...);
}

g_handler = std::make_unique<Handler>();
setvect(muint16Vector, &ISR);
查看更多
姐就是有狂的资本
5楼-- · 2019-07-15 07:18

With the information given in the comments, this is a possible solution:

class SerialPort
{
public:
    // Unrelated functions...

    void isr();  // The serial interrupt handler

    // Other unrelated stuff...
};

std::array<SerialPort, 3> serial_ports;  // Or SerialPort serial_ports[3];

static void serial_isr(int const port_index)
{
    // Common code for all serial ports that for some reason
    // can't be in the class...

    serial_ports[port_index].isr();  // Call actual ISR
}

extern "C" void interrupt serial_isr_1()
{
    // Special code for only this serial port...

    serial_isr(0);
}

extern "C" void interrupt serial_isr_2()
{
    // Special code for only this serial port...

    serial_isr(1);
}

extern "C" void interrupt serial_isr_3()
{
    // Special code for only this serial port...

    serial_isr(2);
}
查看更多
登录 后发表回答