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;
207 allSlavesReinitialized.store(
false);
209 busErrorFound =
true;
212 "Slave at index %u of type %s needs reinitialization!",
213 slave->getSlaveIdentifier().slaveIndex,
214 slave->getSlaveIdentifier().getNameAsCStr());
223 busErrorFound =
false;
224 workerCounterWatchdog.reset();
232 BusErrorHandler::rtMarkLostSlavesInSOEMStruct()
const
235 const int slaveCount = ec_BRD(0x0000, ECT_REG_TYPE,
sizeof(w), &w, EC_TIMEOUTSAFE);
236 if (slaveCount == EC_NOFRAME)
241 if (slaveCount < ec_slavecount)
244 "Number of Slaves (%i) in SOEM struct is less than configured Slaves (%i).",
248 std::vector<RegisterDataList> registers;
249 for (
auto i = 1; i <= ec_slavecount; i++)
252 RegisterDataList{
static_cast<std::uint16_t
>(i),
261 std::stringstream ss;
262 ss <<
"Slaves with the following indexes are not reachable: \n";
263 for (
const auto& dataList : registers)
267 if (std::holds_alternative<datatypes::EtherCATDataType::UNSIGNED16>(
data) &&
268 ec_slave[dataList.slaveIndex].configadr ==
269 std::get<datatypes::EtherCATDataType::UNSIGNED16>(
data))
271 ec_slave[dataList.slaveIndex].islost =
false;
275 ss << dataList.slaveIndex <<
", ";
276 ec_slave[dataList.slaveIndex].islost =
true;
279 ss.seekp(ss.str().length() - 2);
280 ss <<
"\n The total number of registers read is " << registers.size() <<
"\n";
281 BUS_ERROR(bus->iterationCount,
"%s", ss.str().c_str());
286 for (
int i = 1; i <= ec_slavecount; i++)
288 ec_slave[i].islost =
false;
294 BusErrorHandler::reinitializeSlaves()
299 for (
const auto& [slave, state] : slaveStates)
301 if (state != SlaveState::Reinitializating)
306 std::uint16_t
index =
307 static_cast<std::uint16_t
>(slave->getSlaveIdentifier().slaveIndex);
309 bool slaveReadyAgain =
false;
311 switch (EtherCATState(ec_slave[
index].state))
319 if (ec_recover_slave(
index, 10000))
328 "Could not recover slave: %s",
329 slave->getSlaveIdentifier().getNameAsCStr());
341 ec_slave[
index].PO2SOconfig = [](std::uint16_t
index) ->
int
345 auto localSlave = bus.getSlaveAtIndex(
index);
347 localSlave->doMappings();
348 localSlave->prepareForSafeOp();
349 localSlave->finishPreparingForSafeOp();
354 ec_reconfig_slave(
index, 10000);
357 ec_slave[
index].PO2SOconfig =
nullptr;
365 slave->prepareForOp();
366 slave->finishPreparingForOp();
380 ec_recover_slave(
index, 10000);
390 if (slave->prepareForRun())
392 slaveReadyAgain =
true;
406 slaveStates.at(slave) = SlaveState::Operational;
409 <<
"Slave at index " << slave->getSlaveIdentifier().slaveIndex <<
" of type "
410 << slave->getSlaveIdentifier().getName()
411 <<
" has been successfully reinitialized. Current bus iteration number is "
412 << bus->iterationCount;
414 allSlavesReinitialized.store(areAllSlavesReinitialized());
420 BusErrorHandler::slaveReinitializingLoop()
422 while (slaveReinitializingThreadRunning.load())
424 while (!allSlavesReinitialized.load())
426 reinitializeSlaves();
429 using namespace std::literals;
430 std::this_thread::sleep_for(100us);
435 BusErrorHandler::areAllSlavesReinitialized()
const
438 for (
const auto& [slave, state] : slaveStates)
440 r |= (state == SlaveState::Reinitializating);
445 BusErrorHandler::Watchdog::Watchdog(std::uint32_t minDurationUS) :
446 minDuration(minDurationUS), lastTime(
armarx::
rtNow())
451 BusErrorHandler::Watchdog::expired()
const
453 return (
armarx::rtNow() - lastTime).toMicroSeconds() > minDuration;
457 BusErrorHandler::Watchdog::reset()