00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "ethercat_hardware/ethercat_com.h"
00036 #include <stdio.h>
00037 #include <errno.h>
00038
00039 EthercatDirectCom::EthercatDirectCom(EtherCAT_DataLinkLayer *dll) :
00040 dll_(dll)
00041 {
00042 assert(dll_ != NULL);
00043 }
00044
00045 EthercatDirectCom::~EthercatDirectCom()
00046 {
00047 dll_ = NULL;
00048 }
00049
00050 bool EthercatDirectCom::txandrx_once(struct EtherCAT_Frame * frame)
00051 {
00052 assert(frame!=NULL);
00053 int handle = dll_->tx(frame);
00054 if (handle < 0)
00055 return false;
00056 return dll_->rx(frame, handle);
00057 }
00058
00059 bool EthercatDirectCom::txandrx(struct EtherCAT_Frame * frame)
00060 {
00061 return dll_->txandrx(frame);
00062 }
00063
00064 EthercatOobCom::EthercatOobCom(struct netif *ni) :
00065 ni_(ni),
00066 state_(IDLE),
00067 frame_(NULL),
00068 handle_(-1),
00069 line_(0)
00070 {
00071 assert(ni_!=NULL);
00072
00073 pthread_mutexattr_t mutex_attr;
00074 int error = pthread_mutexattr_init(&mutex_attr);
00075 if (error != 0) {
00076 fprintf(stderr,"%s : Initializing mutex attr failed : %d\n", __func__, error);
00077 return;
00078 }
00079 error = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK_NP);
00080 if (error != 0) {
00081 fprintf(stderr,"%s : Setting type of mutex attr failed : %d\n", __func__, error);
00082 return;
00083 }
00084 error = pthread_mutex_init(&mutex_, &mutex_attr);
00085 if (error != 0) {
00086 fprintf(stderr,"%s : Initializing mutex failed : %d\n", __func__, error);
00087 return;
00088 }
00089 error = pthread_cond_init(&share_cond_,NULL);
00090 if (error != 0) {
00091 fprintf(stderr,"%s : Initializing share condition failed : %d\n", __func__, error);
00092 return;
00093 }
00094 error = pthread_cond_init(&busy_cond_,NULL);
00095 if (error != 0) {
00096 fprintf(stderr,"%s : Initializing busy condition failed : %d\n", __func__, error);
00097 }
00098 return;
00099 }
00100
00101 EthercatOobCom::~EthercatOobCom()
00102 {
00103 ni_=NULL;
00104 }
00105
00106
00107 bool EthercatOobCom::lock(unsigned line)
00108 {
00109 int error;
00110 if (0 != (error = pthread_mutex_lock(&mutex_))) {
00111 fprintf(stderr, "%s : lock %d at %d\n", __func__, error, line);
00112 return false;
00113 }
00114 line_ = line;
00115 return true;
00116 }
00117
00118 bool EthercatOobCom::trylock(unsigned line)
00119 {
00120 int error;
00121 if (0 != (error = pthread_mutex_trylock(&mutex_))) {
00122 if (error != EBUSY) {
00123 fprintf(stderr, "%s : lock %d at %d\n", __func__, error, line);
00124 }
00125 return false;
00126 }
00127 line_ = line;
00128 return true;
00129 }
00130
00131
00132 bool EthercatOobCom::unlock(unsigned line)
00133 {
00134 int error;
00135 if (0 != (error = pthread_mutex_unlock(&mutex_))) {
00136 fprintf(stderr, "%s : unlock %d at %d\n", __func__, error, line);
00137 return false;
00138 }
00139 line_ = 0;
00140 return true;
00141 }
00142
00143
00144
00145
00146 bool EthercatOobCom::txandrx_once(struct EtherCAT_Frame * frame)
00147 {
00148 assert(frame != NULL);
00149
00150 if (!lock(__LINE__))
00151 return false;
00152
00153
00154 while (state_ != IDLE) {
00155 pthread_cond_wait(&share_cond_,&mutex_);
00156 }
00157 frame_ = frame;
00158 state_ = READY_TO_SEND;
00159
00160
00161 do {
00162 pthread_cond_wait(&busy_cond_,&mutex_);
00163 } while (state_ != WAITING_TO_RECV);
00164
00165
00166 bool success = false;
00167 if (handle_ >= 0) {
00168 success = ni_->rx(frame_, ni_, handle_);
00169 }
00170 handle_=-1;
00171
00172
00173 assert(frame_ == frame);
00174 state_ = IDLE;
00175 pthread_cond_signal(&share_cond_);
00176
00177 unlock(__LINE__);
00178
00179 return success;
00180 }
00181
00182 bool EthercatOobCom::txandrx(struct EtherCAT_Frame * frame)
00183 {
00184 static const unsigned MAX_TRIES=10;
00185 for (unsigned tries=0; tries<MAX_TRIES; ++tries) {
00186 if (this->txandrx_once(frame)) {
00187 return true;
00188 }
00189 }
00190 return false;
00191 }
00192
00193
00194 void EthercatOobCom::tx()
00195 {
00196 if (!trylock(__LINE__))
00197 return;
00198
00199 if (state_ == READY_TO_SEND) {
00200
00201 assert(frame_!=NULL);
00202 handle_ = ni_->tx(frame_, ni_);
00203 state_ = WAITING_TO_RECV;
00204 pthread_cond_signal(&busy_cond_);
00205 }
00206
00207 unlock(__LINE__);
00208 }
00209