CanInterface Dispatcher, it depends on MyThread (MyThings lib)
Revision 0:3ca0a6d1e2a1, committed 2015-04-02
- 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
--- /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