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 <math.h>
emilmont 10:3bc89ef62ce7 17 #include <string.h>
emilmont 10:3bc89ef62ce7 18
emilmont 10:3bc89ef62ce7 19 #include "can_api.h"
emilmont 10:3bc89ef62ce7 20 #include "cmsis.h"
emilmont 10:3bc89ef62ce7 21 #include "pinmap.h"
emilmont 10:3bc89ef62ce7 22 #include "error.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, 4},
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, 4},
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 // This table has the sampling points as close to 75% as possible. The first
emilmont 10:3bc89ef62ce7 76 // value is TSEG1, the second TSEG2.
emilmont 10:3bc89ef62ce7 77 static const int timing_pts[23][2] = {
emilmont 10:3bc89ef62ce7 78 {0x0, 0x0}, // 2, 50%
emilmont 10:3bc89ef62ce7 79 {0x1, 0x0}, // 3, 67%
emilmont 10:3bc89ef62ce7 80 {0x2, 0x0}, // 4, 75%
emilmont 10:3bc89ef62ce7 81 {0x3, 0x0}, // 5, 80%
emilmont 10:3bc89ef62ce7 82 {0x3, 0x1}, // 6, 67%
emilmont 10:3bc89ef62ce7 83 {0x4, 0x1}, // 7, 71%
emilmont 10:3bc89ef62ce7 84 {0x5, 0x1}, // 8, 75%
emilmont 10:3bc89ef62ce7 85 {0x6, 0x1}, // 9, 78%
emilmont 10:3bc89ef62ce7 86 {0x6, 0x2}, // 10, 70%
emilmont 10:3bc89ef62ce7 87 {0x7, 0x2}, // 11, 73%
emilmont 10:3bc89ef62ce7 88 {0x8, 0x2}, // 12, 75%
emilmont 10:3bc89ef62ce7 89 {0x9, 0x2}, // 13, 77%
emilmont 10:3bc89ef62ce7 90 {0x9, 0x3}, // 14, 71%
emilmont 10:3bc89ef62ce7 91 {0xA, 0x3}, // 15, 73%
emilmont 10:3bc89ef62ce7 92 {0xB, 0x3}, // 16, 75%
emilmont 10:3bc89ef62ce7 93 {0xC, 0x3}, // 17, 76%
emilmont 10:3bc89ef62ce7 94 {0xD, 0x3}, // 18, 78%
emilmont 10:3bc89ef62ce7 95 {0xD, 0x4}, // 19, 74%
emilmont 10:3bc89ef62ce7 96 {0xE, 0x4}, // 20, 75%
emilmont 10:3bc89ef62ce7 97 {0xF, 0x4}, // 21, 76%
emilmont 10:3bc89ef62ce7 98 {0xF, 0x5}, // 22, 73%
emilmont 10:3bc89ef62ce7 99 {0xF, 0x6}, // 23, 70%
emilmont 10:3bc89ef62ce7 100 {0xF, 0x7}, // 24, 67%
emilmont 10:3bc89ef62ce7 101 };
emilmont 10:3bc89ef62ce7 102
emilmont 10:3bc89ef62ce7 103 static unsigned int can_speed(unsigned int sclk, unsigned int pclk, unsigned int cclk, unsigned char psjw) {
emilmont 10:3bc89ef62ce7 104 uint32_t btr;
emilmont 10:3bc89ef62ce7 105 uint16_t brp = 0;
emilmont 10:3bc89ef62ce7 106 uint32_t calcbit;
emilmont 10:3bc89ef62ce7 107 uint32_t bitwidth;
emilmont 10:3bc89ef62ce7 108 int hit = 0;
emilmont 10:3bc89ef62ce7 109 int bits;
emilmont 10:3bc89ef62ce7 110
emilmont 10:3bc89ef62ce7 111 bitwidth = sclk / (pclk * cclk);
emilmont 10:3bc89ef62ce7 112
emilmont 10:3bc89ef62ce7 113 brp = bitwidth / 0x18;
emilmont 10:3bc89ef62ce7 114 while ((!hit) && (brp < bitwidth / 4)) {
emilmont 10:3bc89ef62ce7 115 brp++;
emilmont 10:3bc89ef62ce7 116 for (bits = 22; bits > 0; bits--) {
emilmont 10:3bc89ef62ce7 117 calcbit = (bits + 3) * (brp + 1);
emilmont 10:3bc89ef62ce7 118 if (calcbit == bitwidth) {
emilmont 10:3bc89ef62ce7 119 hit = 1;
emilmont 10:3bc89ef62ce7 120 break;
emilmont 10:3bc89ef62ce7 121 }
emilmont 10:3bc89ef62ce7 122 }
emilmont 10:3bc89ef62ce7 123 }
emilmont 10:3bc89ef62ce7 124
emilmont 10:3bc89ef62ce7 125 if (hit) {
emilmont 10:3bc89ef62ce7 126 btr = ((timing_pts[bits][1] << 20) & 0x00700000)
emilmont 10:3bc89ef62ce7 127 | ((timing_pts[bits][0] << 16) & 0x000F0000)
emilmont 10:3bc89ef62ce7 128 | ((psjw << 14) & 0x0000C000)
emilmont 10:3bc89ef62ce7 129 | ((brp << 0) & 0x000003FF);
emilmont 10:3bc89ef62ce7 130 } else {
emilmont 10:3bc89ef62ce7 131 btr = 0xFFFFFFFF;
emilmont 10:3bc89ef62ce7 132 }
emilmont 10:3bc89ef62ce7 133
emilmont 10:3bc89ef62ce7 134 return btr;
emilmont 10:3bc89ef62ce7 135 }
emilmont 10:3bc89ef62ce7 136
emilmont 10:3bc89ef62ce7 137 void can_init(can_t *obj, PinName rd, PinName td) {
emilmont 10:3bc89ef62ce7 138 CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
emilmont 10:3bc89ef62ce7 139 CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
emilmont 10:3bc89ef62ce7 140 obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td);
emilmont 10:3bc89ef62ce7 141 if ((int)obj->dev == NC) {
emilmont 10:3bc89ef62ce7 142 error("CAN pin mapping failed");
emilmont 10:3bc89ef62ce7 143 }
emilmont 10:3bc89ef62ce7 144
emilmont 10:3bc89ef62ce7 145 switch ((int)obj->dev) {
emilmont 10:3bc89ef62ce7 146 case CAN_1: LPC_SC->PCONP |= 1 << 13; break;
emilmont 10:3bc89ef62ce7 147 case CAN_2: LPC_SC->PCONP |= 1 << 14; break;
emilmont 10:3bc89ef62ce7 148 }
emilmont 10:3bc89ef62ce7 149
emilmont 10:3bc89ef62ce7 150 pinmap_pinout(rd, PinMap_CAN_RD);
emilmont 10:3bc89ef62ce7 151 pinmap_pinout(td, PinMap_CAN_TD);
emilmont 10:3bc89ef62ce7 152
emilmont 10:3bc89ef62ce7 153 can_reset(obj);
emilmont 10:3bc89ef62ce7 154 obj->dev->IER = 0; // Disable Interrupts
emilmont 10:3bc89ef62ce7 155 can_frequency(obj, 100000);
emilmont 10:3bc89ef62ce7 156
emilmont 10:3bc89ef62ce7 157 LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter
emilmont 10:3bc89ef62ce7 158 }
emilmont 10:3bc89ef62ce7 159
emilmont 10:3bc89ef62ce7 160 void can_free(can_t *obj) {
emilmont 10:3bc89ef62ce7 161 switch ((int)obj->dev) {
emilmont 10:3bc89ef62ce7 162 case CAN_1: LPC_SC->PCONP &= ~(1 << 13); break;
emilmont 10:3bc89ef62ce7 163 case CAN_2: LPC_SC->PCONP &= ~(1 << 14); break;
emilmont 10:3bc89ef62ce7 164 }
emilmont 10:3bc89ef62ce7 165 }
emilmont 10:3bc89ef62ce7 166
emilmont 10:3bc89ef62ce7 167 int can_frequency(can_t *obj, int f) {
emilmont 10:3bc89ef62ce7 168 int pclk = PeripheralClock;
emilmont 10:3bc89ef62ce7 169 int btr = can_speed(SystemCoreClock, pclk, (unsigned int)f, 1);
emilmont 10:3bc89ef62ce7 170
emilmont 10:3bc89ef62ce7 171 if (btr > 0) {
emilmont 10:3bc89ef62ce7 172 uint32_t modmask = can_disable(obj);
emilmont 10:3bc89ef62ce7 173 obj->dev->BTR = btr;
emilmont 10:3bc89ef62ce7 174 obj->dev->MOD = modmask;
emilmont 10:3bc89ef62ce7 175 return 1;
emilmont 10:3bc89ef62ce7 176 } else {
emilmont 10:3bc89ef62ce7 177 return 0;
emilmont 10:3bc89ef62ce7 178 }
emilmont 10:3bc89ef62ce7 179 }
emilmont 10:3bc89ef62ce7 180
emilmont 10:3bc89ef62ce7 181 int can_write(can_t *obj, CAN_Message msg, int cc) {
emilmont 10:3bc89ef62ce7 182 unsigned int CANStatus;
emilmont 10:3bc89ef62ce7 183 CANMsg m;
emilmont 10:3bc89ef62ce7 184
emilmont 10:3bc89ef62ce7 185 can_enable(obj);
emilmont 10:3bc89ef62ce7 186
emilmont 10:3bc89ef62ce7 187 m.id = msg.id ;
emilmont 10:3bc89ef62ce7 188 m.dlc = msg.len & 0xF;
emilmont 10:3bc89ef62ce7 189 m.rtr = msg.type;
emilmont 10:3bc89ef62ce7 190 m.type = msg.format;
emilmont 10:3bc89ef62ce7 191 memcpy(m.data, msg.data, msg.len);
emilmont 10:3bc89ef62ce7 192 const unsigned int *buf = (const unsigned int *)&m;
emilmont 10:3bc89ef62ce7 193
emilmont 10:3bc89ef62ce7 194 CANStatus = obj->dev->SR;
emilmont 10:3bc89ef62ce7 195 if (CANStatus & 0x00000004) {
emilmont 10:3bc89ef62ce7 196 obj->dev->TFI1 = buf[0] & 0xC00F0000;
emilmont 10:3bc89ef62ce7 197 obj->dev->TID1 = buf[1];
emilmont 10:3bc89ef62ce7 198 obj->dev->TDA1 = buf[2];
emilmont 10:3bc89ef62ce7 199 obj->dev->TDB1 = buf[3];
emilmont 10:3bc89ef62ce7 200 if(cc) {
emilmont 10:3bc89ef62ce7 201 obj->dev->CMR = 0x30;
emilmont 10:3bc89ef62ce7 202 } else {
emilmont 10:3bc89ef62ce7 203 obj->dev->CMR = 0x21;
emilmont 10:3bc89ef62ce7 204 }
emilmont 10:3bc89ef62ce7 205 return 1;
emilmont 10:3bc89ef62ce7 206
emilmont 10:3bc89ef62ce7 207 } else if (CANStatus & 0x00000400) {
emilmont 10:3bc89ef62ce7 208 obj->dev->TFI2 = buf[0] & 0xC00F0000;
emilmont 10:3bc89ef62ce7 209 obj->dev->TID2 = buf[1];
emilmont 10:3bc89ef62ce7 210 obj->dev->TDA2 = buf[2];
emilmont 10:3bc89ef62ce7 211 obj->dev->TDB2 = buf[3];
emilmont 10:3bc89ef62ce7 212 if (cc) {
emilmont 10:3bc89ef62ce7 213 obj->dev->CMR = 0x50;
emilmont 10:3bc89ef62ce7 214 } else {
emilmont 10:3bc89ef62ce7 215 obj->dev->CMR = 0x41;
emilmont 10:3bc89ef62ce7 216 }
emilmont 10:3bc89ef62ce7 217 return 1;
emilmont 10:3bc89ef62ce7 218
emilmont 10:3bc89ef62ce7 219 } else if (CANStatus & 0x00040000) {
emilmont 10:3bc89ef62ce7 220 obj->dev->TFI3 = buf[0] & 0xC00F0000;
emilmont 10:3bc89ef62ce7 221 obj->dev->TID3 = buf[1];
emilmont 10:3bc89ef62ce7 222 obj->dev->TDA3 = buf[2];
emilmont 10:3bc89ef62ce7 223 obj->dev->TDB3 = buf[3];
emilmont 10:3bc89ef62ce7 224 if (cc) {
emilmont 10:3bc89ef62ce7 225 obj->dev->CMR = 0x90;
emilmont 10:3bc89ef62ce7 226 } else {
emilmont 10:3bc89ef62ce7 227 obj->dev->CMR = 0x81;
emilmont 10:3bc89ef62ce7 228 }
emilmont 10:3bc89ef62ce7 229 return 1;
emilmont 10:3bc89ef62ce7 230 }
emilmont 10:3bc89ef62ce7 231
emilmont 10:3bc89ef62ce7 232 return 0;
emilmont 10:3bc89ef62ce7 233 }
emilmont 10:3bc89ef62ce7 234
emilmont 10:3bc89ef62ce7 235 int can_read(can_t *obj, CAN_Message *msg) {
emilmont 10:3bc89ef62ce7 236 CANMsg x;
emilmont 10:3bc89ef62ce7 237 unsigned int *i = (unsigned int *)&x;
emilmont 10:3bc89ef62ce7 238
emilmont 10:3bc89ef62ce7 239 can_enable(obj);
emilmont 10:3bc89ef62ce7 240
emilmont 10:3bc89ef62ce7 241 if (obj->dev->GSR & 0x1) {
emilmont 10:3bc89ef62ce7 242 *i++ = obj->dev->RFS; // Frame
emilmont 10:3bc89ef62ce7 243 *i++ = obj->dev->RID; // ID
emilmont 10:3bc89ef62ce7 244 *i++ = obj->dev->RDA; // Data A
emilmont 10:3bc89ef62ce7 245 *i++ = obj->dev->RDB; // Data B
emilmont 10:3bc89ef62ce7 246 obj->dev->CMR = 0x04; // release receive buffer
emilmont 10:3bc89ef62ce7 247
emilmont 10:3bc89ef62ce7 248 msg->id = x.id;
emilmont 10:3bc89ef62ce7 249 msg->len = x.dlc;
emilmont 10:3bc89ef62ce7 250 msg->format = (x.type)? CANExtended : CANStandard;
emilmont 10:3bc89ef62ce7 251 msg->type = (x.rtr)? CANRemote: CANData;
emilmont 10:3bc89ef62ce7 252 memcpy(msg->data,x.data,x.dlc);
emilmont 10:3bc89ef62ce7 253 return 1;
emilmont 10:3bc89ef62ce7 254 }
emilmont 10:3bc89ef62ce7 255
emilmont 10:3bc89ef62ce7 256 return 0;
emilmont 10:3bc89ef62ce7 257 }
emilmont 10:3bc89ef62ce7 258
emilmont 10:3bc89ef62ce7 259 void can_reset(can_t *obj) {
emilmont 10:3bc89ef62ce7 260 can_disable(obj);
emilmont 10:3bc89ef62ce7 261 obj->dev->GSR = 0; // Reset error counter when CAN1MOD is in reset
emilmont 10:3bc89ef62ce7 262 }
emilmont 10:3bc89ef62ce7 263
emilmont 10:3bc89ef62ce7 264 unsigned char can_rderror(can_t *obj) {
emilmont 10:3bc89ef62ce7 265 return (obj->dev->GSR >> 16) & 0xFF;
emilmont 10:3bc89ef62ce7 266 }
emilmont 10:3bc89ef62ce7 267
emilmont 10:3bc89ef62ce7 268 unsigned char can_tderror(can_t *obj) {
emilmont 10:3bc89ef62ce7 269 return (obj->dev->GSR >> 24) & 0xFF;
emilmont 10:3bc89ef62ce7 270 }
emilmont 10:3bc89ef62ce7 271
emilmont 10:3bc89ef62ce7 272 void can_monitor(can_t *obj, int silent) {
emilmont 10:3bc89ef62ce7 273 uint32_t mod_mask = can_disable(obj);
emilmont 10:3bc89ef62ce7 274 if (silent) {
emilmont 10:3bc89ef62ce7 275 obj->dev->MOD |= (1 << 1);
emilmont 10:3bc89ef62ce7 276 } else {
emilmont 10:3bc89ef62ce7 277 obj->dev->MOD &= ~(1 << 1);
emilmont 10:3bc89ef62ce7 278 }
emilmont 10:3bc89ef62ce7 279 if (!(mod_mask & 1)) {
emilmont 10:3bc89ef62ce7 280 can_enable(obj);
emilmont 10:3bc89ef62ce7 281 }
emilmont 10:3bc89ef62ce7 282 }