Changeset 2518 for trunk/MagicSoft/Cosy/candrv
- Timestamp:
- 11/17/03 13:50:48 (21 years ago)
- Location:
- trunk/MagicSoft/Cosy/candrv
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/MagicSoft/Cosy/candrv/canopen.cc
r1727 r2518 32 32 #include "canopen.h" 33 33 34 #include <iostream .h> // cout35 #include <iomanip .h> // setw, setfill34 #include <iostream> // cout 35 #include <iomanip> // setw, setfill 36 36 37 37 ClassImp(CanOpen); 38 39 using namespace std; 38 40 39 41 // -------------------------------------------------------------------------- … … 44 46 CanOpen::CanOpen(const char *dev, const int baud, MLog &out) : VmodIcan(dev, baud, out) 45 47 { 46 for (int i=0; i<32; i++)47 for (int j=0; j<4; j++)48 {49 pthread_cond_init(&fPdoCond[i][j], NULL);50 pthread_mutex_init(&fPdoMux[i][j], NULL);51 pthread_mutex_lock(&fPdoMux[i][j]);52 }53 54 48 lout << "- CanOpen initialized." << endl; 55 49 } … … 61 55 CanOpen::~CanOpen() 62 56 { 63 for (int i=0; i<32; i++)64 for (int j=0; j<4; j++)65 {66 pthread_cond_destroy(&fPdoCond[i][j]);67 pthread_mutex_destroy(&fPdoMux[i][j]);68 }69 57 lout << "- CanOpen destroyed." << endl; 70 58 } … … 126 114 { 127 115 HandlePDO1(node, data, tv); 128 pthread_cond_broadcast(&fPdoCond[node-1][0]);116 fPdoCond[node-1][0].Broadcast(); 129 117 } 130 118 return; … … 133 121 { 134 122 HandlePDO2(node, data, tv); 135 pthread_cond_broadcast(&fPdoCond[node-1][1]);123 fPdoCond[node-1][1].Broadcast(); 136 124 } 137 125 return; … … 140 128 { 141 129 HandlePDO3(node, data, tv); 142 pthread_cond_broadcast(&fPdoCond[node-1][2]);130 fPdoCond[node-1][2].Broadcast(); 143 131 } 144 132 return; … … 147 135 { 148 136 HandlePDO4(node, data, tv); 149 pthread_cond_broadcast(&fPdoCond[node-1][3]);137 fPdoCond[node-1][3].Broadcast(); 150 138 } 151 139 return; -
trunk/MagicSoft/Cosy/candrv/network.cc
r2278 r2518 269 269 if (fNodes[i] && fNodeInitialized[i]) 270 270 { 271 lout << "- Stopping Node #" << dec << i << endl; 271 lout << "- Stopping Node #" << dec << i; 272 lout << " (" << fNodes[i]->GetNodeName() << ")" << endl; 272 273 fNodes[i]->StopDevice(); 273 274 } -
trunk/MagicSoft/Cosy/candrv/nodedrv.cc
r2278 r2518 61 61 // and the node name. The name is a name for debug output. 62 62 // 63 NodeDrv::NodeDrv(BYTE_t nodeid, const char *name, MLog &out) : Log(out), fNetwork(NULL), fId(32), fError(0), fIsZombie(kTRUE) 63 NodeDrv::NodeDrv(BYTE_t nodeid, const char *name, MLog &out) : Log(out), fNetwork(NULL), fId(32), fError(0), fIsZombie(kTRUE), fGuard(NULL) 64 64 { 65 65 if (nodeid>0x1f) … … 79 79 } 80 80 81 fTimerOn = kFALSE;82 fTimeout = new TTimer(this, 100, kFALSE); // 100ms, asynchronous83 84 81 lout << "- Node #" << (int)nodeid << " (" << name << ") initialized." << endl; 85 82 … … 92 89 NodeDrv::~NodeDrv() 93 90 { 94 fTimerOn = kFALSE;95 delete fTimeout;96 91 } 97 92 … … 492 487 // least one Nodeguard message was answered. 493 488 // 489 class NodeGuard : public MThread 490 { 491 Double_t fTimeoutTime; 492 Double_t fGuardTime; 493 Int_t fLifeTimeFactor; 494 495 Bool_t fIsCanOpen; 496 497 NodeDrv *fDrv; 498 499 public: 500 NodeGuard(NodeDrv *drv, Int_t guard, Int_t ltf, Bool_t canopen) 501 : MThread(false), fGuardTime(guard/1000.), fLifeTimeFactor(ltf), fIsCanOpen(canopen), fDrv(drv) { } 502 503 void Reset(timeval_t *tv=NULL) 504 { 505 Timer t; 506 if (tv) 507 t.SetTimer(tv); 508 else 509 t.Now(); 510 511 fTimeoutTime = t + (fGuardTime*fLifeTimeFactor); 512 } 513 514 void *Thread() 515 { 516 Reset(); 517 518 while (!HasStopFlag()) 519 { 520 // Sending nodeguards seems to result in 521 // loosing CANbus messages or CANbus answers... 522 // strange. Also protecting VmodIcan::SendCanFrame 523 // by a Mutex doesn't help. 524 if (fIsCanOpen) 525 fDrv->SendNodeguard(); 526 527 Timer t; 528 t.Now(); 529 530 const Timer t0 = t+fGuardTime; 531 532 while (!HasStopFlag() && t<t0 && t<fTimeoutTime) 533 { 534 usleep(5); 535 t.Now(); 536 } 537 538 //cout << "-d-> " << (Long_t)((fTimeoutTime-t)*1000) << endl; 539 //cout << "-o-> " << (ULong_t)((fTimeoutTime)*1000)<< " " << (ULong_t)((t)*1000) << endl; 540 //cout << "-g-> " << (Long_t)((t-t0)*1000)<< endl; 541 542 if (t<fTimeoutTime) 543 continue; 544 545 fDrv->SetZombie(false); 546 return 0; 547 } 548 return 0; 549 } 550 }; 551 494 552 void NodeDrv::StartGuarding(Bool_t real=kTRUE) 495 553 { 496 if (f TimerOn)554 if (fGuard) 497 555 return; 498 556 499 if (!real) 500 SendNodeguard(); 501 502 fTimerOn = kTRUE; 503 fTimeout->SetTime(fGuardTime); 504 fTimeout->Reset(); 505 506 Timer t; 507 fTimeoutTime = t.Now() + (fGuardTime*fLifeTimeFactor/1000.); 508 //cout << GetNodeName() << ": " << fmod(fTimeoutTime*10000, 10000)/10 << endl; 509 510 fTimeout->TurnOn(); 511 //fTimeout->Start(fGuardTime, kTRUE); 557 fGuard = new NodeGuard(this, fGuardTime, fLifeTimeFactor, real); 558 fGuard->Start(); 512 559 513 560 lout << "- " << GetNodeName() << ": Guarding (" << dec; … … 517 564 void NodeDrv::StartGuarding(Int_t ms, Int_t ltf, Bool_t real) 518 565 { 519 if (f TimerOn)566 if (fGuard) 520 567 { 521 568 lout << "- " << GetNodeName() << ": ERROR - Guarding already started." << endl; 522 569 return; 523 570 } 571 524 572 fGuardTime = ms; 525 573 fLifeTimeFactor = ltf; … … 530 578 void NodeDrv::StopGuarding() 531 579 { 532 if (!f TimerOn)580 if (!fGuard) 533 581 return; 534 582 535 fTimeout->TurnOff();536 f TimerOn = kFALSE;583 delete fGuard; 584 fGuard=NULL; 537 585 538 586 lout << "- " << GetNodeName() << ": Guarding stopped." << endl; 539 }540 541 // --------------------------------------------------------------------------542 //543 // Handle the Nodeguard-Timer Event.544 // It checks whether the node timed out. If it timed out it is set to545 // the Zombie state.546 // A new Nodeguard request is send and a new timer event is triggered.547 //548 Bool_t NodeDrv::HandleTimer(TTimer *t)549 {550 //551 // WARNING:552 // It seems, that you should never access ANY output from553 // here. Neither the GUI, nor COUT. This can result in554 // 'unexpected async reply'555 //556 557 /*558 Fons:559 -----560 561 timers never trigger at the same time or when in a TTimer::Notify.562 Little explanation:563 564 - there are two types of timers synchronous and a-synchronous.565 - synchronous timers are only handled via the ROOT eventloop566 (see TUnixSystem::DispatchOneEvent()). If there are no mouse/keyboard567 events then the synchronous timer queue is checked. So if the processing568 of a mouse/keyboard event takes a long time synchronous timers are not569 called for a while. To prevent this from happening one can call in long570 procedures gSystem->ProcessEvents(). The system schedules only the571 next timer in the queue when the current one's Notify() has finished.572 - a-synchronous timers are triggered via SIGALARM, i.e. the program is573 interupted and execution jumps to the Notify() function. When the574 notify is finished the next a-sync timer is scheduled and the system575 resumes from the place where it was initially interrupted. One of the576 things to remember when using a-sync timers is don't make any graphics577 calls in them. X11 is not re-entrant and it might be that the SIGALARM578 signal interrupted the system while being in X11. A-sync timers are best579 used to set flags that you can test at a convenient and controlled580 time.581 */582 if (fIsZombie)583 return kTRUE;584 585 Timer time;586 Double_t now = time.Now();587 if (now > fTimeoutTime)588 {589 cout << GetNodeName() << ": " << "==out==> " << fmod(now*1000, 10000)/10 << " > " << fmod(fTimeoutTime*10000, 10000)/10 << endl;590 //cout << "ERROR - " << GetNodeName() << " didn't respond in timeout window." << endl;591 //lout << "ERROR - " << GetNodeName() << " didn't respond in timeout window." << endl;592 //cout << dec << "+" << (int)GetId() << ": Handle: " << fmod(now, 500) << endl;593 //cout << dec << "+" << (int)GetId() << ": Handle: " << fmod(fTimeoutTime, 500) << endl;594 //cout << fGuardTime << endl;595 fIsZombie = true;596 //SetZombie();597 598 return kTRUE;599 }600 601 SendNodeguard();602 603 return kTRUE;604 587 } 605 588 … … 611 594 void NodeDrv::HandleNodeguard(timeval_t *tv) 612 595 { 613 Timer t(tv); 614 fTimeoutTime = t + (fGuardTime*fLifeTimeFactor/1000.); 615 //cout << GetNodeName() << ": " << fmod(fTimeoutTime*10000, 10000)/10 << endl; 616 } 617 618 void NodeDrv::SetZombie() 596 if (fGuard) 597 fGuard->Reset(tv); 598 } 599 600 void NodeDrv::SetZombie(bool stopguard) 619 601 { 620 602 fIsZombie = true; 621 StopGuarding(); 622 } 603 if (stopguard) 604 StopGuarding(); 605 else 606 lout << " - " << GetNodeName() << ": Zombie set due to timeout." << endl; 607 } -
trunk/MagicSoft/Cosy/candrv/nodedrv.h
r2278 r2518 19 19 20 20 class Network; 21 class NodeGuard; 21 22 22 class NodeDrv : public Log , public TObject23 class NodeDrv : public Log 23 24 { 24 25 private: … … 30 31 int fError; 31 32 32 Bool_t fIsZombie; // A Zombie node is a node which doesn't answer...33 Bool_t fIsZombie; // A Zombie node is a node which doesn't answer... 33 34 34 TTimer *fTimeout; 35 Int_t fGuardTime; // Guardtime [ms] 36 Int_t fLifeTimeFactor; 37 Double_t fTimeoutTime; 38 Bool_t fTimerOn; 35 NodeGuard *fGuard; 39 36 40 Bool_t HandleTimer(TTimer *t); 37 Int_t fGuardTime; // Guardtime [ms] 38 Int_t fLifeTimeFactor; 41 39 42 40 protected: … … 46 44 Int_t GetLifeTimeFactor() const { return fLifeTimeFactor; } 47 45 Int_t GetGuardTime() const { return fGuardTime; } 48 49 virtual void SetZombie();50 46 51 47 public: … … 67 63 68 64 bool IsZombieNode() const { return fIsZombie; } 65 void SetZombie(bool stopguard=true); 69 66 70 67 virtual void HandleSDO(WORD_t idx, BYTE_t subidx, LWORD_t val, timeval_t *tv); -
trunk/MagicSoft/Cosy/candrv/sdolist.cc
r1109 r2518 10 10 fFirst = new PendingSDO; 11 11 fLast = fFirst; 12 13 pthread_mutex_init(&fMux, NULL);14 12 } 15 13 16 14 PendingSDOList::~PendingSDOList() 17 15 { 18 // pthread_mutex_lock(&fMux);19 20 16 DelAll(); 21 17 delete fFirst; 22 23 pthread_mutex_destroy(&fMux);24 18 } 25 19 26 20 void PendingSDOList::DelAll() 27 21 { 28 pthread_mutex_lock(&fMux);22 fMux.Lock(); 29 23 30 24 PendingSDO *prev = fFirst; … … 41 35 fLast = fFirst; 42 36 43 pthread_mutex_unlock(&fMux);37 fMux.UnLock(); 44 38 } 45 39 … … 48 42 PendingSDO *sdo = fFirst; 49 43 50 pthread_mutex_lock(&fMux);44 fMux.Lock(); 51 45 while ((sdo=sdo->Next)) 52 46 if (sdo->Node==node && sdo->Idx==idx && sdo->Subidx==subidx) … … 60 54 fLast->Next = new PendingSDO(node, idx, subidx); 61 55 fLast = fLast->Next; 62 pthread_mutex_unlock(&fMux);56 fMux.UnLock(); 63 57 } 64 58 … … 68 62 PendingSDO *sdo; 69 63 70 pthread_mutex_lock(&fMux);64 fMux.Lock(); 71 65 while ((sdo=prev->Next)) 72 66 { … … 86 80 break; 87 81 } 88 pthread_mutex_unlock(&fMux);82 fMux.UnLock(); 89 83 } 90 84 … … 99 93 PendingSDO *sdo = fFirst; 100 94 101 pthread_mutex_lock(&fMux);95 fMux.Lock(); 102 96 while ((sdo=sdo->Next)) 103 97 if (sdo->Node==node) … … 106 100 break; 107 101 } 108 pthread_mutex_unlock(&fMux);102 fMux.UnLock(); 109 103 110 104 return rc; … … 116 110 PendingSDO *sdo = fFirst; 117 111 118 pthread_mutex_lock(&fMux);112 fMux.Lock(); 119 113 while ((sdo=sdo->Next)) 120 114 if (sdo->Node==node && sdo->Idx==idx && sdo->Subidx==subidx) … … 123 117 break; 124 118 } 125 pthread_mutex_unlock(&fMux);119 fMux.UnLock(); 126 120 127 121 return rc; -
trunk/MagicSoft/Cosy/candrv/sdolist.h
r1109 r2518 1 #ifndef SDOLIST_H 2 #define SDOLIST_H 3 4 #ifdef __CINT__ 5 struct pthread_mutex_t; 6 #else 7 #include <pthread.h> 8 #endif 1 #ifndef COSY_SdoList 2 #define COSY_SdoList 9 3 10 4 #ifdef __CINT__ … … 14 8 #include <TROOT.h> 15 9 #include "gendef.h" 10 #endif 11 12 #ifndef ROOT_TMutex 13 #include <TMutex.h> 16 14 #endif 17 15 … … 36 34 PendingSDO *fLast; 37 35 38 pthread_mutex_tfMux;36 TMutex fMux; 39 37 40 38 public: -
trunk/MagicSoft/Cosy/candrv/vmodican.cc
r2407 r2518 783 783 arg.pm = pm; 784 784 785 if (!Ioctl(DPM_WRITE_MBOX, &arg)) 786 return FALSE; 787 788 return arg.rval; 785 return Ioctl(DPM_WRITE_MBOX, &arg) ? arg.rval : 0; 789 786 } 790 787
Note:
See TracChangeset
for help on using the changeset viewer.