fix for mbed lib issue 3 (i2c problem) see also https://mbed.org/users/mbed_official/code/mbed/issues/3 affected implementations: LPC812, LPC11U24, LPC1768, LPC2368, LPC4088
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