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