From 8008cf554771284fecf8794839601bc7afa7a7a2 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Tue, 31 Aug 2021 22:25:53 +0800 Subject: [PATCH] boardd: remove global panda (#21962) --- selfdrive/boardd/boardd.cc | 88 ++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 46 deletions(-) diff --git a/selfdrive/boardd/boardd.cc b/selfdrive/boardd/boardd.cc index bea09129b..3f09ec949 100644 --- a/selfdrive/boardd/boardd.cc +++ b/selfdrive/boardd/boardd.cc @@ -35,14 +35,12 @@ #define SATURATE_IL 1600 #define NIBBLE_TO_HEX(n) ((n) < 10 ? (n) + '0' : ((n) - 10) + 'a') -Panda * panda = nullptr; std::atomic safety_setter_thread_running(false); std::atomic ignition(false); ExitHandler do_exit; - -void safety_setter_thread() { +void safety_setter_thread(Panda *panda) { LOGD("Starting safety setter thread"); // diagnostic only is the default, needed for VIN query panda->set_safety_model(cereal::CarParams::SafetyModel::ELM327); @@ -101,24 +99,21 @@ void safety_setter_thread() { } -bool usb_connect() { - static bool connected_once = false; - - std::unique_ptr tmp_panda; +Panda *usb_connect() { + std::unique_ptr panda; try { - assert(panda == nullptr); - tmp_panda = std::make_unique(); + panda = std::make_unique(); } catch (std::exception &e) { - return false; + return nullptr; } Params params = Params(); if (getenv("BOARDD_LOOPBACK")) { - tmp_panda->set_loopback(true); + panda->set_loopback(true); } - if (auto fw_sig = tmp_panda->get_firmware_version(); fw_sig) { + if (auto fw_sig = panda->get_firmware_version(); fw_sig) { params.put("PandaFirmware", (const char *)fw_sig->data(), fw_sig->size()); // Convert to hex for offroad @@ -131,25 +126,24 @@ bool usb_connect() { params.put("PandaFirmwareHex", fw_sig_hex_buf, 16); LOGW("fw signature: %.*s", 16, fw_sig_hex_buf); - } else { return false; } + } else { return nullptr; } // get panda serial - if (auto serial = tmp_panda->get_serial(); serial) { + if (auto serial = panda->get_serial(); serial) { params.put("PandaDongleId", serial->c_str(), serial->length()); LOGW("panda serial: %s", serial->c_str()); - } else { return false; } + } else { return nullptr; } // power on charging, only the first time. Panda can also change mode and it causes a brief disconneciton #ifndef __x86_64__ - if (!connected_once) { - tmp_panda->set_usb_power_mode(cereal::PandaState::UsbPowerMode::CDP); - } + static std::once_flag connected_once; + std::call_once(connected_once, &Panda::set_usb_power_mode, panda, cereal::PandaState::UsbPowerMode::CDP); #endif - if (tmp_panda->has_rtc) { + if (panda->has_rtc) { setenv("TZ","UTC",1); struct tm sys_time = util::get_time(); - struct tm rtc_time = tmp_panda->get_rtc(); + struct tm rtc_time = panda->get_rtc(); if (!util::time_valid(sys_time) && util::time_valid(rtc_time)) { LOGE("System time wrong, setting from RTC. " @@ -164,29 +158,31 @@ bool usb_connect() { } } - connected_once = true; - panda = tmp_panda.release(); - return true; + return panda.release(); } // must be called before threads or with mutex -static bool usb_retry_connect() { +static Panda *usb_retry_connect() { LOGW("attempting to connect"); - while (!do_exit && !usb_connect()) { util::sleep_for(100); } - if (panda) { - LOGW("connected to board"); - } - return !do_exit; + while (!do_exit) { + Panda *panda = usb_connect(); + if (panda) { + LOGW("connected to board"); + return panda; + } + util::sleep_for(100); + }; + return nullptr; } -void can_recv(PubMaster &pm) { +void can_recv(Panda *panda, PubMaster &pm) { kj::Array can_data; panda->can_receive(can_data); auto bytes = can_data.asBytes(); pm.send("can", bytes.begin(), bytes.size()); } -void can_send_thread(bool fake_send) { +void can_send_thread(Panda *panda, bool fake_send) { LOGD("start send thread"); AlignedBuffer aligned_buf; @@ -223,7 +219,7 @@ void can_send_thread(bool fake_send) { delete context; } -void can_recv_thread() { +void can_recv_thread(Panda *panda) { LOGD("start recv thread"); // can = 8006 @@ -234,7 +230,7 @@ void can_recv_thread() { uint64_t next_frame_time = nanos_since_boot() + dt; while (!do_exit && panda->connected) { - can_recv(pm); + can_recv(panda, pm); uint64_t cur_time = nanos_since_boot(); int64_t remaining = next_frame_time - cur_time; @@ -251,7 +247,7 @@ void can_recv_thread() { } } -void panda_state_thread(bool spoofing_started) { +void panda_state_thread(Panda *&panda, bool spoofing_started) { LOGD("start panda state thread"); PubMaster pm({"pandaState"}); @@ -308,7 +304,7 @@ void panda_state_thread(bool spoofing_started) { if (!safety_setter_thread_running) { safety_setter_thread_running = true; - std::thread(safety_setter_thread).detach(); + std::thread(safety_setter_thread, panda).detach(); } else { LOGW("Safety setter thread already running"); } @@ -400,7 +396,7 @@ void panda_state_thread(bool spoofing_started) { } } -void hardware_control_thread() { +void hardware_control_thread(Panda *panda) { LOGD("start hardware control thread"); SubMaster sm({"deviceState", "driverCameraState"}); @@ -481,7 +477,7 @@ static void pigeon_publish_raw(PubMaster &pm, const std::string &dat) { pm.send("ubloxRaw", msg); } -void pigeon_thread() { +void pigeon_thread(Panda *panda) { PubMaster pm({"ubloxRaw"}); bool ignition_last = false; @@ -554,28 +550,28 @@ void pigeon_thread() { delete pigeon; } - int main() { - int err; LOGW("starting boardd"); // set process priority and affinity - err = set_realtime_priority(54); + int err = set_realtime_priority(54); LOG("set priority returns %d", err); err = set_core_affinity(Hardware::TICI() ? 4 : 3); LOG("set affinity returns %d", err); while (!do_exit) { + Panda *panda = nullptr; std::vector threads; - threads.push_back(std::thread(panda_state_thread, getenv("STARTED") != nullptr)); + threads.emplace_back(panda_state_thread, std::ref(panda), getenv("STARTED") != nullptr); // connect to the board - if (usb_retry_connect()) { - threads.push_back(std::thread(can_send_thread, getenv("FAKESEND") != nullptr)); - threads.push_back(std::thread(can_recv_thread)); - threads.push_back(std::thread(hardware_control_thread)); - threads.push_back(std::thread(pigeon_thread)); + panda = usb_retry_connect(); + if (panda != nullptr) { + threads.emplace_back(can_send_thread, panda, getenv("FAKESEND") != nullptr); + threads.emplace_back(can_recv_thread, panda); + threads.emplace_back(hardware_control_thread, panda); + threads.emplace_back(pigeon_thread, panda); } for (auto &t : threads) t.join();