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
Child:
16:7da2369b400c
Added LPC4088 target and interrupt chaining code

Who changed what in which revision?

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