mbed SDK library sources

Fork of mbed-src by mbed official

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Fri Oct 25 15:00:04 2013 +0100
Revision:
41:e8b66477f5bf
Parent:
29:6ac4027eff2b
Synchronized with git revision 317a1f66d2a2d4efe5544d3bf6c2aaf1d147a968

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 15:4892fe388435 1 /* mbed Microcontroller Library
bogdanm 15:4892fe388435 2 * Copyright (c) 2006-2013 ARM Limited
bogdanm 15:4892fe388435 3 *
bogdanm 15:4892fe388435 4 * Licensed under the Apache License, Version 2.0 (the "License");
bogdanm 15:4892fe388435 5 * you may not use this file except in compliance with the License.
bogdanm 15:4892fe388435 6 * You may obtain a copy of the License at
bogdanm 15:4892fe388435 7 *
bogdanm 15:4892fe388435 8 * http://www.apache.org/licenses/LICENSE-2.0
bogdanm 15:4892fe388435 9 *
bogdanm 15:4892fe388435 10 * Unless required by applicable law or agreed to in writing, software
bogdanm 15:4892fe388435 11 * distributed under the License is distributed on an "AS IS" BASIS,
bogdanm 15:4892fe388435 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bogdanm 15:4892fe388435 13 * See the License for the specific language governing permissions and
bogdanm 15:4892fe388435 14 * limitations under the License.
bogdanm 15:4892fe388435 15 */
emilmont 17:151ab7482c89 16 #include "can_api.h"
bogdanm 15:4892fe388435 17
bogdanm 15:4892fe388435 18 #include "cmsis.h"
bogdanm 15:4892fe388435 19 #include "pinmap.h"
bogdanm 15:4892fe388435 20 #include "error.h"
bogdanm 15:4892fe388435 21
emilmont 17:151ab7482c89 22 #include <math.h>
emilmont 17:151ab7482c89 23 #include <string.h>
emilmont 17:151ab7482c89 24
emilmont 17:151ab7482c89 25 #define CAN_NUM 2
emilmont 16:7da2369b400c 26
bogdanm 15:4892fe388435 27 /* Acceptance filter mode in AFMR register */
bogdanm 15:4892fe388435 28 #define ACCF_OFF 0x01
bogdanm 15:4892fe388435 29 #define ACCF_BYPASS 0x02
bogdanm 15:4892fe388435 30 #define ACCF_ON 0x00
bogdanm 15:4892fe388435 31 #define ACCF_FULLCAN 0x04
bogdanm 15:4892fe388435 32
bogdanm 15:4892fe388435 33 /* There are several bit timing calculators on the internet.
bogdanm 15:4892fe388435 34 http://www.port.de/engl/canprod/sv_req_form.html
bogdanm 15:4892fe388435 35 http://www.kvaser.com/can/index.htm
bogdanm 15:4892fe388435 36 */
bogdanm 15:4892fe388435 37
bogdanm 15:4892fe388435 38 static const PinMap PinMap_CAN_RD[] = {
bogdanm 15:4892fe388435 39 {P0_0 , CAN_1, 1},
bogdanm 15:4892fe388435 40 {P0_4 , CAN_2, 2},
bogdanm 15:4892fe388435 41 {P0_21, CAN_1, 4},
bogdanm 15:4892fe388435 42 {P2_7 , CAN_2, 1},
bogdanm 15:4892fe388435 43 {NC , NC , 0}
bogdanm 15:4892fe388435 44 };
bogdanm 15:4892fe388435 45
bogdanm 15:4892fe388435 46 static const PinMap PinMap_CAN_TD[] = {
bogdanm 15:4892fe388435 47 {P0_1 , CAN_1, 1},
bogdanm 15:4892fe388435 48 {P0_5 , CAN_2, 2},
bogdanm 15:4892fe388435 49 {P0_22, CAN_1, 4},
bogdanm 15:4892fe388435 50 {P2_8 , CAN_2, 1},
bogdanm 15:4892fe388435 51 {NC , NC , 0}
bogdanm 15:4892fe388435 52 };
bogdanm 15:4892fe388435 53
bogdanm 15:4892fe388435 54 // Type definition to hold a CAN message
bogdanm 15:4892fe388435 55 struct CANMsg {
bogdanm 15:4892fe388435 56 unsigned int reserved1 : 16;
bogdanm 15:4892fe388435 57 unsigned int dlc : 4; // Bits 16..19: DLC - Data Length Counter
bogdanm 15:4892fe388435 58 unsigned int reserved0 : 10;
bogdanm 15:4892fe388435 59 unsigned int rtr : 1; // Bit 30: Set if this is a RTR message
bogdanm 15:4892fe388435 60 unsigned int type : 1; // Bit 31: Set if this is a 29-bit ID message
bogdanm 15:4892fe388435 61 unsigned int id; // CAN Message ID (11-bit or 29-bit)
bogdanm 15:4892fe388435 62 unsigned char data[8]; // CAN Message Data Bytes 0-7
bogdanm 15:4892fe388435 63 };
bogdanm 15:4892fe388435 64 typedef struct CANMsg CANMsg;
bogdanm 15:4892fe388435 65
emilmont 17:151ab7482c89 66 static uint32_t can_irq_ids[CAN_NUM] = {0};
emilmont 17:151ab7482c89 67 static can_irq_handler irq_handler;
emilmont 17:151ab7482c89 68
bogdanm 15:4892fe388435 69 static uint32_t can_disable(can_t *obj) {
bogdanm 15:4892fe388435 70 uint32_t sm = obj->dev->MOD;
bogdanm 15:4892fe388435 71 obj->dev->MOD |= 1;
bogdanm 15:4892fe388435 72 return sm;
bogdanm 15:4892fe388435 73 }
bogdanm 15:4892fe388435 74
bogdanm 15:4892fe388435 75 static inline void can_enable(can_t *obj) {
bogdanm 15:4892fe388435 76 if (obj->dev->MOD & 1) {
bogdanm 15:4892fe388435 77 obj->dev->MOD &= ~(1);
bogdanm 15:4892fe388435 78 }
bogdanm 15:4892fe388435 79 }
bogdanm 15:4892fe388435 80
emilmont 17:151ab7482c89 81 int can_mode(can_t *obj, CanMode mode)
emilmont 17:151ab7482c89 82 {
emilmont 17:151ab7482c89 83 return 0; // not implemented
emilmont 17:151ab7482c89 84 }
emilmont 17:151ab7482c89 85
mbed_official 41:e8b66477f5bf 86 int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) {
mbed_official 41:e8b66477f5bf 87 return 0; // not implemented
mbed_official 41:e8b66477f5bf 88 }
mbed_official 41:e8b66477f5bf 89
emilmont 17:151ab7482c89 90 static inline void can_irq(uint32_t icr, uint32_t index) {
emilmont 17:151ab7482c89 91 uint32_t i;
emilmont 17:151ab7482c89 92
emilmont 17:151ab7482c89 93 for(i = 0; i < 8; i++)
emilmont 17:151ab7482c89 94 {
emilmont 17:151ab7482c89 95 if((can_irq_ids[index] != 0) && (icr & (1 << i)))
emilmont 17:151ab7482c89 96 {
emilmont 17:151ab7482c89 97 switch (i) {
emilmont 17:151ab7482c89 98 case 0: irq_handler(can_irq_ids[index], IRQ_RX); break;
emilmont 17:151ab7482c89 99 case 1: irq_handler(can_irq_ids[index], IRQ_TX); break;
emilmont 17:151ab7482c89 100 case 2: irq_handler(can_irq_ids[index], IRQ_ERROR); break;
emilmont 17:151ab7482c89 101 case 3: irq_handler(can_irq_ids[index], IRQ_OVERRUN); break;
emilmont 17:151ab7482c89 102 case 4: irq_handler(can_irq_ids[index], IRQ_WAKEUP); break;
emilmont 17:151ab7482c89 103 case 5: irq_handler(can_irq_ids[index], IRQ_PASSIVE); break;
emilmont 17:151ab7482c89 104 case 6: irq_handler(can_irq_ids[index], IRQ_ARB); break;
emilmont 17:151ab7482c89 105 case 7: irq_handler(can_irq_ids[index], IRQ_BUS); break;
emilmont 17:151ab7482c89 106 case 8: irq_handler(can_irq_ids[index], IRQ_READY); break;
emilmont 17:151ab7482c89 107 }
emilmont 17:151ab7482c89 108 }
emilmont 17:151ab7482c89 109 }
emilmont 17:151ab7482c89 110 }
emilmont 17:151ab7482c89 111
emilmont 17:151ab7482c89 112 // Have to check that the CAN block is active before reading the Interrupt
emilmont 17:151ab7482c89 113 // Control Register, or the mbed hangs
emilmont 17:151ab7482c89 114 void can_irq_n() {
emilmont 17:151ab7482c89 115 uint32_t icr;
emilmont 17:151ab7482c89 116
emilmont 17:151ab7482c89 117 if(LPC_SC->PCONP & (1 << 13)) {
emilmont 17:151ab7482c89 118 icr = LPC_CAN1->ICR & 0x1FF;
emilmont 17:151ab7482c89 119 can_irq(icr, 0);
emilmont 17:151ab7482c89 120 }
emilmont 17:151ab7482c89 121
emilmont 17:151ab7482c89 122 if(LPC_SC->PCONP & (1 << 14)) {
emilmont 17:151ab7482c89 123 icr = LPC_CAN2->ICR & 0x1FF;
emilmont 17:151ab7482c89 124 can_irq(icr, 1);
emilmont 17:151ab7482c89 125 }
emilmont 17:151ab7482c89 126 }
emilmont 17:151ab7482c89 127
emilmont 17:151ab7482c89 128 // Register CAN object's irq handler
emilmont 17:151ab7482c89 129 void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id) {
emilmont 17:151ab7482c89 130 irq_handler = handler;
emilmont 17:151ab7482c89 131 can_irq_ids[obj->index] = id;
emilmont 17:151ab7482c89 132 }
emilmont 17:151ab7482c89 133
emilmont 17:151ab7482c89 134 // Unregister CAN object's irq handler
emilmont 17:151ab7482c89 135 void can_irq_free(can_t *obj) {
emilmont 17:151ab7482c89 136 obj->dev->IER &= ~(1);
emilmont 17:151ab7482c89 137 can_irq_ids[obj->index] = 0;
emilmont 17:151ab7482c89 138
emilmont 17:151ab7482c89 139 if ((can_irq_ids[0] == 0) && (can_irq_ids[1] == 0)) {
emilmont 17:151ab7482c89 140 NVIC_DisableIRQ(CAN_IRQn);
emilmont 17:151ab7482c89 141 }
emilmont 17:151ab7482c89 142 }
emilmont 17:151ab7482c89 143
emilmont 17:151ab7482c89 144 // Clear or set a irq
emilmont 17:151ab7482c89 145 void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) {
emilmont 17:151ab7482c89 146 uint32_t ier;
emilmont 17:151ab7482c89 147
emilmont 17:151ab7482c89 148 switch (type) {
emilmont 17:151ab7482c89 149 case IRQ_RX: ier = (1 << 0); break;
emilmont 17:151ab7482c89 150 case IRQ_TX: ier = (1 << 1); break;
emilmont 17:151ab7482c89 151 case IRQ_ERROR: ier = (1 << 2); break;
emilmont 17:151ab7482c89 152 case IRQ_OVERRUN: ier = (1 << 3); break;
emilmont 17:151ab7482c89 153 case IRQ_WAKEUP: ier = (1 << 4); break;
emilmont 17:151ab7482c89 154 case IRQ_PASSIVE: ier = (1 << 5); break;
emilmont 17:151ab7482c89 155 case IRQ_ARB: ier = (1 << 6); break;
emilmont 17:151ab7482c89 156 case IRQ_BUS: ier = (1 << 7); break;
emilmont 17:151ab7482c89 157 case IRQ_READY: ier = (1 << 8); break;
emilmont 17:151ab7482c89 158 default: return;
emilmont 17:151ab7482c89 159 }
emilmont 17:151ab7482c89 160
emilmont 17:151ab7482c89 161 obj->dev->MOD |= 1;
emilmont 17:151ab7482c89 162 if(enable == 0) {
emilmont 17:151ab7482c89 163 obj->dev->IER &= ~ier;
emilmont 17:151ab7482c89 164 }
emilmont 17:151ab7482c89 165 else {
emilmont 17:151ab7482c89 166 obj->dev->IER |= ier;
emilmont 17:151ab7482c89 167 }
emilmont 17:151ab7482c89 168 obj->dev->MOD &= ~(1);
emilmont 17:151ab7482c89 169
emilmont 17:151ab7482c89 170 // Enable NVIC if at least 1 interrupt is active
mbed_official 29:6ac4027eff2b 171 if(((LPC_SC->PCONP & (1 << 13)) && LPC_CAN1->IER) || ((LPC_SC->PCONP & (1 << 14)) && LPC_CAN2->IER)) {
emilmont 17:151ab7482c89 172 NVIC_SetVector(CAN_IRQn, (uint32_t) &can_irq_n);
emilmont 17:151ab7482c89 173 NVIC_EnableIRQ(CAN_IRQn);
emilmont 17:151ab7482c89 174 }
emilmont 17:151ab7482c89 175 else {
emilmont 17:151ab7482c89 176 NVIC_DisableIRQ(CAN_IRQn);
emilmont 17:151ab7482c89 177 }
emilmont 17:151ab7482c89 178 }
emilmont 17:151ab7482c89 179
bogdanm 15:4892fe388435 180 // This table has the sampling points as close to 75% as possible. The first
bogdanm 15:4892fe388435 181 // value is TSEG1, the second TSEG2.
bogdanm 15:4892fe388435 182 static const int timing_pts[23][2] = {
bogdanm 15:4892fe388435 183 {0x0, 0x0}, // 2, 50%
bogdanm 15:4892fe388435 184 {0x1, 0x0}, // 3, 67%
bogdanm 15:4892fe388435 185 {0x2, 0x0}, // 4, 75%
bogdanm 15:4892fe388435 186 {0x3, 0x0}, // 5, 80%
bogdanm 15:4892fe388435 187 {0x3, 0x1}, // 6, 67%
bogdanm 15:4892fe388435 188 {0x4, 0x1}, // 7, 71%
bogdanm 15:4892fe388435 189 {0x5, 0x1}, // 8, 75%
bogdanm 15:4892fe388435 190 {0x6, 0x1}, // 9, 78%
bogdanm 15:4892fe388435 191 {0x6, 0x2}, // 10, 70%
bogdanm 15:4892fe388435 192 {0x7, 0x2}, // 11, 73%
bogdanm 15:4892fe388435 193 {0x8, 0x2}, // 12, 75%
bogdanm 15:4892fe388435 194 {0x9, 0x2}, // 13, 77%
bogdanm 15:4892fe388435 195 {0x9, 0x3}, // 14, 71%
bogdanm 15:4892fe388435 196 {0xA, 0x3}, // 15, 73%
bogdanm 15:4892fe388435 197 {0xB, 0x3}, // 16, 75%
bogdanm 15:4892fe388435 198 {0xC, 0x3}, // 17, 76%
bogdanm 15:4892fe388435 199 {0xD, 0x3}, // 18, 78%
bogdanm 15:4892fe388435 200 {0xD, 0x4}, // 19, 74%
bogdanm 15:4892fe388435 201 {0xE, 0x4}, // 20, 75%
bogdanm 15:4892fe388435 202 {0xF, 0x4}, // 21, 76%
bogdanm 15:4892fe388435 203 {0xF, 0x5}, // 22, 73%
bogdanm 15:4892fe388435 204 {0xF, 0x6}, // 23, 70%
bogdanm 15:4892fe388435 205 {0xF, 0x7}, // 24, 67%
bogdanm 15:4892fe388435 206 };
bogdanm 15:4892fe388435 207
bogdanm 15:4892fe388435 208 static unsigned int can_speed(unsigned int sclk, unsigned int pclk, unsigned int cclk, unsigned char psjw) {
bogdanm 15:4892fe388435 209 uint32_t btr;
bogdanm 15:4892fe388435 210 uint16_t brp = 0;
bogdanm 15:4892fe388435 211 uint32_t calcbit;
bogdanm 15:4892fe388435 212 uint32_t bitwidth;
bogdanm 15:4892fe388435 213 int hit = 0;
bogdanm 15:4892fe388435 214 int bits;
bogdanm 15:4892fe388435 215
bogdanm 15:4892fe388435 216 bitwidth = sclk / (pclk * cclk);
bogdanm 15:4892fe388435 217
bogdanm 15:4892fe388435 218 brp = bitwidth / 0x18;
bogdanm 15:4892fe388435 219 while ((!hit) && (brp < bitwidth / 4)) {
bogdanm 15:4892fe388435 220 brp++;
bogdanm 15:4892fe388435 221 for (bits = 22; bits > 0; bits--) {
bogdanm 15:4892fe388435 222 calcbit = (bits + 3) * (brp + 1);
bogdanm 15:4892fe388435 223 if (calcbit == bitwidth) {
bogdanm 15:4892fe388435 224 hit = 1;
bogdanm 15:4892fe388435 225 break;
bogdanm 15:4892fe388435 226 }
bogdanm 15:4892fe388435 227 }
bogdanm 15:4892fe388435 228 }
bogdanm 15:4892fe388435 229
bogdanm 15:4892fe388435 230 if (hit) {
bogdanm 15:4892fe388435 231 btr = ((timing_pts[bits][1] << 20) & 0x00700000)
bogdanm 15:4892fe388435 232 | ((timing_pts[bits][0] << 16) & 0x000F0000)
bogdanm 15:4892fe388435 233 | ((psjw << 14) & 0x0000C000)
bogdanm 15:4892fe388435 234 | ((brp << 0) & 0x000003FF);
bogdanm 15:4892fe388435 235 } else {
bogdanm 15:4892fe388435 236 btr = 0xFFFFFFFF;
bogdanm 15:4892fe388435 237 }
bogdanm 15:4892fe388435 238
bogdanm 15:4892fe388435 239 return btr;
emilmont 17:151ab7482c89 240
bogdanm 15:4892fe388435 241 }
bogdanm 15:4892fe388435 242
bogdanm 15:4892fe388435 243 void can_init(can_t *obj, PinName rd, PinName td) {
bogdanm 15:4892fe388435 244 CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
bogdanm 15:4892fe388435 245 CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
bogdanm 15:4892fe388435 246 obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td);
bogdanm 15:4892fe388435 247 if ((int)obj->dev == NC) {
bogdanm 15:4892fe388435 248 error("CAN pin mapping failed");
bogdanm 15:4892fe388435 249 }
emilmont 17:151ab7482c89 250
bogdanm 15:4892fe388435 251 switch ((int)obj->dev) {
bogdanm 15:4892fe388435 252 case CAN_1: LPC_SC->PCONP |= 1 << 13; break;
bogdanm 15:4892fe388435 253 case CAN_2: LPC_SC->PCONP |= 1 << 14; break;
bogdanm 15:4892fe388435 254 }
emilmont 17:151ab7482c89 255
bogdanm 15:4892fe388435 256 pinmap_pinout(rd, PinMap_CAN_RD);
bogdanm 15:4892fe388435 257 pinmap_pinout(td, PinMap_CAN_TD);
bogdanm 15:4892fe388435 258
emilmont 17:151ab7482c89 259 switch ((int)obj->dev) {
emilmont 17:151ab7482c89 260 case CAN_1: obj->index = 0; break;
emilmont 17:151ab7482c89 261 case CAN_2: obj->index = 1; break;
emilmont 17:151ab7482c89 262 }
emilmont 17:151ab7482c89 263
bogdanm 15:4892fe388435 264 can_reset(obj);
bogdanm 15:4892fe388435 265 obj->dev->IER = 0; // Disable Interrupts
bogdanm 15:4892fe388435 266 can_frequency(obj, 100000);
emilmont 17:151ab7482c89 267
bogdanm 15:4892fe388435 268 LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter
bogdanm 15:4892fe388435 269 }
bogdanm 15:4892fe388435 270
bogdanm 15:4892fe388435 271 void can_free(can_t *obj) {
bogdanm 15:4892fe388435 272 switch ((int)obj->dev) {
bogdanm 15:4892fe388435 273 case CAN_1: LPC_SC->PCONP &= ~(1 << 13); break;
bogdanm 15:4892fe388435 274 case CAN_2: LPC_SC->PCONP &= ~(1 << 14); break;
bogdanm 15:4892fe388435 275 }
bogdanm 15:4892fe388435 276 }
bogdanm 15:4892fe388435 277
bogdanm 15:4892fe388435 278 int can_frequency(can_t *obj, int f) {
bogdanm 15:4892fe388435 279 int pclk = PeripheralClock;
emilmont 17:151ab7482c89 280
bogdanm 15:4892fe388435 281 int btr = can_speed(SystemCoreClock, pclk, (unsigned int)f, 1);
emilmont 17:151ab7482c89 282
bogdanm 15:4892fe388435 283 if (btr > 0) {
bogdanm 15:4892fe388435 284 uint32_t modmask = can_disable(obj);
bogdanm 15:4892fe388435 285 obj->dev->BTR = btr;
bogdanm 15:4892fe388435 286 obj->dev->MOD = modmask;
bogdanm 15:4892fe388435 287 return 1;
bogdanm 15:4892fe388435 288 } else {
bogdanm 15:4892fe388435 289 return 0;
bogdanm 15:4892fe388435 290 }
bogdanm 15:4892fe388435 291 }
bogdanm 15:4892fe388435 292
bogdanm 15:4892fe388435 293 int can_write(can_t *obj, CAN_Message msg, int cc) {
bogdanm 15:4892fe388435 294 unsigned int CANStatus;
bogdanm 15:4892fe388435 295 CANMsg m;
emilmont 17:151ab7482c89 296
bogdanm 15:4892fe388435 297 can_enable(obj);
emilmont 17:151ab7482c89 298
bogdanm 15:4892fe388435 299 m.id = msg.id ;
bogdanm 15:4892fe388435 300 m.dlc = msg.len & 0xF;
bogdanm 15:4892fe388435 301 m.rtr = msg.type;
bogdanm 15:4892fe388435 302 m.type = msg.format;
bogdanm 15:4892fe388435 303 memcpy(m.data, msg.data, msg.len);
bogdanm 15:4892fe388435 304 const unsigned int *buf = (const unsigned int *)&m;
emilmont 17:151ab7482c89 305
bogdanm 15:4892fe388435 306 CANStatus = obj->dev->SR;
bogdanm 15:4892fe388435 307 if (CANStatus & 0x00000004) {
bogdanm 15:4892fe388435 308 obj->dev->TFI1 = buf[0] & 0xC00F0000;
bogdanm 15:4892fe388435 309 obj->dev->TID1 = buf[1];
bogdanm 15:4892fe388435 310 obj->dev->TDA1 = buf[2];
bogdanm 15:4892fe388435 311 obj->dev->TDB1 = buf[3];
bogdanm 15:4892fe388435 312 if(cc) {
bogdanm 15:4892fe388435 313 obj->dev->CMR = 0x30;
bogdanm 15:4892fe388435 314 } else {
bogdanm 15:4892fe388435 315 obj->dev->CMR = 0x21;
bogdanm 15:4892fe388435 316 }
bogdanm 15:4892fe388435 317 return 1;
emilmont 17:151ab7482c89 318
bogdanm 15:4892fe388435 319 } else if (CANStatus & 0x00000400) {
bogdanm 15:4892fe388435 320 obj->dev->TFI2 = buf[0] & 0xC00F0000;
bogdanm 15:4892fe388435 321 obj->dev->TID2 = buf[1];
bogdanm 15:4892fe388435 322 obj->dev->TDA2 = buf[2];
bogdanm 15:4892fe388435 323 obj->dev->TDB2 = buf[3];
bogdanm 15:4892fe388435 324 if (cc) {
bogdanm 15:4892fe388435 325 obj->dev->CMR = 0x50;
bogdanm 15:4892fe388435 326 } else {
bogdanm 15:4892fe388435 327 obj->dev->CMR = 0x41;
bogdanm 15:4892fe388435 328 }
bogdanm 15:4892fe388435 329 return 1;
emilmont 17:151ab7482c89 330
bogdanm 15:4892fe388435 331 } else if (CANStatus & 0x00040000) {
bogdanm 15:4892fe388435 332 obj->dev->TFI3 = buf[0] & 0xC00F0000;
bogdanm 15:4892fe388435 333 obj->dev->TID3 = buf[1];
bogdanm 15:4892fe388435 334 obj->dev->TDA3 = buf[2];
bogdanm 15:4892fe388435 335 obj->dev->TDB3 = buf[3];
bogdanm 15:4892fe388435 336 if (cc) {
bogdanm 15:4892fe388435 337 obj->dev->CMR = 0x90;
bogdanm 15:4892fe388435 338 } else {
bogdanm 15:4892fe388435 339 obj->dev->CMR = 0x81;
bogdanm 15:4892fe388435 340 }
bogdanm 15:4892fe388435 341 return 1;
bogdanm 15:4892fe388435 342 }
emilmont 17:151ab7482c89 343
bogdanm 15:4892fe388435 344 return 0;
bogdanm 15:4892fe388435 345 }
bogdanm 15:4892fe388435 346
mbed_official 41:e8b66477f5bf 347 int can_read(can_t *obj, CAN_Message *msg, int handle) {
bogdanm 15:4892fe388435 348 CANMsg x;
bogdanm 15:4892fe388435 349 unsigned int *i = (unsigned int *)&x;
emilmont 17:151ab7482c89 350
bogdanm 15:4892fe388435 351 can_enable(obj);
emilmont 17:151ab7482c89 352
bogdanm 15:4892fe388435 353 if (obj->dev->GSR & 0x1) {
bogdanm 15:4892fe388435 354 *i++ = obj->dev->RFS; // Frame
bogdanm 15:4892fe388435 355 *i++ = obj->dev->RID; // ID
bogdanm 15:4892fe388435 356 *i++ = obj->dev->RDA; // Data A
bogdanm 15:4892fe388435 357 *i++ = obj->dev->RDB; // Data B
bogdanm 15:4892fe388435 358 obj->dev->CMR = 0x04; // release receive buffer
emilmont 17:151ab7482c89 359
bogdanm 15:4892fe388435 360 msg->id = x.id;
bogdanm 15:4892fe388435 361 msg->len = x.dlc;
bogdanm 15:4892fe388435 362 msg->format = (x.type)? CANExtended : CANStandard;
bogdanm 15:4892fe388435 363 msg->type = (x.rtr)? CANRemote: CANData;
bogdanm 15:4892fe388435 364 memcpy(msg->data,x.data,x.dlc);
bogdanm 15:4892fe388435 365 return 1;
bogdanm 15:4892fe388435 366 }
emilmont 17:151ab7482c89 367
bogdanm 15:4892fe388435 368 return 0;
bogdanm 15:4892fe388435 369 }
bogdanm 15:4892fe388435 370
bogdanm 15:4892fe388435 371 void can_reset(can_t *obj) {
bogdanm 15:4892fe388435 372 can_disable(obj);
bogdanm 15:4892fe388435 373 obj->dev->GSR = 0; // Reset error counter when CAN1MOD is in reset
bogdanm 15:4892fe388435 374 }
bogdanm 15:4892fe388435 375
bogdanm 15:4892fe388435 376 unsigned char can_rderror(can_t *obj) {
bogdanm 15:4892fe388435 377 return (obj->dev->GSR >> 16) & 0xFF;
bogdanm 15:4892fe388435 378 }
bogdanm 15:4892fe388435 379
bogdanm 15:4892fe388435 380 unsigned char can_tderror(can_t *obj) {
bogdanm 15:4892fe388435 381 return (obj->dev->GSR >> 24) & 0xFF;
bogdanm 15:4892fe388435 382 }
bogdanm 15:4892fe388435 383
bogdanm 15:4892fe388435 384 void can_monitor(can_t *obj, int silent) {
bogdanm 15:4892fe388435 385 uint32_t mod_mask = can_disable(obj);
bogdanm 15:4892fe388435 386 if (silent) {
bogdanm 15:4892fe388435 387 obj->dev->MOD |= (1 << 1);
bogdanm 15:4892fe388435 388 } else {
bogdanm 15:4892fe388435 389 obj->dev->MOD &= ~(1 << 1);
bogdanm 15:4892fe388435 390 }
bogdanm 15:4892fe388435 391 if (!(mod_mask & 1)) {
bogdanm 15:4892fe388435 392 can_enable(obj);
bogdanm 15:4892fe388435 393 }
bogdanm 15:4892fe388435 394 }