#include "nvcan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* for hardware timestamps - since Linux 2.6.30 */ #ifndef SO_TIMESTAMPING #define SO_TIMESTAMPING 37 #endif /* from #include - since Linux 2.6.30 */ #define SOF_TIMESTAMPING_SOFTWARE (1<<4) #define SOF_TIMESTAMPING_RX_SOFTWARE (1<<3) #define SOF_TIMESTAMPING_RAW_HARDWARE (1<<6) #define MAXSOCK 16 /* max. number of CAN interfaces given on the cmdline */ #define MAXIFNAMES 30 /* size of receive name index to omit ioctls */ #define MAXCOL 6 /* number of different colors for colorized output */ #define ANYDEV "any" /* name of interface to receive from any CAN interface */ #define ANL "\r\n" /* newline in ASC mode */ #define SILENT_INI 42 /* detect user setting on commandline */ #define SILENT_OFF 0 /* no silent mode */ #define SILENT_ANI 1 /* silent mode with animation */ #define SILENT_ON 2 /* silent mode (completely silent) */ #include #define BUF_SIZE 1000 std::string CANNAME[] = {"can0","can1"}; nvcan::nvcan(const char * strcanname) { // qDebug("nvcan"); // connect(this,SIGNAL(SIG_CANOPENSTATE(bool,int,const char*)),this,SLOT(onMsg(bool,int,const char*))); CANNAME[0] = strcanname; mfault = new iv::Ivfault("can_socket"); mivlog = new iv::Ivlog("can_socket"); mfault->SetFaultState(0,0,"Prepare Initialize."); mpsendthread = new std::thread(&nvcan::threadsend,this); } void nvcan::ExecRecv(int s) { } void nvcan::run() { int currmax = 1; fd_set rdfs; int s[MAXSOCK]; int ret; struct sockaddr_can addr; char ctrlmsg[CMSG_SPACE(sizeof(struct timeval) + 3*sizeof(struct timespec) + sizeof(__u32))]; struct iovec iov; struct msghdr msg; struct canfd_frame frame; int nbytes, i, maxdlen; struct ifreq ifr; struct timeval tv, last_tv; struct timeval timeout_config = { 0, 0 }, *timeout_current = 0; mfault->SetFaultState(0,0,"Initializing."); for(i=0;iSetFaultState(2,1,"Create Socket Error."); emit SIG_CANOPENSTATE(false,-1,"Create Socket Error"); return; } addr.can_family = AF_CAN; memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name)); strncpy(ifr.ifr_name, CANNAME[i].data(), 5); if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) { mfault->SetFaultState(2,2,"SIOCGIFINDEX."); emit SIG_CANOPENSTATE(false,-2,"SIOCGIFINDEX"); return; } addr.can_ifindex = ifr.ifr_ifindex; if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) { mfault->SetFaultState(2,3,"bind error."); emit SIG_CANOPENSTATE(false,-3,"bind error"); return; } } mps = &s[0]; mbCANOpen = true; mivlog->verbose("open can succesfully."); mfault->SetFaultState(0,0,"CAN OK."); emit SIG_CANOPENSTATE(true,0,"open can card successfully"); std::cout<<"can open succesfully."< xvectorlat; #endif int secondretrycount = 0; while((!QThread::isInterruptionRequested())&&(mbCANOpen)) { FD_ZERO(&rdfs); for (i=0; iSetFaultState(2,4,"select error."); std::cout<<"select error."<error("%s interface down", CANNAME[i].data()); mfault->SetFaultState(1, 0, "interface down"); emit SIG_CANOPENSTATE(false,-5,"can card down"); fprintf(stderr, "%s: interface down\n", CANNAME[i].data()); return; } continue; // perror("read"); // return 1; } if ((size_t)nbytes == CAN_MTU) maxdlen = CAN_MAX_DLEN; else if ((size_t)nbytes == CANFD_MTU) maxdlen = CANFD_MAX_DLEN; else { mivlog->warn("read incomplete message"); continue; } bRecv = true; nrecvcount++; // qDebug("receive msg."); mMutex.lock(); basecan_msg msg; msg.id = frame.can_id&0x1fffffff; if((frame.can_id&0x80000000)!= 0)msg.isExtern = true; else msg.isExtern = false; if((frame.can_id&0x40000000)!= 0)msg.isRemote = true; else msg.isRemote = false; msg.nLen = frame.len; nsecondrecvcount++; if((frame.len<9)&&(frame.len>0))memcpy(msg.data,frame.data,frame.len); if(mMsgRecvBuf[i].size() 1000) { if(nRecvState == 0) { nRecvState = -1; mfault->SetFaultState(0,1,"More than 1 second not receive data."); } } else { if(nRecvState == -1) { nRecvState = 0; mfault->SetFaultState(0,0,"CAN OK."); } } if(bRecv)continue; mWaitMutex.lock(); mwc.wait(&mWaitMutex,1); mWaitMutex.unlock(); #ifdef TEST_PROG // qDebug("send time : %lld",QDateTime::currentMSecsSinceEpoch()); #endif struct canfd_frame framesend[2500]; #ifdef SEND_STAT qint64 sendsettime[2500]; #endif for(int nch =0;nch2500)nbufsize = 2500; for(i=0;i=2500)break; memcpy(framesend[i].data,mMsgSendBuf[nch].at(i).data,8); framesend[i].can_id = mMsgSendBuf[nch].at(i).id; if(mMsgSendBuf[nch].at(i).isExtern) { framesend[i].can_id = framesend[i].can_id|0x80000000; } else { framesend[i].can_id = framesend[i].can_id&0x7ff; } if(mMsgSendBuf[nch].at(i).isRemote) { framesend[i].can_id= framesend[i].can_id|0x40000000; } framesend[i].len = mMsgSendBuf[nch].at(i).nLen; #ifdef SEND_STAT sendsettime[i] = mMsgSendBuf[nch].at(i).mSetTime; #endif nsend++; } mMsgSendBuf[nch].clear(); mMutex.unlock(); if(nsend > 0) { for(i=0;ierror("write error 1"); // perror("write error 1."); nretry++; secondretrycount++; if(nretry > 5) { // std::cout<<"retry fail,retry:"< 0) { qint64 xlatmax = 0; qint64 xlatavg = 0; for(j=0;j xlatmax)xlatmax = xvectorlat[j]; xlatavg = xlatavg + xvectorlat[j]; } xlatavg = xlatavg/nsendcount; std::cout<<" max latency: "< xvectorlat; #endif int secondretrycount = 0; while(mbSendRun) { mWaitMutex.lock(); mwc.wait(&mWaitMutex,100); mWaitMutex.unlock(); #ifdef TEST_PROG // qDebug("send time : %lld",QDateTime::currentMSecsSinceEpoch()); #endif struct canfd_frame framesend[2500]; #ifdef SEND_STAT qint64 sendsettime[2500]; #endif for(int nch =0;nch2500)nbufsize = 2500; for(i=0;i=2500)break; memcpy(framesend[i].data,mMsgSendBuf[nch].at(i).data,8); framesend[i].can_id = mMsgSendBuf[nch].at(i).id; if(mMsgSendBuf[nch].at(i).isExtern) { framesend[i].can_id = framesend[i].can_id|0x80000000; } else { framesend[i].can_id = framesend[i].can_id&0x7ff; } if(mMsgSendBuf[nch].at(i).isRemote) { framesend[i].can_id= framesend[i].can_id|0x40000000; } framesend[i].len = mMsgSendBuf[nch].at(i).nLen; #ifdef SEND_STAT sendsettime[i] = mMsgSendBuf[nch].at(i).mSetTime; #endif nsend++; } mMsgSendBuf[nch].clear(); mMutex.unlock(); if(nsend > 0) { for(i=0;ierror("write error 1"); // perror("write error 1."); nretry++; secondretrycount++; if(nretry > 30) { // std::cout<<"retry fail,retry:"< 0) { qint64 xlatmax = 0; qint64 xlatavg = 0; for(j=0;j xlatmax)xlatmax = xvectorlat[j]; xlatavg = xlatavg + xvectorlat[j]; } xlatavg = xlatavg/nsendcount; std::cout<<" max latency: "<SetFaultState(1, 0, "can closed"); mivlog->error("can is closed at %d",xTime.elapsed()); qDebug("can is closed."); break; } } } int nvcan::GetMessage(const int nch,basecan_msg *pMsg, const int nCap) { if((nch>1)||(nch < 0))return -1; if(mMsgRecvBuf[nch].size() == 0)return 0; int nRtn; nRtn = nCap; mMutex.lock(); if(nRtn > mMsgRecvBuf[nch].size())nRtn = mMsgRecvBuf[nch].size(); int i; for(i=0;i::iterator iter; iter = mMsgRecvBuf[nch].begin(); for(i=0;i1)||(nch < 0))return -1; mMutex.lock(); if(mMsgSendBuf[nch].size() > BUF_SIZE) { std::cout<<"buffer full."< 100) { std::cout<<"buffer data more 100"<verbose("msg is %s ",strres); }