Pigeon (ublox) initialization fixes (#22712)

* add timeout to wait_for_ack

* fix ignition edge detection race condition

* local_ignition -> ignition_local

* gate power_save on !pigeon_active

* millis_since_boot

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
old-commit-hash: 21c4bfc7be
commatwo_master
Robbe Derks 4 years ago committed by GitHub
parent fd2bc4ce18
commit a6a2693a1c
  1. 24
      selfdrive/boardd/boardd.cc
  2. 5
      selfdrive/boardd/pigeon.cc
  3. 2
      selfdrive/boardd/pigeon.h

@ -39,6 +39,7 @@
using namespace std::chrono_literals; using namespace std::chrono_literals;
std::atomic<bool> ignition(false); std::atomic<bool> ignition(false);
std::atomic<bool> pigeon_active(false);
ExitHandler do_exit; ExitHandler do_exit;
@ -268,16 +269,16 @@ bool send_panda_state(PubMaster *pm, Panda *panda, bool spoofing_started) {
panda->set_safety_model(cereal::CarParams::SafetyModel::NO_OUTPUT); panda->set_safety_model(cereal::CarParams::SafetyModel::NO_OUTPUT);
} }
bool ignition = ((pandaState.ignition_line != 0) || (pandaState.ignition_can != 0)); bool ignition_local = ((pandaState.ignition_line != 0) || (pandaState.ignition_can != 0));
#ifndef __x86_64__ #ifndef __x86_64__
bool power_save_desired = !ignition; bool power_save_desired = !ignition_local && !pigeon_active;
if (pandaState.power_save_enabled != power_save_desired) { if (pandaState.power_save_enabled != power_save_desired) {
panda->set_power_saving(power_save_desired); panda->set_power_saving(power_save_desired);
} }
// set safety mode to NO_OUTPUT when car is off. ELM327 is an alternative if we want to leverage athenad/connect // set safety mode to NO_OUTPUT when car is off. ELM327 is an alternative if we want to leverage athenad/connect
if (!ignition && (pandaState.safety_model != (uint8_t)(cereal::CarParams::SafetyModel::NO_OUTPUT))) { if (!ignition_local && (pandaState.safety_model != (uint8_t)(cereal::CarParams::SafetyModel::NO_OUTPUT))) {
panda->set_safety_model(cereal::CarParams::SafetyModel::NO_OUTPUT); panda->set_safety_model(cereal::CarParams::SafetyModel::NO_OUTPUT);
} }
#endif #endif
@ -320,7 +321,7 @@ bool send_panda_state(PubMaster *pm, Panda *panda, bool spoofing_started) {
} }
pm->send("pandaStates", msg); pm->send("pandaStates", msg);
return ignition; return ignition_local;
} }
void send_peripheral_state(PubMaster *pm, Panda *panda) { void send_peripheral_state(PubMaster *pm, Panda *panda) {
@ -498,10 +499,11 @@ void pigeon_thread(Panda *panda) {
while (!do_exit && panda->connected) { while (!do_exit && panda->connected) {
bool need_reset = false; bool need_reset = false;
bool ignition_local = ignition;
std::string recv = pigeon->receive(); std::string recv = pigeon->receive();
// Parse message header // Parse message header
if (ignition && recv.length() >= 3) { if (ignition_local && recv.length() >= 3) {
if (recv[0] == (char)ublox::PREAMBLE1 && recv[1] == (char)ublox::PREAMBLE2) { if (recv[0] == (char)ublox::PREAMBLE1 && recv[1] == (char)ublox::PREAMBLE2) {
const char msg_cls = recv[2]; const char msg_cls = recv[2];
uint64_t t = nanos_since_boot(); uint64_t t = nanos_since_boot();
@ -514,7 +516,7 @@ void pigeon_thread(Panda *panda) {
// Check based on message frequency // Check based on message frequency
for (const auto& [msg_cls, max_dt] : cls_max_dt) { for (const auto& [msg_cls, max_dt] : cls_max_dt) {
int64_t dt = (int64_t)nanos_since_boot() - (int64_t)last_recv_time[msg_cls]; int64_t dt = (int64_t)nanos_since_boot() - (int64_t)last_recv_time[msg_cls];
if (ignition_last && ignition && dt > max_dt) { if (ignition_last && ignition_local && dt > max_dt) {
LOGD("ublox receive timeout, msg class: 0x%02x, dt %llu", msg_cls, dt); LOGD("ublox receive timeout, msg class: 0x%02x, dt %llu", msg_cls, dt);
// TODO: turn on reset after verification of logs // TODO: turn on reset after verification of logs
// need_reset = true; // need_reset = true;
@ -522,7 +524,7 @@ void pigeon_thread(Panda *panda) {
} }
// Check based on null bytes // Check based on null bytes
if (ignition && recv.length() > 0 && recv[0] == (char)0x00) { if (ignition_local && recv.length() > 0 && recv[0] == (char)0x00) {
need_reset = true; need_reset = true;
LOGW("received invalid ublox message while onroad, resetting panda GPS"); LOGW("received invalid ublox message while onroad, resetting panda GPS");
} }
@ -533,7 +535,8 @@ void pigeon_thread(Panda *panda) {
// init pigeon on rising ignition edge // init pigeon on rising ignition edge
// since it was turned off in low power mode // since it was turned off in low power mode
if((ignition && !ignition_last) || need_reset) { if((ignition_local && !ignition_last) || need_reset) {
pigeon_active = true;
pigeon->init(); pigeon->init();
// Set receive times to current time // Set receive times to current time
@ -541,14 +544,15 @@ void pigeon_thread(Panda *panda) {
for (const auto& [msg_cls, dt] : cls_max_dt) { for (const auto& [msg_cls, dt] : cls_max_dt) {
last_recv_time[msg_cls] = t; last_recv_time[msg_cls] = t;
} }
} else if (!ignition && ignition_last) { } else if (!ignition_local && ignition_last) {
// power off on falling edge of ignition // power off on falling edge of ignition
LOGD("powering off pigeon\n"); LOGD("powering off pigeon\n");
pigeon->stop(); pigeon->stop();
pigeon->set_power(false); pigeon->set_power(false);
pigeon_active = false;
} }
ignition_last = ignition; ignition_last = ignition_local;
// 10ms - 100 Hz // 10ms - 100 Hz
util::sleep_for(10); util::sleep_for(10);

@ -41,8 +41,9 @@ Pigeon * Pigeon::connect(const char * tty) {
return pigeon; return pigeon;
} }
bool Pigeon::wait_for_ack(const std::string &ack, const std::string &nack) { bool Pigeon::wait_for_ack(const std::string &ack, const std::string &nack, int timeout_ms) {
std::string s; std::string s;
const double start_t = millis_since_boot();
while (!do_exit) { while (!do_exit) {
s += receive(); s += receive();
@ -52,7 +53,7 @@ bool Pigeon::wait_for_ack(const std::string &ack, const std::string &nack) {
} else if (s.find(nack) != std::string::npos) { } else if (s.find(nack) != std::string::npos) {
LOGE("Received NACK from ublox"); LOGE("Received NACK from ublox");
return false; return false;
} else if (s.size() > 0x1000) { } else if (s.size() > 0x1000 || ((millis_since_boot() - start_t) > timeout_ms)) {
LOGE("No response from ublox"); LOGE("No response from ublox");
return false; return false;
} }

@ -16,7 +16,7 @@ class Pigeon {
void init(); void init();
void stop(); void stop();
bool wait_for_ack(); bool wait_for_ack();
bool wait_for_ack(const std::string &ack, const std::string &nack); bool wait_for_ack(const std::string &ack, const std::string &nack, int timeout_ms = 1000);
bool send_with_ack(const std::string &cmd); bool send_with_ack(const std::string &cmd);
virtual void set_baud(int baud) = 0; virtual void set_baud(int baud) = 0;
virtual void send(const std::string &s) = 0; virtual void send(const std::string &s) = 0;

Loading…
Cancel
Save