diff --git a/include/can_interface.h b/include/can_interface.h index 4cbd6e2..4986993 100644 --- a/include/can_interface.h +++ b/include/can_interface.h @@ -438,6 +438,15 @@ class ICAN virtual void RegisterRXMessage(ICANRXMessage &msg) = 0; virtual void Tick() = 0; + + enum class ErrorStatus + { + ERROR_ACTIVE, + ERROR_PASSIVE, + BUS_OFF + }; + + virtual ErrorStatus GetErrorStatus() = 0; }; /** @@ -486,7 +495,7 @@ class MultiplexedSignalGroup : public std::array, pub { public: template - MultiplexedSignalGroup(uint64_t multiplexor_value, Ts &... signals) + MultiplexedSignalGroup(uint64_t multiplexor_value, Ts &...signals) : std::array{&signals...} { static_assert(sizeof...(signals) == num_signals, "Wrong number of signals passed into SignalGroup."); @@ -495,7 +504,7 @@ class MultiplexedSignalGroup : public std::array, pub } template - MultiplexedSignalGroup(bool always_active, uint64_t multiplexor_value, Ts &... signals) + MultiplexedSignalGroup(bool always_active, uint64_t multiplexor_value, Ts &...signals) : std::array{&signals...} { static_assert(sizeof...(signals) == num_signals, "Wrong number of signals passed into SignalGroup."); @@ -533,7 +542,7 @@ class CANTXMessage : public ICANTXMessage uint8_t length, uint32_t period, ICANSignal &signal_1, - Ts &... signals) + Ts &...signals) : can_interface_{can_interface}, message_{id, extended_id, length, std::array()}, transmit_timer_{period, [this]() { this->EncodeAndSend(); }, VirtualTimer::Type::kRepeating}, @@ -554,7 +563,7 @@ class CANTXMessage : public ICANTXMessage * @param signals The ICANSignals contained in the message */ CANTXMessage( - ICAN &can_interface, uint32_t id, uint8_t length, uint32_t period, ICANSignal &signal_1, Ts &... signals) + ICAN &can_interface, uint32_t id, uint8_t length, uint32_t period, ICANSignal &signal_1, Ts &...signals) : CANTXMessage(can_interface, id, false, length, period, signal_1, signals...) { } @@ -579,7 +588,7 @@ class CANTXMessage : public ICANTXMessage uint32_t period, VirtualTimerGroup &timer_group, ICANSignal &signal_1, - Ts &... signals) + Ts &...signals) : CANTXMessage(can_interface, id, extended_id, length, period, signal_1, signals...) { timer_group.AddTimer(transmit_timer_); @@ -604,7 +613,7 @@ class CANTXMessage : public ICANTXMessage uint32_t period, VirtualTimerGroup &timer_group, ICANSignal &signal_1, - Ts &... signals) + Ts &...signals) : CANTXMessage(can_interface, id, false, length, period, timer_group, signal_1, signals...) { } @@ -666,7 +675,7 @@ class MultiplexedCANTXMessage : public ICANTXMessage uint32_t period, std::array multiplexor_values_to_transmit, ITypedCANSignal &multiplexor, - Ts &... signal_groups) + Ts &...signal_groups) : can_interface_{can_interface}, message_{id, extended_id, length, std::array()}, #if !defined(NATIVE) // workaround for unit tests @@ -709,7 +718,7 @@ class MultiplexedCANTXMessage : public ICANTXMessage uint32_t period, std::array multiplexor_values_to_transmit, ITypedCANSignal &multiplexor, - Ts &... signal_groups) + Ts &...signal_groups) : MultiplexedCANTXMessage( can_interface, id, false, length, period, multiplexor_values_to_transmit, multiplexor, signal_groups...) { @@ -739,7 +748,7 @@ class MultiplexedCANTXMessage : public ICANTXMessage VirtualTimerGroup &timer_group, std::array multiplexor_values_to_transmit, ITypedCANSignal &multiplexor, - Ts &... signal_groups) + Ts &...signal_groups) : MultiplexedCANTXMessage(can_interface, id, extended_id, @@ -776,7 +785,7 @@ class MultiplexedCANTXMessage : public ICANTXMessage VirtualTimerGroup &timer_group, std::array multiplexor_values_to_transmit, ITypedCANSignal &multiplexor, - Ts &... signal_groups) + Ts &...signal_groups) : MultiplexedCANTXMessage(can_interface, id, false, @@ -893,7 +902,7 @@ class PGNCANTXMessage : public ICANTXMessage uint8_t length, uint32_t period, ICANSignal &signal_1, - Ts &... signals) + Ts &...signals) : can_interface_{can_interface}, message_{id, length, std::array()}, transmit_timer_{period, [this]() { this->EncodeAndSend(); }, VirtualTimer::Type::kRepeating}, @@ -921,7 +930,7 @@ class PGNCANTXMessage : public ICANTXMessage uint32_t period, VirtualTimerGroup &timer_group, ICANSignal &signal_1, - Ts &... signals) + Ts &...signals) : PGNCANTXMessage(can_interface, id, length, period, signal_1, signals...) { timer_group.AddTimer(transmit_timer_); @@ -972,7 +981,7 @@ class CANRXMessage : public ICANRXMessage std::function get_millis, std::function callback_function, ICANSignal &signal_1, - Ts &... signals) + Ts &...signals) : can_interface_{can_interface}, id_{id}, get_millis_{get_millis}, @@ -988,7 +997,7 @@ class CANRXMessage : public ICANRXMessage uint32_t id, std::function get_millis, ICANSignal &signal_1, - Ts &... signals) + Ts &...signals) : CANRXMessage{can_interface, id, get_millis, nullptr, signal_1, signals...} { } @@ -1001,13 +1010,13 @@ class CANRXMessage : public ICANRXMessage uint32_t id, std::function callback_function, ICANSignal &signal_1, - Ts &... signals) + Ts &...signals) : CANRXMessage{can_interface, id, []() { return millis(); }, callback_function, signal_1, signals...} { } template - CANRXMessage(ICAN &can_interface, uint32_t id, ICANSignal &signal_1, Ts &... signals) + CANRXMessage(ICAN &can_interface, uint32_t id, ICANSignal &signal_1, Ts &...signals) : CANRXMessage{can_interface, id, []() { return millis(); }, nullptr, signal_1, signals...} { } @@ -1075,7 +1084,7 @@ class MultiplexedCANRXMessage : public ICANRXMessage std::function get_millis, std::function callback_function, ITypedCANSignal &multiplexor, - Ts &... signal_groups) + Ts &...signal_groups) : can_interface_{can_interface}, id_{id}, get_millis_{get_millis}, @@ -1102,7 +1111,7 @@ class MultiplexedCANRXMessage : public ICANRXMessage uint32_t id, std::function get_millis, ITypedCANSignal &multiplexor, - Ts &... signal_groups) + Ts &...signal_groups) : MultiplexedCANRXMessage{can_interface, id, get_millis, nullptr, multiplexor, signal_groups...} { } @@ -1115,7 +1124,7 @@ class MultiplexedCANRXMessage : public ICANRXMessage uint32_t id, std::function callback_function, ITypedCANSignal &multiplexor, - Ts &... signal_groups) + Ts &...signal_groups) : MultiplexedCANRXMessage{ can_interface, id, []() { return millis(); }, callback_function, multiplexor, signal_groups...} { @@ -1125,7 +1134,7 @@ class MultiplexedCANRXMessage : public ICANRXMessage MultiplexedCANRXMessage(ICAN &can_interface, uint32_t id, ITypedCANSignal &multiplexor, - Ts &... signal_groups) + Ts &...signal_groups) : MultiplexedCANRXMessage{can_interface, id, []() { return millis(); }, nullptr, multiplexor, signal_groups...} { } @@ -1226,7 +1235,7 @@ class PGNCANRXMessage : public ICANRXMessage std::function get_millis, std::function callback_function, ICANSignal &signal_1, - Ts &... signals) + Ts &...signals) : can_interface_{can_interface}, id_{id}, get_millis_{get_millis}, @@ -1242,7 +1251,7 @@ class PGNCANRXMessage : public ICANRXMessage PGNCANMessage::ExtendedId id, std::function get_millis, ICANSignal &signal_1, - Ts &... signals) + Ts &...signals) : PGNCANRXMessage{can_interface, id, get_millis, nullptr, signal_1, signals...} { } @@ -1255,13 +1264,13 @@ class PGNCANRXMessage : public ICANRXMessage PGNCANMessage::ExtendedId id, std::function callback_function, ICANSignal &signal_1, - Ts &... signals) + Ts &...signals) : PGNCANRXMessage{can_interface, id, []() { return millis(); }, callback_function, signal_1, signals...} { } template - PGNCANRXMessage(ICAN &can_interface, PGNCANMessage::ExtendedId id, ICANSignal &signal_1, Ts &... signals) + PGNCANRXMessage(ICAN &can_interface, PGNCANMessage::ExtendedId id, ICANSignal &signal_1, Ts &...signals) : PGNCANRXMessage{can_interface, id, []() { return millis(); }, nullptr, signal_1, signals...} { } diff --git a/include/esp_can.h b/include/esp_can.h index b8273b9..356eb3c 100644 --- a/include/esp_can.h +++ b/include/esp_can.h @@ -23,6 +23,8 @@ class ESPCAN : public ICAN void Tick() override; + ErrorStatus GetErrorStatus() override; + private: static std::vector rx_messages_; twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(GPIO_NUM_5, GPIO_NUM_4, TWAI_MODE_NORMAL); diff --git a/include/teensy_can.h b/include/teensy_can.h index 1e5242f..61609c8 100644 --- a/include/teensy_can.h +++ b/include/teensy_can.h @@ -35,6 +35,8 @@ class TeensyCAN : public ICAN void Tick() override; + ErrorStatus GetErrorStatus() override; + private: static std::vector rx_messages_; CAN_message_t message_t{}; diff --git a/src/esp_can.cpp b/src/esp_can.cpp index 2afd596..be5e60d 100644 --- a/src/esp_can.cpp +++ b/src/esp_can.cpp @@ -125,4 +125,25 @@ void ESPCAN::Tick() } } +ICAN::ErrorStatus ESPCAN::GetErrorStatus() +{ + twai_status_info_t status; + twai_get_status_info(&status); + + // ref: + // https://docs.espressif.com/projects/esp-idf/en/v4.2.2/esp32s2/api-reference/peripherals/twai.html#error-states-and-counters + if (status.tx_error_counter < 128 && status.rx_error_counter < 128) + { + return ICAN::ErrorStatus::ERROR_ACTIVE; + } + else if (status.tx_error_counter >= 128 || status.rx_error_counter >= 128) + { + return ICAN::ErrorStatus::ERROR_PASSIVE; + } + else if (status.tx_error_counter >= 256) + { + return ICAN::ErrorStatus::BUS_OFF; + } +} + #endif \ No newline at end of file diff --git a/src/teensy_can.cpp b/src/teensy_can.cpp index c5433b2..09d032b 100644 --- a/src/teensy_can.cpp +++ b/src/teensy_can.cpp @@ -92,7 +92,8 @@ bool TeensyCAN::SendMessage(CANMessage &msg) } template -_MB_ptr TeensyCAN::ProcessMessage = [](const CAN_message_t &msg) { +_MB_ptr TeensyCAN::ProcessMessage = [](const CAN_message_t &msg) +{ std::array msg_data{}; memcpy(msg_data.data(), msg.buf, 8); CANMessage received_message{static_cast(msg.id), msg.len, msg_data}; @@ -101,4 +102,36 @@ _MB_ptr TeensyCAN::ProcessMessage = [](const CAN_message_t &msg) { rx_messages_[i]->DecodeSignals(received_message); } }; + +template +ICAN::ErrorStatus TeensyCAN::GetErrorStatus() +{ + CAN_error_t err; + // Repeated code due to limitations of C++11, look into alternatives without repeated code + if (bus_num == 2) + { + can_bus_2.error(err, false); + } + else if (bus_num == 3) + { + can_bus_3.error(err, false); + } + else + { + can_bus_1.error(err, false); + } + + if (err.FLT_CONF == "Error Active") + { + return ICAN::ErrorStatus::ERROR_ACTIVE; + } + else if (err.FLT_CONF == "Error Passive") + { + return ICAN::ErrorStatus::ERROR_PASSIVE; + } + else if (err.FLT_CONF == "Bus off") + { + return ICAN::ErrorStatus::BUS_OFF; + } +} #endif \ No newline at end of file