21 static constexpr
unsigned int workerCounterWatchdogTimeout = 20000;
24 bus(bus), workerCounterWatchdog(workerCounterWatchdogTimeout)
26 slaveReinitializingThreadRunning.store(
true);
27 slaveReinitializingThread = std::thread(&BusErrorHandler::slaveReinitializingLoop,
this);
32 slaveReinitializingThreadRunning.store(
false);
33 slaveReinitializingThread.join();
40 rtUpdateSlaveStates();
48 BUS_TIMING_CEND(bus_rtHandleSlaveErrors_getErrorReporter, bus->iterationCount, 0.3)
50 for (
const auto& slave : bus->
getSlaves())
56 slave->getSlaveIdentifier(), bus_rtHandleSlaveErrors_slaveHasError, 0.3)
61 if (!slave->handleErrors())
64 reporter, slave->getSlaveIdentifier(),
"Unhandled error in slave")
68 slave->getSlaveIdentifier(), bus_rtHandleSlaveErrors_slaveHandleError, 0.3)
72 slaveErrorFound = reporter.hasErrors();
78 return busErrorFound || slaveErrorFound;
84 return !allSlavesReinitialized.load();
90 return slaveStates.at(slave) != SlaveState::Operational;
96 expectedWorkCounter = wkc;
100 slaveStates.insert({
s.get(), SlaveState::Operational});
105 BusErrorHandler::rtUpdateSlaveStates()
109 if (workerCounterWatchdog.expired())
111 if (bus->
lastWorkCounter == EC_NOFRAME && !allSlavesReinitialized.load())
115 "The last work counter is EC_NOFRAME not all slaves have been "
116 "reinitialized yet!");
121 "Last Work Counter: %i, Second Last Unexpected Work Counter: %i, "
122 "Expected Work Counter: %i",
124 secondLastUnexpectedWorkCounter,
125 expectedWorkCounter);
130 rtMarkLostSlavesInSOEMStruct();
132 std::stringstream lost_ss;
133 std::stringstream redisc_ss;
134 bool print_lost =
false;
135 bool print_redisc =
false;
136 lost_ss <<
"The following slaves have been lost: \n";
137 redisc_ss <<
"The following slaves have been rediscovered: \n";
138 for (
const auto& slave : bus->
getSlaves())
140 if (ec_slave[slave->getSlaveIdentifier().slaveIndex].islost)
142 if (slaveStates.at(slave.get()) != SlaveState::Lost)
144 lost_ss << slave->getSlaveIdentifier().getNameAsCStr() <<
"("
145 << slave->getSlaveIdentifier().slaveIndex <<
")\n";
146 busErrorFound =
true;
150 slaveStates.at(slave.get()) = SlaveState::Lost;
151 allSlavesReinitialized.store(
false);
155 if (slaveStates.at(slave.get()) == SlaveState::Lost)
157 slaveStates.at(slave.get()) = SlaveState::Reinitializating;
159 redisc_ss << slave->getSlaveIdentifier().getNameAsCStr() <<
"("
160 << slave->getSlaveIdentifier().slaveIndex <<
")\n";
166 BUS_ERROR(bus->iterationCount, lost_ss.str().c_str());
170 BUS_INFO(bus->iterationCount, redisc_ss.str().c_str());
176 for (
const auto& slave : bus->
getSlaves())
179 ec_slave[slave->getSlaveIdentifier().slaveIndex].state) !=
181 ec_slave[slave->getSlaveIdentifier().slaveIndex].islost == 0 &&
182 (slaveStates.at(slave.get()) != SlaveState::Reinitializating))
184 slaveStates.at(slave.get()) = SlaveState::Reinitializating;
187 "Slave at index %u of type %s needs reinitialization!",
188 slave->getSlaveIdentifier().slaveIndex,
189 slave->getSlaveIdentifier().getNameAsCStr());
198 busErrorFound =
false;
199 workerCounterWatchdog.reset();
207 BusErrorHandler::rtMarkLostSlavesInSOEMStruct()
const
210 const int slaveCount = ec_BRD(0x0000, ECT_REG_TYPE,
sizeof(w), &w, EC_TIMEOUTSAFE);
211 if (slaveCount == EC_NOFRAME)
216 if (slaveCount < ec_slavecount)
219 "Number of Slaves (%i) in SOEM struct is less than configured Slaves (%i).",
223 std::vector<RegisterDataList> registers;
224 for (
auto i = 1; i <= ec_slavecount; i++)
227 RegisterDataList{
static_cast<std::uint16_t
>(i),
236 std::stringstream ss;
237 ss <<
"Slaves with the following indexes are not reachable: \n";
238 for (
const auto& dataList : registers)
242 if (std::holds_alternative<datatypes::EtherCATDataType::UNSIGNED16>(
data) &&
243 ec_slave[dataList.slaveIndex].configadr ==
244 std::get<datatypes::EtherCATDataType::UNSIGNED16>(
data))
246 ec_slave[dataList.slaveIndex].islost =
false;
250 ss << dataList.slaveIndex <<
", ";
251 ec_slave[dataList.slaveIndex].islost =
true;
254 ss.seekp(ss.str().length() - 2);
255 ss <<
"\n The total number of registers read is " << registers.size() <<
"\n";
256 BUS_ERROR(bus->iterationCount,
"%s", ss.str().c_str());
261 for (
int i = 1; i <= ec_slavecount; i++)
263 ec_slave[i].islost =
false;
269 BusErrorHandler::reinitializeSlaves()
274 for (
const auto& [slave, state] : slaveStates)
276 if (state != SlaveState::Reinitializating)
281 std::uint16_t
index =
282 static_cast<std::uint16_t
>(slave->getSlaveIdentifier().slaveIndex);
284 bool slaveReadyAgain =
false;
286 switch (EtherCATState(ec_slave[
index].state))
294 if (ec_recover_slave(
index, 10000))
303 "Could not recover slave: %s",
304 slave->getSlaveIdentifier().getNameAsCStr());
316 ec_slave[
index].PO2SOconfig = [](std::uint16_t
index) ->
int
320 auto localSlave = bus.getSlaveAtIndex(
index);
322 localSlave->doMappings();
323 localSlave->prepareForSafeOp();
324 localSlave->finishPreparingForSafeOp();
329 ec_reconfig_slave(
index, 10000);
332 ec_slave[
index].PO2SOconfig =
nullptr;
340 slave->prepareForOp();
341 slave->finishPreparingForOp();
355 ec_recover_slave(
index, 10000);
365 if (slave->prepareForRun())
367 slaveReadyAgain =
true;
381 slaveStates.at(slave) = SlaveState::Operational;
384 <<
"Slave at index " << slave->getSlaveIdentifier().slaveIndex <<
" of type "
385 << slave->getSlaveIdentifier().getName()
386 <<
" has been successfully reinitialized. Current bus iteration number is "
387 << bus->iterationCount;
389 allSlavesReinitialized.store(areAllSlavesReinitialized());
395 BusErrorHandler::slaveReinitializingLoop()
397 while (slaveReinitializingThreadRunning.load())
399 while (!allSlavesReinitialized.load())
401 reinitializeSlaves();
404 using namespace std::literals;
405 std::this_thread::sleep_for(100us);
410 BusErrorHandler::areAllSlavesReinitialized()
const
413 for (
const auto& [slave, state] : slaveStates)
415 r |= (state == SlaveState::Reinitializating);
420 BusErrorHandler::Watchdog::Watchdog(std::uint32_t minDurationUS) :
421 minDuration(minDurationUS), lastTime(
armarx::
rtNow())
426 BusErrorHandler::Watchdog::expired()
const
428 return (
armarx::rtNow() - lastTime).toMicroSeconds() > minDuration;
432 BusErrorHandler::Watchdog::reset()