Skip to content

Commit 0afdf9c

Browse files
authored
Refactor CAN driver to support multiple instances
1 parent 1c1bb91 commit 0afdf9c

1 file changed

Lines changed: 69 additions & 24 deletions

File tree

  • ports/espressif/common-hal/canio

ports/espressif/common-hal/canio/CAN.c

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@
1616

1717
#include "hal/twai_types.h"
1818

19-
static bool reserved_can;
19+
static byte reserved_can_instance; /* Bit assigned instances 0x01 (CAN0) or 0x02 (CAN1) 0x00-NoneAssigned 0x03-Both Assigned*/
20+
21+
#define TWAI0 REG_TWAI_BASE(0) /**< \brief (CAN0) APB Base Address */
22+
#define TWAI1 REG_TWAI_BASE(1) /**< \brief (CAN1) APB Base Address */
23+
#define TWAI_INST_NUM 2 /**< \brief (CAN) Number of instances */
24+
25+
static twai_handle_t twai_bus_0;
26+
static twai_handle_t twai_bus_1;
27+
static twai_handle_t *const twai_insts[TWAI_INST_NUM] = { &twai_bus_0, &twai_bus_1 };
2028

2129
static twai_timing_config_t get_t_config(int baudrate) {
2230
switch (baudrate) {
@@ -100,18 +108,36 @@ static twai_timing_config_t get_t_config(int baudrate) {
100108
void common_hal_canio_can_construct(canio_can_obj_t *self, const mcu_pin_obj_t *tx, const mcu_pin_obj_t *rx, int baudrate, bool loopback, bool silent) {
101109
#define DIV_ROUND(a, b) (((a) + (b) / 2) / (b))
102110
#define DIV_ROUND_UP(a, b) (((a) + (b) - 1) / (b))
103-
if (reserved_can) {
111+
if (reserved_can_instance==3) {
104112
mp_raise_ValueError(MP_ERROR_TEXT("All CAN peripherals are in use"));
105113
}
106114

107115
if (loopback && silent) {
108116
mp_raise_ValueError(MP_ERROR_TEXT("loopback + silent mode not supported by peripheral"));
109117
}
110118

119+
byte this_can_instance=0;
120+
if (reserved_can_instance==0x00){ /* None assigned */
121+
reserved_can_instance=0x01; /* First instance is assigned*/
122+
this_can_instance=0; /* Idx of selected instance */
123+
}
124+
else if (reserved_can_instance==0x01) /* First instance allready assigned */
125+
{
126+
reserved_can_instance=0x03; /* Second instance also assigned */
127+
this_can_instance=1; /* Idx of selected instance */
128+
129+
}else if (reserved_can_instance==0x02) /* Second instance is assigned */
130+
{
131+
reserved_can_instance=0x03; /* first instance also assigned*/
132+
this_can_instance=0; /* Idx of selected instance */
133+
}
134+
111135
twai_timing_config_t t_config = get_t_config(baudrate);
112-
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(-1, -1, TWAI_MODE_NORMAL);
136+
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT_V2(this_can_instance,-1, -1, TWAI_MODE_NORMAL);
113137
g_config.tx_io = tx->number;
114138
g_config.rx_io = rx->number;
139+
g_config.controller_id = this_can_instance; /* To ease later de-initing of proper instance */
140+
115141
if (loopback) {
116142
g_config.mode = TWAI_MODE_NO_ACK;
117143
}
@@ -120,17 +146,16 @@ void common_hal_canio_can_construct(canio_can_obj_t *self, const mcu_pin_obj_t *
120146
}
121147

122148
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
123-
124-
esp_err_t result = twai_driver_install(&g_config, &t_config, &f_config);
149+
esp_err_t result = twai_driver_install_v2(&g_config, &t_config, &f_config , twai_insts[this_can_instance]);
125150
if (result == ESP_ERR_NO_MEM) {
126151
mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("ESP-IDF memory allocation failed"));
127152
} else if (result == ESP_ERR_INVALID_ARG) {
128153
raise_ValueError_invalid_pins();
129154
} else if (result != ESP_OK) {
130155
mp_raise_OSError_msg_varg(MP_ERROR_TEXT("twai_driver_install returned esp-idf error #%d"), (int)result);
131156
}
132-
133-
result = twai_start();
157+
158+
result = twai_start_v2(*twai_insts[this_can_instance]);
134159
if (result != ESP_OK) {
135160
mp_raise_OSError_msg_varg(MP_ERROR_TEXT("twai_start returned esp-idf error #%d"), (int)result);
136161
}
@@ -144,9 +169,15 @@ void common_hal_canio_can_construct(canio_can_obj_t *self, const mcu_pin_obj_t *
144169
claim_pin(tx);
145170
claim_pin(rx);
146171

147-
reserved_can = true;
172+
self->twai_driver_handle = twai_insts[this_can_instance];
173+
self->instance = this_can_instance;
174+
175+
148176
}
149177

178+
179+
180+
150181
bool common_hal_canio_can_loopback_get(canio_can_obj_t *self) {
151182
return self->loopback;
152183
}
@@ -157,19 +188,21 @@ int common_hal_canio_can_baudrate_get(canio_can_obj_t *self) {
157188

158189
int common_hal_canio_can_transmit_error_count_get(canio_can_obj_t *self) {
159190
twai_status_info_t info;
160-
twai_get_status_info(&info);
191+
twai_get_status_info_v2( *self->twai_driver_handle,&info);
161192
return info.tx_error_counter;
162193
}
163194

164195
int common_hal_canio_can_receive_error_count_get(canio_can_obj_t *self) {
165196
twai_status_info_t info;
166-
twai_get_status_info(&info);
197+
twai_get_status_info_v2( *self->twai_driver_handle,&info);
167198
return info.rx_error_counter;
168199
}
169200

201+
170202
canio_bus_state_t common_hal_canio_can_state_get(canio_can_obj_t *self) {
171203
twai_status_info_t info;
172-
twai_get_status_info(&info);
204+
205+
twai_get_status_info_v2( *self->twai_driver_handle,&info);
173206
if (info.state == TWAI_STATE_BUS_OFF || info.state == TWAI_STATE_RECOVERING) {
174207
return BUS_STATE_OFF;
175208
}
@@ -182,29 +215,30 @@ canio_bus_state_t common_hal_canio_can_state_get(canio_can_obj_t *self) {
182215
return BUS_STATE_ERROR_ACTIVE;
183216
}
184217

185-
static void can_restart(void) {
218+
219+
static void can_restart(canio_can_obj_t *self) {
186220
twai_status_info_t info;
187-
twai_get_status_info(&info);
221+
twai_get_status_info_v2(*self->twai_driver_handle, &info);
188222
if (info.state != TWAI_STATE_BUS_OFF) {
189223
return;
190224
}
191-
twai_initiate_recovery();
225+
twai_initiate_recovery_v2(*self->twai_driver_handle);
192226
// wait 100ms (hard coded for now) for bus to recover
193227
uint64_t deadline = port_get_raw_ticks(NULL) + 100;
194228
do {
195-
twai_get_status_info(&info);
229+
twai_get_status_info_v2(*self->twai_driver_handle,&info);
196230
} while (port_get_raw_ticks(NULL) < deadline && (info.state == TWAI_STATE_BUS_OFF || info.state == TWAI_STATE_RECOVERING));
197231
}
198232

199233
static void canio_maybe_auto_restart(canio_can_obj_t *self) {
200234
if (self->auto_restart) {
201-
can_restart();
235+
can_restart(self);
202236
}
203237
}
204238

205239
void common_hal_canio_can_restart(canio_can_obj_t *self) {
206240
if (!common_hal_canio_can_auto_restart_get(self)) {
207-
can_restart();
241+
can_restart(self);
208242
}
209243
}
210244

@@ -217,6 +251,9 @@ void common_hal_canio_can_auto_restart_set(canio_can_obj_t *self, bool value) {
217251
canio_maybe_auto_restart(self);
218252
}
219253

254+
255+
256+
220257
void common_hal_canio_can_send(canio_can_obj_t *self, mp_obj_t message_in) {
221258
canio_maybe_auto_restart(self);
222259
canio_message_obj_t *message = message_in;
@@ -232,7 +269,7 @@ void common_hal_canio_can_send(canio_can_obj_t *self, mp_obj_t message_in) {
232269
memcpy(message_out.data, message->data, message->size);
233270
}
234271
// Allow transmission to occur in background
235-
twai_transmit(&message_out, 0);
272+
twai_transmit_v2(*self->twai_driver_handle,&message_out, 0);
236273
}
237274

238275
bool common_hal_canio_can_silent_get(canio_can_obj_t *self) {
@@ -251,18 +288,26 @@ void common_hal_canio_can_check_for_deinit(canio_can_obj_t *self) {
251288

252289
void common_hal_canio_can_deinit(canio_can_obj_t *self) {
253290
if (self->tx_pin) {
254-
(void)twai_stop();
255-
(void)twai_driver_uninstall();
291+
(void)twai_stop_v2(*self->twai_driver_handle);
292+
(void)twai_driver_uninstall_v2(*self->twai_driver_handle);
256293
reset_pin_number(self->tx_pin->number);
257294
reset_pin_number(self->rx_pin->number);
258-
reserved_can = false;
295+
296+
if (self->instance==0){
297+
reserved_can_instance&=0x02; /* free first instance - clear 1st bit */
298+
}else if (self->instance==1){
299+
reserved_can_instance&=0x01; /* free second instance - clear 2nd bit */
300+
}
301+
259302
}
260303
self->tx_pin = NULL;
261304
self->rx_pin = NULL;
262305
}
263306

264307
void common_hal_canio_reset(void) {
265-
(void)twai_stop();
266-
(void)twai_driver_uninstall();
267-
reserved_can = false;
308+
(void)twai_stop_v2(*twai_insts[0]);
309+
(void)twai_driver_uninstall_v2(*twai_insts[0]);
310+
(void)twai_stop_v2(*twai_insts[1]);
311+
(void)twai_driver_uninstall_v2(*twai_insts[1]);
312+
reserved_can_instance=0; /* unassign both bits */
268313
}

0 commit comments

Comments
 (0)