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 <math.h> 00017 #include <string.h> 00018 00019 #include "can_api.h" 00020 #include "cmsis.h" 00021 #include "pinmap.h" 00022 #include "error.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, 4}, 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, 4}, 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 // This table has the sampling points as close to 75% as possible. The first 00076 // value is TSEG1, the second TSEG2. 00077 static const int timing_pts[23][2] = { 00078 {0x0, 0x0}, // 2, 50% 00079 {0x1, 0x0}, // 3, 67% 00080 {0x2, 0x0}, // 4, 75% 00081 {0x3, 0x0}, // 5, 80% 00082 {0x3, 0x1}, // 6, 67% 00083 {0x4, 0x1}, // 7, 71% 00084 {0x5, 0x1}, // 8, 75% 00085 {0x6, 0x1}, // 9, 78% 00086 {0x6, 0x2}, // 10, 70% 00087 {0x7, 0x2}, // 11, 73% 00088 {0x8, 0x2}, // 12, 75% 00089 {0x9, 0x2}, // 13, 77% 00090 {0x9, 0x3}, // 14, 71% 00091 {0xA, 0x3}, // 15, 73% 00092 {0xB, 0x3}, // 16, 75% 00093 {0xC, 0x3}, // 17, 76% 00094 {0xD, 0x3}, // 18, 78% 00095 {0xD, 0x4}, // 19, 74% 00096 {0xE, 0x4}, // 20, 75% 00097 {0xF, 0x4}, // 21, 76% 00098 {0xF, 0x5}, // 22, 73% 00099 {0xF, 0x6}, // 23, 70% 00100 {0xF, 0x7}, // 24, 67% 00101 }; 00102 00103 static unsigned int can_speed(unsigned int sclk, unsigned int pclk, unsigned int cclk, unsigned char psjw) { 00104 uint32_t btr; 00105 uint16_t brp = 0; 00106 uint32_t calcbit; 00107 uint32_t bitwidth; 00108 int hit = 0; 00109 int bits; 00110 00111 bitwidth = sclk / (pclk * cclk); 00112 00113 brp = bitwidth / 0x18; 00114 while ((!hit) && (brp < bitwidth / 4)) { 00115 brp++; 00116 for (bits = 22; bits > 0; bits--) { 00117 calcbit = (bits + 3) * (brp + 1); 00118 if (calcbit == bitwidth) { 00119 hit = 1; 00120 break; 00121 } 00122 } 00123 } 00124 00125 if (hit) { 00126 btr = ((timing_pts[bits][1] << 20) & 0x00700000) 00127 | ((timing_pts[bits][0] << 16) & 0x000F0000) 00128 | ((psjw << 14) & 0x0000C000) 00129 | ((brp << 0) & 0x000003FF); 00130 } else { 00131 btr = 0xFFFFFFFF; 00132 } 00133 00134 return btr; 00135 } 00136 00137 void can_init(can_t *obj, PinName rd, PinName td) { 00138 CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD); 00139 CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD); 00140 obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td); 00141 if ((int)obj->dev == NC) { 00142 error("CAN pin mapping failed"); 00143 } 00144 00145 switch ((int)obj->dev) { 00146 case CAN_1: LPC_SC->PCONP |= 1 << 13; break; 00147 case CAN_2: LPC_SC->PCONP |= 1 << 14; break; 00148 } 00149 00150 pinmap_pinout(rd, PinMap_CAN_RD); 00151 pinmap_pinout(td, PinMap_CAN_TD); 00152 00153 can_reset(obj); 00154 obj->dev->IER = 0; // Disable Interrupts 00155 can_frequency(obj, 100000); 00156 00157 LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter 00158 } 00159 00160 void can_free(can_t *obj) { 00161 switch ((int)obj->dev) { 00162 case CAN_1: LPC_SC->PCONP &= ~(1 << 13); break; 00163 case CAN_2: LPC_SC->PCONP &= ~(1 << 14); break; 00164 } 00165 } 00166 00167 int can_frequency(can_t *obj, int f) { 00168 int pclk = PeripheralClock ; 00169 int btr = can_speed(SystemCoreClock, pclk, (unsigned int)f, 1); 00170 00171 if (btr > 0) { 00172 uint32_t modmask = can_disable(obj); 00173 obj->dev->BTR = btr; 00174 obj->dev->MOD = modmask; 00175 return 1; 00176 } else { 00177 return 0; 00178 } 00179 } 00180 00181 int can_write(can_t *obj, CAN_Message msg, int cc) { 00182 unsigned int CANStatus; 00183 CANMsg m; 00184 00185 can_enable(obj); 00186 00187 m.id = msg.id ; 00188 m.dlc = msg.len & 0xF; 00189 m.rtr = msg.type; 00190 m.type = msg.format; 00191 memcpy(m.data, msg.data, msg.len); 00192 const unsigned int *buf = (const unsigned int *)&m; 00193 00194 CANStatus = obj->dev->SR; 00195 if (CANStatus & 0x00000004) { 00196 obj->dev->TFI1 = buf[0] & 0xC00F0000; 00197 obj->dev->TID1 = buf[1]; 00198 obj->dev->TDA1 = buf[2]; 00199 obj->dev->TDB1 = buf[3]; 00200 if(cc) { 00201 obj->dev->CMR = 0x30; 00202 } else { 00203 obj->dev->CMR = 0x21; 00204 } 00205 return 1; 00206 00207 } else if (CANStatus & 0x00000400) { 00208 obj->dev->TFI2 = buf[0] & 0xC00F0000; 00209 obj->dev->TID2 = buf[1]; 00210 obj->dev->TDA2 = buf[2]; 00211 obj->dev->TDB2 = buf[3]; 00212 if (cc) { 00213 obj->dev->CMR = 0x50; 00214 } else { 00215 obj->dev->CMR = 0x41; 00216 } 00217 return 1; 00218 00219 } else if (CANStatus & 0x00040000) { 00220 obj->dev->TFI3 = buf[0] & 0xC00F0000; 00221 obj->dev->TID3 = buf[1]; 00222 obj->dev->TDA3 = buf[2]; 00223 obj->dev->TDB3 = buf[3]; 00224 if (cc) { 00225 obj->dev->CMR = 0x90; 00226 } else { 00227 obj->dev->CMR = 0x81; 00228 } 00229 return 1; 00230 } 00231 00232 return 0; 00233 } 00234 00235 int can_read(can_t *obj, CAN_Message *msg) { 00236 CANMsg x; 00237 unsigned int *i = (unsigned int *)&x; 00238 00239 can_enable(obj); 00240 00241 if (obj->dev->GSR & 0x1) { 00242 *i++ = obj->dev->RFS; // Frame 00243 *i++ = obj->dev->RID; // ID 00244 *i++ = obj->dev->RDA; // Data A 00245 *i++ = obj->dev->RDB; // Data B 00246 obj->dev->CMR = 0x04; // release receive buffer 00247 00248 msg->id = x.id; 00249 msg->len = x.dlc; 00250 msg->format = (x.type)? CANExtended : CANStandard; 00251 msg->type = (x.rtr)? CANRemote: CANData; 00252 memcpy(msg->data,x.data,x.dlc); 00253 return 1; 00254 } 00255 00256 return 0; 00257 } 00258 00259 void can_reset(can_t *obj) { 00260 can_disable(obj); 00261 obj->dev->GSR = 0; // Reset error counter when CAN1MOD is in reset 00262 } 00263 00264 unsigned char can_rderror(can_t *obj) { 00265 return (obj->dev->GSR >> 16) & 0xFF; 00266 } 00267 00268 unsigned char can_tderror(can_t *obj) { 00269 return (obj->dev->GSR >> 24) & 0xFF; 00270 } 00271 00272 void can_monitor(can_t *obj, int silent) { 00273 uint32_t mod_mask = can_disable(obj); 00274 if (silent) { 00275 obj->dev->MOD |= (1 << 1); 00276 } else { 00277 obj->dev->MOD &= ~(1 << 1); 00278 } 00279 if (!(mod_mask & 1)) { 00280 can_enable(obj); 00281 } 00282 }
Generated on Tue Jul 12 2022 13:47:00 by
1.7.2
