CanInterface Dispatcher, it depends on MyThread (MyThings lib)

Dependents:   PYRN

CANInterface.cpp

Committer:
clemounet
Date:
2015-04-14
Revision:
1:b9201bec01bf
Parent:
0:3ca0a6d1e2a1

File content as of revision 1:b9201bec01bf:



#include "CANInterface.h"

#define __DEBUG__ 5
#ifndef __MODULE__
#define __MODULE__ "CANInterface.cpp"
#endif
#include "MyDebug.h"

#include "CANInterface.h"

#define CAN_THREAD_STACK_SIZE   768

static CAN can1(p9, p10);
static CAN can2(p30, p29);

DigitalOut led3(LED3);
DigitalOut led4(LED4);

/*
void cbRx1(void) {
    CANMessage m;
    can1.read(m);
    if(led3 == 1)
        led3 = 0;
    else
        led3 = 1;
}

void cbRx2(void) {
    CANMessage m;
    can2.read(m);
    if(led4 == 1)
        led4 = 0;
    else
        led4 = 1;
}
*/

CANInterface::CANInterface():
    MyThread("CANInterface",CAN_THREAD_STACK_SIZE) {
    nCurrentCbs = 0;
    // Setup the physical interfaces
    bus1 = &can1;
    bus1->reset();
    //bus1->attach(&cbRx1);
    bus1->attach(this,&CANInterface::RxCbCan1,CAN::RxIrq);
    bus2 = &can2;
    bus2->reset();
    //bus2->attach(&cbRx2); //,CAN::RxIrq);
    bus2->attach(this,&CANInterface::RxCbCan2,CAN::RxIrq);
    led3 = 1;
    led4 = 1;
}

void CANInterface::Configure(uint8_t ifaceNumber, int speed) {
    DBG("Setting itf(%d) to %d", ifaceNumber,speed);
    CAN* b = (ifaceNumber == 1)? bus1:bus2;
    b->frequency(speed);
}

void CANInterface::AddCallBackForId(int id, MyCallBack *cb) {
    // TODO: Protect this with a mutex
    if(idCbTableMutex.lock(1000) != osEventTimeout) {
        if(nCurrentCbs == CAN_SIMULTANEOUS_CBS) {
            WARN("Sorry Dude, this is not gonna work, too much callback are recorded");
        } else {
            DBG("Adding Entry [%08x] - %p",id,cb);
            idCbEntry *newEntry = idCbTable+nCurrentCbs;
            newEntry->id = id;
            newEntry->cb = cb;
            nCurrentCbs++;
        }
        idCbTableMutex.unlock();
    } else
        ERR("Could not capture the cbtable mutex!");
}
    
void CANInterface::DellCallBackForId(int id) {
    // TODO: Protect this with a mutex
    if(idCbTableMutex.lock(1000) != osEventTimeout) {
        if(nCurrentCbs) {
            for(int i = 0; i<nCurrentCbs; i++){
                if(idCbTable[i].id == id) {
                    DBG("Removing Entry [%08x]",id);
                    memcpy(idCbTable+i,idCbTable+(i+1),nCurrentCbs-(i+1));
                    nCurrentCbs--;
                    break;
                }
            }
        }
        idCbTableMutex.unlock();
    } else
        ERR("Could not capture the cbtable mutex!");
}

void CANInterface::DispatchCANMessage(CANMessage *msg) {
    for(int i = 0; i<nCurrentCbs; i++){
        // Check if the entry is promiscuous
        if(idCbTable[i].id == CAN_ID_PROMISCUOUS_MODE) {
            idCbTable[i].cb->event(1,(void*) msg);
        } else if(idCbTable[i].id == msg->id) {
            // Becarefull with the pointer passed (/!\ make a cpy in the cb)
            idCbTable[i].cb->event(1,(void*) msg);
            break;    
        }
    }
}

int CANInterface::Send(uint8_t ifaceNumber,int id, char *data, uint8_t len) {
    if(sendMutex.lock(1000) != osEventTimeout) {
        DBG("Sending CAN [%08x]-%02X %02X %02X %02X %02X %02X %02X %02X",id,data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]);
        int ret = 0;
        // No Padding but could be implemented here or in the upper layers
        msgTx.id = id;
        memcpy(msgTx.data,data,len);
        // Need to check who is responsible for CANMessage memory management
        if(ifaceNumber == 1)
            ret = bus1->write(msgTx);
        else
            ret = bus2->write(msgTx);
        sendMutex.unlock();
        return ret;
    } else
        ERR("Could not capture the sending mutex!");

    return 0;
}

void CANInterface::Main(void) {
    int i = 0;
    bool gotMsg = false;
    // TODO: Need to be sure that the irq is not firing multiple time before reading
    while(running){
        if((i%100) == 1)
            DBG("CanInterface Running");
        if((bus1->rderror() != 0) || (bus2->rderror() != 0)) {
            ERR("Got Hardware rx errors ovf, need reset?");
           // bus1->reset();
           // bus2->reset();
        }
        if( rxOvf ) {
            ERR("Got Software rx errors ovf, need to extend FIFO!!");
            rxOvf = false;
        }
        CANMessage msg;
        // == This section need to be atomic ==
        NVIC_DisableIRQ(CAN_IRQn);
        gotMsg = fifoRxMsg.get(&msg);
        NVIC_EnableIRQ(CAN_IRQn);
        // ====================================
        if(gotMsg)
            DispatchCANMessage(&msg);
        Thread::wait(100);
        i++;
    }
}

void CANInterface::RxCbCan1(void) {
    __disable_irq();
    CANMessage m;
    if(bus1->read(m)) {
        rxOvf = !fifoRxMsg.put(m);
        if(led3 == 1){
            led3 = 0;
        } else {
            led3 = 1;
        }
    }
    __enable_irq();
}

void CANInterface::RxCbCan2(void) {
    __disable_irq();
    CANMessage m;
    if(bus2->read(m)) {
        rxOvf = !fifoRxMsg.put(m);
        if(led4 == 1) {
            led4 = 0;
        } else {
            led4 = 1;
        }
    }
    __enable_irq();
}