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 mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers can_api.c Source File

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 }