nico@215: nico@215:
nico@215:00001 /* nico@215: 00002 This file is part of CanFestival, a library implementing CanOpen Stack. nico@215: 00003 nico@215: 00004 Copyright (C): Edouard TISSERANT and Francis DUPIN nico@215: 00005 nico@215: 00006 See COPYING file for copyrights details. nico@215: 00007 nico@215: 00008 This library is free software; you can redistribute it and/or nico@215: 00009 modify it under the terms of the GNU Lesser General Public nico@215: 00010 License as published by the Free Software Foundation; either nico@215: 00011 version 2.1 of the License, or (at your option) any later version. nico@215: 00012 nico@215: 00013 This library is distributed in the hope that it will be useful, nico@215: 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of nico@215: 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU nico@215: 00016 Lesser General Public License for more details. nico@215: 00017 nico@215: 00018 You should have received a copy of the GNU Lesser General Public nico@215: 00019 License along with this library; if not, write to the Free Software nico@215: 00020 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA nico@215: 00021 */ nico@215: 00022 nico@215: 00023 #if defined(WIN32) && !defined(__CYGWIN__) nico@215: 00024 #define usleep(micro) Sleep(micro%1000 ? (micro/1000) + 1 : (micro/1000)) nico@215: 00025 #else nico@215: 00026 #include <stdio.h> nico@215: 00027 #include <string.h> nico@215: 00028 #include <errno.h> nico@215: 00029 #include <fcntl.h> nico@215: 00030 #endif nico@215: 00031 nico@215: 00032 #include "cancfg.h" nico@215: 00033 #include "can_driver.h" nico@215: 00034 nico@215: 00035 #ifndef extra_PCAN_init_params etisserant@240: 00036 #define extra_PCAN_init_params nico@215: 00037 #else nico@215: 00038 #define extra_PCAN_init_params\ nico@215: 00039 ,getenv("PCANHwType") ? strtol(getenv("PCANHwType"),NULL,0):0\ nico@215: 00040 ,getenv("PCANIO_Port") ? strtol(getenv("PCANIO_Port"),NULL,0):0\ nico@215: 00041 ,getenv("PCANInterupt") ? strtol(getenv("PCANInterupt"),NULL,0):0 nico@215: 00042 #endif nico@215: 00043 nico@215: 00044 static s_BOARD *first_board = NULL; nico@215: 00045 #ifdef PCAN2_HEADER_ nico@215: 00046 static s_BOARD *second_board = NULL; nico@215: 00047 #endif nico@215: 00048 nico@215: 00049 //pthread_mutex_t PeakCan_mutex = PTHREAD_MUTEX_INITIALIZER; nico@215: 00050 nico@215: 00051 // Define for rtr CAN message etisserant@240: 00052 #define CAN_INIT_TYPE_ST_RTR MSGTYPE_STANDARD | MSGTYPE_RTR nico@215: 00053 nico@215: 00054 /***************************************************************************/ etisserant@240: 00055 int TranslateBaudeRate(char* optarg){ nico@215: 00056 if(!strcmp( optarg, "1M")) return CAN_BAUD_1M; nico@215: 00057 if(!strcmp( optarg, "500K")) return CAN_BAUD_500K; nico@215: 00058 if(!strcmp( optarg, "250K")) return CAN_BAUD_250K; nico@215: 00059 if(!strcmp( optarg, "125K")) return CAN_BAUD_125K; nico@215: 00060 if(!strcmp( optarg, "100K")) return CAN_BAUD_100K; nico@215: 00061 if(!strcmp( optarg, "50K")) return CAN_BAUD_50K; nico@215: 00062 if(!strcmp( optarg, "20K")) return CAN_BAUD_20K; nico@215: 00063 if(!strcmp( optarg, "10K")) return CAN_BAUD_10K; nico@215: 00064 if(!strcmp( optarg, "5K")) return CAN_BAUD_5K; nico@215: 00065 if(!strcmp( optarg, "none")) return 0; nico@215: 00066 return 0x0000; nico@215: 00067 } nico@215: 00068 nico@215: 00069 void etisserant@240: 00070 canInit (s_BOARD *board) nico@215: 00071 { nico@215: 00072 int baudrate; nico@215: 00073 nico@215: 00074 #ifdef PCAN2_HEADER_ nico@215: 00075 // if not the first handler nico@215: 00076 if(second_board == (s_BOARD *)board) etisserant@240: 00077 if(baudrate = TranslateBaudeRate(board->baudrate)) nico@215: 00078 CAN2_Init (baudrate, etisserant@240: 00079 CAN_INIT_TYPE_ST extra_PCAN_init_params); nico@215: 00080 #endif nico@215: 00081 if(first_board == (s_BOARD *)board) etisserant@240: 00082 if(baudrate = TranslateBaudeRate(board->baudrate)) nico@215: 00083 CAN_Init (baudrate, nico@215: 00084 CAN_INIT_TYPE_ST extra_PCAN_init_params); nico@215: 00085 } nico@215: 00086 nico@215: 00087 /*********functions which permit to communicate with the board****************/ etisserant@240: 00088 UNS8 etisserant@240: 00089 canReceive_driver (CAN_HANDLE fd0, Message * m) nico@215: 00090 { etisserant@240: 00091 UNS8 data; nico@215: 00092 TPCANMsg peakMsg; nico@215: 00093 nico@215: 00094 DWORD Res; nico@215: 00095 nico@215: 00096 do{ nico@215: 00097 // We read the queue looking for messages. nico@215: 00098 // nico@215: 00099 //pthread_mutex_lock (&PeakCan_mutex); nico@215: 00100 #ifdef PCAN2_HEADER_ nico@215: 00101 // if not the first handler nico@215: 00102 if(second_board == (s_BOARD *)fd0) nico@215: 00103 Res = CAN2_Read (&peakMsg); nico@215: 00104 else nico@215: 00105 #endif nico@215: 00106 if(first_board == (s_BOARD *)fd0) nico@215: 00107 Res = CAN_Read (&peakMsg); nico@215: 00108 else nico@215: 00109 Res = CAN_ERR_BUSOFF; nico@215: 00110 nico@215: 00111 // A message was received nico@215: 00112 // We process the message(s) nico@215: 00113 // nico@215: 00114 if (Res == CAN_ERR_OK) nico@215: 00115 { nico@215: 00116 // if something different that 11bit or rtr... problem nico@215: 00117 if (peakMsg.MSGTYPE & ~(MSGTYPE_STANDARD | MSGTYPE_RTR)) nico@215: 00118 { nico@215: 00119 if (peakMsg.MSGTYPE == CAN_ERR_BUSOFF) nico@215: 00120 { nico@215: 00121 printf ("!!! Peak board read : re-init\n"); etisserant@240: 00122 canInit((s_BOARD*) fd0); nico@215: 00123 usleep (10000); nico@215: 00124 } nico@215: 00125 nico@215: 00126 // If status, return status if 29bit, return overrun nico@215: 00127 //pthread_mutex_unlock (&PeakCan_mutex); nico@215: 00128 return peakMsg.MSGTYPE == nico@215: 00129 MSGTYPE_STATUS ? peakMsg.DATA[2] : CAN_ERR_OVERRUN; nico@215: 00130 } etisserant@240: 00131 m->cob_id.w = peakMsg.ID; nico@215: 00132 if (peakMsg.MSGTYPE == CAN_INIT_TYPE_ST) /* bits of MSGTYPE_ */ etisserant@240: 00133 m->rtr = 0; nico@215: 00134 else etisserant@240: 00135 m->rtr = 1; etisserant@240: 00136 m->len = peakMsg.LEN; /* count of data bytes (0..8) */ nico@215: 00137 for (data = 0; data < peakMsg.LEN; data++) etisserant@240: 00138 m->data[data] = peakMsg.DATA[data]; /* data bytes, up to 8 */ nico@215: 00139 nico@215: 00140 }else{ nico@215: 00141 //pthread_mutex_unlock (&PeakCan_mutex); nico@215: 00142 //if (Res != CAN_ERR_OK) nico@215: 00143 //{ nico@215: 00144 if (! nico@215: 00145 (Res & CAN_ERR_QRCVEMPTY || Res & CAN_ERR_BUSLIGHT nico@215: 00146 || Res & CAN_ERR_BUSHEAVY)) nico@215: 00147 { nico@215: 00148 printf ("canReceive returned error (%d)\n", Res); nico@215: 00149 return 1; nico@215: 00150 } nico@215: 00151 usleep (1000); nico@215: 00152 } nico@215: 00153 }while(Res != CAN_ERR_OK); nico@215: 00154 return 0; nico@215: 00155 } nico@215: 00156 nico@215: 00157 /***************************************************************************/ etisserant@240: 00158 UNS8 etisserant@240: 00159 canSend_driver (CAN_HANDLE fd0, Message * m) nico@215: 00160 { etisserant@240: 00161 UNS8 data; nico@215: 00162 TPCANMsg peakMsg; etisserant@240: 00163 peakMsg.ID = m->cob_id.w; /* 11/29 bit code */ etisserant@240: 00164 if (m->rtr == 0) nico@215: 00165 peakMsg.MSGTYPE = CAN_INIT_TYPE_ST; /* bits of MSGTYPE_ */ nico@215: 00166 else nico@215: 00167 { etisserant@240: 00168 peakMsg.MSGTYPE = CAN_INIT_TYPE_ST_RTR; /* bits of MSGTYPE_ */ nico@215: 00169 } etisserant@240: 00170 peakMsg.LEN = m->len; nico@215: 00171 /* count of data bytes (0..8) */ etisserant@240: 00172 for (data = 0; data < m->len; data++) etisserant@240: 00173 peakMsg.DATA[data] = m->data[data]; /* data bytes, up to 8 */ nico@215: 00174 do nico@215: 00175 { nico@215: 00176 #ifdef PCAN2_HEADER_ nico@215: 00177 // if not the first handler nico@215: 00178 if(second_board == (s_BOARD *)fd0) nico@215: 00179 errno = CAN2_Write (&peakMsg); nico@215: 00180 else nico@215: 00181 #endif nico@215: 00182 if(first_board == (s_BOARD *)fd0) nico@215: 00183 errno = CAN_Write (&peakMsg); nico@215: 00184 else nico@215: 00185 goto fail; nico@215: 00186 if (errno) nico@215: 00187 { nico@215: 00188 if (errno == CAN_ERR_BUSOFF) nico@215: 00189 { nico@215: 00190 printf ("!!! Peak board write : re-init\n"); etisserant@240: 00191 canInit((s_BOARD*)fd0); nico@215: 00192 usleep (10000); nico@215: 00193 } nico@215: 00194 usleep (1000); nico@215: 00195 } nico@215: 00196 } nico@215: 00197 while (errno != CAN_ERR_OK); nico@215: 00198 return 0; nico@215: 00199 fail: nico@215: 00200 return 1; nico@215: 00201 } nico@215: 00202 nico@215: 00203 /***************************************************************************/ etisserant@240: 00204 CAN_HANDLE etisserant@240: 00205 canOpen_driver (s_BOARD * board) nico@215: 00206 { nico@215: 00207 #ifdef PCAN2_HEADER_ nico@215: 00208 if(first_board != NULL && second_board != NULL) nico@215: 00209 #else nico@215: 00210 if(first_board != NULL) nico@215: 00211 #endif nico@215: 00212 { nico@215: 00213 fprintf (stderr, "Open failed.\n"); nico@215: 00214 fprintf (stderr, nico@215: 00215 "can_peak_win32.c: no more can port available with this pcan library\n"); nico@215: 00216 fprintf (stderr, nico@215: 00217 "can_peak_win32.c: please link another executable with another pcan lib\n"); nico@215: 00218 return NULL; nico@215: 00219 } nico@215: 00220 nico@215: 00221 #ifdef PCAN2_HEADER_ nico@215: 00222 if(first_board == NULL) nico@215: 00223 first_board = board; nico@215: 00224 else nico@215: 00225 second_board = board; nico@215: 00226 #else nico@215: 00227 first_board = board; nico@215: 00228 #endif nico@215: 00229 etisserant@240: 00230 canInit(board); nico@215: 00231 etisserant@240: 00232 return (CAN_HANDLE)board; nico@215: 00233 } nico@215: 00234 nico@215: 00235 /***************************************************************************/ nico@215: 00236 int etisserant@240: 00237 canClose_driver (CAN_HANDLE fd0) nico@215: 00238 { nico@215: 00239 #ifdef PCAN2_HEADER_ nico@215: 00240 // if not the first handler nico@215: 00241 if(second_board == (s_BOARD *)fd0) nico@215: 00242 { nico@215: 00243 CAN2_Close (); nico@215: 00244 second_board = (s_BOARD *)NULL; nico@215: 00245 }else nico@215: 00246 #endif nico@215: 00247 if(first_board == (s_BOARD *)fd0) nico@215: 00248 { nico@215: 00249 CAN_Close (); nico@215: 00250 first_board = (s_BOARD *)NULL; nico@215: 00251 } nico@215: 00252 return 0; nico@215: 00253 } etisserant@240: