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