diff --git a/tracker/code/main/GLOB.cpp b/tracker/code/main/GLOB.cpp index d6d700f..da1ab55 100644 --- a/tracker/code/main/GLOB.cpp +++ b/tracker/code/main/GLOB.cpp @@ -17,6 +17,7 @@ std::string GLOB::str() const s<<"\tlon="<(), "gpio numbered pin for radio enable. current board: 22") ("hw_radio_serial", po::value(), "serial device for MTX2 radio. for rPI4: /dev/serial0") ("hw_ublox_device", po::value(), "I2C device for uBLOX. for rPI4: /dev/i2c-7") - ("latlonalt", po::value< std::vector >()->multitoken(), "Launch site GPS location (decimal) and alt meters") - ("testgps", po::value(), "Generate fake GPS for testing") + ("latlonalt", po::value< std::vector >()->multitoken(), "launch site GPS location (decimal) and alt meters") + ("testgps", po::value(), "generate fake GPS for testing") + ("watchdog", po::value(), "enable watchdog") ; po::options_description cli_options("Command Line Interface options"); @@ -80,6 +81,7 @@ void CLI(int ac, char* av[]) if (vm.count("ssdv")) GLOB::get().cli.ssdv_image = vm["ssdv"].as(); if (vm.count("baud")) GLOB::get().cli.baud = static_cast( vm["baud"].as() ); if (vm.count("testgps")) GLOB::get().cli.testgps = vm["testgps"].as(); + if (vm.count("watchdog")) GLOB::get().cli.watchdog = vm["watchdog"].as(); if (vm.count("latlonalt")) { vector latlonalt_vec = vm["latlonalt"].as< vector >(); GLOB::get().cli.lat = latlonalt_vec[0]; diff --git a/tracker/code/main/main.cpp b/tracker/code/main/main.cpp index 2a7c7da..005be87 100644 --- a/tracker/code/main/main.cpp +++ b/tracker/code/main/main.cpp @@ -25,6 +25,7 @@ #include "GLOB.h" #include "gps_distance_t.h" #include "async_log_t.h" +#include "pulse_t.h" const char* C_RED = "\033[1;31m"; const char* C_GREEN = "\033[1;32m"; @@ -136,7 +137,7 @@ void watchdog_disable() { G_WATCHDOG_V.store('V'); // disable char v = G_WATCHDOG_V.load(); - // std::cout<<"watchdog_disable "< ublox_data = uBLOX_read_msg(uBlox_i2c_fd); // typical blocking time: 0/1/1.2 seconds const string nmea_str = NMEA_get_last_msg(ublox_data.data(), ublox_data.size()); // cout<(chrono::steady_clock::now() - START_TIME).count(); @@ -392,6 +398,32 @@ int main1(int argc, char** argv) }); + // PULSE watch thread + // if any of other threads doesn't ping at least once 10 seconds + // stop reseting hardware watchdog -> REBOOT + // + const bool use_watchdog = G.cli.watchdog; + std::thread pulse_watch_thread([&LOG, &PULSE, use_watchdog]() { + if(not use_watchdog) + return; + LOG.log("main.log", "PULSE watch thread start"); + while(G_RUN) { + this_thread::sleep_for(chrono::seconds(3)); + auto age_proc = PULSE.get_oldest_ping_age(); + float age_secs = float(std::get<0>(age_proc)) / 1e6; + std::string proc = std::get<1>(age_proc); + if(age_secs<15) { + watchdog_reset(); + } else { + cout<<"PULSE: WATCHDOG RESET HOLD !!! process:"< +#include +#include +#include +#include + +#include "GLOB.h" + +// each process can periodically ping this class: +// while(1) { +// ... +// pulse.ping("uBLOX"); +// } +// +// it is then possible to check if all processes are alive +// with get_oldest_ping_age() + +class pulse_t +{ +private: + using map_t = std::map< std::string, std::chrono::high_resolution_clock::time_point >; + map_t map_; + std::mutex mtx_; + +public: + void ping(const std::string& name) + { + std::lock_guard _lock(mtx_); + map_[name] = std::chrono::high_resolution_clock::now(); + } + + std::tuple get_oldest_ping_age() // return oldest ping age in microseconds + { + using namespace std::chrono; + auto now = high_resolution_clock::now(); + long long oldest_age = 0; + std::string oldest_proc; + + { + std::lock_guard _lock(mtx_); + for(const auto& proc : map_) { + const auto age = duration_cast(now-proc.second).count(); + if(age > oldest_age) { + oldest_age = age; + oldest_proc = proc.first; + } + } + } + + return std::make_tuple(oldest_age, oldest_proc); + } + +}; +