2 months, 3 weeks ago.

CAN - attach callback for a specific IrqType [in OS 2]

I have an older project - running on mbed OS 2, and it needs [just] one more feature - tracking of CAN communications errors. I know about the GetRxErrorCounter() and GetTxErrorCounter(), but my needs are beyond those.

// Each ISR signature is like this - 
void BusMetrics::CANReceive_ISR(void);


// Implementation 
BusMetrics::BusMetrics(CANPort * arg_can)
{
    can = arg_can;
    // other initialization not shown (bit-rate, etc.)

    can->Attach(this, &BusMetrics::CANReceive_ISR);    // This works, and my handler receives it - only RxIrq (the default)
    
    // I want the other events  ...

    can->Attach(this, &BusMetrics::CANTransmit_ISR, CAN::TxIrq);      // Compile fails with:
    //Error: No instance of overloaded function "CANPort::Attach"  matches the argument list in "BusMetrics.cpp", Line: 127, Col: 11.

    can->Attach( callback(this, &BusMetrics::CANTransmit_ISR), CAN::TxIrq);   // Fails in the same way
    //Error: No instance of overloaded function "CANPort::Attach"  matches the argument list in "BusMetrics.cpp", Line: 127, Col: 11

    // When I get TxIrq working, then I want EwIrq, DoIrq, WuIrq, EpIrq, AlIrq, and BeIrq
    ...
}

// Fragment from CAN.h, which also has information about the "callback( )" pattern.
void attach(T *obj, void (T::*method)(), IrqType type = RxIrq) 
{
...
}

What will fix this?

1 Answer

2 months, 3 weeks ago.

Hello David,

I think you have just a typo in the snippet above: can->attach shall be lower case 'a'. The code below compiles fine for both LPC1768 and NUCLEO-F103RB with Mbed OS 2. However, I did not test it.

#include "mbed.h"

class   BusMetrics
{
    CAN*    _can;
public:
    BusMetrics(CAN* arg_can) : _can(arg_can)
    {
        // other initialization not shown (bit-rate, etc.)

        _can->attach(callback(this, &BusMetrics::CANRx_ISR), CAN::RxIrq);
        _can->attach(callback(this, &BusMetrics::CANTx_ISR), CAN::TxIrq);
        _can->attach(callback(this, &BusMetrics::CANEw_ISR), CAN::EwIrq);
        _can->attach(callback(this, &BusMetrics::CANDo_ISR), CAN::DoIrq);
        _can->attach(callback(this, &BusMetrics::CANWu_ISR), CAN::WuIrq);
        _can->attach(callback(this, &BusMetrics::CANEp_ISR), CAN::EpIrq);
        _can->attach(callback(this, &BusMetrics::CANAl_ISR), CAN::AlIrq);
        _can->attach(callback(this, &BusMetrics::CANBe_ISR), CAN::BeIrq);
        _can->attach(callback(this, &BusMetrics::CANId_ISR), CAN::IdIrq);
    }

    void CANRx_ISR(void) { printf("'CANRx_ISR()' called\r\n"); }
    void CANTx_ISR(void) { printf("'CANTx_ISR()' called\r\n"); }
    void CANEw_ISR(void) { printf("'CANEw_ISR()' called\r\n"); }
    void CANDo_ISR(void) { printf("'CANDo_ISR()' called\r\n"); }
    void CANWu_ISR(void) { printf("'CANWu_ISR()' called\r\n"); }
    void CANEp_ISR(void) { printf("'CANEp_ISR()' called\r\n"); }
    void CANAl_ISR(void) { printf("'CANAl_ISR()' called\r\n"); }
    void CANBe_ISR(void) { printf("'CANBe_ISR()' called\r\n"); }
    void CANId_ISR(void) { printf("'CANId_ISR()' called\r\n"); }
};

CAN         can(p30, p29);      // LPC1768
//CAN         can(PB_8, PB_9);    // NUCLEO-F103RB
DigitalOut  led(LED1);
BusMetrics  busMetrics(&can);   // Creates an instance of BusMestrics (attaches ISRs)

int main(void)
{
    while (1) {
        led = !led;
        wait(1);
    }
}

Accepted Answer

One of those moments - when I saw your reference to a lower-case 'a', I thought - I think my code-base has one more layer in the middle, between my code sample and the CAN api - and I was right (and it had only a single 'A'ttach method...

Thanks for the quick response - I can stop banging my head on the glass now.

I think I need to inherit CAN in my intermediate shim, and then I can call on-thru to the various 'a'ttach methods of interest.

posted by David Smart 19 Sep 2019