Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
CANInterface.cpp@1:b9201bec01bf, 2015-04-14 (annotated)
- Committer:
- clemounet
- Date:
- Tue Apr 14 13:26:18 2015 +0000
- Revision:
- 1:b9201bec01bf
- Parent:
- 0:3ca0a6d1e2a1
.up
Who changed what in which revision?
User | Revision | Line number | New 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 | } |