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:
mbed_official
Date:
Thu Apr 30 09:15:06 2015 +0100
Revision:
530:2939f5396008
Parent:
227:7bd0639b8911
Synchronized with git revision 334b3418dfe6e5d09d62fee80232883fcd1cbb1e

Full URL: https://github.com/mbedmicro/mbed/commit/334b3418dfe6e5d09d62fee80232883fcd1cbb1e/

Implement some CAN modes for the LPC1549/LPC11Cxx/LPC1768

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 */
mbed_official 227:7bd0639b8911 16 #include "mbed_assert.h"
emilmont 10:3bc89ef62ce7 17 #include "can_api.h"
emilmont 10:3bc89ef62ce7 18
emilmont 10:3bc89ef62ce7 19 #include "cmsis.h"
emilmont 10:3bc89ef62ce7 20 #include "pinmap.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
mbed_official 41:e8b66477f5bf 81 int can_mode(can_t *obj, CanMode mode) {
mbed_official 530:2939f5396008 82 int success = 0;
mbed_official 530:2939f5396008 83 switch (mode) {
mbed_official 530:2939f5396008 84 case MODE_RESET:
mbed_official 530:2939f5396008 85 // Clear all special modes
mbed_official 530:2939f5396008 86 can_reset(obj);
mbed_official 530:2939f5396008 87 obj->dev->MOD &=~ 0x06;
mbed_official 530:2939f5396008 88 success = 1;
mbed_official 530:2939f5396008 89 break;
mbed_official 530:2939f5396008 90 case MODE_NORMAL:
mbed_official 530:2939f5396008 91 // Clear all special modes
mbed_official 530:2939f5396008 92 can_disable(obj);
mbed_official 530:2939f5396008 93 obj->dev->MOD &=~ 0x06;
mbed_official 530:2939f5396008 94 can_enable(obj);
mbed_official 530:2939f5396008 95 success = 1;
mbed_official 530:2939f5396008 96 break;
mbed_official 530:2939f5396008 97 case MODE_SILENT:
mbed_official 530:2939f5396008 98 // Set listen-only mode and clear self-test mode
mbed_official 530:2939f5396008 99 can_disable(obj);
mbed_official 530:2939f5396008 100 obj->dev->MOD |= 0x02;
mbed_official 530:2939f5396008 101 obj->dev->MOD &=~ 0x04;
mbed_official 530:2939f5396008 102 can_enable(obj);
mbed_official 530:2939f5396008 103 success = 1;
mbed_official 530:2939f5396008 104 break;
mbed_official 530:2939f5396008 105 case MODE_TEST_LOCAL:
mbed_official 530:2939f5396008 106 // Set self-test mode and clear listen-only mode
mbed_official 530:2939f5396008 107 can_disable(obj);
mbed_official 530:2939f5396008 108 obj->dev->MOD |= 0x04;
mbed_official 530:2939f5396008 109 obj->dev->MOD &=~ 0x02;
mbed_official 530:2939f5396008 110 can_enable(obj);
mbed_official 530:2939f5396008 111 success = 1;
mbed_official 530:2939f5396008 112 break;
mbed_official 530:2939f5396008 113 case MODE_TEST_SILENT:
mbed_official 530:2939f5396008 114 case MODE_TEST_GLOBAL:
mbed_official 530:2939f5396008 115 default:
mbed_official 530:2939f5396008 116 success = 0;
mbed_official 530:2939f5396008 117 break;
mbed_official 530:2939f5396008 118 }
mbed_official 530:2939f5396008 119
mbed_official 530:2939f5396008 120 return success;
mbed_official 41:e8b66477f5bf 121 }
mbed_official 41:e8b66477f5bf 122
mbed_official 41:e8b66477f5bf 123 int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) {
bogdanm 15:4892fe388435 124 return 0; // not implemented
bogdanm 15:4892fe388435 125 }
bogdanm 15:4892fe388435 126
bogdanm 15:4892fe388435 127 static inline void can_irq(uint32_t icr, uint32_t index) {
bogdanm 15:4892fe388435 128 uint32_t i;
bogdanm 15:4892fe388435 129
bogdanm 15:4892fe388435 130 for(i = 0; i < 8; i++)
bogdanm 15:4892fe388435 131 {
bogdanm 15:4892fe388435 132 if((can_irq_ids[index] != 0) && (icr & (1 << i)))
bogdanm 15:4892fe388435 133 {
bogdanm 15:4892fe388435 134 switch (i) {
bogdanm 15:4892fe388435 135 case 0: irq_handler(can_irq_ids[index], IRQ_RX); break;
bogdanm 15:4892fe388435 136 case 1: irq_handler(can_irq_ids[index], IRQ_TX); break;
bogdanm 15:4892fe388435 137 case 2: irq_handler(can_irq_ids[index], IRQ_ERROR); break;
bogdanm 15:4892fe388435 138 case 3: irq_handler(can_irq_ids[index], IRQ_OVERRUN); break;
bogdanm 15:4892fe388435 139 case 4: irq_handler(can_irq_ids[index], IRQ_WAKEUP); break;
bogdanm 15:4892fe388435 140 case 5: irq_handler(can_irq_ids[index], IRQ_PASSIVE); break;
bogdanm 15:4892fe388435 141 case 6: irq_handler(can_irq_ids[index], IRQ_ARB); break;
bogdanm 15:4892fe388435 142 case 7: irq_handler(can_irq_ids[index], IRQ_BUS); break;
bogdanm 15:4892fe388435 143 case 8: irq_handler(can_irq_ids[index], IRQ_READY); break;
bogdanm 15:4892fe388435 144 }
bogdanm 15:4892fe388435 145 }
bogdanm 15:4892fe388435 146 }
bogdanm 15:4892fe388435 147 }
bogdanm 15:4892fe388435 148
bogdanm 15:4892fe388435 149 // Have to check that the CAN block is active before reading the Interrupt
bogdanm 15:4892fe388435 150 // Control Register, or the mbed hangs
bogdanm 15:4892fe388435 151 void can_irq_n() {
bogdanm 15:4892fe388435 152 uint32_t icr;
bogdanm 15:4892fe388435 153
bogdanm 15:4892fe388435 154 if(LPC_SC->PCONP & (1 << 13)) {
bogdanm 15:4892fe388435 155 icr = LPC_CAN1->ICR & 0x1FF;
bogdanm 15:4892fe388435 156 can_irq(icr, 0);
bogdanm 15:4892fe388435 157 }
bogdanm 15:4892fe388435 158
bogdanm 15:4892fe388435 159 if(LPC_SC->PCONP & (1 << 14)) {
bogdanm 15:4892fe388435 160 icr = LPC_CAN2->ICR & 0x1FF;
bogdanm 15:4892fe388435 161 can_irq(icr, 1);
bogdanm 15:4892fe388435 162 }
bogdanm 15:4892fe388435 163 }
bogdanm 15:4892fe388435 164
bogdanm 15:4892fe388435 165 // Register CAN object's irq handler
bogdanm 15:4892fe388435 166 void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id) {
bogdanm 15:4892fe388435 167 irq_handler = handler;
bogdanm 15:4892fe388435 168 can_irq_ids[obj->index] = id;
bogdanm 15:4892fe388435 169 }
bogdanm 15:4892fe388435 170
bogdanm 15:4892fe388435 171 // Unregister CAN object's irq handler
bogdanm 15:4892fe388435 172 void can_irq_free(can_t *obj) {
bogdanm 15:4892fe388435 173 obj->dev->IER &= ~(1);
bogdanm 15:4892fe388435 174 can_irq_ids[obj->index] = 0;
bogdanm 15:4892fe388435 175
bogdanm 15:4892fe388435 176 if ((can_irq_ids[0] == 0) && (can_irq_ids[1] == 0)) {
bogdanm 15:4892fe388435 177 NVIC_DisableIRQ(CAN_IRQn);
bogdanm 15:4892fe388435 178 }
bogdanm 15:4892fe388435 179 }
bogdanm 15:4892fe388435 180
bogdanm 15:4892fe388435 181 // Clear or set a irq
bogdanm 15:4892fe388435 182 void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) {
bogdanm 15:4892fe388435 183 uint32_t ier;
bogdanm 15:4892fe388435 184
bogdanm 15:4892fe388435 185 switch (type) {
bogdanm 15:4892fe388435 186 case IRQ_RX: ier = (1 << 0); break;
bogdanm 15:4892fe388435 187 case IRQ_TX: ier = (1 << 1); break;
bogdanm 15:4892fe388435 188 case IRQ_ERROR: ier = (1 << 2); break;
bogdanm 15:4892fe388435 189 case IRQ_OVERRUN: ier = (1 << 3); break;
bogdanm 15:4892fe388435 190 case IRQ_WAKEUP: ier = (1 << 4); break;
bogdanm 15:4892fe388435 191 case IRQ_PASSIVE: ier = (1 << 5); break;
bogdanm 15:4892fe388435 192 case IRQ_ARB: ier = (1 << 6); break;
bogdanm 15:4892fe388435 193 case IRQ_BUS: ier = (1 << 7); break;
bogdanm 15:4892fe388435 194 case IRQ_READY: ier = (1 << 8); break;
bogdanm 15:4892fe388435 195 default: return;
bogdanm 15:4892fe388435 196 }
bogdanm 15:4892fe388435 197
bogdanm 15:4892fe388435 198 obj->dev->MOD |= 1;
bogdanm 15:4892fe388435 199 if(enable == 0) {
bogdanm 15:4892fe388435 200 obj->dev->IER &= ~ier;
bogdanm 15:4892fe388435 201 }
bogdanm 15:4892fe388435 202 else {
bogdanm 15:4892fe388435 203 obj->dev->IER |= ier;
bogdanm 15:4892fe388435 204 }
bogdanm 15:4892fe388435 205 obj->dev->MOD &= ~(1);
bogdanm 15:4892fe388435 206
bogdanm 15:4892fe388435 207 // Enable NVIC if at least 1 interrupt is active
bogdanm 20:4263a77256ae 208 if(((LPC_SC->PCONP & (1 << 13)) && LPC_CAN1->IER) || ((LPC_SC->PCONP & (1 << 14)) && LPC_CAN2->IER)) {
bogdanm 15:4892fe388435 209 NVIC_SetVector(CAN_IRQn, (uint32_t) &can_irq_n);
bogdanm 15:4892fe388435 210 NVIC_EnableIRQ(CAN_IRQn);
bogdanm 15:4892fe388435 211 }
bogdanm 15:4892fe388435 212 else {
bogdanm 15:4892fe388435 213 NVIC_DisableIRQ(CAN_IRQn);
bogdanm 15:4892fe388435 214 }
bogdanm 15:4892fe388435 215 }
bogdanm 15:4892fe388435 216
emilmont 10:3bc89ef62ce7 217 static int can_pclk(can_t *obj) {
emilmont 10:3bc89ef62ce7 218 int value = 0;
emilmont 10:3bc89ef62ce7 219 switch ((int)obj->dev) {
emilmont 10:3bc89ef62ce7 220 case CAN_1: value = (LPC_SC->PCLKSEL0 & (0x3 << 26)) >> 26; break;
emilmont 10:3bc89ef62ce7 221 case CAN_2: value = (LPC_SC->PCLKSEL0 & (0x3 << 28)) >> 28; break;
emilmont 10:3bc89ef62ce7 222 }
emilmont 10:3bc89ef62ce7 223
emilmont 10:3bc89ef62ce7 224 switch (value) {
emilmont 10:3bc89ef62ce7 225 case 1: return 1;
emilmont 10:3bc89ef62ce7 226 case 2: return 2;
emilmont 10:3bc89ef62ce7 227 case 3: return 6;
emilmont 10:3bc89ef62ce7 228 default: return 4;
emilmont 10:3bc89ef62ce7 229 }
emilmont 10:3bc89ef62ce7 230 }
emilmont 10:3bc89ef62ce7 231
emilmont 10:3bc89ef62ce7 232 // This table has the sampling points as close to 75% as possible. The first
emilmont 10:3bc89ef62ce7 233 // value is TSEG1, the second TSEG2.
emilmont 10:3bc89ef62ce7 234 static const int timing_pts[23][2] = {
emilmont 10:3bc89ef62ce7 235 {0x0, 0x0}, // 2, 50%
emilmont 10:3bc89ef62ce7 236 {0x1, 0x0}, // 3, 67%
emilmont 10:3bc89ef62ce7 237 {0x2, 0x0}, // 4, 75%
emilmont 10:3bc89ef62ce7 238 {0x3, 0x0}, // 5, 80%
emilmont 10:3bc89ef62ce7 239 {0x3, 0x1}, // 6, 67%
emilmont 10:3bc89ef62ce7 240 {0x4, 0x1}, // 7, 71%
emilmont 10:3bc89ef62ce7 241 {0x5, 0x1}, // 8, 75%
emilmont 10:3bc89ef62ce7 242 {0x6, 0x1}, // 9, 78%
emilmont 10:3bc89ef62ce7 243 {0x6, 0x2}, // 10, 70%
emilmont 10:3bc89ef62ce7 244 {0x7, 0x2}, // 11, 73%
emilmont 10:3bc89ef62ce7 245 {0x8, 0x2}, // 12, 75%
emilmont 10:3bc89ef62ce7 246 {0x9, 0x2}, // 13, 77%
emilmont 10:3bc89ef62ce7 247 {0x9, 0x3}, // 14, 71%
emilmont 10:3bc89ef62ce7 248 {0xA, 0x3}, // 15, 73%
emilmont 10:3bc89ef62ce7 249 {0xB, 0x3}, // 16, 75%
emilmont 10:3bc89ef62ce7 250 {0xC, 0x3}, // 17, 76%
emilmont 10:3bc89ef62ce7 251 {0xD, 0x3}, // 18, 78%
emilmont 10:3bc89ef62ce7 252 {0xD, 0x4}, // 19, 74%
emilmont 10:3bc89ef62ce7 253 {0xE, 0x4}, // 20, 75%
emilmont 10:3bc89ef62ce7 254 {0xF, 0x4}, // 21, 76%
emilmont 10:3bc89ef62ce7 255 {0xF, 0x5}, // 22, 73%
emilmont 10:3bc89ef62ce7 256 {0xF, 0x6}, // 23, 70%
emilmont 10:3bc89ef62ce7 257 {0xF, 0x7}, // 24, 67%
emilmont 10:3bc89ef62ce7 258 };
emilmont 10:3bc89ef62ce7 259
emilmont 10:3bc89ef62ce7 260 static unsigned int can_speed(unsigned int sclk, unsigned int pclk, unsigned int cclk, unsigned char psjw) {
emilmont 10:3bc89ef62ce7 261 uint32_t btr;
emilmont 10:3bc89ef62ce7 262 uint16_t brp = 0;
emilmont 10:3bc89ef62ce7 263 uint32_t calcbit;
emilmont 10:3bc89ef62ce7 264 uint32_t bitwidth;
emilmont 10:3bc89ef62ce7 265 int hit = 0;
emilmont 10:3bc89ef62ce7 266 int bits;
emilmont 10:3bc89ef62ce7 267
emilmont 10:3bc89ef62ce7 268 bitwidth = sclk / (pclk * cclk);
emilmont 10:3bc89ef62ce7 269
emilmont 10:3bc89ef62ce7 270 brp = bitwidth / 0x18;
emilmont 10:3bc89ef62ce7 271 while ((!hit) && (brp < bitwidth / 4)) {
emilmont 10:3bc89ef62ce7 272 brp++;
emilmont 10:3bc89ef62ce7 273 for (bits = 22; bits > 0; bits--) {
emilmont 10:3bc89ef62ce7 274 calcbit = (bits + 3) * (brp + 1);
emilmont 10:3bc89ef62ce7 275 if (calcbit == bitwidth) {
emilmont 10:3bc89ef62ce7 276 hit = 1;
emilmont 10:3bc89ef62ce7 277 break;
emilmont 10:3bc89ef62ce7 278 }
emilmont 10:3bc89ef62ce7 279 }
emilmont 10:3bc89ef62ce7 280 }
emilmont 10:3bc89ef62ce7 281
emilmont 10:3bc89ef62ce7 282 if (hit) {
emilmont 10:3bc89ef62ce7 283 btr = ((timing_pts[bits][1] << 20) & 0x00700000)
emilmont 10:3bc89ef62ce7 284 | ((timing_pts[bits][0] << 16) & 0x000F0000)
emilmont 10:3bc89ef62ce7 285 | ((psjw << 14) & 0x0000C000)
emilmont 10:3bc89ef62ce7 286 | ((brp << 0) & 0x000003FF);
emilmont 10:3bc89ef62ce7 287 } else {
emilmont 10:3bc89ef62ce7 288 btr = 0xFFFFFFFF;
emilmont 10:3bc89ef62ce7 289 }
emilmont 10:3bc89ef62ce7 290
emilmont 10:3bc89ef62ce7 291 return btr;
emilmont 10:3bc89ef62ce7 292
emilmont 10:3bc89ef62ce7 293 }
emilmont 10:3bc89ef62ce7 294
emilmont 10:3bc89ef62ce7 295 void can_init(can_t *obj, PinName rd, PinName td) {
emilmont 10:3bc89ef62ce7 296 CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
emilmont 10:3bc89ef62ce7 297 CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
emilmont 10:3bc89ef62ce7 298 obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td);
mbed_official 227:7bd0639b8911 299 MBED_ASSERT((int)obj->dev != NC);
emilmont 10:3bc89ef62ce7 300
emilmont 10:3bc89ef62ce7 301 switch ((int)obj->dev) {
emilmont 10:3bc89ef62ce7 302 case CAN_1: LPC_SC->PCONP |= 1 << 13; break;
emilmont 10:3bc89ef62ce7 303 case CAN_2: LPC_SC->PCONP |= 1 << 14; break;
emilmont 10:3bc89ef62ce7 304 }
emilmont 10:3bc89ef62ce7 305
emilmont 10:3bc89ef62ce7 306 pinmap_pinout(rd, PinMap_CAN_RD);
emilmont 10:3bc89ef62ce7 307 pinmap_pinout(td, PinMap_CAN_TD);
bogdanm 15:4892fe388435 308
bogdanm 15:4892fe388435 309 switch ((int)obj->dev) {
bogdanm 15:4892fe388435 310 case CAN_1: obj->index = 0; break;
bogdanm 15:4892fe388435 311 case CAN_2: obj->index = 1; break;
bogdanm 15:4892fe388435 312 }
bogdanm 15:4892fe388435 313
emilmont 10:3bc89ef62ce7 314 can_reset(obj);
emilmont 10:3bc89ef62ce7 315 obj->dev->IER = 0; // Disable Interrupts
emilmont 10:3bc89ef62ce7 316 can_frequency(obj, 100000);
emilmont 10:3bc89ef62ce7 317
emilmont 10:3bc89ef62ce7 318 LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter
emilmont 10:3bc89ef62ce7 319 }
emilmont 10:3bc89ef62ce7 320
emilmont 10:3bc89ef62ce7 321 void can_free(can_t *obj) {
emilmont 10:3bc89ef62ce7 322 switch ((int)obj->dev) {
emilmont 10:3bc89ef62ce7 323 case CAN_1: LPC_SC->PCONP &= ~(1 << 13); break;
emilmont 10:3bc89ef62ce7 324 case CAN_2: LPC_SC->PCONP &= ~(1 << 14); break;
emilmont 10:3bc89ef62ce7 325 }
emilmont 10:3bc89ef62ce7 326 }
emilmont 10:3bc89ef62ce7 327
emilmont 10:3bc89ef62ce7 328 int can_frequency(can_t *obj, int f) {
emilmont 10:3bc89ef62ce7 329 int pclk = can_pclk(obj);
emilmont 10:3bc89ef62ce7 330
emilmont 10:3bc89ef62ce7 331 int btr = can_speed(SystemCoreClock, pclk, (unsigned int)f, 1);
emilmont 10:3bc89ef62ce7 332
emilmont 10:3bc89ef62ce7 333 if (btr > 0) {
emilmont 10:3bc89ef62ce7 334 uint32_t modmask = can_disable(obj);
emilmont 10:3bc89ef62ce7 335 obj->dev->BTR = btr;
emilmont 10:3bc89ef62ce7 336 obj->dev->MOD = modmask;
emilmont 10:3bc89ef62ce7 337 return 1;
emilmont 10:3bc89ef62ce7 338 } else {
emilmont 10:3bc89ef62ce7 339 return 0;
emilmont 10:3bc89ef62ce7 340 }
emilmont 10:3bc89ef62ce7 341 }
emilmont 10:3bc89ef62ce7 342
emilmont 10:3bc89ef62ce7 343 int can_write(can_t *obj, CAN_Message msg, int cc) {
emilmont 10:3bc89ef62ce7 344 unsigned int CANStatus;
emilmont 10:3bc89ef62ce7 345 CANMsg m;
emilmont 10:3bc89ef62ce7 346
emilmont 10:3bc89ef62ce7 347 can_enable(obj);
emilmont 10:3bc89ef62ce7 348
emilmont 10:3bc89ef62ce7 349 m.id = msg.id ;
emilmont 10:3bc89ef62ce7 350 m.dlc = msg.len & 0xF;
emilmont 10:3bc89ef62ce7 351 m.rtr = msg.type;
emilmont 10:3bc89ef62ce7 352 m.type = msg.format;
emilmont 10:3bc89ef62ce7 353 memcpy(m.data, msg.data, msg.len);
emilmont 10:3bc89ef62ce7 354 const unsigned int *buf = (const unsigned int *)&m;
emilmont 10:3bc89ef62ce7 355
emilmont 10:3bc89ef62ce7 356 CANStatus = obj->dev->SR;
mbed_official 530:2939f5396008 357
mbed_official 530:2939f5396008 358 // Send the message to ourself if in a test mode
mbed_official 530:2939f5396008 359 if (obj->dev->MOD & 0x04) {
mbed_official 530:2939f5396008 360 cc = 1;
mbed_official 530:2939f5396008 361 }
mbed_official 530:2939f5396008 362
emilmont 10:3bc89ef62ce7 363 if (CANStatus & 0x00000004) {
emilmont 10:3bc89ef62ce7 364 obj->dev->TFI1 = buf[0] & 0xC00F0000;
emilmont 10:3bc89ef62ce7 365 obj->dev->TID1 = buf[1];
emilmont 10:3bc89ef62ce7 366 obj->dev->TDA1 = buf[2];
emilmont 10:3bc89ef62ce7 367 obj->dev->TDB1 = buf[3];
emilmont 10:3bc89ef62ce7 368 if(cc) {
emilmont 10:3bc89ef62ce7 369 obj->dev->CMR = 0x30;
emilmont 10:3bc89ef62ce7 370 } else {
emilmont 10:3bc89ef62ce7 371 obj->dev->CMR = 0x21;
emilmont 10:3bc89ef62ce7 372 }
emilmont 10:3bc89ef62ce7 373 return 1;
emilmont 10:3bc89ef62ce7 374
emilmont 10:3bc89ef62ce7 375 } else if (CANStatus & 0x00000400) {
emilmont 10:3bc89ef62ce7 376 obj->dev->TFI2 = buf[0] & 0xC00F0000;
emilmont 10:3bc89ef62ce7 377 obj->dev->TID2 = buf[1];
emilmont 10:3bc89ef62ce7 378 obj->dev->TDA2 = buf[2];
emilmont 10:3bc89ef62ce7 379 obj->dev->TDB2 = buf[3];
emilmont 10:3bc89ef62ce7 380 if (cc) {
emilmont 10:3bc89ef62ce7 381 obj->dev->CMR = 0x50;
emilmont 10:3bc89ef62ce7 382 } else {
emilmont 10:3bc89ef62ce7 383 obj->dev->CMR = 0x41;
emilmont 10:3bc89ef62ce7 384 }
emilmont 10:3bc89ef62ce7 385 return 1;
emilmont 10:3bc89ef62ce7 386
emilmont 10:3bc89ef62ce7 387 } else if (CANStatus & 0x00040000) {
emilmont 10:3bc89ef62ce7 388 obj->dev->TFI3 = buf[0] & 0xC00F0000;
emilmont 10:3bc89ef62ce7 389 obj->dev->TID3 = buf[1];
emilmont 10:3bc89ef62ce7 390 obj->dev->TDA3 = buf[2];
emilmont 10:3bc89ef62ce7 391 obj->dev->TDB3 = buf[3];
emilmont 10:3bc89ef62ce7 392 if (cc) {
emilmont 10:3bc89ef62ce7 393 obj->dev->CMR = 0x90;
emilmont 10:3bc89ef62ce7 394 } else {
emilmont 10:3bc89ef62ce7 395 obj->dev->CMR = 0x81;
emilmont 10:3bc89ef62ce7 396 }
emilmont 10:3bc89ef62ce7 397 return 1;
emilmont 10:3bc89ef62ce7 398 }
emilmont 10:3bc89ef62ce7 399
emilmont 10:3bc89ef62ce7 400 return 0;
emilmont 10:3bc89ef62ce7 401 }
emilmont 10:3bc89ef62ce7 402
mbed_official 41:e8b66477f5bf 403 int can_read(can_t *obj, CAN_Message *msg, int handle) {
emilmont 10:3bc89ef62ce7 404 CANMsg x;
emilmont 10:3bc89ef62ce7 405 unsigned int *i = (unsigned int *)&x;
emilmont 10:3bc89ef62ce7 406
emilmont 10:3bc89ef62ce7 407 can_enable(obj);
emilmont 10:3bc89ef62ce7 408
emilmont 10:3bc89ef62ce7 409 if (obj->dev->GSR & 0x1) {
emilmont 10:3bc89ef62ce7 410 *i++ = obj->dev->RFS; // Frame
emilmont 10:3bc89ef62ce7 411 *i++ = obj->dev->RID; // ID
emilmont 10:3bc89ef62ce7 412 *i++ = obj->dev->RDA; // Data A
emilmont 10:3bc89ef62ce7 413 *i++ = obj->dev->RDB; // Data B
emilmont 10:3bc89ef62ce7 414 obj->dev->CMR = 0x04; // release receive buffer
emilmont 10:3bc89ef62ce7 415
emilmont 10:3bc89ef62ce7 416 msg->id = x.id;
emilmont 10:3bc89ef62ce7 417 msg->len = x.dlc;
emilmont 10:3bc89ef62ce7 418 msg->format = (x.type)? CANExtended : CANStandard;
emilmont 10:3bc89ef62ce7 419 msg->type = (x.rtr)? CANRemote: CANData;
emilmont 10:3bc89ef62ce7 420 memcpy(msg->data,x.data,x.dlc);
emilmont 10:3bc89ef62ce7 421 return 1;
emilmont 10:3bc89ef62ce7 422 }
emilmont 10:3bc89ef62ce7 423
emilmont 10:3bc89ef62ce7 424 return 0;
emilmont 10:3bc89ef62ce7 425 }
emilmont 10:3bc89ef62ce7 426
emilmont 10:3bc89ef62ce7 427 void can_reset(can_t *obj) {
emilmont 10:3bc89ef62ce7 428 can_disable(obj);
emilmont 10:3bc89ef62ce7 429 obj->dev->GSR = 0; // Reset error counter when CAN1MOD is in reset
emilmont 10:3bc89ef62ce7 430 }
emilmont 10:3bc89ef62ce7 431
emilmont 10:3bc89ef62ce7 432 unsigned char can_rderror(can_t *obj) {
emilmont 10:3bc89ef62ce7 433 return (obj->dev->GSR >> 16) & 0xFF;
emilmont 10:3bc89ef62ce7 434 }
emilmont 10:3bc89ef62ce7 435
emilmont 10:3bc89ef62ce7 436 unsigned char can_tderror(can_t *obj) {
emilmont 10:3bc89ef62ce7 437 return (obj->dev->GSR >> 24) & 0xFF;
emilmont 10:3bc89ef62ce7 438 }
emilmont 10:3bc89ef62ce7 439
emilmont 10:3bc89ef62ce7 440 void can_monitor(can_t *obj, int silent) {
emilmont 10:3bc89ef62ce7 441 uint32_t mod_mask = can_disable(obj);
emilmont 10:3bc89ef62ce7 442 if (silent) {
emilmont 10:3bc89ef62ce7 443 obj->dev->MOD |= (1 << 1);
emilmont 10:3bc89ef62ce7 444 } else {
emilmont 10:3bc89ef62ce7 445 obj->dev->MOD &= ~(1 << 1);
emilmont 10:3bc89ef62ce7 446 }
emilmont 10:3bc89ef62ce7 447 if (!(mod_mask & 1)) {
emilmont 10:3bc89ef62ce7 448 can_enable(obj);
emilmont 10:3bc89ef62ce7 449 }
emilmont 10:3bc89ef62ce7 450 }