CanInterface Dispatcher, it depends on MyThread (MyThings lib)

Dependents:   PYRN

Files at this revision

API Documentation at this revision

Comitter:
clemounet
Date:
Thu Apr 02 07:30:22 2015 +0000
Child:
1:b9201bec01bf
Commit message:
My CAN Library it depends on MyThread

Changed in this revision

CANDiagSensor.cpp Show annotated file Show diff for this revision Revisions of this file
CANDiagSensor.h Show annotated file Show diff for this revision Revisions of this file
CANFifoMessage.cpp Show annotated file Show diff for this revision Revisions of this file
CANFifoMessage.h Show annotated file Show diff for this revision Revisions of this file
CANInterface.cpp Show annotated file Show diff for this revision Revisions of this file
CANInterface.h Show annotated file Show diff for this revision Revisions of this file
CANSniffer.cpp Show annotated file Show diff for this revision Revisions of this file
CANSniffer.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CANDiagSensor.cpp	Thu Apr 02 07:30:22 2015 +0000
@@ -0,0 +1,11 @@
+
+
+#include "CANDiagSensor.h"
+
+#define __DEBUG__ 0
+#ifndef __MODULE__
+#define __MODULE__ "CANDiagSensor.cpp"
+#endif
+#include "MyDebug.h"
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CANDiagSensor.h	Thu Apr 02 07:30:22 2015 +0000
@@ -0,0 +1,30 @@
+
+
+#ifndef CAN_DIAG_SENSOR_H
+#define CAN_DIAG_SENSOR_H
+
+#include "MySensor.h"
+#include "CANInterface.h"
+#include "MyCallBack.h"
+
+#if 0
+
+class CANDiagSensor: public MySensor, MyCallBack {
+    CANInterface *can;
+public:
+    CANDiagSensor(CANInterface *can);
+    virtual void InitResultsStatic();
+    virtual void KeepAliveStart();
+    virtual void KeepAliveStop();
+    virtual void KeepAliveSequence();
+    virtual void DiagStart();
+    virtual void DiagStop();
+    virtual void Loop();
+    virtual void StoreLastImpact(void);
+    virtual void DiagSequence();
+    virtual void Event(int ID, void *data);
+};
+
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CANFifoMessage.cpp	Thu Apr 02 07:30:22 2015 +0000
@@ -0,0 +1,44 @@
+#include "CANFifoMessage.h"
+
+CANFifoMessage::CANFifoMessage() {
+    this->head = 0;
+    this->tail = 0;
+}
+uint32_t CANFifoMessage::available() {
+    return (FIFO_SIZE + this->head - this->tail) % FIFO_SIZE;
+}
+
+uint32_t CANFifoMessage::free() {
+    return (FIFO_SIZE - 1 - available());
+}
+
+bool CANFifoMessage::put(CANMessage data){
+    uint32_t next;
+
+    // check if FIFO has room
+    next = (this->head + 1) % FIFO_SIZE;
+    if (next == this->tail) {
+        return false;   // FIFO full
+    }
+
+    this->buffer[this->head] = data;
+    this->head = next;
+
+    return true;
+}
+
+bool CANFifoMessage::get(CANMessage* data) {
+    uint32_t next;
+
+    // check if FIFO has data
+    if (this->head == this->tail) {
+        return false; // FIFO empty
+    }
+
+    next = (this->tail + 1) % FIFO_SIZE;
+
+    *data = this->buffer[this->tail];
+    this->tail = next;
+
+    return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CANFifoMessage.h	Thu Apr 02 07:30:22 2015 +0000
@@ -0,0 +1,20 @@
+#ifndef CAN_FIFO_MESSAGE
+#define CAN_FIFO_MESSAGE
+
+#include "mbed.h"
+#include "CAN.h"
+
+#define FIFO_SIZE   25
+
+class CANFifoMessage {
+    CANMessage buffer[FIFO_SIZE];
+    uint32_t head, tail;
+public:
+    CANFifoMessage();
+    bool put(CANMessage data);// returns 0 on success
+    bool get(CANMessage* data);
+    uint32_t available();
+    uint32_t free();
+};
+
+#endif /* CAN_FIFO_MESSAGE */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CANInterface.cpp	Thu Apr 02 07:30:22 2015 +0000
@@ -0,0 +1,186 @@
+
+
+#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();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CANInterface.h	Thu Apr 02 07:30:22 2015 +0000
@@ -0,0 +1,51 @@
+
+#ifndef CAN_INTERFACE_H
+#define CAN_INTERFACE_H
+
+#include "MyThread.h"
+#include "MyCallBack.h"
+#include "CAN.h"
+#include "CANFifoMessage.h"
+
+#define CAN_ID_PROMISCUOUS_MODE 0xffffffff      
+
+#define CAN_SIMULTANEOUS_CBS    8
+#define CAN_SIMULTANEOUS_MSG    15
+
+class CANInterface: public MyThread {
+protected:
+    typedef struct _idCbEntry{
+        uint32_t id;            // 29b and 11b can ids are supported
+        MyCallBack *cb;
+    } idCbEntry;
+    
+    Mutex idCbTableMutex;
+    Mutex sendMutex;
+    
+    uint8_t nCurrentCbs;           // How much entries we got in our table
+    idCbEntry idCbTable[CAN_SIMULTANEOUS_CBS];     // This mean that we allow at most 8 sensors to receive events simultaneously
+    
+    CAN *bus1;
+    CAN *bus2;
+    
+    bool rxOvf;
+    CANFifoMessage fifoRxMsg;
+    CANMessage msgTx;
+
+public:
+    CANInterface();
+    virtual void Configure(uint8_t ifaceNumber, int speed);
+    virtual void AddCallBackForId(int id, MyCallBack *cb);
+    virtual void DellCallBackForId(int id);
+    virtual void DispatchCANMessage(CANMessage *msg);
+    virtual int  Send(uint8_t ifaceNumber,int id, char *data, uint8_t len);
+    virtual void Main();
+    
+    virtual void RxCbCan1(void);
+    virtual void RxCbCan2(void);
+        
+    virtual CAN *GetCan1() { return bus1; }
+    virtual CAN *GetCan2() { return bus2; }
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CANSniffer.cpp	Thu Apr 02 07:30:22 2015 +0000
@@ -0,0 +1,29 @@
+
+#include "CANSniffer.h"
+#include "CAN.h"
+
+#define __DEBUG__ 5
+#ifndef __MODULE__
+#define __MODULE__ "CANSniffer.cpp"
+#endif
+#include "MyDebug.h"
+
+CANSniffer::CANSniffer(CANInterface *itf){
+    if(itf) {
+        canItf = itf;
+        itf->AddCallBackForId(CAN_ID_PROMISCUOUS_MODE,this);
+    }
+}
+
+void CANSniffer::event(int ID, void *data) {
+    //char buff[23];
+    if(ID == 1) {
+        // Remember we don't own the CANMessage here.
+        CANMessage *msg = (CANMessage*) data; 
+        //sprintf(buff,"CANSniffer [%08x]:",msg->id);
+        //DBG_MEMDUMP((const char*)buff,(const char*)msg->data,msg->len);
+        int id = msg->id;
+        unsigned char *data = msg->data;
+        DBG("Received 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]);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CANSniffer.h	Thu Apr 02 07:30:22 2015 +0000
@@ -0,0 +1,16 @@
+
+#ifndef CAN_SNIFFER_H
+#define CAN_SNIFFER_H
+
+#include "CANInterface.h"
+#include "MyCallBack.h"
+
+class CANSniffer: public MyCallBack {
+protected:
+    CANInterface *canItf;
+public:
+    CANSniffer(CANInterface *itf);
+    virtual void event(int ID, void *data);
+};
+
+#endif // CAN_SNIFFER_H
\ No newline at end of file