Internal Interface Wrap
API reference
Loading...
Searching...
No Matches
BaseCan.h
Go to the documentation of this file.
1
25#pragma once
26
27#include "HardwareTypes.h"
28#include <atomic>
29#include <cstdint>
30#include <string_view>
31
37//--------------------------------------
38// HardFOC CAN Error Codes (Table)
39//--------------------------------------
48#define HF_CAN_ERR_LIST(X) \
49 /* Success codes */ \
50 X(CAN_SUCCESS, 0, "Success") \
51 /* General errors */ \
52 X(CAN_ERR_FAILURE, 1, "General failure") \
53 X(CAN_ERR_NOT_INITIALIZED, 2, "Not initialized") \
54 X(CAN_ERR_ALREADY_INITIALIZED, 3, "Already initialized") \
55 X(CAN_ERR_INVALID_PARAMETER, 4, "Invalid parameter") \
56 X(CAN_ERR_NULL_POINTER, 5, "Null pointer") \
57 X(CAN_ERR_OUT_OF_MEMORY, 6, "Out of memory") \
58 /* Bus errors */ \
59 X(CAN_ERR_BUS_OFF, 7, "Bus off state") \
60 X(CAN_ERR_BUS_ERROR, 8, "Bus error") \
61 X(CAN_ERR_BUS_BUSY, 9, "Bus busy") \
62 X(CAN_ERR_BUS_NOT_AVAILABLE, 10, "Bus not available") \
63 X(CAN_ERR_BUS_RECOVERY_FAILED, 11, "Bus recovery failed") \
64 X(CAN_ERR_BUS_ARBITRATION_LOST, 12, "Bus arbitration lost") \
65 /* Message errors */ \
66 X(CAN_ERR_MESSAGE_TIMEOUT, 13, "Message timeout") \
67 X(CAN_ERR_MESSAGE_LOST, 14, "Message lost") \
68 X(CAN_ERR_MESSAGE_INVALID, 15, "Invalid message") \
69 X(CAN_ERR_MESSAGE_TOO_LONG, 16, "Message too long") \
70 X(CAN_ERR_MESSAGE_INVALID_ID, 17, "Invalid message ID") \
71 X(CAN_ERR_MESSAGE_INVALID_DLC, 18, "Invalid data length code") \
72 X(CAN_ERR_QUEUE_FULL, 19, "Queue full") \
73 X(CAN_ERR_QUEUE_EMPTY, 20, "Queue empty") \
74 /* Transmission errors */ \
75 X(CAN_ERR_TX_FAILED, 21, "Transmission failed") \
76 X(CAN_ERR_TX_ABORTED, 22, "Transmission aborted") \
77 X(CAN_ERR_TX_ERROR_PASSIVE, 23, "Transmit error passive") \
78 X(CAN_ERR_TX_ERROR_WARNING, 24, "Transmit error warning") \
79 /* Reception errors */ \
80 X(CAN_ERR_RX_OVERRUN, 25, "Receive overrun") \
81 X(CAN_ERR_RX_ERROR_PASSIVE, 26, "Receive error passive") \
82 X(CAN_ERR_RX_ERROR_WARNING, 27, "Receive error warning") \
83 X(CAN_ERR_RX_FIFO_FULL, 28, "Receive FIFO full") \
84 /* Hardware errors */ \
85 X(CAN_ERR_HARDWARE_FAULT, 29, "Hardware fault") \
86 X(CAN_ERR_COMMUNICATION_FAILURE, 30, "Communication failure") \
87 X(CAN_ERR_DEVICE_NOT_RESPONDING, 31, "Device not responding") \
88 X(CAN_ERR_VOLTAGE_OUT_OF_RANGE, 32, "Voltage out of range") \
89 X(CAN_ERR_CLOCK_ERROR, 33, "Clock error") \
90 X(CAN_ERR_TRANSCEIVER_ERROR, 34, "Transceiver error") \
91 /* Configuration errors */ \
92 X(CAN_ERR_INVALID_CONFIGURATION, 35, "Invalid configuration") \
93 X(CAN_ERR_UNSUPPORTED_OPERATION, 36, "Unsupported operation") \
94 X(CAN_ERR_INVALID_BAUD_RATE, 37, "Invalid baud rate") \
95 X(CAN_ERR_INVALID_CONTROLLER_ID, 38, "Invalid controller ID") \
96 X(CAN_ERR_FILTER_ERROR, 39, "Filter error") \
97 X(CAN_ERR_FILTER_FULL, 40, "Filter table full") \
98 /* Protocol errors */ \
99 X(CAN_ERR_STUFF_ERROR, 41, "Bit stuffing error") \
100 X(CAN_ERR_FORM_ERROR, 42, "Frame format error") \
101 X(CAN_ERR_CRC_ERROR, 43, "CRC error") \
102 X(CAN_ERR_ACK_ERROR, 44, "Acknowledgment error") \
103 X(CAN_ERR_BIT_ERROR, 45, "Bit error") \
104 /* System errors */ \
105 X(CAN_ERR_SYSTEM_ERROR, 46, "System error") \
106 X(CAN_ERR_PERMISSION_DENIED, 47, "Permission denied") \
107 X(CAN_ERR_OPERATION_ABORTED, 48, "Operation aborted") \
108 \
109 /* Extended CAN errors (for ESP32 compatibility) */ \
110 X(CAN_ERR_FAIL, 49, "Generic failure") \
111 X(CAN_ERR_RESOURCE_BUSY, 50, "Resource busy") \
112 X(CAN_ERR_INVALID_STATE, 51, "Invalid state") \
113 X(CAN_ERR_NOT_SUPPORTED, 52, "Not supported") \
114 X(CAN_ERR_TIMEOUT_ALT, 53, "Operation timeout") \
115 X(CAN_ERR_UNKNOWN, 54, "Unknown error")
116
117enum class hf_can_err_t : hf_u8_t {
118#define X(NAME, VALUE, DESC) NAME = VALUE,
120#undef X
121};
122
128constexpr std::string_view HfCanErrToString(hf_can_err_t err) noexcept {
129 switch (err) {
130#define X(NAME, VALUE, DESC) \
131 case hf_can_err_t::NAME: \
132 return DESC;
134#undef X
135 default:
137 }
138}
139
158
159//--------------------------------------
160// CAN / CAN FD frame model (BaseCan v2)
161//--------------------------------------
162
164inline constexpr hf_u8_t HF_CAN_CLASSIC_MAX_LEN = 8U;
166inline constexpr hf_u8_t HF_CAN_FD_MAX_LEN = 64U;
168inline constexpr hf_u32_t HF_CAN_MAX_STD_ID = 0x7FFU;
170inline constexpr hf_u32_t HF_CAN_MAX_EXT_ID = 0x1FFFFFFFU;
172inline constexpr hf_u8_t HF_CAN_DLC_INVALID = 0xFFU;
173
179namespace hf_can_flag {
180inline constexpr hf_u8_t EXT = 0x01U;
181inline constexpr hf_u8_t RTR = 0x02U;
182inline constexpr hf_u8_t FDF = 0x04U;
183inline constexpr hf_u8_t BRS = 0x08U;
184inline constexpr hf_u8_t ESI = 0x10U;
185inline constexpr hf_u8_t ALL = EXT | RTR | FDF | BRS | ESI;
186} // namespace hf_can_flag
187
194constexpr hf_u8_t HfCanDlcToLen(hf_u8_t dlc, bool fd) noexcept {
195 constexpr hf_u8_t kFdTable[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64};
196 if (dlc > 15U) {
197 return 0U;
198 }
199 if (!fd) {
200 return dlc > 8U ? 8U : dlc;
201 }
202 return kFdTable[dlc];
203}
204
209constexpr hf_u8_t HfCanLenToDlc(hf_u8_t len, bool fd) noexcept {
210 if (len <= 8U) {
211 return len;
212 }
213 if (!fd || len > HF_CAN_FD_MAX_LEN) {
214 return HF_CAN_DLC_INVALID;
215 }
216 for (hf_u8_t dlc = 9U; dlc < 16U; ++dlc) {
217 if (HfCanDlcToLen(dlc, true) >= len) {
218 return dlc;
219 }
220 }
221 return HF_CAN_DLC_INVALID;
222}
223
228constexpr bool HfCanIsValidLength(hf_u8_t len, bool fd) noexcept {
229 if (!fd) {
230 return len <= HF_CAN_CLASSIC_MAX_LEN;
231 }
232 const hf_u8_t dlc = HfCanLenToDlc(len, true);
233 return dlc != HF_CAN_DLC_INVALID && HfCanDlcToLen(dlc, true) == len;
234}
235
251
281 // === Core CAN Message Fields ===
285
286 // === Standard CAN Flags ===
288 bool is_rtr;
289 bool is_ss;
290 bool is_self;
292
293 // === Metadata and Diagnostics ===
299
300 // === CAN FD Fields ===
301 bool is_canfd;
302 bool is_brs;
303 bool is_esi;
304
306 : id(0), dlc(8), data{}, is_extended(false), is_rtr(false), is_ss(false), is_self(false),
308 error_count(0), is_canfd(false), is_brs(false), is_esi(false) {}
309
310 // --- Length -------------------------------------------------------------
311
313 constexpr hf_u8_t GetMaxDataLength() const noexcept {
315 }
316
318 constexpr hf_u8_t GetLength() const noexcept {
319 return dlc;
320 }
321
326 constexpr bool IsValidLength(hf_u8_t len) const noexcept {
327 return HfCanIsValidLength(len, is_canfd);
328 }
329
335 bool SetLength(hf_u8_t len) noexcept {
336 if (!IsValidLength(len)) {
337 return false;
338 }
339 dlc = len;
340 dlc_non_comp = false;
341 return true;
342 }
343
345 constexpr bool IsValidDLC(hf_u8_t len) const noexcept {
346 return IsValidLength(len);
347 }
348
350 constexpr hf_u8_t GetEffectiveDLC() const noexcept {
351 return dlc;
352 }
353
355 bool SetDLC(hf_u8_t len) noexcept {
356 return SetLength(len);
357 }
358
360 constexpr hf_u8_t GetDlcCode() const noexcept {
362 }
363
369 bool SetDlcCode(hf_u8_t code) noexcept {
370 if (code > 15U) {
371 return false;
372 }
373 dlc = HfCanDlcToLen(code, is_canfd);
374 dlc_non_comp = !is_canfd && code > 8U;
375 return true;
376 }
377
383 bool SetData(const hf_u8_t* src, hf_u8_t len) noexcept {
384 if (!IsValidLength(len) || (src == nullptr && len != 0U)) {
385 return false;
386 }
387 for (hf_u8_t i = 0; i < len; ++i) {
388 data[i] = src[i];
389 }
390 dlc = len;
391 dlc_non_comp = false;
392 return true;
393 }
394
395 // --- Frame kind and flags ---------------------------------------------------
396
398 void SetStandardFrame() noexcept {
399 is_extended = false;
400 }
401
403 void SetExtendedFrame() noexcept {
404 is_extended = true;
405 }
406
408 void SetDataFrame() noexcept {
409 is_rtr = false;
410 }
411
413 void SetRemoteFrame() noexcept {
414 is_rtr = true;
415 }
416
418 void SetSingleShot() noexcept {
419 is_ss = true;
420 }
421
423 void SetSelfReception() noexcept {
424 is_self = true;
425 }
426
431 void SetFdFrame(bool brs = false) noexcept {
432 is_canfd = true;
433 is_rtr = false;
434 is_brs = brs;
435 }
436
441 bool SetClassicFrame() noexcept {
443 return false;
444 }
445 is_canfd = false;
446 is_brs = false;
447 is_esi = false;
448 return true;
449 }
450
452 constexpr hf_u8_t GetFlags() const noexcept {
453 return static_cast<hf_u8_t>(
456 (is_esi ? hf_can_flag::ESI : 0U));
457 }
458
463 bool SetFlags(hf_u8_t flags) noexcept {
464 if ((flags & static_cast<hf_u8_t>(~hf_can_flag::ALL)) != 0U) {
465 return false;
466 }
467 is_extended = (flags & hf_can_flag::EXT) != 0U;
468 is_rtr = (flags & hf_can_flag::RTR) != 0U;
469 is_canfd = (flags & hf_can_flag::FDF) != 0U;
470 is_brs = (flags & hf_can_flag::BRS) != 0U;
471 is_esi = (flags & hf_can_flag::ESI) != 0U;
472 return true;
473 }
474
475 // --- Validation -------------------------------------------------------------
476
478 constexpr bool IsValidId() const noexcept {
480 }
481
486 constexpr hf_can_frame_error_t Validate() const noexcept {
487 if (!IsValidId()) {
489 }
490 if (is_canfd) {
491 if (is_rtr) {
493 }
494 if (dlc > HF_CAN_FD_MAX_LEN) {
496 }
497 if (!HfCanIsValidLength(dlc, true)) {
499 }
501 }
502 if (is_brs || is_esi) {
504 }
507 }
509 }
510
512 constexpr bool IsValid() const noexcept {
514 }
515
516 // --- Conversion to / from a transport frame ---------------------------------
517
524 template <typename Frame>
525 void ToFrame(Frame& out) const noexcept {
526 static_assert(sizeof(out.data) == HF_CAN_FD_MAX_LEN, "frame data must be 64 bytes");
527 out.id = id;
528 out.len = dlc;
529 out.flags = GetFlags();
530 for (hf_u8_t i = 0; i < HF_CAN_FD_MAX_LEN; ++i) {
531 out.data[i] = data[i];
532 }
533 out.ts_us = static_cast<decltype(out.ts_us)>(timestamp_us);
534 }
535
541 template <typename Frame>
542 static hf_can_message_t FromFrame(const Frame& in) noexcept {
543 static_assert(sizeof(in.data) == HF_CAN_FD_MAX_LEN, "frame data must be 64 bytes");
545 m.id = in.id;
546 m.dlc = in.len;
547 (void)m.SetFlags(static_cast<hf_u8_t>(in.flags & hf_can_flag::ALL));
548 for (hf_u8_t i = 0; i < HF_CAN_FD_MAX_LEN; ++i) {
549 m.data[i] = in.data[i];
550 }
551 m.timestamp_us = static_cast<hf_u64_t>(in.ts_us);
552 return m;
553 }
554};
555
561 STOPPED = 0,
565 BUS_OFF,
566};
567
571 if (tec > 255U) {
573 }
574 if (tec >= 128U || rec >= 128U) {
576 }
577 if (tec >= 96U || rec >= 96U) {
579 }
581}
582
595
631
636using hf_can_receive_callback_t = void (*)(const hf_can_message_t& message);
637
650using hf_can_fd_receive_callback_t = void (*)(const hf_can_message_t& message,
651 const hf_can_reception_info_t& info);
652
659 // Message counters (atomic for ISR safety)
660 std::atomic<hf_u64_t> messages_sent{0};
661 std::atomic<hf_u64_t> messages_received{0};
662 std::atomic<hf_u64_t> bytes_transmitted{0};
663 std::atomic<hf_u64_t> bytes_received{0};
664
665 // Error counters (atomic for ISR safety)
666 std::atomic<hf_u32_t> send_failures{0};
667 std::atomic<hf_u32_t> receive_failures{0};
668 std::atomic<hf_u32_t> bus_error_count{0};
669 std::atomic<hf_u32_t> arbitration_lost_count{0};
670 std::atomic<hf_u32_t> tx_failed_count{0};
671 std::atomic<hf_u32_t> bus_off_events{0};
672 std::atomic<hf_u32_t> error_warning_events{0};
673
674 // Performance metrics (atomic for ISR safety)
675 std::atomic<hf_u64_t> uptime_seconds{0};
676 std::atomic<hf_u32_t> last_activity_timestamp{0};
677 std::atomic<hf_can_err_t> last_error{hf_can_err_t::CAN_SUCCESS};
678
679 // Queue statistics (atomic for ISR safety)
680 std::atomic<hf_u32_t> tx_queue_peak{0};
681 std::atomic<hf_u32_t> rx_queue_peak{0};
682 std::atomic<hf_u32_t> tx_queue_overflows{0};
683 std::atomic<hf_u32_t> rx_queue_overflows{0};
684
685 // Default constructor - all fields are initialized with in-class initialization
686 hf_can_statistics_t() noexcept = default;
687};
688
703
705 : tx_error_count(0), rx_error_count(0), tx_queue_peak(0), rx_queue_peak(0),
706 last_error_timestamp(0), controller_resets(0), bus_load_percentage(0),
707 bit_error_rate(0.0f) {}
708};
709
731class BaseCan {
732public:
736 virtual ~BaseCan() noexcept = default;
737
738 // Non-copyable, non-movable (can be changed in derived classes if needed)
739 BaseCan(const BaseCan&) = delete;
740 BaseCan& operator=(const BaseCan&) = delete;
741 BaseCan(BaseCan&&) = delete;
742 BaseCan& operator=(BaseCan&&) = delete;
743
748 bool EnsureInitialized() noexcept {
749 if (!initialized_) {
750 initialized_ = (Initialize() == hf_can_err_t::CAN_SUCCESS);
751 }
752 return initialized_;
753 }
754
759 bool EnsureDeinitialized() noexcept {
760 if (initialized_) {
761 initialized_ = !(Deinitialize() == hf_can_err_t::CAN_SUCCESS);
762 }
763 return !initialized_;
764 }
765
770 [[nodiscard]] bool IsInitialized() const noexcept {
771 return initialized_;
772 }
773
774 //==============================================//
775 // PURE VIRTUAL FUNCTIONS [MUST BE OVERRIDDEN] //
776 //==============================================//
777
782 virtual hf_can_err_t Initialize() noexcept = 0;
783
788 virtual hf_can_err_t Deinitialize() noexcept = 0;
789
796 virtual hf_can_err_t SendMessage(const hf_can_message_t& message,
797 hf_u32_t timeout_ms = 1000) noexcept = 0;
798
805 virtual hf_can_err_t ReceiveMessage(hf_can_message_t& message,
806 hf_u32_t timeout_ms = 0) noexcept = 0;
807
813 virtual hf_can_err_t SetReceiveCallback(hf_can_receive_callback_t callback) noexcept = 0;
814
822 virtual hf_can_err_t SetAcceptanceFilter(hf_u32_t id, hf_u32_t mask,
823 bool extended = false) noexcept = 0;
824
830 virtual hf_can_err_t GetStatus(hf_can_status_t& status) noexcept = 0;
831
836 virtual hf_can_err_t Reset() noexcept = 0;
837
838 //==============================================//
839 // (OPTIONAL IMPLEMENTATIONS) //
840 //==============================================//
841
846 virtual void ClearReceiveCallback() noexcept {}
847
854 return SetAcceptanceFilter(0, 0, false);
855 }
856
865 return SendMessage(message, 0);
866 }
867
874 (void)status;
876 }
877
889
897 (void)callback; // Suppress unused parameter warning
899 }
900
906 virtual bool SupportsCanFD() const noexcept {
907 return false;
908 }
909
918 virtual bool SetCanFDMode(bool enable, hf_u32_t data_baudrate = 2000000,
919 hf_u32_t timeout_ms = 1000) noexcept {
920 (void)enable;
921 (void)data_baudrate;
922 (void)timeout_ms;
923 return false;
924 }
925
938 virtual bool ConfigureCanFDTiming(hf_u16_t nominal_prescaler, hf_u8_t nominal_tseg1,
939 hf_u8_t nominal_tseg2, hf_u16_t data_prescaler,
940 hf_u8_t data_tseg1, hf_u8_t data_tseg2,
941 hf_u8_t sjw = 1) noexcept {
942 (void)nominal_prescaler;
943 (void)nominal_tseg1;
944 (void)nominal_tseg2;
945 (void)data_prescaler;
946 (void)data_tseg1;
947 (void)data_tseg2;
948 (void)sjw;
949 return false;
950 }
951
959 virtual bool SetTransmitterDelayCompensation(hf_u8_t tdc_offset, hf_u8_t tdc_filter) noexcept {
960 (void)tdc_offset;
961 (void)tdc_filter;
962 return false;
963 }
964
973 virtual hf_u32_t SendMessageBatch(const hf_can_message_t* messages, hf_u32_t count,
974 hf_u32_t timeout_ms = 1000) noexcept {
975 if (!messages || count == 0) {
976 return 0;
977 }
978
979 hf_u32_t sent_count = 0;
980 for (hf_u32_t i = 0; i < count; ++i) {
981 if (SendMessage(messages[i], timeout_ms) == hf_can_err_t::CAN_SUCCESS) {
982 sent_count++;
983 }
984 }
985 return sent_count;
986 }
987
997 hf_u32_t timeout_ms = 100) noexcept {
998 if (!messages || max_count == 0) {
999 return 0;
1000 }
1001
1002 hf_u32_t received_count = 0;
1003 for (hf_u32_t i = 0; i < max_count; ++i) {
1004 if (ReceiveMessage(messages[i], timeout_ms) == hf_can_err_t::CAN_SUCCESS) {
1005 received_count++;
1006 } else {
1007 break; // No more messages available
1008 }
1009 }
1010 return received_count;
1011 }
1012
1013 //==============================================//
1014 // STATISTICS AND DIAGNOSTICS STRUCTURES //
1015 //==============================================//
1016
1022 virtual hf_can_err_t ResetStatistics() noexcept {
1023 // Reset all atomic counters to zero (atomic operations are thread-safe)
1024 statistics_.messages_sent.store(0);
1025 statistics_.messages_received.store(0);
1026 statistics_.bytes_transmitted.store(0);
1027 statistics_.bytes_received.store(0);
1028 statistics_.send_failures.store(0);
1029 statistics_.receive_failures.store(0);
1030 statistics_.bus_error_count.store(0);
1031 statistics_.arbitration_lost_count.store(0);
1032 statistics_.tx_failed_count.store(0);
1033 statistics_.bus_off_events.store(0);
1034 statistics_.error_warning_events.store(0);
1035 statistics_.uptime_seconds.store(0);
1036 statistics_.last_activity_timestamp.store(0);
1037 statistics_.last_error.store(hf_can_err_t::CAN_SUCCESS);
1038 statistics_.tx_queue_peak.store(0);
1039 statistics_.rx_queue_peak.store(0);
1040 statistics_.tx_queue_overflows.store(0);
1041 statistics_.rx_queue_overflows.store(0);
1043 }
1044
1050 virtual hf_can_err_t ResetDiagnostics() noexcept {
1051 diagnostics_ = hf_can_diagnostics_t{}; // Reset diagnostics to default values
1053 }
1054
1061 virtual hf_can_err_t GetStatistics(hf_can_statistics_t& statistics) noexcept {
1062 // Copy atomic values to non-atomic structure for return (atomic operations are thread-safe)
1063 statistics.messages_sent = statistics_.messages_sent.load();
1064 statistics.messages_received = statistics_.messages_received.load();
1065 statistics.bytes_transmitted = statistics_.bytes_transmitted.load();
1066 statistics.bytes_received = statistics_.bytes_received.load();
1067 statistics.send_failures = statistics_.send_failures.load();
1068 statistics.receive_failures = statistics_.receive_failures.load();
1069 statistics.bus_error_count = statistics_.bus_error_count.load();
1070 statistics.arbitration_lost_count = statistics_.arbitration_lost_count.load();
1071 statistics.tx_failed_count = statistics_.tx_failed_count.load();
1072 statistics.bus_off_events = statistics_.bus_off_events.load();
1073 statistics.error_warning_events = statistics_.error_warning_events.load();
1074 statistics.uptime_seconds = statistics_.uptime_seconds.load();
1075 statistics.last_activity_timestamp = statistics_.last_activity_timestamp.load();
1076 statistics.last_error = statistics_.last_error.load();
1077 statistics.tx_queue_peak = statistics_.tx_queue_peak.load();
1078 statistics.rx_queue_peak = statistics_.rx_queue_peak.load();
1079 statistics.tx_queue_overflows = statistics_.tx_queue_overflows.load();
1080 statistics.rx_queue_overflows = statistics_.rx_queue_overflows.load();
1082 }
1083
1090 virtual hf_can_err_t GetDiagnostics(hf_can_diagnostics_t& diagnostics) noexcept {
1091 diagnostics = diagnostics_; // Return diagnostics by default
1093 }
1094
1095protected:
1099 BaseCan() noexcept : initialized_(false), statistics_{}, diagnostics_{} {}
1100
1101 //==============================================//
1102 // VARIABLES //
1103 //==============================================//
1104
1108};
1109
1110//==============================================//
1111// END OF BASECAN - CLEAN AND MODERN API //
1112//==============================================//
constexpr hf_u32_t HF_CAN_MAX_EXT_ID
Largest 29-bit (extended format) identifier.
Definition BaseCan.h:170
constexpr hf_can_bus_state_t HfCanStateFromCounters(hf_u16_t tec, hf_u16_t rec) noexcept
Error state implied by the counters (warning at 96, passive at 128, bus-off above 255).
Definition BaseCan.h:570
constexpr hf_u8_t HF_CAN_FD_MAX_LEN
Largest CAN FD payload in bytes.
Definition BaseCan.h:166
constexpr std::string_view HfCanErrToString(hf_can_err_t err) noexcept
Convert hf_can_err_t to human-readable string.
Definition BaseCan.h:128
void(*)(const hf_can_message_t &message) hf_can_receive_callback_t
CAN message receive callback function type.
Definition BaseCan.h:636
constexpr hf_u8_t HfCanDlcToLen(hf_u8_t dlc, bool fd) noexcept
DLC code to payload length in bytes (ISO 11898-1).
Definition BaseCan.h:194
void(*)(const hf_can_message_t &message, const hf_can_reception_info_t &info) hf_can_fd_receive_callback_t
Definition BaseCan.h:651
constexpr hf_u8_t HF_CAN_DLC_INVALID
Returned by HfCanLenToDlc() when a length cannot be carried.
Definition BaseCan.h:172
hf_can_bus_state_t
Controller error state (ISO 11898-1 fault confinement).
Definition BaseCan.h:560
@ STOPPED
not started / in reset
@ ERROR_ACTIVE
TEC and REC < 96.
@ ERROR_PASSIVE
TEC or REC >= 128.
@ BUS_OFF
TEC > 255.
@ ERROR_WARNING
TEC or REC >= 96.
constexpr hf_u32_t HF_CAN_MAX_STD_ID
Largest 11-bit (base format) identifier.
Definition BaseCan.h:168
hf_can_frame_error_t
Why a frame is not well formed.
Definition BaseCan.h:241
@ ID_RANGE
identifier does not fit 11 / 29 bits
@ CLASSIC_TOO_LONG
classic frame with length > 8
@ FD_TOO_LONG
FD frame with length > 64.
@ FD_LENGTH_NOT_EXACT
FD length that has no DLC code (for example 9)
@ RTR_ON_FD
FD frames have no remote form.
@ RTR_WITH_DATA
remote frame with a requested length above 8
@ FD_BITS_ON_CLASSIC
BRS / ESI without FD format.
#define X(NAME, VALUE, DESC)
Definition BaseCan.h:118
constexpr hf_u8_t HfCanLenToDlc(hf_u8_t len, bool fd) noexcept
Payload length in bytes to the smallest DLC code that carries it.
Definition BaseCan.h:209
hf_can_err_t
Definition BaseCan.h:117
@ CAN_ERR_UNSUPPORTED_OPERATION
constexpr hf_u8_t HF_CAN_CLASSIC_MAX_LEN
Largest classic CAN payload in bytes.
Definition BaseCan.h:164
constexpr bool HfCanIsValidLength(hf_u8_t len, bool fd) noexcept
Is len a payload length a frame of this kind can have exactly?
Definition BaseCan.h:228
Platform-agnostic hardware type definitions for the HardFOC system.
uint32_t hf_u32_t
Platform-agnostic 32-bit unsigned integer type.
Definition HardwareTypes.h:52
uint8_t hf_u8_t
Platform-agnostic 8-bit unsigned integer type.
Definition HardwareTypes.h:40
constexpr hf_pin_num_t HF_INVALID_PIN
Invalid pin constant for unassigned or invalid pins.
Definition HardwareTypes.h:104
hf_i32_t hf_pin_num_t
Platform-agnostic GPIO pin number type.
Definition HardwareTypes.h:99
uint64_t hf_u64_t
Platform-agnostic 64-bit unsigned integer type.
Definition HardwareTypes.h:58
uint16_t hf_u16_t
Platform-agnostic 16-bit unsigned integer type.
Definition HardwareTypes.h:46
hf_u32_t hf_baud_rate_t
Platform-agnostic baud rate type.
Definition HardwareTypes.h:153
Abstract base class defining the unified CAN bus API.
Definition BaseCan.h:731
bool EnsureDeinitialized() noexcept
Ensures that the CAN bus is deinitialized.
Definition BaseCan.h:759
virtual hf_u32_t ReceiveMessageBatch(hf_can_message_t *messages, hf_u32_t max_count, hf_u32_t timeout_ms=100) noexcept
Receive multiple messages in a batch.
Definition BaseCan.h:996
virtual hf_can_err_t GetDiagnostics(hf_can_diagnostics_t &diagnostics) noexcept
Get CAN diagnostic information.
Definition BaseCan.h:1090
BaseCan() noexcept
Protected constructor.
Definition BaseCan.h:1099
bool IsInitialized() const noexcept
Checks if the class is initialized.
Definition BaseCan.h:770
hf_can_statistics_t statistics_
CAN operation statistics.
Definition BaseCan.h:1106
virtual bool SetCanFDMode(bool enable, hf_u32_t data_baudrate=2000000, hf_u32_t timeout_ms=1000) noexcept
Enable or disable CAN-FD mode.
Definition BaseCan.h:918
hf_can_err_t TrySendMessage(const hf_can_message_t &message) noexcept
Queue a message for transmission without blocking.
Definition BaseCan.h:864
virtual hf_can_err_t SetReceiveCallbackFD(hf_can_fd_receive_callback_t callback) noexcept
Set CAN-FD receive callback with enhanced information.
Definition BaseCan.h:896
virtual hf_can_err_t ClearAcceptanceFilter() noexcept
Clear all acceptance filters (accept all messages).
Definition BaseCan.h:853
virtual bool SupportsCanFD() const noexcept
Check if CAN-FD is supported by this controller.
Definition BaseCan.h:906
bool initialized_
Initialization status.
Definition BaseCan.h:1105
virtual bool ConfigureCanFDTiming(hf_u16_t nominal_prescaler, hf_u8_t nominal_tseg1, hf_u8_t nominal_tseg2, hf_u16_t data_prescaler, hf_u8_t data_tseg1, hf_u8_t data_tseg2, hf_u8_t sjw=1) noexcept
Configure CAN-FD timing parameters.
Definition BaseCan.h:938
virtual hf_u32_t SendMessageBatch(const hf_can_message_t *messages, hf_u32_t count, hf_u32_t timeout_ms=1000) noexcept
Send multiple messages in a batch.
Definition BaseCan.h:973
hf_can_diagnostics_t diagnostics_
CAN diagnostic information.
Definition BaseCan.h:1107
virtual hf_can_err_t ResetDiagnostics() noexcept
Reset CAN diagnostic information.
Definition BaseCan.h:1050
virtual hf_can_err_t Initialize() noexcept=0
Initialize the CAN controller (must be implemented by derived classes).
virtual hf_can_err_t GetStatistics(hf_can_statistics_t &statistics) noexcept
Get CAN operation statistics.
Definition BaseCan.h:1061
virtual ~BaseCan() noexcept=default
Virtual destructor ensures proper cleanup in derived classes.
virtual hf_can_err_t ResetStatistics() noexcept
Reset CAN operation statistics.
Definition BaseCan.h:1022
virtual hf_can_err_t RequestBusRecovery() noexcept
Request recovery from bus-off.
Definition BaseCan.h:886
virtual bool SetTransmitterDelayCompensation(hf_u8_t tdc_offset, hf_u8_t tdc_filter) noexcept
Set transmitter delay compensation (CAN-FD feature).
Definition BaseCan.h:959
virtual hf_can_err_t GetBusStatus(hf_can_bus_status_t &status) noexcept
Read the controller error state, TEC/REC and queue counters.
Definition BaseCan.h:873
#define HF_CAN_ERR_LIST(X)
HardFOC CAN error codes.
Definition BaseCan.h:48
Packed frame flags (see hf_can_message_t::GetFlags()).
Definition BaseCan.h:179
constexpr hf_u8_t BRS
bit-rate switch (FD only)
Definition BaseCan.h:183
constexpr hf_u8_t ESI
error state indicator (FD only)
Definition BaseCan.h:184
constexpr hf_u8_t ALL
Definition BaseCan.h:185
constexpr hf_u8_t EXT
29-bit identifier
Definition BaseCan.h:180
constexpr hf_u8_t FDF
FD frame format.
Definition BaseCan.h:182
constexpr hf_u8_t RTR
remote request (classic only)
Definition BaseCan.h:181
Error counters and queue statistics of one controller (BaseCan::GetBusStatus()).
Definition BaseCan.h:587
hf_u16_t tec
transmit error counter
Definition BaseCan.h:589
hf_u32_t rx_overruns
frames lost because the RX queue was full
Definition BaseCan.h:591
hf_u16_t rec
receive error counter
Definition BaseCan.h:590
hf_u32_t bus_off_count
bus-off events since Initialize()
Definition BaseCan.h:593
hf_can_bus_state_t state
controller error state
Definition BaseCan.h:588
hf_u32_t tx_queue_full
sends refused because the TX queue was full
Definition BaseCan.h:592
Platform-agnostic CAN bus configuration.
Definition BaseCan.h:145
hf_u16_t tx_queue_size
TX queue size (implementation-dependent)
Definition BaseCan.h:151
hf_u16_t rx_queue_size
RX queue size (implementation-dependent)
Definition BaseCan.h:152
hf_pin_num_t rx_pin
CAN RX pin.
Definition BaseCan.h:147
bool silent_mode
Enable silent mode (listen-only)
Definition BaseCan.h:150
hf_can_config_t() noexcept
Definition BaseCan.h:154
bool loopback_mode
Enable loopback mode for testing.
Definition BaseCan.h:149
hf_baud_rate_t baudrate
CAN baudrate (bps)
Definition BaseCan.h:148
hf_pin_num_t tx_pin
CAN TX pin.
Definition BaseCan.h:146
CAN diagnostics structure for detailed error analysis.
Definition BaseCan.h:694
hf_u32_t tx_error_count
Transmit error counter.
Definition BaseCan.h:695
hf_u32_t rx_queue_peak
Peak RX queue usage.
Definition BaseCan.h:698
float bit_error_rate
Bit error rate (errors/bits)
Definition BaseCan.h:702
hf_u32_t rx_error_count
Receive error counter.
Definition BaseCan.h:696
hf_u32_t last_error_timestamp
Timestamp of last error.
Definition BaseCan.h:699
hf_u32_t tx_queue_peak
Peak TX queue usage.
Definition BaseCan.h:697
hf_u32_t controller_resets
Number of controller resets.
Definition BaseCan.h:700
hf_u32_t bus_load_percentage
Current bus load percentage.
Definition BaseCan.h:701
hf_can_diagnostics_t() noexcept
Definition BaseCan.h:704
Platform-agnostic CAN / CAN FD message (BaseCan v2).
Definition BaseCan.h:280
static hf_can_message_t FromFrame(const Frame &in) noexcept
Build a message from a frame with members id, len, flags, data[64], ts_us.
Definition BaseCan.h:542
void ToFrame(Frame &out) const noexcept
Copy into a frame with members id, len, flags, data[64], ts_us.
Definition BaseCan.h:525
hf_u32_t id
Message ID (11 or 29-bit)
Definition BaseCan.h:282
constexpr bool IsValidId() const noexcept
Validate message ID for current frame format.
Definition BaseCan.h:478
hf_u64_t timestamp_us
RX timestamp in microseconds (driver clock)
Definition BaseCan.h:294
hf_u8_t error_count
Associated error count.
Definition BaseCan.h:298
bool SetData(const hf_u8_t *src, hf_u8_t len) noexcept
Copy len bytes into the payload and set the length.
Definition BaseCan.h:383
hf_u8_t controller_id
Originating controller ID.
Definition BaseCan.h:296
void SetSingleShot() noexcept
Set single shot transmission.
Definition BaseCan.h:418
constexpr hf_u8_t GetFlags() const noexcept
Flags packed as hf_can_flag bits.
Definition BaseCan.h:452
constexpr hf_u8_t GetEffectiveDLC() const noexcept
Same as GetLength(); kept for source compatibility.
Definition BaseCan.h:350
bool is_self
Self reception request flag.
Definition BaseCan.h:290
void SetFdFrame(bool brs=false) noexcept
Make this an FD frame.
Definition BaseCan.h:431
hf_u8_t data[HF_CAN_FD_MAX_LEN]
Payload (64 bytes, FD-sized)
Definition BaseCan.h:284
bool is_rtr
Remote transmission request flag.
Definition BaseCan.h:288
hf_u8_t retry_count
Number of transmission retries.
Definition BaseCan.h:297
constexpr hf_can_frame_error_t Validate() const noexcept
Structural check drivers apply before transmit and after receive.
Definition BaseCan.h:486
bool SetDLC(hf_u8_t len) noexcept
Same as SetLength(); kept for source compatibility.
Definition BaseCan.h:355
hf_can_message_t() noexcept
Definition BaseCan.h:305
bool SetClassicFrame() noexcept
Make this a classic frame (clears BRS / ESI).
Definition BaseCan.h:441
constexpr hf_u8_t GetDlcCode() const noexcept
4-bit DLC code for the current length (HF_CAN_DLC_INVALID if invalid).
Definition BaseCan.h:360
constexpr hf_u8_t GetMaxDataLength() const noexcept
Largest payload for the current frame kind (8 classic, 64 FD).
Definition BaseCan.h:313
constexpr bool IsValidLength(hf_u8_t len) const noexcept
Is len a valid payload length for the current frame kind?
Definition BaseCan.h:326
hf_u8_t dlc
Payload length in BYTES (0..8 classic, 0..64 FD)
Definition BaseCan.h:283
constexpr bool IsValidDLC(hf_u8_t len) const noexcept
Same as IsValidLength(); kept for source compatibility.
Definition BaseCan.h:345
void SetStandardFrame() noexcept
Set standard frame format (11-bit ID).
Definition BaseCan.h:398
bool is_canfd
FD frame format (FDF)
Definition BaseCan.h:301
void SetDataFrame() noexcept
Set data frame (not remote).
Definition BaseCan.h:408
bool is_ss
Single shot flag (no retransmission)
Definition BaseCan.h:289
constexpr bool IsValid() const noexcept
Validate() == NONE.
Definition BaseCan.h:512
bool SetDlcCode(hf_u8_t code) noexcept
Set the length from a 4-bit DLC code (as read from a controller).
Definition BaseCan.h:369
bool dlc_non_comp
Received classic DLC code was 9..15 (length is 8)
Definition BaseCan.h:291
bool is_extended
Extended ID flag (29-bit vs 11-bit)
Definition BaseCan.h:287
void SetExtendedFrame() noexcept
Set extended frame format (29-bit ID).
Definition BaseCan.h:403
constexpr hf_u8_t GetLength() const noexcept
Payload length in bytes.
Definition BaseCan.h:318
bool SetLength(hf_u8_t len) noexcept
Set the payload length in bytes.
Definition BaseCan.h:335
bool is_brs
Bit Rate Switching (FD only)
Definition BaseCan.h:302
bool is_esi
Error State Indicator (FD only)
Definition BaseCan.h:303
void SetSelfReception() noexcept
Set self reception request.
Definition BaseCan.h:423
hf_u32_t sequence_number
Message sequence number.
Definition BaseCan.h:295
void SetRemoteFrame() noexcept
Set remote frame.
Definition BaseCan.h:413
bool SetFlags(hf_u8_t flags) noexcept
Set the flags from hf_can_flag bits.
Definition BaseCan.h:463
CAN-FD specific receive callback with enhanced information.
Definition BaseCan.h:643
bool data_phase_error
Error occurred in data phase.
Definition BaseCan.h:646
float bit_timing_tolerance
Measured bit timing tolerance.
Definition BaseCan.h:648
bool arbitration_lost
Arbitration was lost during transmission.
Definition BaseCan.h:647
hf_u32_t timestamp_us
Reception timestamp in microseconds.
Definition BaseCan.h:644
hf_u8_t rx_fifo_level
RX FIFO level when received.
Definition BaseCan.h:645
CAN bus statistics structure for performance monitoring.
Definition BaseCan.h:658
std::atomic< hf_u32_t > tx_queue_overflows
TX queue overflow count.
Definition BaseCan.h:682
std::atomic< hf_u64_t > bytes_received
Total bytes received.
Definition BaseCan.h:663
std::atomic< hf_u64_t > messages_sent
Total messages successfully sent.
Definition BaseCan.h:660
std::atomic< hf_u32_t > bus_error_count
Total bus errors.
Definition BaseCan.h:668
std::atomic< hf_u32_t > error_warning_events
Error warning events.
Definition BaseCan.h:672
std::atomic< hf_u32_t > arbitration_lost_count
Arbitration lost events.
Definition BaseCan.h:669
std::atomic< hf_u32_t > rx_queue_overflows
RX queue overflow count.
Definition BaseCan.h:683
std::atomic< hf_u32_t > send_failures
Failed send operations.
Definition BaseCan.h:666
std::atomic< hf_u64_t > bytes_transmitted
Total bytes transmitted.
Definition BaseCan.h:662
std::atomic< hf_u32_t > rx_queue_peak
Peak RX queue usage.
Definition BaseCan.h:681
std::atomic< hf_u32_t > last_activity_timestamp
Last activity timestamp.
Definition BaseCan.h:676
std::atomic< hf_u32_t > tx_failed_count
Transmission failures.
Definition BaseCan.h:670
std::atomic< hf_u64_t > uptime_seconds
Total uptime in seconds.
Definition BaseCan.h:675
std::atomic< hf_can_err_t > last_error
Last error encountered.
Definition BaseCan.h:677
hf_can_statistics_t() noexcept=default
std::atomic< hf_u32_t > tx_queue_peak
Peak TX queue usage.
Definition BaseCan.h:680
std::atomic< hf_u32_t > receive_failures
Failed receive operations.
Definition BaseCan.h:667
std::atomic< hf_u64_t > messages_received
Total messages successfully received.
Definition BaseCan.h:661
std::atomic< hf_u32_t > bus_off_events
Bus-off occurrences.
Definition BaseCan.h:671
CAN bus status information structure.
Definition BaseCan.h:600
hf_u32_t crc_errors
CRC errors.
Definition BaseCan.h:620
bool error_warning
Error warning state.
Definition BaseCan.h:606
hf_u32_t rx_missed_count
Missed reception count.
Definition BaseCan.h:604
hf_u32_t ack_errors
Acknowledgment errors.
Definition BaseCan.h:622
hf_u32_t data_baudrate
Data bit rate (data phase for CAN-FD)
Definition BaseCan.h:613
hf_u32_t tx_error_count
Transmit error counter.
Definition BaseCan.h:601
bool error_passive
Error passive state.
Definition BaseCan.h:607
hf_u32_t canfd_tx_count
Number of CAN-FD frames transmitted.
Definition BaseCan.h:614
hf_u32_t form_errors
CAN-FD form errors.
Definition BaseCan.h:618
hf_u32_t nominal_baudrate
Nominal bit rate (arbitration phase)
Definition BaseCan.h:612
hf_u32_t brs_rx_count
Number of BRS frames received.
Definition BaseCan.h:617
bool bus_off
Bus-off state.
Definition BaseCan.h:605
hf_u32_t canfd_rx_count
Number of CAN-FD frames received.
Definition BaseCan.h:615
hf_u32_t brs_tx_count
Number of BRS frames transmitted.
Definition BaseCan.h:616
hf_u32_t bit_errors
Bit errors.
Definition BaseCan.h:621
hf_u32_t tx_failed_count
Failed transmission count.
Definition BaseCan.h:603
bool canfd_brs_enabled
Bit Rate Switching is enabled.
Definition BaseCan.h:611
hf_u32_t stuff_errors
Stuff errors.
Definition BaseCan.h:619
bool canfd_enabled
CAN-FD mode is active.
Definition BaseCan.h:610
hf_u32_t rx_error_count
Receive error counter.
Definition BaseCan.h:602
hf_can_status_t() noexcept
Definition BaseCan.h:624