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:
Mon Aug 05 14:12:34 2013 +0300
Revision:
13:0645d8841f51
Parent:
vendor/NXP/LPC1768/hal/can_api.c@10:3bc89ef62ce7
Child:
15:4892fe388435
Update mbed sources to revision 64

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
emilmont 10:3bc89ef62ce7 25 /* Acceptance filter mode in AFMR register */
emilmont 10:3bc89ef62ce7 26 #define ACCF_OFF 0x01
emilmont 10:3bc89ef62ce7 27 #define ACCF_BYPASS 0x02
emilmont 10:3bc89ef62ce7 28 #define ACCF_ON 0x00
emilmont 10:3bc89ef62ce7 29 #define ACCF_FULLCAN 0x04
emilmont 10:3bc89ef62ce7 30
emilmont 10:3bc89ef62ce7 31 /* There are several bit timing calculators on the internet.
emilmont 10:3bc89ef62ce7 32 http://www.port.de/engl/canprod/sv_req_form.html
emilmont 10:3bc89ef62ce7 33 http://www.kvaser.com/can/index.htm
emilmont 10:3bc89ef62ce7 34 */
emilmont 10:3bc89ef62ce7 35
emilmont 10:3bc89ef62ce7 36 static const PinMap PinMap_CAN_RD[] = {
emilmont 10:3bc89ef62ce7 37 {P0_0 , CAN_1, 1},
emilmont 10:3bc89ef62ce7 38 {P0_4 , CAN_2, 2},
emilmont 10:3bc89ef62ce7 39 {P0_21, CAN_1, 3},
emilmont 10:3bc89ef62ce7 40 {P2_7 , CAN_2, 1},
emilmont 10:3bc89ef62ce7 41 {NC , NC , 0}
emilmont 10:3bc89ef62ce7 42 };
emilmont 10:3bc89ef62ce7 43
emilmont 10:3bc89ef62ce7 44 static const PinMap PinMap_CAN_TD[] = {
emilmont 10:3bc89ef62ce7 45 {P0_1 , CAN_1, 1},
emilmont 10:3bc89ef62ce7 46 {P0_5 , CAN_2, 2},
emilmont 10:3bc89ef62ce7 47 {P0_22, CAN_1, 3},
emilmont 10:3bc89ef62ce7 48 {P2_8 , CAN_2, 1},
emilmont 10:3bc89ef62ce7 49 {NC , NC , 0}
emilmont 10:3bc89ef62ce7 50 };
emilmont 10:3bc89ef62ce7 51
emilmont 10:3bc89ef62ce7 52 // Type definition to hold a CAN message
emilmont 10:3bc89ef62ce7 53 struct CANMsg {
emilmont 10:3bc89ef62ce7 54 unsigned int reserved1 : 16;
emilmont 10:3bc89ef62ce7 55 unsigned int dlc : 4; // Bits 16..19: DLC - Data Length Counter
emilmont 10:3bc89ef62ce7 56 unsigned int reserved0 : 10;
emilmont 10:3bc89ef62ce7 57 unsigned int rtr : 1; // Bit 30: Set if this is a RTR message
emilmont 10:3bc89ef62ce7 58 unsigned int type : 1; // Bit 31: Set if this is a 29-bit ID message
emilmont 10:3bc89ef62ce7 59 unsigned int id; // CAN Message ID (11-bit or 29-bit)
emilmont 10:3bc89ef62ce7 60 unsigned char data[8]; // CAN Message Data Bytes 0-7
emilmont 10:3bc89ef62ce7 61 };
emilmont 10:3bc89ef62ce7 62 typedef struct CANMsg CANMsg;
emilmont 10:3bc89ef62ce7 63
emilmont 10:3bc89ef62ce7 64 static uint32_t can_disable(can_t *obj) {
emilmont 10:3bc89ef62ce7 65 uint32_t sm = obj->dev->MOD;
emilmont 10:3bc89ef62ce7 66 obj->dev->MOD |= 1;
emilmont 10:3bc89ef62ce7 67 return sm;
emilmont 10:3bc89ef62ce7 68 }
emilmont 10:3bc89ef62ce7 69
emilmont 10:3bc89ef62ce7 70 static inline void can_enable(can_t *obj) {
emilmont 10:3bc89ef62ce7 71 if (obj->dev->MOD & 1) {
emilmont 10:3bc89ef62ce7 72 obj->dev->MOD &= ~(1);
emilmont 10:3bc89ef62ce7 73 }
emilmont 10:3bc89ef62ce7 74 }
emilmont 10:3bc89ef62ce7 75
emilmont 10:3bc89ef62ce7 76 static int can_pclk(can_t *obj) {
emilmont 10:3bc89ef62ce7 77 int value = 0;
emilmont 10:3bc89ef62ce7 78 switch ((int)obj->dev) {
emilmont 10:3bc89ef62ce7 79 case CAN_1: value = (LPC_SC->PCLKSEL0 & (0x3 << 26)) >> 26; break;
emilmont 10:3bc89ef62ce7 80 case CAN_2: value = (LPC_SC->PCLKSEL0 & (0x3 << 28)) >> 28; break;
emilmont 10:3bc89ef62ce7 81 }
emilmont 10:3bc89ef62ce7 82
emilmont 10:3bc89ef62ce7 83 switch (value) {
emilmont 10:3bc89ef62ce7 84 case 1: return 1;
emilmont 10:3bc89ef62ce7 85 case 2: return 2;
emilmont 10:3bc89ef62ce7 86 case 3: return 6;
emilmont 10:3bc89ef62ce7 87 default: return 4;
emilmont 10:3bc89ef62ce7 88 }
emilmont 10:3bc89ef62ce7 89 }
emilmont 10:3bc89ef62ce7 90
emilmont 10:3bc89ef62ce7 91 // This table has the sampling points as close to 75% as possible. The first
emilmont 10:3bc89ef62ce7 92 // value is TSEG1, the second TSEG2.
emilmont 10:3bc89ef62ce7 93 static const int timing_pts[23][2] = {
emilmont 10:3bc89ef62ce7 94 {0x0, 0x0}, // 2, 50%
emilmont 10:3bc89ef62ce7 95 {0x1, 0x0}, // 3, 67%
emilmont 10:3bc89ef62ce7 96 {0x2, 0x0}, // 4, 75%
emilmont 10:3bc89ef62ce7 97 {0x3, 0x0}, // 5, 80%
emilmont 10:3bc89ef62ce7 98 {0x3, 0x1}, // 6, 67%
emilmont 10:3bc89ef62ce7 99 {0x4, 0x1}, // 7, 71%
emilmont 10:3bc89ef62ce7 100 {0x5, 0x1}, // 8, 75%
emilmont 10:3bc89ef62ce7 101 {0x6, 0x1}, // 9, 78%
emilmont 10:3bc89ef62ce7 102 {0x6, 0x2}, // 10, 70%
emilmont 10:3bc89ef62ce7 103 {0x7, 0x2}, // 11, 73%
emilmont 10:3bc89ef62ce7 104 {0x8, 0x2}, // 12, 75%
emilmont 10:3bc89ef62ce7 105 {0x9, 0x2}, // 13, 77%
emilmont 10:3bc89ef62ce7 106 {0x9, 0x3}, // 14, 71%
emilmont 10:3bc89ef62ce7 107 {0xA, 0x3}, // 15, 73%
emilmont 10:3bc89ef62ce7 108 {0xB, 0x3}, // 16, 75%
emilmont 10:3bc89ef62ce7 109 {0xC, 0x3}, // 17, 76%
emilmont 10:3bc89ef62ce7 110 {0xD, 0x3}, // 18, 78%
emilmont 10:3bc89ef62ce7 111 {0xD, 0x4}, // 19, 74%
emilmont 10:3bc89ef62ce7 112 {0xE, 0x4}, // 20, 75%
emilmont 10:3bc89ef62ce7 113 {0xF, 0x4}, // 21, 76%
emilmont 10:3bc89ef62ce7 114 {0xF, 0x5}, // 22, 73%
emilmont 10:3bc89ef62ce7 115 {0xF, 0x6}, // 23, 70%
emilmont 10:3bc89ef62ce7 116 {0xF, 0x7}, // 24, 67%
emilmont 10:3bc89ef62ce7 117 };
emilmont 10:3bc89ef62ce7 118
emilmont 10:3bc89ef62ce7 119 static unsigned int can_speed(unsigned int sclk, unsigned int pclk, unsigned int cclk, unsigned char psjw) {
emilmont 10:3bc89ef62ce7 120 uint32_t btr;
emilmont 10:3bc89ef62ce7 121 uint16_t brp = 0;
emilmont 10:3bc89ef62ce7 122 uint32_t calcbit;
emilmont 10:3bc89ef62ce7 123 uint32_t bitwidth;
emilmont 10:3bc89ef62ce7 124 int hit = 0;
emilmont 10:3bc89ef62ce7 125 int bits;
emilmont 10:3bc89ef62ce7 126
emilmont 10:3bc89ef62ce7 127 bitwidth = sclk / (pclk * cclk);
emilmont 10:3bc89ef62ce7 128
emilmont 10:3bc89ef62ce7 129 brp = bitwidth / 0x18;
emilmont 10:3bc89ef62ce7 130 while ((!hit) && (brp < bitwidth / 4)) {
emilmont 10:3bc89ef62ce7 131 brp++;
emilmont 10:3bc89ef62ce7 132 for (bits = 22; bits > 0; bits--) {
emilmont 10:3bc89ef62ce7 133 calcbit = (bits + 3) * (brp + 1);
emilmont 10:3bc89ef62ce7 134 if (calcbit == bitwidth) {
emilmont 10:3bc89ef62ce7 135 hit = 1;
emilmont 10:3bc89ef62ce7 136 break;
emilmont 10:3bc89ef62ce7 137 }
emilmont 10:3bc89ef62ce7 138 }
emilmont 10:3bc89ef62ce7 139 }
emilmont 10:3bc89ef62ce7 140
emilmont 10:3bc89ef62ce7 141 if (hit) {
emilmont 10:3bc89ef62ce7 142 btr = ((timing_pts[bits][1] << 20) & 0x00700000)
emilmont 10:3bc89ef62ce7 143 | ((timing_pts[bits][0] << 16) & 0x000F0000)
emilmont 10:3bc89ef62ce7 144 | ((psjw << 14) & 0x0000C000)
emilmont 10:3bc89ef62ce7 145 | ((brp << 0) & 0x000003FF);
emilmont 10:3bc89ef62ce7 146 } else {
emilmont 10:3bc89ef62ce7 147 btr = 0xFFFFFFFF;
emilmont 10:3bc89ef62ce7 148 }
emilmont 10:3bc89ef62ce7 149
emilmont 10:3bc89ef62ce7 150 return btr;
emilmont 10:3bc89ef62ce7 151
emilmont 10:3bc89ef62ce7 152 }
emilmont 10:3bc89ef62ce7 153
emilmont 10:3bc89ef62ce7 154 void can_init(can_t *obj, PinName rd, PinName td) {
emilmont 10:3bc89ef62ce7 155 CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
emilmont 10:3bc89ef62ce7 156 CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
emilmont 10:3bc89ef62ce7 157 obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td);
emilmont 10:3bc89ef62ce7 158 if ((int)obj->dev == NC) {
emilmont 10:3bc89ef62ce7 159 error("CAN pin mapping failed");
emilmont 10:3bc89ef62ce7 160 }
emilmont 10:3bc89ef62ce7 161
emilmont 10:3bc89ef62ce7 162 switch ((int)obj->dev) {
emilmont 10:3bc89ef62ce7 163 case CAN_1: LPC_SC->PCONP |= 1 << 13; break;
emilmont 10:3bc89ef62ce7 164 case CAN_2: LPC_SC->PCONP |= 1 << 14; break;
emilmont 10:3bc89ef62ce7 165 }
emilmont 10:3bc89ef62ce7 166
emilmont 10:3bc89ef62ce7 167 pinmap_pinout(rd, PinMap_CAN_RD);
emilmont 10:3bc89ef62ce7 168 pinmap_pinout(td, PinMap_CAN_TD);
emilmont 10:3bc89ef62ce7 169
emilmont 10:3bc89ef62ce7 170 can_reset(obj);
emilmont 10:3bc89ef62ce7 171 obj->dev->IER = 0; // Disable Interrupts
emilmont 10:3bc89ef62ce7 172 can_frequency(obj, 100000);
emilmont 10:3bc89ef62ce7 173
emilmont 10:3bc89ef62ce7 174 LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter
emilmont 10:3bc89ef62ce7 175 }
emilmont 10:3bc89ef62ce7 176
emilmont 10:3bc89ef62ce7 177 void can_free(can_t *obj) {
emilmont 10:3bc89ef62ce7 178 switch ((int)obj->dev) {
emilmont 10:3bc89ef62ce7 179 case CAN_1: LPC_SC->PCONP &= ~(1 << 13); break;
emilmont 10:3bc89ef62ce7 180 case CAN_2: LPC_SC->PCONP &= ~(1 << 14); break;
emilmont 10:3bc89ef62ce7 181 }
emilmont 10:3bc89ef62ce7 182 }
emilmont 10:3bc89ef62ce7 183
emilmont 10:3bc89ef62ce7 184 int can_frequency(can_t *obj, int f) {
emilmont 10:3bc89ef62ce7 185 int pclk = can_pclk(obj);
emilmont 10:3bc89ef62ce7 186
emilmont 10:3bc89ef62ce7 187 int btr = can_speed(SystemCoreClock, pclk, (unsigned int)f, 1);
emilmont 10:3bc89ef62ce7 188
emilmont 10:3bc89ef62ce7 189 if (btr > 0) {
emilmont 10:3bc89ef62ce7 190 uint32_t modmask = can_disable(obj);
emilmont 10:3bc89ef62ce7 191 obj->dev->BTR = btr;
emilmont 10:3bc89ef62ce7 192 obj->dev->MOD = modmask;
emilmont 10:3bc89ef62ce7 193 return 1;
emilmont 10:3bc89ef62ce7 194 } else {
emilmont 10:3bc89ef62ce7 195 return 0;
emilmont 10:3bc89ef62ce7 196 }
emilmont 10:3bc89ef62ce7 197 }
emilmont 10:3bc89ef62ce7 198
emilmont 10:3bc89ef62ce7 199 int can_write(can_t *obj, CAN_Message msg, int cc) {
emilmont 10:3bc89ef62ce7 200 unsigned int CANStatus;
emilmont 10:3bc89ef62ce7 201 CANMsg m;
emilmont 10:3bc89ef62ce7 202
emilmont 10:3bc89ef62ce7 203 can_enable(obj);
emilmont 10:3bc89ef62ce7 204
emilmont 10:3bc89ef62ce7 205 m.id = msg.id ;
emilmont 10:3bc89ef62ce7 206 m.dlc = msg.len & 0xF;
emilmont 10:3bc89ef62ce7 207 m.rtr = msg.type;
emilmont 10:3bc89ef62ce7 208 m.type = msg.format;
emilmont 10:3bc89ef62ce7 209 memcpy(m.data, msg.data, msg.len);
emilmont 10:3bc89ef62ce7 210 const unsigned int *buf = (const unsigned int *)&m;
emilmont 10:3bc89ef62ce7 211
emilmont 10:3bc89ef62ce7 212 CANStatus = obj->dev->SR;
emilmont 10:3bc89ef62ce7 213 if (CANStatus & 0x00000004) {
emilmont 10:3bc89ef62ce7 214 obj->dev->TFI1 = buf[0] & 0xC00F0000;
emilmont 10:3bc89ef62ce7 215 obj->dev->TID1 = buf[1];
emilmont 10:3bc89ef62ce7 216 obj->dev->TDA1 = buf[2];
emilmont 10:3bc89ef62ce7 217 obj->dev->TDB1 = buf[3];
emilmont 10:3bc89ef62ce7 218 if(cc) {
emilmont 10:3bc89ef62ce7 219 obj->dev->CMR = 0x30;
emilmont 10:3bc89ef62ce7 220 } else {
emilmont 10:3bc89ef62ce7 221 obj->dev->CMR = 0x21;
emilmont 10:3bc89ef62ce7 222 }
emilmont 10:3bc89ef62ce7 223 return 1;
emilmont 10:3bc89ef62ce7 224
emilmont 10:3bc89ef62ce7 225 } else if (CANStatus & 0x00000400) {
emilmont 10:3bc89ef62ce7 226 obj->dev->TFI2 = buf[0] & 0xC00F0000;
emilmont 10:3bc89ef62ce7 227 obj->dev->TID2 = buf[1];
emilmont 10:3bc89ef62ce7 228 obj->dev->TDA2 = buf[2];
emilmont 10:3bc89ef62ce7 229 obj->dev->TDB2 = buf[3];
emilmont 10:3bc89ef62ce7 230 if (cc) {
emilmont 10:3bc89ef62ce7 231 obj->dev->CMR = 0x50;
emilmont 10:3bc89ef62ce7 232 } else {
emilmont 10:3bc89ef62ce7 233 obj->dev->CMR = 0x41;
emilmont 10:3bc89ef62ce7 234 }
emilmont 10:3bc89ef62ce7 235 return 1;
emilmont 10:3bc89ef62ce7 236
emilmont 10:3bc89ef62ce7 237 } else if (CANStatus & 0x00040000) {
emilmont 10:3bc89ef62ce7 238 obj->dev->TFI3 = buf[0] & 0xC00F0000;
emilmont 10:3bc89ef62ce7 239 obj->dev->TID3 = buf[1];
emilmont 10:3bc89ef62ce7 240 obj->dev->TDA3 = buf[2];
emilmont 10:3bc89ef62ce7 241 obj->dev->TDB3 = buf[3];
emilmont 10:3bc89ef62ce7 242 if (cc) {
emilmont 10:3bc89ef62ce7 243 obj->dev->CMR = 0x90;
emilmont 10:3bc89ef62ce7 244 } else {
emilmont 10:3bc89ef62ce7 245 obj->dev->CMR = 0x81;
emilmont 10:3bc89ef62ce7 246 }
emilmont 10:3bc89ef62ce7 247 return 1;
emilmont 10:3bc89ef62ce7 248 }
emilmont 10:3bc89ef62ce7 249
emilmont 10:3bc89ef62ce7 250 return 0;
emilmont 10:3bc89ef62ce7 251 }
emilmont 10:3bc89ef62ce7 252
emilmont 10:3bc89ef62ce7 253 int can_read(can_t *obj, CAN_Message *msg) {
emilmont 10:3bc89ef62ce7 254 CANMsg x;
emilmont 10:3bc89ef62ce7 255 unsigned int *i = (unsigned int *)&x;
emilmont 10:3bc89ef62ce7 256
emilmont 10:3bc89ef62ce7 257 can_enable(obj);
emilmont 10:3bc89ef62ce7 258
emilmont 10:3bc89ef62ce7 259 if (obj->dev->GSR & 0x1) {
emilmont 10:3bc89ef62ce7 260 *i++ = obj->dev->RFS; // Frame
emilmont 10:3bc89ef62ce7 261 *i++ = obj->dev->RID; // ID
emilmont 10:3bc89ef62ce7 262 *i++ = obj->dev->RDA; // Data A
emilmont 10:3bc89ef62ce7 263 *i++ = obj->dev->RDB; // Data B
emilmont 10:3bc89ef62ce7 264 obj->dev->CMR = 0x04; // release receive buffer
emilmont 10:3bc89ef62ce7 265
emilmont 10:3bc89ef62ce7 266 msg->id = x.id;
emilmont 10:3bc89ef62ce7 267 msg->len = x.dlc;
emilmont 10:3bc89ef62ce7 268 msg->format = (x.type)? CANExtended : CANStandard;
emilmont 10:3bc89ef62ce7 269 msg->type = (x.rtr)? CANRemote: CANData;
emilmont 10:3bc89ef62ce7 270 memcpy(msg->data,x.data,x.dlc);
emilmont 10:3bc89ef62ce7 271 return 1;
emilmont 10:3bc89ef62ce7 272 }
emilmont 10:3bc89ef62ce7 273
emilmont 10:3bc89ef62ce7 274 return 0;
emilmont 10:3bc89ef62ce7 275 }
emilmont 10:3bc89ef62ce7 276
emilmont 10:3bc89ef62ce7 277 void can_reset(can_t *obj) {
emilmont 10:3bc89ef62ce7 278 can_disable(obj);
emilmont 10:3bc89ef62ce7 279 obj->dev->GSR = 0; // Reset error counter when CAN1MOD is in reset
emilmont 10:3bc89ef62ce7 280 }
emilmont 10:3bc89ef62ce7 281
emilmont 10:3bc89ef62ce7 282 unsigned char can_rderror(can_t *obj) {
emilmont 10:3bc89ef62ce7 283 return (obj->dev->GSR >> 16) & 0xFF;
emilmont 10:3bc89ef62ce7 284 }
emilmont 10:3bc89ef62ce7 285
emilmont 10:3bc89ef62ce7 286 unsigned char can_tderror(can_t *obj) {
emilmont 10:3bc89ef62ce7 287 return (obj->dev->GSR >> 24) & 0xFF;
emilmont 10:3bc89ef62ce7 288 }
emilmont 10:3bc89ef62ce7 289
emilmont 10:3bc89ef62ce7 290 void can_monitor(can_t *obj, int silent) {
emilmont 10:3bc89ef62ce7 291 uint32_t mod_mask = can_disable(obj);
emilmont 10:3bc89ef62ce7 292 if (silent) {
emilmont 10:3bc89ef62ce7 293 obj->dev->MOD |= (1 << 1);
emilmont 10:3bc89ef62ce7 294 } else {
emilmont 10:3bc89ef62ce7 295 obj->dev->MOD &= ~(1 << 1);
emilmont 10:3bc89ef62ce7 296 }
emilmont 10:3bc89ef62ce7 297 if (!(mod_mask & 1)) {
emilmont 10:3bc89ef62ce7 298 can_enable(obj);
emilmont 10:3bc89ef62ce7 299 }
emilmont 10:3bc89ef62ce7 300 }