Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
can_api.c
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "can_api.h" 00017 00018 #if DEVICE_CAN 00019 00020 #include "cmsis.h" 00021 00022 #include "pinmap.h" 00023 #include "error.h" 00024 00025 #include <math.h> 00026 #include <string.h> 00027 00028 /* Acceptance filter mode in AFMR register */ 00029 #define ACCF_OFF 0x01 00030 #define ACCF_BYPASS 0x02 00031 #define ACCF_ON 0x00 00032 #define ACCF_FULLCAN 0x04 00033 00034 /* There are several bit timing calculators on the internet. 00035 http://www.port.de/engl/canprod/sv_req_form.html 00036 http://www.kvaser.com/can/index.htm 00037 */ 00038 00039 static const PinMap PinMap_CAN_RD[] = { 00040 {P0_0 , CAN_1, 1}, 00041 {P0_4 , CAN_2, 2}, 00042 {P0_21, CAN_1, 3}, 00043 {P2_7 , CAN_2, 1}, 00044 {NC , NC , 0} 00045 }; 00046 00047 static const PinMap PinMap_CAN_TD[] = { 00048 {P0_1 , CAN_1, 1}, 00049 {P0_5 , CAN_2, 2}, 00050 {P0_22, CAN_1, 3}, 00051 {P2_8 , CAN_2, 1}, 00052 {NC , NC , 0} 00053 }; 00054 00055 // Type definition to hold a CAN message 00056 struct CANMsg { 00057 unsigned int reserved1 : 16; 00058 unsigned int dlc : 4; // Bits 16..19: DLC - Data Length Counter 00059 unsigned int reserved0 : 10; 00060 unsigned int rtr : 1; // Bit 30: Set if this is a RTR message 00061 unsigned int type : 1; // Bit 31: Set if this is a 29-bit ID message 00062 unsigned int id; // CAN Message ID (11-bit or 29-bit) 00063 unsigned char data[8]; // CAN Message Data Bytes 0-7 00064 }; 00065 typedef struct CANMsg CANMsg; 00066 00067 static uint32_t can_disable(can_t *obj) { 00068 uint32_t sm = obj->dev->MOD; 00069 obj->dev->MOD |= 1; 00070 return sm; 00071 } 00072 00073 static inline void can_enable(can_t *obj) { 00074 if (obj->dev->MOD & 1) { 00075 obj->dev->MOD &= ~(1); 00076 } 00077 } 00078 00079 static int can_pclk(can_t *obj) { 00080 int value = 0; 00081 switch ((int)obj->dev) { 00082 case CAN_1: value = (LPC_SC->PCLKSEL0 & (0x3 << 26)) >> 26; break; 00083 case CAN_2: value = (LPC_SC->PCLKSEL0 & (0x3 << 28)) >> 28; break; 00084 } 00085 00086 switch (value) { 00087 case 1: return 1; 00088 case 2: return 2; 00089 case 3: return 6; 00090 default: return 4; 00091 } 00092 } 00093 00094 // This table has the sampling points as close to 75% as possible. The first 00095 // value is TSEG1, the second TSEG2. 00096 static const int timing_pts[23][2] = { 00097 {0x0, 0x0}, // 2, 50% 00098 {0x1, 0x0}, // 3, 67% 00099 {0x2, 0x0}, // 4, 75% 00100 {0x3, 0x0}, // 5, 80% 00101 {0x3, 0x1}, // 6, 67% 00102 {0x4, 0x1}, // 7, 71% 00103 {0x5, 0x1}, // 8, 75% 00104 {0x6, 0x1}, // 9, 78% 00105 {0x6, 0x2}, // 10, 70% 00106 {0x7, 0x2}, // 11, 73% 00107 {0x8, 0x2}, // 12, 75% 00108 {0x9, 0x2}, // 13, 77% 00109 {0x9, 0x3}, // 14, 71% 00110 {0xA, 0x3}, // 15, 73% 00111 {0xB, 0x3}, // 16, 75% 00112 {0xC, 0x3}, // 17, 76% 00113 {0xD, 0x3}, // 18, 78% 00114 {0xD, 0x4}, // 19, 74% 00115 {0xE, 0x4}, // 20, 75% 00116 {0xF, 0x4}, // 21, 76% 00117 {0xF, 0x5}, // 22, 73% 00118 {0xF, 0x6}, // 23, 70% 00119 {0xF, 0x7}, // 24, 67% 00120 }; 00121 00122 static unsigned int can_speed(unsigned int sclk, unsigned int pclk, unsigned int cclk, unsigned char psjw) { 00123 uint32_t btr; 00124 uint16_t brp = 0; 00125 uint32_t calcbit; 00126 uint32_t bitwidth; 00127 int hit = 0; 00128 int bits; 00129 00130 bitwidth = sclk / (pclk * cclk); 00131 00132 brp = bitwidth / 0x18; 00133 while ((!hit) && (brp < bitwidth / 4)) { 00134 brp++; 00135 for (bits = 22; bits > 0; bits--) { 00136 calcbit = (bits + 3) * (brp + 1); 00137 if (calcbit == bitwidth) { 00138 hit = 1; 00139 break; 00140 } 00141 } 00142 } 00143 00144 if (hit) { 00145 btr = ((timing_pts[bits][1] << 20) & 0x00700000) 00146 | ((timing_pts[bits][0] << 16) & 0x000F0000) 00147 | ((psjw << 14) & 0x0000C000) 00148 | ((brp << 0) & 0x000003FF); 00149 } else { 00150 btr = 0xFFFFFFFF; 00151 } 00152 00153 return btr; 00154 00155 } 00156 00157 void can_init(can_t *obj, PinName rd, PinName td) { 00158 CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD); 00159 CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD); 00160 obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td); 00161 if ((int)obj->dev == NC) { 00162 error("CAN pin mapping failed"); 00163 } 00164 00165 switch ((int)obj->dev) { 00166 case CAN_1: LPC_SC->PCONP |= 1 << 13; break; 00167 case CAN_2: LPC_SC->PCONP |= 1 << 14; break; 00168 } 00169 00170 pinmap_pinout(rd, PinMap_CAN_RD); 00171 pinmap_pinout(td, PinMap_CAN_TD); 00172 00173 can_reset(obj); 00174 obj->dev->IER = 0; // Disable Interrupts 00175 can_frequency(obj, 100000); 00176 00177 LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter 00178 } 00179 00180 void can_free(can_t *obj) { 00181 switch ((int)obj->dev) { 00182 case CAN_1: LPC_SC->PCONP &= ~(1 << 13); break; 00183 case CAN_2: LPC_SC->PCONP &= ~(1 << 14); break; 00184 } 00185 } 00186 00187 int can_frequency(can_t *obj, int f) { 00188 int pclk = can_pclk(obj); 00189 int btr = can_speed(SystemCoreClock , pclk, (unsigned int)f, 1); 00190 00191 if (btr > 0) { 00192 uint32_t modmask = can_disable(obj); 00193 obj->dev->BTR = btr; 00194 obj->dev->MOD = modmask; 00195 return 1; 00196 } else { 00197 return 0; 00198 } 00199 } 00200 00201 int can_write(can_t *obj, CAN_Message msg, int cc) { 00202 unsigned int CANStatus; 00203 CANMsg m; 00204 00205 can_enable(obj); 00206 00207 m.id = msg.id ; 00208 m.dlc = msg.len & 0xF; 00209 m.rtr = msg.type; 00210 m.type = msg.format; 00211 memcpy(m.data, msg.data, msg.len); 00212 const unsigned int *buf = (const unsigned int *)&m; 00213 00214 CANStatus = obj->dev->SR; 00215 if (CANStatus & 0x00000004) { 00216 obj->dev->TFI1 = buf[0] & 0xC00F0000; 00217 obj->dev->TID1 = buf[1]; 00218 obj->dev->TDA1 = buf[2]; 00219 obj->dev->TDB1 = buf[3]; 00220 if(cc) { 00221 obj->dev->CMR = 0x30; 00222 } else { 00223 obj->dev->CMR = 0x21; 00224 } 00225 return 1; 00226 00227 } else if (CANStatus & 0x00000400) { 00228 obj->dev->TFI2 = buf[0] & 0xC00F0000; 00229 obj->dev->TID2 = buf[1]; 00230 obj->dev->TDA2 = buf[2]; 00231 obj->dev->TDB2 = buf[3]; 00232 if (cc) { 00233 obj->dev->CMR = 0x50; 00234 } else { 00235 obj->dev->CMR = 0x41; 00236 } 00237 return 1; 00238 00239 } else if (CANStatus & 0x00040000) { 00240 obj->dev->TFI3 = buf[0] & 0xC00F0000; 00241 obj->dev->TID3 = buf[1]; 00242 obj->dev->TDA3 = buf[2]; 00243 obj->dev->TDB3 = buf[3]; 00244 if (cc) { 00245 obj->dev->CMR = 0x90; 00246 } else { 00247 obj->dev->CMR = 0x81; 00248 } 00249 return 1; 00250 } 00251 00252 return 0; 00253 } 00254 00255 int can_read(can_t *obj, CAN_Message *msg) { 00256 CANMsg x; 00257 unsigned int *i = (unsigned int *)&x; 00258 00259 can_enable(obj); 00260 00261 if (obj->dev->GSR & 0x1) { 00262 *i++ = obj->dev->RFS; // Frame 00263 *i++ = obj->dev->RID; // ID 00264 *i++ = obj->dev->RDA; // Data A 00265 *i++ = obj->dev->RDB; // Data B 00266 obj->dev->CMR = 0x04; // release receive buffer 00267 00268 msg->id = x.id; 00269 msg->len = x.dlc; 00270 msg->format = (x.type)? CANExtended : CANStandard; 00271 msg->type = (x.rtr)? CANRemote: CANData; 00272 memcpy(msg->data,x.data,x.dlc); 00273 return 1; 00274 } 00275 00276 return 0; 00277 } 00278 00279 void can_reset(can_t *obj) { 00280 can_disable(obj); 00281 obj->dev->GSR = 0; // Reset error counter when CAN1MOD is in reset 00282 } 00283 00284 unsigned char can_rderror(can_t *obj) { 00285 return (obj->dev->GSR >> 16) & 0xFF; 00286 } 00287 00288 unsigned char can_tderror(can_t *obj) { 00289 return (obj->dev->GSR >> 24) & 0xFF; 00290 } 00291 00292 void can_monitor(can_t *obj, int silent) { 00293 uint32_t mod_mask = can_disable(obj); 00294 if (silent) { 00295 obj->dev->MOD |= (1 << 1); 00296 } else { 00297 obj->dev->MOD &= ~(1 << 1); 00298 } 00299 if (!(mod_mask & 1)) { 00300 can_enable(obj); 00301 } 00302 } 00303 00304 #endif 00305
Generated on Thu Jul 14 2022 07:43:03 by
1.7.2