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