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:
emilmont
Date:
Fri Jun 14 17:49:17 2013 +0100
Revision:
10:3bc89ef62ce7
Unify mbed library sources

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