ESPHome 2026.1.4
Loading...
Searching...
No Matches
esp32_can.cpp
Go to the documentation of this file.
1#ifdef USE_ESP32
2#include "esp32_can.h"
3#include "esphome/core/log.h"
4
5#include <driver/twai.h>
6
7// WORKAROUND, because CAN_IO_UNUSED is just defined as (-1) in this version
8// of the framework which does not work with -fpermissive
9#undef CAN_IO_UNUSED
10#define CAN_IO_UNUSED ((gpio_num_t) -1)
11
12namespace esphome {
13namespace esp32_can {
14
15static const char *const TAG = "esp32_can";
16
17static bool get_bitrate(canbus::CanSpeed bitrate, twai_timing_config_t *t_config) {
18 switch (bitrate) {
19#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32C61) || \
20 defined(USE_ESP32_VARIANT_ESP32H2) || defined(USE_ESP32_VARIANT_ESP32P4) || defined(USE_ESP32_VARIANT_ESP32S2) || \
21 defined(USE_ESP32_VARIANT_ESP32S3)
23 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_1KBITS();
24 return true;
26 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_5KBITS();
27 return true;
29 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_10KBITS();
30 return true;
32 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_12_5KBITS();
33 return true;
35 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_16KBITS();
36 return true;
38 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_20KBITS();
39 return true;
40#endif
42 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_25KBITS();
43 return true;
45 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_50KBITS();
46 return true;
48 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_100KBITS();
49 return true;
51 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_125KBITS();
52 return true;
54 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_250KBITS();
55 return true;
57 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_500KBITS();
58 return true;
60 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_800KBITS();
61 return true;
63 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_1MBITS();
64 return true;
65 default:
66 return false;
67 }
68}
69
71 static int next_twai_ctrl_num = 0;
72 if (static_cast<unsigned>(next_twai_ctrl_num) >= SOC_TWAI_CONTROLLER_NUM) {
73 ESP_LOGW(TAG, "Maximum number of esp32_can components created already");
74 this->mark_failed();
75 return false;
76 }
77
78 // Select TWAI mode based on configuration
79 twai_mode_t twai_mode = (this->mode_ == CAN_MODE_LISTEN_ONLY) ? TWAI_MODE_LISTEN_ONLY : TWAI_MODE_NORMAL;
80
81 if (this->mode_ == CAN_MODE_LISTEN_ONLY) {
82 ESP_LOGI(TAG, "CAN bus configured in LISTEN_ONLY mode (passive, no ACKs)");
83 }
84
85 twai_general_config_t g_config =
86 TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t) this->tx_, (gpio_num_t) this->rx_, twai_mode);
87 g_config.controller_id = next_twai_ctrl_num++;
88 if (this->tx_queue_len_.has_value()) {
89 g_config.tx_queue_len = this->tx_queue_len_.value();
90 }
91 if (this->rx_queue_len_.has_value()) {
92 g_config.rx_queue_len = this->rx_queue_len_.value();
93 }
94
95 twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
96 twai_timing_config_t t_config;
97
98 if (!get_bitrate(this->bit_rate_, &t_config)) {
99 // invalid bit rate
100 this->mark_failed();
101 return false;
102 }
103
104 // Install TWAI driver
105 if (twai_driver_install_v2(&g_config, &t_config, &f_config, &(this->twai_handle_)) != ESP_OK) {
106 // Failed to install driver
107 this->mark_failed();
108 return false;
109 }
110
111 // Start TWAI driver
112 if (twai_start_v2(this->twai_handle_) != ESP_OK) {
113 // Failed to start driver
114 this->mark_failed();
115 return false;
116 }
117 return true;
118}
119
121 // In listen-only mode, we cannot transmit
122 if (this->mode_ == CAN_MODE_LISTEN_ONLY) {
123 ESP_LOGW(TAG, "Cannot send messages in LISTEN_ONLY mode");
124 return canbus::ERROR_FAIL;
125 }
126
127 if (this->twai_handle_ == nullptr) {
128 // not setup yet or setup failed
129 return canbus::ERROR_FAIL;
130 }
131
132 if (frame->can_data_length_code > canbus::CAN_MAX_DATA_LENGTH) {
134 }
135
136 uint32_t flags = TWAI_MSG_FLAG_NONE;
137 if (frame->use_extended_id) {
138 flags |= TWAI_MSG_FLAG_EXTD;
139 }
140 if (frame->remote_transmission_request) {
141 flags |= TWAI_MSG_FLAG_RTR;
142 }
143
144 twai_message_t message = {
145 .flags = flags,
146 .identifier = frame->can_id,
147 .data_length_code = frame->can_data_length_code,
148 .data = {}, // to suppress warning, data is initialized properly below
149 };
150 if (!frame->remote_transmission_request) {
151 memcpy(message.data, frame->data, frame->can_data_length_code);
152 }
153
154 if (twai_transmit_v2(this->twai_handle_, &message, this->tx_enqueue_timeout_ticks_) == ESP_OK) {
155 return canbus::ERROR_OK;
156 } else {
158 }
159}
160
162 if (this->twai_handle_ == nullptr) {
163 // not setup yet or setup failed
164 return canbus::ERROR_FAIL;
165 }
166
167 twai_message_t message;
168
169 if (twai_receive_v2(this->twai_handle_, &message, 0) != ESP_OK) {
170 return canbus::ERROR_NOMSG;
171 }
172
173 frame->can_id = message.identifier;
174 frame->use_extended_id = message.flags & TWAI_MSG_FLAG_EXTD;
175 frame->remote_transmission_request = message.flags & TWAI_MSG_FLAG_RTR;
176 frame->can_data_length_code = message.data_length_code;
177
178 if (!frame->remote_transmission_request) {
179 size_t dlc =
180 message.data_length_code < canbus::CAN_MAX_DATA_LENGTH ? message.data_length_code : canbus::CAN_MAX_DATA_LENGTH;
181 memcpy(frame->data, message.data, dlc);
182 }
183
184 return canbus::ERROR_OK;
185}
186
187} // namespace esp32_can
188} // namespace esphome
189
190#endif
virtual void mark_failed()
Mark this component as failed.
canbus::Error read_message(struct canbus::CanFrame *frame) override
optional< uint32_t > rx_queue_len_
Definition esp32_can.h:40
TickType_t tx_enqueue_timeout_ticks_
Definition esp32_can.h:38
optional< uint32_t > tx_queue_len_
Definition esp32_can.h:39
canbus::Error send_message(struct canbus::CanFrame *frame) override
bool setup_internal() override
Definition esp32_can.cpp:70
bool has_value() const
Definition optional.h:92
value_type const & value() const
Definition optional.h:94
const char * message
Definition component.cpp:38
uint16_t flags
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
uint8_t can_data_length_code
Definition canbus.h:61