Clément BENOIT / CAN

Dependents:   PYRN

Committer:
clemounet
Date:
Tue Apr 14 13:26:18 2015 +0000
Revision:
1:b9201bec01bf
Parent:
0:3ca0a6d1e2a1
.up

Who changed what in which revision?

UserRevisionLine numberNew contents of line
clemounet 0:3ca0a6d1e2a1 1
clemounet 0:3ca0a6d1e2a1 2
clemounet 0:3ca0a6d1e2a1 3 #include "CANInterface.h"
clemounet 0:3ca0a6d1e2a1 4
clemounet 0:3ca0a6d1e2a1 5 #define __DEBUG__ 5
clemounet 0:3ca0a6d1e2a1 6 #ifndef __MODULE__
clemounet 0:3ca0a6d1e2a1 7 #define __MODULE__ "CANInterface.cpp"
clemounet 0:3ca0a6d1e2a1 8 #endif
clemounet 0:3ca0a6d1e2a1 9 #include "MyDebug.h"
clemounet 0:3ca0a6d1e2a1 10
clemounet 0:3ca0a6d1e2a1 11 #include "CANInterface.h"
clemounet 0:3ca0a6d1e2a1 12
clemounet 0:3ca0a6d1e2a1 13 #define CAN_THREAD_STACK_SIZE 768
clemounet 0:3ca0a6d1e2a1 14
clemounet 0:3ca0a6d1e2a1 15 static CAN can1(p9, p10);
clemounet 0:3ca0a6d1e2a1 16 static CAN can2(p30, p29);
clemounet 0:3ca0a6d1e2a1 17
clemounet 0:3ca0a6d1e2a1 18 DigitalOut led3(LED3);
clemounet 0:3ca0a6d1e2a1 19 DigitalOut led4(LED4);
clemounet 0:3ca0a6d1e2a1 20
clemounet 0:3ca0a6d1e2a1 21 /*
clemounet 0:3ca0a6d1e2a1 22 void cbRx1(void) {
clemounet 0:3ca0a6d1e2a1 23 CANMessage m;
clemounet 0:3ca0a6d1e2a1 24 can1.read(m);
clemounet 0:3ca0a6d1e2a1 25 if(led3 == 1)
clemounet 0:3ca0a6d1e2a1 26 led3 = 0;
clemounet 0:3ca0a6d1e2a1 27 else
clemounet 0:3ca0a6d1e2a1 28 led3 = 1;
clemounet 0:3ca0a6d1e2a1 29 }
clemounet 0:3ca0a6d1e2a1 30
clemounet 0:3ca0a6d1e2a1 31 void cbRx2(void) {
clemounet 0:3ca0a6d1e2a1 32 CANMessage m;
clemounet 0:3ca0a6d1e2a1 33 can2.read(m);
clemounet 0:3ca0a6d1e2a1 34 if(led4 == 1)
clemounet 0:3ca0a6d1e2a1 35 led4 = 0;
clemounet 0:3ca0a6d1e2a1 36 else
clemounet 0:3ca0a6d1e2a1 37 led4 = 1;
clemounet 0:3ca0a6d1e2a1 38 }
clemounet 0:3ca0a6d1e2a1 39 */
clemounet 0:3ca0a6d1e2a1 40
clemounet 0:3ca0a6d1e2a1 41 CANInterface::CANInterface():
clemounet 0:3ca0a6d1e2a1 42 MyThread("CANInterface",CAN_THREAD_STACK_SIZE) {
clemounet 0:3ca0a6d1e2a1 43 nCurrentCbs = 0;
clemounet 0:3ca0a6d1e2a1 44 // Setup the physical interfaces
clemounet 0:3ca0a6d1e2a1 45 bus1 = &can1;
clemounet 0:3ca0a6d1e2a1 46 bus1->reset();
clemounet 0:3ca0a6d1e2a1 47 //bus1->attach(&cbRx1);
clemounet 0:3ca0a6d1e2a1 48 bus1->attach(this,&CANInterface::RxCbCan1,CAN::RxIrq);
clemounet 0:3ca0a6d1e2a1 49 bus2 = &can2;
clemounet 0:3ca0a6d1e2a1 50 bus2->reset();
clemounet 0:3ca0a6d1e2a1 51 //bus2->attach(&cbRx2); //,CAN::RxIrq);
clemounet 0:3ca0a6d1e2a1 52 bus2->attach(this,&CANInterface::RxCbCan2,CAN::RxIrq);
clemounet 0:3ca0a6d1e2a1 53 led3 = 1;
clemounet 0:3ca0a6d1e2a1 54 led4 = 1;
clemounet 0:3ca0a6d1e2a1 55 }
clemounet 0:3ca0a6d1e2a1 56
clemounet 0:3ca0a6d1e2a1 57 void CANInterface::Configure(uint8_t ifaceNumber, int speed) {
clemounet 0:3ca0a6d1e2a1 58 DBG("Setting itf(%d) to %d", ifaceNumber,speed);
clemounet 0:3ca0a6d1e2a1 59 CAN* b = (ifaceNumber == 1)? bus1:bus2;
clemounet 0:3ca0a6d1e2a1 60 b->frequency(speed);
clemounet 0:3ca0a6d1e2a1 61 }
clemounet 0:3ca0a6d1e2a1 62
clemounet 0:3ca0a6d1e2a1 63 void CANInterface::AddCallBackForId(int id, MyCallBack *cb) {
clemounet 0:3ca0a6d1e2a1 64 // TODO: Protect this with a mutex
clemounet 0:3ca0a6d1e2a1 65 if(idCbTableMutex.lock(1000) != osEventTimeout) {
clemounet 0:3ca0a6d1e2a1 66 if(nCurrentCbs == CAN_SIMULTANEOUS_CBS) {
clemounet 0:3ca0a6d1e2a1 67 WARN("Sorry Dude, this is not gonna work, too much callback are recorded");
clemounet 0:3ca0a6d1e2a1 68 } else {
clemounet 0:3ca0a6d1e2a1 69 DBG("Adding Entry [%08x] - %p",id,cb);
clemounet 0:3ca0a6d1e2a1 70 idCbEntry *newEntry = idCbTable+nCurrentCbs;
clemounet 0:3ca0a6d1e2a1 71 newEntry->id = id;
clemounet 0:3ca0a6d1e2a1 72 newEntry->cb = cb;
clemounet 0:3ca0a6d1e2a1 73 nCurrentCbs++;
clemounet 0:3ca0a6d1e2a1 74 }
clemounet 0:3ca0a6d1e2a1 75 idCbTableMutex.unlock();
clemounet 0:3ca0a6d1e2a1 76 } else
clemounet 0:3ca0a6d1e2a1 77 ERR("Could not capture the cbtable mutex!");
clemounet 0:3ca0a6d1e2a1 78 }
clemounet 0:3ca0a6d1e2a1 79
clemounet 0:3ca0a6d1e2a1 80 void CANInterface::DellCallBackForId(int id) {
clemounet 0:3ca0a6d1e2a1 81 // TODO: Protect this with a mutex
clemounet 0:3ca0a6d1e2a1 82 if(idCbTableMutex.lock(1000) != osEventTimeout) {
clemounet 0:3ca0a6d1e2a1 83 if(nCurrentCbs) {
clemounet 0:3ca0a6d1e2a1 84 for(int i = 0; i<nCurrentCbs; i++){
clemounet 0:3ca0a6d1e2a1 85 if(idCbTable[i].id == id) {
clemounet 0:3ca0a6d1e2a1 86 DBG("Removing Entry [%08x]",id);
clemounet 0:3ca0a6d1e2a1 87 memcpy(idCbTable+i,idCbTable+(i+1),nCurrentCbs-(i+1));
clemounet 0:3ca0a6d1e2a1 88 nCurrentCbs--;
clemounet 0:3ca0a6d1e2a1 89 break;
clemounet 0:3ca0a6d1e2a1 90 }
clemounet 0:3ca0a6d1e2a1 91 }
clemounet 0:3ca0a6d1e2a1 92 }
clemounet 0:3ca0a6d1e2a1 93 idCbTableMutex.unlock();
clemounet 0:3ca0a6d1e2a1 94 } else
clemounet 0:3ca0a6d1e2a1 95 ERR("Could not capture the cbtable mutex!");
clemounet 0:3ca0a6d1e2a1 96 }
clemounet 0:3ca0a6d1e2a1 97
clemounet 0:3ca0a6d1e2a1 98 void CANInterface::DispatchCANMessage(CANMessage *msg) {
clemounet 0:3ca0a6d1e2a1 99 for(int i = 0; i<nCurrentCbs; i++){
clemounet 0:3ca0a6d1e2a1 100 // Check if the entry is promiscuous
clemounet 0:3ca0a6d1e2a1 101 if(idCbTable[i].id == CAN_ID_PROMISCUOUS_MODE) {
clemounet 0:3ca0a6d1e2a1 102 idCbTable[i].cb->event(1,(void*) msg);
clemounet 0:3ca0a6d1e2a1 103 } else if(idCbTable[i].id == msg->id) {
clemounet 0:3ca0a6d1e2a1 104 // Becarefull with the pointer passed (/!\ make a cpy in the cb)
clemounet 0:3ca0a6d1e2a1 105 idCbTable[i].cb->event(1,(void*) msg);
clemounet 0:3ca0a6d1e2a1 106 break;
clemounet 0:3ca0a6d1e2a1 107 }
clemounet 0:3ca0a6d1e2a1 108 }
clemounet 0:3ca0a6d1e2a1 109 }
clemounet 0:3ca0a6d1e2a1 110
clemounet 0:3ca0a6d1e2a1 111 int CANInterface::Send(uint8_t ifaceNumber,int id, char *data, uint8_t len) {
clemounet 0:3ca0a6d1e2a1 112 if(sendMutex.lock(1000) != osEventTimeout) {
clemounet 0:3ca0a6d1e2a1 113 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]);
clemounet 0:3ca0a6d1e2a1 114 int ret = 0;
clemounet 0:3ca0a6d1e2a1 115 // No Padding but could be implemented here or in the upper layers
clemounet 0:3ca0a6d1e2a1 116 msgTx.id = id;
clemounet 0:3ca0a6d1e2a1 117 memcpy(msgTx.data,data,len);
clemounet 0:3ca0a6d1e2a1 118 // Need to check who is responsible for CANMessage memory management
clemounet 0:3ca0a6d1e2a1 119 if(ifaceNumber == 1)
clemounet 0:3ca0a6d1e2a1 120 ret = bus1->write(msgTx);
clemounet 0:3ca0a6d1e2a1 121 else
clemounet 0:3ca0a6d1e2a1 122 ret = bus2->write(msgTx);
clemounet 0:3ca0a6d1e2a1 123 sendMutex.unlock();
clemounet 0:3ca0a6d1e2a1 124 return ret;
clemounet 0:3ca0a6d1e2a1 125 } else
clemounet 0:3ca0a6d1e2a1 126 ERR("Could not capture the sending mutex!");
clemounet 0:3ca0a6d1e2a1 127
clemounet 0:3ca0a6d1e2a1 128 return 0;
clemounet 0:3ca0a6d1e2a1 129 }
clemounet 0:3ca0a6d1e2a1 130
clemounet 0:3ca0a6d1e2a1 131 void CANInterface::Main(void) {
clemounet 0:3ca0a6d1e2a1 132 int i = 0;
clemounet 0:3ca0a6d1e2a1 133 bool gotMsg = false;
clemounet 0:3ca0a6d1e2a1 134 // TODO: Need to be sure that the irq is not firing multiple time before reading
clemounet 0:3ca0a6d1e2a1 135 while(running){
clemounet 0:3ca0a6d1e2a1 136 if((i%100) == 1)
clemounet 0:3ca0a6d1e2a1 137 DBG("CanInterface Running");
clemounet 0:3ca0a6d1e2a1 138 if((bus1->rderror() != 0) || (bus2->rderror() != 0)) {
clemounet 0:3ca0a6d1e2a1 139 ERR("Got Hardware rx errors ovf, need reset?");
clemounet 1:b9201bec01bf 140 // bus1->reset();
clemounet 1:b9201bec01bf 141 // bus2->reset();
clemounet 0:3ca0a6d1e2a1 142 }
clemounet 0:3ca0a6d1e2a1 143 if( rxOvf ) {
clemounet 0:3ca0a6d1e2a1 144 ERR("Got Software rx errors ovf, need to extend FIFO!!");
clemounet 0:3ca0a6d1e2a1 145 rxOvf = false;
clemounet 0:3ca0a6d1e2a1 146 }
clemounet 0:3ca0a6d1e2a1 147 CANMessage msg;
clemounet 0:3ca0a6d1e2a1 148 // == This section need to be atomic ==
clemounet 0:3ca0a6d1e2a1 149 NVIC_DisableIRQ(CAN_IRQn);
clemounet 0:3ca0a6d1e2a1 150 gotMsg = fifoRxMsg.get(&msg);
clemounet 0:3ca0a6d1e2a1 151 NVIC_EnableIRQ(CAN_IRQn);
clemounet 0:3ca0a6d1e2a1 152 // ====================================
clemounet 0:3ca0a6d1e2a1 153 if(gotMsg)
clemounet 0:3ca0a6d1e2a1 154 DispatchCANMessage(&msg);
clemounet 0:3ca0a6d1e2a1 155 Thread::wait(100);
clemounet 0:3ca0a6d1e2a1 156 i++;
clemounet 0:3ca0a6d1e2a1 157 }
clemounet 0:3ca0a6d1e2a1 158 }
clemounet 0:3ca0a6d1e2a1 159
clemounet 0:3ca0a6d1e2a1 160 void CANInterface::RxCbCan1(void) {
clemounet 0:3ca0a6d1e2a1 161 __disable_irq();
clemounet 0:3ca0a6d1e2a1 162 CANMessage m;
clemounet 0:3ca0a6d1e2a1 163 if(bus1->read(m)) {
clemounet 0:3ca0a6d1e2a1 164 rxOvf = !fifoRxMsg.put(m);
clemounet 0:3ca0a6d1e2a1 165 if(led3 == 1){
clemounet 0:3ca0a6d1e2a1 166 led3 = 0;
clemounet 0:3ca0a6d1e2a1 167 } else {
clemounet 0:3ca0a6d1e2a1 168 led3 = 1;
clemounet 0:3ca0a6d1e2a1 169 }
clemounet 0:3ca0a6d1e2a1 170 }
clemounet 0:3ca0a6d1e2a1 171 __enable_irq();
clemounet 0:3ca0a6d1e2a1 172 }
clemounet 0:3ca0a6d1e2a1 173
clemounet 0:3ca0a6d1e2a1 174 void CANInterface::RxCbCan2(void) {
clemounet 0:3ca0a6d1e2a1 175 __disable_irq();
clemounet 0:3ca0a6d1e2a1 176 CANMessage m;
clemounet 0:3ca0a6d1e2a1 177 if(bus2->read(m)) {
clemounet 0:3ca0a6d1e2a1 178 rxOvf = !fifoRxMsg.put(m);
clemounet 0:3ca0a6d1e2a1 179 if(led4 == 1) {
clemounet 0:3ca0a6d1e2a1 180 led4 = 0;
clemounet 0:3ca0a6d1e2a1 181 } else {
clemounet 0:3ca0a6d1e2a1 182 led4 = 1;
clemounet 0:3ca0a6d1e2a1 183 }
clemounet 0:3ca0a6d1e2a1 184 }
clemounet 0:3ca0a6d1e2a1 185 __enable_irq();
clemounet 0:3ca0a6d1e2a1 186 }