mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

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:
bogdanm
Date:
Wed Aug 07 16:43:59 2013 +0300
Revision:
15:4892fe388435
Parent:
13:0645d8841f51
Child:
19:398f4c622e1b
Added LPC4088 target and interrupt chaining code

Who changed what in which revision?

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