1 /*
2 * This file is part of the MicroPython project, http://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2014-2018 Damien P. George
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
27 #include <string.h>
28
29 #include "py/objarray.h"
30 #include "py/runtime.h"
31 #include "py/gc.h"
32 #include "py/binary.h"
33 #include "py/stream.h"
34 #include "py/mperrno.h"
35 #include "py/mphal.h"
36 #include "bufhelper.h"
37 #include "can.h"
38 #include "irq.h"
39
40 #if MICROPY_HW_ENABLE_CAN
41
42 #if MICROPY_HW_ENABLE_FDCAN
43
44 #define CAN_MAX_FILTER (64)
45
46 #define CAN_FIFO0 FDCAN_RX_FIFO0
47 #define CAN_FIFO1 FDCAN_RX_FIFO1
48 #define CAN_FILTER_FIFO0 (0)
49
50 // Default timings; 125Kbps assuming 48MHz clock
51 #define CAN_DEFAULT_PRESCALER (32)
52 #define CAN_DEFAULT_SJW (1)
53 #define CAN_DEFAULT_BS1 (8)
54 #define CAN_DEFAULT_BS2 (3)
55
56 #define CAN_MODE_NORMAL FDCAN_MODE_NORMAL
57 #define CAN_MODE_LOOPBACK FDCAN_MODE_EXTERNAL_LOOPBACK
58 #define CAN_MODE_SILENT FDCAN_MODE_BUS_MONITORING
59 #define CAN_MODE_SILENT_LOOPBACK FDCAN_MODE_INTERNAL_LOOPBACK
60
61 #define CAN1_RX0_IRQn FDCAN1_IT0_IRQn
62 #define CAN1_RX1_IRQn FDCAN1_IT1_IRQn
63 #define CAN2_RX0_IRQn FDCAN2_IT0_IRQn
64 #define CAN2_RX1_IRQn FDCAN2_IT1_IRQn
65
66 #define CAN_IT_FIFO0_FULL FDCAN_IT_RX_FIFO0_FULL
67 #define CAN_IT_FIFO1_FULL FDCAN_IT_RX_FIFO1_FULL
68 #define CAN_IT_FIFO0_OVRF FDCAN_IT_RX_FIFO0_MESSAGE_LOST
69 #define CAN_IT_FIFO1_OVRF FDCAN_IT_RX_FIFO1_MESSAGE_LOST
70 #define CAN_IT_FIFO0_PENDING FDCAN_IT_RX_FIFO0_NEW_MESSAGE
71 #define CAN_IT_FIFO1_PENDING FDCAN_IT_RX_FIFO1_NEW_MESSAGE
72 #define CAN_FLAG_FIFO0_FULL FDCAN_FLAG_RX_FIFO0_FULL
73 #define CAN_FLAG_FIFO1_FULL FDCAN_FLAG_RX_FIFO1_FULL
74 #define CAN_FLAG_FIFO0_OVRF FDCAN_FLAG_RX_FIFO0_MESSAGE_LOST
75 #define CAN_FLAG_FIFO1_OVRF FDCAN_FLAG_RX_FIFO1_MESSAGE_LOST
76
77 #define __HAL_CAN_ENABLE_IT __HAL_FDCAN_ENABLE_IT
78 #define __HAL_CAN_DISABLE_IT __HAL_FDCAN_DISABLE_IT
79 #define __HAL_CAN_CLEAR_FLAG __HAL_FDCAN_CLEAR_FLAG
80 #define __HAL_CAN_MSG_PENDING HAL_FDCAN_GetRxFifoFillLevel
81
82 // Both banks start at 0
83 STATIC uint8_t can2_start_bank = 0;
84
85 #else
86
87 #define CAN_MAX_FILTER (28)
88
89 #define CAN_DEFAULT_PRESCALER (100)
90 #define CAN_DEFAULT_SJW (1)
91 #define CAN_DEFAULT_BS1 (6)
92 #define CAN_DEFAULT_BS2 (8)
93
94 #define CAN_IT_FIFO0_FULL CAN_IT_FF0
95 #define CAN_IT_FIFO1_FULL CAN_IT_FF1
96 #define CAN_IT_FIFO0_OVRF CAN_IT_FOV0
97 #define CAN_IT_FIFO1_OVRF CAN_IT_FOV1
98 #define CAN_IT_FIFO0_PENDING CAN_IT_FMP0
99 #define CAN_IT_FIFO1_PENDING CAN_IT_FMP1
100 #define CAN_FLAG_FIFO0_FULL CAN_FLAG_FF0
101 #define CAN_FLAG_FIFO1_FULL CAN_FLAG_FF1
102 #define CAN_FLAG_FIFO0_OVRF CAN_FLAG_FOV0
103 #define CAN_FLAG_FIFO1_OVRF CAN_FLAG_FOV1
104
105 STATIC uint8_t can2_start_bank = 14;
106
107 #endif
108
pyb_can_print(const mp_print_t * print,mp_obj_t self_in,mp_print_kind_t kind)109 STATIC void pyb_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
110 pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
111 if (!self->is_enabled) {
112 mp_printf(print, "CAN(%u)", self->can_id);
113 } else {
114 qstr mode;
115 switch (self->can.Init.Mode) {
116 case CAN_MODE_NORMAL:
117 mode = MP_QSTR_NORMAL;
118 break;
119 case CAN_MODE_LOOPBACK:
120 mode = MP_QSTR_LOOPBACK;
121 break;
122 case CAN_MODE_SILENT:
123 mode = MP_QSTR_SILENT;
124 break;
125 case CAN_MODE_SILENT_LOOPBACK:
126 default:
127 mode = MP_QSTR_SILENT_LOOPBACK;
128 break;
129 }
130 mp_printf(print, "CAN(%u, CAN.%q, extframe=%q, auto_restart=%q)",
131 self->can_id,
132 mode,
133 self->extframe ? MP_QSTR_True : MP_QSTR_False,
134 #if MICROPY_HW_ENABLE_FDCAN
135 (self->can.Instance->CCCR & FDCAN_CCCR_DAR) ? MP_QSTR_True : MP_QSTR_False
136 #else
137 (self->can.Instance->MCR & CAN_MCR_ABOM) ? MP_QSTR_True : MP_QSTR_False
138 #endif
139 );
140 }
141 }
142
pyb_can_get_source_freq()143 STATIC uint32_t pyb_can_get_source_freq() {
144 uint32_t can_kern_clk = 0;
145
146 // Find CAN kernel clock
147 #if defined(STM32H7)
148 switch (__HAL_RCC_GET_FDCAN_SOURCE()) {
149 case RCC_FDCANCLKSOURCE_HSE:
150 can_kern_clk = HSE_VALUE;
151 break;
152 case RCC_FDCANCLKSOURCE_PLL: {
153 PLL1_ClocksTypeDef pll1_clocks;
154 HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
155 can_kern_clk = pll1_clocks.PLL1_Q_Frequency;
156 break;
157 }
158 case RCC_FDCANCLKSOURCE_PLL2: {
159 PLL2_ClocksTypeDef pll2_clocks;
160 HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
161 can_kern_clk = pll2_clocks.PLL2_Q_Frequency;
162 break;
163 }
164 }
165 #else // F4 and F7 and assume other MCUs too.
166 // CAN1/CAN2/CAN3 on APB1 use GetPCLK1Freq, alternatively use the following:
167 // can_kern_clk = ((HSE_VALUE / osc_config.PLL.PLLM ) * osc_config.PLL.PLLN) /
168 // (osc_config.PLL.PLLQ * clk_init.AHBCLKDivider * clk_init.APB1CLKDivider);
169 can_kern_clk = HAL_RCC_GetPCLK1Freq();
170 #endif
171
172 return can_kern_clk;
173 }
174
175 // init(mode, extframe=False, prescaler=100, *, sjw=1, bs1=6, bs2=8)
pyb_can_init_helper(pyb_can_obj_t * self,size_t n_args,const mp_obj_t * pos_args,mp_map_t * kw_args)176 STATIC mp_obj_t pyb_can_init_helper(pyb_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
177 enum { ARG_mode, ARG_extframe, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, ARG_auto_restart, ARG_baudrate, ARG_sample_point };
178 static const mp_arg_t allowed_args[] = {
179 { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} },
180 { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} },
181 { MP_QSTR_prescaler, MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} },
182 { MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} },
183 { MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} },
184 { MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2} },
185 { MP_QSTR_auto_restart, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
186 { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
187 { MP_QSTR_sample_point, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 75} }, // 75% sampling point
188 };
189
190 // parse args
191 mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
192 mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
193
194 self->extframe = args[ARG_extframe].u_bool;
195
196 // set the CAN configuration values
197 memset(&self->can, 0, sizeof(self->can));
198
199 // Calculate CAN bit timing from baudrate if provided
200 if (args[ARG_baudrate].u_int != 0) {
201 uint32_t baudrate = args[ARG_baudrate].u_int;
202 uint32_t sampoint = args[ARG_sample_point].u_int;
203 uint32_t can_kern_clk = pyb_can_get_source_freq();
204 bool timing_found = false;
205
206 // The following max values work on all MCUs for classical CAN.
207 for (int brp = 1; brp < 512 && !timing_found; brp++) {
208 for (int bs1 = 1; bs1 < 16 && !timing_found; bs1++) {
209 for (int bs2 = 1; bs2 < 8 && !timing_found; bs2++) {
210 if ((baudrate == (can_kern_clk / (brp * (1 + bs1 + bs2)))) &&
211 ((sampoint * 10) == (((1 + bs1) * 1000) / (1 + bs1 + bs2)))) {
212 args[ARG_bs1].u_int = bs1;
213 args[ARG_bs2].u_int = bs2;
214 args[ARG_prescaler].u_int = brp;
215 timing_found = true;
216 }
217 }
218 }
219 }
220 if (!timing_found) {
221 mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("couldn't match baudrate and sample point"));
222 }
223 }
224
225 // init CAN (if it fails, it's because the port doesn't exist)
226 if (!can_init(self, args[ARG_mode].u_int, args[ARG_prescaler].u_int, args[ARG_sjw].u_int,
227 args[ARG_bs1].u_int, args[ARG_bs2].u_int, args[ARG_auto_restart].u_bool)) {
228 mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("CAN(%d) doesn't exist"), self->can_id);
229 }
230
231 return mp_const_none;
232 }
233
234 // CAN(bus, ...)
pyb_can_make_new(const mp_obj_type_t * type,size_t n_args,size_t n_kw,const mp_obj_t * args)235 STATIC mp_obj_t pyb_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
236 // check arguments
237 mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
238
239 // work out port
240 mp_uint_t can_idx;
241 if (mp_obj_is_str(args[0])) {
242 const char *port = mp_obj_str_get_str(args[0]);
243 if (0) {
244 #ifdef MICROPY_HW_CAN1_NAME
245 } else if (strcmp(port, MICROPY_HW_CAN1_NAME) == 0) {
246 can_idx = PYB_CAN_1;
247 #endif
248 #ifdef MICROPY_HW_CAN2_NAME
249 } else if (strcmp(port, MICROPY_HW_CAN2_NAME) == 0) {
250 can_idx = PYB_CAN_2;
251 #endif
252 #ifdef MICROPY_HW_CAN3_NAME
253 } else if (strcmp(port, MICROPY_HW_CAN3_NAME) == 0) {
254 can_idx = PYB_CAN_3;
255 #endif
256 } else {
257 mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("CAN(%s) doesn't exist"), port);
258 }
259 } else {
260 can_idx = mp_obj_get_int(args[0]);
261 }
262 if (can_idx < 1 || can_idx > MP_ARRAY_SIZE(MP_STATE_PORT(pyb_can_obj_all))) {
263 mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("CAN(%d) doesn't exist"), can_idx);
264 }
265
266 // check if the CAN is reserved for system use or not
267 if (MICROPY_HW_CAN_IS_RESERVED(can_idx)) {
268 mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("CAN(%d) is reserved"), can_idx);
269 }
270
271 pyb_can_obj_t *self;
272 if (MP_STATE_PORT(pyb_can_obj_all)[can_idx - 1] == NULL) {
273 self = m_new_obj(pyb_can_obj_t);
274 self->base.type = &pyb_can_type;
275 self->can_id = can_idx;
276 self->is_enabled = false;
277 MP_STATE_PORT(pyb_can_obj_all)[can_idx - 1] = self;
278 } else {
279 self = MP_STATE_PORT(pyb_can_obj_all)[can_idx - 1];
280 }
281
282 if (!self->is_enabled || n_args > 1) {
283 if (self->is_enabled) {
284 // The caller is requesting a reconfiguration of the hardware
285 // this can only be done if the hardware is in init mode
286 can_deinit(self);
287 }
288
289 self->rxcallback0 = mp_const_none;
290 self->rxcallback1 = mp_const_none;
291 self->rx_state0 = RX_STATE_FIFO_EMPTY;
292 self->rx_state1 = RX_STATE_FIFO_EMPTY;
293
294 if (n_args > 1 || n_kw > 0) {
295 // start the peripheral
296 mp_map_t kw_args;
297 mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
298 pyb_can_init_helper(self, n_args - 1, args + 1, &kw_args);
299 }
300 }
301
302 return MP_OBJ_FROM_PTR(self);
303 }
304
pyb_can_init(size_t n_args,const mp_obj_t * args,mp_map_t * kw_args)305 STATIC mp_obj_t pyb_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
306 return pyb_can_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args);
307 }
308 STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_can_init_obj, 1, pyb_can_init);
309
310 // deinit()
pyb_can_deinit(mp_obj_t self_in)311 STATIC mp_obj_t pyb_can_deinit(mp_obj_t self_in) {
312 pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
313 can_deinit(self);
314 return mp_const_none;
315 }
316 STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_can_deinit_obj, pyb_can_deinit);
317
318 // Force a software restart of the controller, to allow transmission after a bus error
pyb_can_restart(mp_obj_t self_in)319 STATIC mp_obj_t pyb_can_restart(mp_obj_t self_in) {
320 pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
321 if (!self->is_enabled) {
322 mp_raise_ValueError(NULL);
323 }
324 CAN_TypeDef *can = self->can.Instance;
325 #if MICROPY_HW_ENABLE_FDCAN
326 can->CCCR |= FDCAN_CCCR_INIT;
327 while ((can->CCCR & FDCAN_CCCR_INIT) == 0) {
328 }
329 can->CCCR &= ~FDCAN_CCCR_INIT;
330 while ((can->CCCR & FDCAN_CCCR_INIT)) {
331 }
332 #else
333 can->MCR |= CAN_MCR_INRQ;
334 while ((can->MSR & CAN_MSR_INAK) == 0) {
335 }
336 can->MCR &= ~CAN_MCR_INRQ;
337 while ((can->MSR & CAN_MSR_INAK)) {
338 }
339 #endif
340 return mp_const_none;
341 }
342 STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_can_restart_obj, pyb_can_restart);
343
344 // Get the state of the controller
pyb_can_state(mp_obj_t self_in)345 STATIC mp_obj_t pyb_can_state(mp_obj_t self_in) {
346 pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
347 mp_int_t state = CAN_STATE_STOPPED;
348 if (self->is_enabled) {
349 CAN_TypeDef *can = self->can.Instance;
350 #if MICROPY_HW_ENABLE_FDCAN
351 if (can->PSR & FDCAN_PSR_BO) {
352 state = CAN_STATE_BUS_OFF;
353 } else if (can->PSR & FDCAN_PSR_EP) {
354 state = CAN_STATE_ERROR_PASSIVE;
355 } else if (can->PSR & FDCAN_PSR_EW) {
356 state = CAN_STATE_ERROR_WARNING;
357 } else {
358 state = CAN_STATE_ERROR_ACTIVE;
359 }
360 #else
361 if (can->ESR & CAN_ESR_BOFF) {
362 state = CAN_STATE_BUS_OFF;
363 } else if (can->ESR & CAN_ESR_EPVF) {
364 state = CAN_STATE_ERROR_PASSIVE;
365 } else if (can->ESR & CAN_ESR_EWGF) {
366 state = CAN_STATE_ERROR_WARNING;
367 } else {
368 state = CAN_STATE_ERROR_ACTIVE;
369 }
370 #endif
371 }
372 return MP_OBJ_NEW_SMALL_INT(state);
373 }
374 STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_can_state_obj, pyb_can_state);
375
376 // Get info about error states and TX/RX buffers
pyb_can_info(size_t n_args,const mp_obj_t * args)377 STATIC mp_obj_t pyb_can_info(size_t n_args, const mp_obj_t *args) {
378 #if MICROPY_HW_ENABLE_FDCAN
379 // TODO implement for FDCAN
380 return mp_const_none;
381 #else
382 pyb_can_obj_t *self = MP_OBJ_TO_PTR(args[0]);
383 mp_obj_list_t *list;
384 if (n_args == 1) {
385 list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL));
386 } else {
387 if (!mp_obj_is_type(args[1], &mp_type_list)) {
388 mp_raise_TypeError(NULL);
389 }
390 list = MP_OBJ_TO_PTR(args[1]);
391 if (list->len < 8) {
392 mp_raise_ValueError(NULL);
393 }
394 }
395 CAN_TypeDef *can = self->can.Instance;
396 uint32_t esr = can->ESR;
397 list->items[0] = MP_OBJ_NEW_SMALL_INT(esr >> CAN_ESR_TEC_Pos & 0xff);
398 list->items[1] = MP_OBJ_NEW_SMALL_INT(esr >> CAN_ESR_REC_Pos & 0xff);
399 list->items[2] = MP_OBJ_NEW_SMALL_INT(self->num_error_warning);
400 list->items[3] = MP_OBJ_NEW_SMALL_INT(self->num_error_passive);
401 list->items[4] = MP_OBJ_NEW_SMALL_INT(self->num_bus_off);
402 int n_tx_pending = 0x01121223 >> ((can->TSR >> CAN_TSR_TME_Pos & 7) << 2) & 0xf;
403 list->items[5] = MP_OBJ_NEW_SMALL_INT(n_tx_pending);
404 list->items[6] = MP_OBJ_NEW_SMALL_INT(can->RF0R >> CAN_RF0R_FMP0_Pos & 3);
405 list->items[7] = MP_OBJ_NEW_SMALL_INT(can->RF1R >> CAN_RF1R_FMP1_Pos & 3);
406 return MP_OBJ_FROM_PTR(list);
407 #endif
408 }
409 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_can_info_obj, 1, 2, pyb_can_info);
410
411 // any(fifo) - return `True` if any message waiting on the FIFO, else `False`
pyb_can_any(mp_obj_t self_in,mp_obj_t fifo_in)412 STATIC mp_obj_t pyb_can_any(mp_obj_t self_in, mp_obj_t fifo_in) {
413 pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
414 mp_int_t fifo = mp_obj_get_int(fifo_in);
415 if (fifo == 0) {
416 if (__HAL_CAN_MSG_PENDING(&self->can, CAN_FIFO0) != 0) {
417 return mp_const_true;
418 }
419 } else {
420 if (__HAL_CAN_MSG_PENDING(&self->can, CAN_FIFO1) != 0) {
421 return mp_const_true;
422 }
423 }
424 return mp_const_false;
425 }
426 STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_any_obj, pyb_can_any);
427
428 // send(send, addr, *, timeout=5000)
pyb_can_send(size_t n_args,const mp_obj_t * pos_args,mp_map_t * kw_args)429 STATIC mp_obj_t pyb_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
430 enum { ARG_data, ARG_id, ARG_timeout, ARG_rtr };
431 static const mp_arg_t allowed_args[] = {
432 { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
433 { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
434 { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
435 { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
436 };
437
438 // parse args
439 pyb_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
440 mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
441 mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
442
443 // get the buffer to send from
444 mp_buffer_info_t bufinfo;
445 uint8_t data[1];
446 pyb_buf_get_for_send(args[ARG_data].u_obj, &bufinfo, data);
447
448 if (bufinfo.len > 8) {
449 mp_raise_ValueError(MP_ERROR_TEXT("CAN data field too long"));
450 }
451
452 // send the data
453 CanTxMsgTypeDef tx_msg;
454
455 #if MICROPY_HW_ENABLE_FDCAN
456 uint8_t tx_data[8];
457 tx_msg.MessageMarker = 0;
458 tx_msg.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
459 tx_msg.BitRateSwitch = FDCAN_BRS_OFF;
460 tx_msg.FDFormat = FDCAN_CLASSIC_CAN;
461 tx_msg.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
462 tx_msg.DataLength = (bufinfo.len << 16); // TODO DLC for len > 8
463
464 if (self->extframe) {
465 tx_msg.Identifier = args[ARG_id].u_int & 0x1FFFFFFF;
466 tx_msg.IdType = FDCAN_EXTENDED_ID;
467 } else {
468 tx_msg.Identifier = args[ARG_id].u_int & 0x7FF;
469 tx_msg.IdType = FDCAN_STANDARD_ID;
470 }
471 if (args[ARG_rtr].u_bool == false) {
472 tx_msg.TxFrameType = FDCAN_DATA_FRAME;
473 } else {
474 tx_msg.TxFrameType = FDCAN_REMOTE_FRAME;
475 }
476 #else
477 tx_msg.DLC = bufinfo.len;
478 uint8_t *tx_data = tx_msg.Data; // Data is uint32_t but holds only 1 byte
479
480 if (self->extframe) {
481 tx_msg.ExtId = args[ARG_id].u_int & 0x1FFFFFFF;
482 tx_msg.IDE = CAN_ID_EXT;
483 } else {
484 tx_msg.StdId = args[ARG_id].u_int & 0x7FF;
485 tx_msg.IDE = CAN_ID_STD;
486 }
487 if (args[ARG_rtr].u_bool == false) {
488 tx_msg.RTR = CAN_RTR_DATA;
489 } else {
490 tx_msg.RTR = CAN_RTR_REMOTE;
491 }
492 #endif
493
494 for (mp_uint_t i = 0; i < bufinfo.len; i++) {
495 tx_data[i] = ((byte *)bufinfo.buf)[i];
496 }
497
498 HAL_StatusTypeDef status;
499 #if MICROPY_HW_ENABLE_FDCAN
500 uint32_t timeout_ms = args[ARG_timeout].u_int;
501 uint32_t start = HAL_GetTick();
502 while (HAL_FDCAN_GetTxFifoFreeLevel(&self->can) == 0) {
503 if (timeout_ms == 0) {
504 mp_raise_OSError(MP_ETIMEDOUT);
505 }
506 // Check for the Timeout
507 if (timeout_ms != HAL_MAX_DELAY) {
508 if (HAL_GetTick() - start >= timeout_ms) {
509 mp_raise_OSError(MP_ETIMEDOUT);
510 }
511 }
512 MICROPY_EVENT_POLL_HOOK
513 }
514 status = HAL_FDCAN_AddMessageToTxFifoQ(&self->can, &tx_msg, tx_data);
515 #else
516 self->can.pTxMsg = &tx_msg;
517 status = CAN_Transmit(&self->can, args[ARG_timeout].u_int);
518 #endif
519
520 if (status != HAL_OK) {
521 mp_hal_raise(status);
522 }
523
524 return mp_const_none;
525 }
526 STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_can_send_obj, 1, pyb_can_send);
527
528 // recv(fifo, list=None, *, timeout=5000)
pyb_can_recv(size_t n_args,const mp_obj_t * pos_args,mp_map_t * kw_args)529 STATIC mp_obj_t pyb_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
530 enum { ARG_fifo, ARG_list, ARG_timeout };
531 static const mp_arg_t allowed_args[] = {
532 { MP_QSTR_fifo, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
533 { MP_QSTR_list, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
534 { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
535 };
536
537 // parse args
538 pyb_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
539 mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
540 mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
541
542 // receive the data
543 CanRxMsgTypeDef rx_msg;
544 #if MICROPY_HW_ENABLE_FDCAN
545 uint8_t rx_data[8];
546 #else
547 uint8_t *rx_data = rx_msg.Data;
548 #endif
549
550 mp_uint_t fifo = args[ARG_fifo].u_int;
551 if (fifo == 0) {
552 fifo = CAN_FIFO0;
553 } else if (fifo == 1) {
554 fifo = CAN_FIFO1;
555 } else {
556 mp_raise_TypeError(NULL);
557 }
558
559 int ret = can_receive(&self->can, fifo, &rx_msg, rx_data, args[ARG_timeout].u_int);
560 if (ret < 0) {
561 mp_raise_OSError(-ret);
562 }
563
564 #if MICROPY_HW_ENABLE_FDCAN
565 uint32_t rx_dlc = rx_msg.DataLength;
566 #else
567 uint32_t rx_dlc = rx_msg.DLC;
568 #endif
569
570 // Manage the rx state machine
571 if ((fifo == CAN_FIFO0 && self->rxcallback0 != mp_const_none) ||
572 (fifo == CAN_FIFO1 && self->rxcallback1 != mp_const_none)) {
573 byte *state = (fifo == CAN_FIFO0) ? &self->rx_state0 : &self->rx_state1;
574
575 switch (*state) {
576 case RX_STATE_FIFO_EMPTY:
577 break;
578 case RX_STATE_MESSAGE_PENDING:
579 if (__HAL_CAN_MSG_PENDING(&self->can, fifo) == 0) {
580 // Fifo is empty
581 __HAL_CAN_ENABLE_IT(&self->can, (fifo == CAN_FIFO0) ? CAN_IT_FIFO0_PENDING : CAN_IT_FIFO1_PENDING);
582 *state = RX_STATE_FIFO_EMPTY;
583 }
584 break;
585 case RX_STATE_FIFO_FULL:
586 __HAL_CAN_ENABLE_IT(&self->can, (fifo == CAN_FIFO0) ? CAN_IT_FIFO0_FULL : CAN_IT_FIFO1_FULL);
587 *state = RX_STATE_MESSAGE_PENDING;
588 break;
589 case RX_STATE_FIFO_OVERFLOW:
590 __HAL_CAN_ENABLE_IT(&self->can, (fifo == CAN_FIFO0) ? CAN_IT_FIFO0_OVRF : CAN_IT_FIFO1_OVRF);
591 __HAL_CAN_ENABLE_IT(&self->can, (fifo == CAN_FIFO0) ? CAN_IT_FIFO0_FULL : CAN_IT_FIFO1_FULL);
592 *state = RX_STATE_MESSAGE_PENDING;
593 break;
594 }
595 }
596
597 // Create the tuple, or get the list, that will hold the return values
598 // Also populate the fourth element, either a new bytes or reuse existing memoryview
599 mp_obj_t ret_obj = args[ARG_list].u_obj;
600 mp_obj_t *items;
601 if (ret_obj == mp_const_none) {
602 ret_obj = mp_obj_new_tuple(4, NULL);
603 items = ((mp_obj_tuple_t *)MP_OBJ_TO_PTR(ret_obj))->items;
604 items[3] = mp_obj_new_bytes(rx_data, rx_dlc);
605 } else {
606 // User should provide a list of length at least 4 to hold the values
607 if (!mp_obj_is_type(ret_obj, &mp_type_list)) {
608 mp_raise_TypeError(NULL);
609 }
610 mp_obj_list_t *list = MP_OBJ_TO_PTR(ret_obj);
611 if (list->len < 4) {
612 mp_raise_ValueError(NULL);
613 }
614 items = list->items;
615 // Fourth element must be a memoryview which we assume points to a
616 // byte-like array which is large enough, and then we resize it inplace
617 if (!mp_obj_is_type(items[3], &mp_type_memoryview)) {
618 mp_raise_TypeError(NULL);
619 }
620 mp_obj_array_t *mv = MP_OBJ_TO_PTR(items[3]);
621 if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE)
622 || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))) {
623 mp_raise_ValueError(NULL);
624 }
625 mv->len = rx_dlc;
626 memcpy(mv->items, rx_data, rx_dlc);
627 }
628
629 // Populate the first 3 values of the tuple/list
630 #if MICROPY_HW_ENABLE_FDCAN
631 items[0] = MP_OBJ_NEW_SMALL_INT(rx_msg.Identifier);
632 items[1] = rx_msg.RxFrameType == FDCAN_REMOTE_FRAME ? mp_const_true : mp_const_false;
633 items[2] = MP_OBJ_NEW_SMALL_INT(rx_msg.FilterIndex);
634 #else
635 items[0] = MP_OBJ_NEW_SMALL_INT((rx_msg.IDE == CAN_ID_STD ? rx_msg.StdId : rx_msg.ExtId));
636 items[1] = rx_msg.RTR == CAN_RTR_REMOTE ? mp_const_true : mp_const_false;
637 items[2] = MP_OBJ_NEW_SMALL_INT(rx_msg.FMI);
638 #endif
639
640 // Return the result
641 return ret_obj;
642 }
643 STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_can_recv_obj, 1, pyb_can_recv);
644
645 // initfilterbanks(n)
pyb_can_initfilterbanks(mp_obj_t self,mp_obj_t bank_in)646 STATIC mp_obj_t pyb_can_initfilterbanks(mp_obj_t self, mp_obj_t bank_in) {
647 #if MICROPY_HW_ENABLE_FDCAN
648 can2_start_bank = 0;
649 #else
650 can2_start_bank = mp_obj_get_int(bank_in);
651 #endif
652
653 for (int f = 0; f < CAN_MAX_FILTER; f++) {
654 can_clearfilter(MP_OBJ_TO_PTR(self), f, can2_start_bank);
655 }
656 return mp_const_none;
657 }
658 STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_initfilterbanks_fun_obj, pyb_can_initfilterbanks);
659 STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pyb_can_initfilterbanks_obj, MP_ROM_PTR(&pyb_can_initfilterbanks_fun_obj));
660
pyb_can_clearfilter(mp_obj_t self_in,mp_obj_t bank_in)661 STATIC mp_obj_t pyb_can_clearfilter(mp_obj_t self_in, mp_obj_t bank_in) {
662 pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
663 mp_int_t f = mp_obj_get_int(bank_in);
664 if (self->can_id == 2) {
665 f += can2_start_bank;
666 }
667 can_clearfilter(self, f, can2_start_bank);
668 return mp_const_none;
669 }
670 STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_clearfilter_obj, pyb_can_clearfilter);
671
672 // setfilter(bank, mode, fifo, params, *, rtr)
673 #define EXTENDED_ID_TO_16BIT_FILTER(id) (((id & 0xC00000) >> 13) | ((id & 0x38000) >> 15)) | 8
pyb_can_setfilter(size_t n_args,const mp_obj_t * pos_args,mp_map_t * kw_args)674 STATIC mp_obj_t pyb_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
675 enum { ARG_bank, ARG_mode, ARG_fifo, ARG_params, ARG_rtr };
676 static const mp_arg_t allowed_args[] = {
677 { MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
678 { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
679 { MP_QSTR_fifo, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_FILTER_FIFO0} },
680 { MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
681 { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
682 };
683
684 // parse args
685 pyb_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
686 mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
687 mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
688
689 #if MICROPY_HW_ENABLE_FDCAN
690 FDCAN_FilterTypeDef filter = {0};
691 filter.IdType = FDCAN_STANDARD_ID;
692 // TODO check filter index
693 filter.FilterIndex = args[ARG_bank].u_int;
694
695 // Check filter mode
696 if (((args[ARG_mode].u_int != FDCAN_FILTER_RANGE) &&
697 (args[ARG_mode].u_int != FDCAN_FILTER_DUAL) &&
698 (args[ARG_mode].u_int != FDCAN_FILTER_MASK))) {
699 goto error;
700 }
701
702 // Check FIFO index.
703 if (args[ARG_fifo].u_int == 0) {
704 filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
705 } else if (args[ARG_fifo].u_int == 1) {
706 filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
707 } else {
708 goto error;
709 }
710
711 size_t len;
712 mp_obj_t *params;
713 mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms);
714 if (len != 2) { // Check params len
715 goto error;
716 }
717 filter.FilterID1 = mp_obj_get_int(params[0]);
718 filter.FilterID2 = mp_obj_get_int(params[1]);
719 filter.FilterType = args[ARG_mode].u_int;
720 HAL_FDCAN_ConfigFilter(&self->can, &filter);
721
722 #else
723
724 size_t len;
725 size_t rtr_len;
726 mp_uint_t rtr_masks[4] = {0, 0, 0, 0};
727 mp_obj_t *rtr_flags;
728 mp_obj_t *params;
729 mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms);
730 if (args[ARG_rtr].u_obj != MP_OBJ_NULL) {
731 mp_obj_get_array(args[ARG_rtr].u_obj, &rtr_len, &rtr_flags);
732 }
733
734 CAN_FilterConfTypeDef filter;
735 if (args[ARG_mode].u_int == MASK16 || args[ARG_mode].u_int == LIST16) {
736 if (len != 4) {
737 goto error;
738 }
739 filter.FilterScale = CAN_FILTERSCALE_16BIT;
740 if (self->extframe) {
741 if (args[ARG_rtr].u_obj != MP_OBJ_NULL) {
742 if (args[ARG_mode].u_int == MASK16) {
743 rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x02 : 0;
744 rtr_masks[1] = 0x02;
745 rtr_masks[2] = mp_obj_get_int(rtr_flags[1]) ? 0x02 : 0;
746 rtr_masks[3] = 0x02;
747 } else { // LIST16
748 rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x02 : 0;
749 rtr_masks[1] = mp_obj_get_int(rtr_flags[1]) ? 0x02 : 0;
750 rtr_masks[2] = mp_obj_get_int(rtr_flags[2]) ? 0x02 : 0;
751 rtr_masks[3] = mp_obj_get_int(rtr_flags[3]) ? 0x02 : 0;
752 }
753 }
754 filter.FilterIdLow = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[0])) | rtr_masks[0]; // id1
755 filter.FilterMaskIdLow = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[1])) | rtr_masks[1]; // mask1
756 filter.FilterIdHigh = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[2])) | rtr_masks[2]; // id2
757 filter.FilterMaskIdHigh = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[3])) | rtr_masks[3]; // mask2
758 } else { // Basic frames
759 if (args[ARG_rtr].u_obj != MP_OBJ_NULL) {
760 if (args[ARG_mode].u_int == MASK16) {
761 rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x10 : 0;
762 rtr_masks[1] = 0x10;
763 rtr_masks[2] = mp_obj_get_int(rtr_flags[1]) ? 0x10 : 0;
764 rtr_masks[3] = 0x10;
765 } else { // LIST16
766 rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x10 : 0;
767 rtr_masks[1] = mp_obj_get_int(rtr_flags[1]) ? 0x10 : 0;
768 rtr_masks[2] = mp_obj_get_int(rtr_flags[2]) ? 0x10 : 0;
769 rtr_masks[3] = mp_obj_get_int(rtr_flags[3]) ? 0x10 : 0;
770 }
771 }
772 filter.FilterIdLow = (mp_obj_get_int(params[0]) << 5) | rtr_masks[0]; // id1
773 filter.FilterMaskIdLow = (mp_obj_get_int(params[1]) << 5) | rtr_masks[1]; // mask1
774 filter.FilterIdHigh = (mp_obj_get_int(params[2]) << 5) | rtr_masks[2]; // id2
775 filter.FilterMaskIdHigh = (mp_obj_get_int(params[3]) << 5) | rtr_masks[3]; // mask2
776 }
777 if (args[ARG_mode].u_int == MASK16) {
778 filter.FilterMode = CAN_FILTERMODE_IDMASK;
779 }
780 if (args[ARG_mode].u_int == LIST16) {
781 filter.FilterMode = CAN_FILTERMODE_IDLIST;
782 }
783 } else if (args[ARG_mode].u_int == MASK32 || args[ARG_mode].u_int == LIST32) {
784 if (len != 2) {
785 goto error;
786 }
787 filter.FilterScale = CAN_FILTERSCALE_32BIT;
788 if (args[ARG_rtr].u_obj != MP_OBJ_NULL) {
789 if (args[ARG_mode].u_int == MASK32) {
790 rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x02 : 0;
791 rtr_masks[1] = 0x02;
792 } else { // LIST32
793 rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x02 : 0;
794 rtr_masks[1] = mp_obj_get_int(rtr_flags[1]) ? 0x02 : 0;
795 }
796 }
797 filter.FilterIdHigh = (mp_obj_get_int(params[0]) & 0x1FFFE000) >> 13;
798 filter.FilterIdLow = (((mp_obj_get_int(params[0]) & 0x00001FFF) << 3) | 4) | rtr_masks[0];
799 filter.FilterMaskIdHigh = (mp_obj_get_int(params[1]) & 0x1FFFE000) >> 13;
800 filter.FilterMaskIdLow = (((mp_obj_get_int(params[1]) & 0x00001FFF) << 3) | 4) | rtr_masks[1];
801 if (args[ARG_mode].u_int == MASK32) {
802 filter.FilterMode = CAN_FILTERMODE_IDMASK;
803 }
804 if (args[ARG_mode].u_int == LIST32) {
805 filter.FilterMode = CAN_FILTERMODE_IDLIST;
806 }
807 } else {
808 goto error;
809 }
810
811 filter.FilterFIFOAssignment = args[ARG_fifo].u_int;
812 filter.FilterNumber = args[ARG_bank].u_int;
813 if (self->can_id == 1) {
814 if (filter.FilterNumber >= can2_start_bank) {
815 goto error;
816 }
817 } else if (self->can_id == 2) {
818 filter.FilterNumber = filter.FilterNumber + can2_start_bank;
819 if (filter.FilterNumber > 27) {
820 goto error;
821 }
822 } else {
823 if (filter.FilterNumber > 13) { // CAN3 is independant and has its own 14 filters.
824 goto error;
825 }
826 }
827 filter.FilterActivation = ENABLE;
828 filter.BankNumber = can2_start_bank;
829 HAL_CAN_ConfigFilter(&self->can, &filter);
830 #endif
831
832 return mp_const_none;
833 error:
834 mp_raise_ValueError(MP_ERROR_TEXT("CAN filter parameter error"));
835 }
836 STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_can_setfilter_obj, 1, pyb_can_setfilter);
837
pyb_can_rxcallback(mp_obj_t self_in,mp_obj_t fifo_in,mp_obj_t callback_in)838 STATIC mp_obj_t pyb_can_rxcallback(mp_obj_t self_in, mp_obj_t fifo_in, mp_obj_t callback_in) {
839 pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
840 mp_int_t fifo = mp_obj_get_int(fifo_in);
841 mp_obj_t *callback;
842
843 callback = (fifo == 0) ? &self->rxcallback0 : &self->rxcallback1;
844 if (callback_in == mp_const_none) {
845 __HAL_CAN_DISABLE_IT(&self->can, (fifo == 0) ? CAN_IT_FIFO0_PENDING : CAN_IT_FIFO1_PENDING);
846 __HAL_CAN_DISABLE_IT(&self->can, (fifo == 0) ? CAN_IT_FIFO0_FULL : CAN_IT_FIFO1_FULL);
847 __HAL_CAN_DISABLE_IT(&self->can, (fifo == 0) ? CAN_IT_FIFO0_OVRF : CAN_IT_FIFO1_OVRF);
848 __HAL_CAN_CLEAR_FLAG(&self->can, (fifo == CAN_FIFO0) ? CAN_FLAG_FIFO0_FULL : CAN_FLAG_FIFO1_FULL);
849 __HAL_CAN_CLEAR_FLAG(&self->can, (fifo == CAN_FIFO0) ? CAN_FLAG_FIFO0_OVRF : CAN_FLAG_FIFO1_OVRF);
850 *callback = mp_const_none;
851 } else if (*callback != mp_const_none) {
852 // Rx call backs has already been initialized
853 // only the callback function should be changed
854 *callback = callback_in;
855 } else if (mp_obj_is_callable(callback_in)) {
856 *callback = callback_in;
857 uint32_t irq = 0;
858 if (self->can_id == PYB_CAN_1) {
859 irq = (fifo == 0) ? CAN1_RX0_IRQn : CAN1_RX1_IRQn;
860 #if defined(CAN2)
861 } else if (self->can_id == PYB_CAN_2) {
862 irq = (fifo == 0) ? CAN2_RX0_IRQn : CAN2_RX1_IRQn;
863 #endif
864 #if defined(CAN3)
865 } else {
866 irq = (fifo == 0) ? CAN3_RX0_IRQn : CAN3_RX1_IRQn;
867 #endif
868 }
869 NVIC_SetPriority(irq, IRQ_PRI_CAN);
870 HAL_NVIC_EnableIRQ(irq);
871 __HAL_CAN_ENABLE_IT(&self->can, (fifo == 0) ? CAN_IT_FIFO0_PENDING : CAN_IT_FIFO1_PENDING);
872 __HAL_CAN_ENABLE_IT(&self->can, (fifo == 0) ? CAN_IT_FIFO0_FULL : CAN_IT_FIFO1_FULL);
873 __HAL_CAN_ENABLE_IT(&self->can, (fifo == 0) ? CAN_IT_FIFO0_OVRF : CAN_IT_FIFO1_OVRF);
874 }
875 return mp_const_none;
876 }
877 STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_can_rxcallback_obj, pyb_can_rxcallback);
878
879 STATIC const mp_rom_map_elem_t pyb_can_locals_dict_table[] = {
880 // instance methods
881 { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_can_init_obj) },
882 { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_can_deinit_obj) },
883 { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&pyb_can_restart_obj) },
884 { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&pyb_can_state_obj) },
885 { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&pyb_can_info_obj) },
886 { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_can_any_obj) },
887 { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pyb_can_send_obj) },
888 { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&pyb_can_recv_obj) },
889 { MP_ROM_QSTR(MP_QSTR_initfilterbanks), MP_ROM_PTR(&pyb_can_initfilterbanks_obj) },
890 { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&pyb_can_setfilter_obj) },
891 { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&pyb_can_clearfilter_obj) },
892 { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&pyb_can_rxcallback_obj) },
893
894 #if MICROPY_HW_ENABLE_FDCAN
895 { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) },
896 { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_LOOPBACK) },
897 { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_SILENT) },
898 { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_SILENT_LOOPBACK) },
899
900 { MP_ROM_QSTR(MP_QSTR_RANGE), MP_ROM_INT(FDCAN_FILTER_RANGE) },
901 { MP_ROM_QSTR(MP_QSTR_DUAL), MP_ROM_INT(FDCAN_FILTER_DUAL) },
902 { MP_ROM_QSTR(MP_QSTR_MASK), MP_ROM_INT(FDCAN_FILTER_MASK) },
903 #else
904 // class constants
905 // Note: we use the ST constants >> 4 so they fit in a small-int. The
906 // right-shift is undone when the constants are used in the init function.
907 { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL >> 4) },
908 { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_LOOPBACK >> 4) },
909 { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_SILENT >> 4) },
910 { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_SILENT_LOOPBACK >> 4) },
911
912 { MP_ROM_QSTR(MP_QSTR_MASK16), MP_ROM_INT(MASK16) },
913 { MP_ROM_QSTR(MP_QSTR_LIST16), MP_ROM_INT(LIST16) },
914 { MP_ROM_QSTR(MP_QSTR_MASK32), MP_ROM_INT(MASK32) },
915 { MP_ROM_QSTR(MP_QSTR_LIST32), MP_ROM_INT(LIST32) },
916 #endif
917
918 // values for CAN.state()
919 { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) },
920 { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_ERROR_ACTIVE) },
921 { MP_ROM_QSTR(MP_QSTR_ERROR_WARNING), MP_ROM_INT(CAN_STATE_ERROR_WARNING) },
922 { MP_ROM_QSTR(MP_QSTR_ERROR_PASSIVE), MP_ROM_INT(CAN_STATE_ERROR_PASSIVE) },
923 { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) },
924 };
925 STATIC MP_DEFINE_CONST_DICT(pyb_can_locals_dict, pyb_can_locals_dict_table);
926
can_ioctl(mp_obj_t self_in,mp_uint_t request,uintptr_t arg,int * errcode)927 STATIC mp_uint_t can_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
928 pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
929 mp_uint_t ret;
930 if (request == MP_STREAM_POLL) {
931 uintptr_t flags = arg;
932 ret = 0;
933 if ((flags & MP_STREAM_POLL_RD)
934 && ((__HAL_CAN_MSG_PENDING(&self->can, CAN_FIFO0) != 0)
935 || (__HAL_CAN_MSG_PENDING(&self->can, CAN_FIFO1) != 0))) {
936 ret |= MP_STREAM_POLL_RD;
937 }
938 #if MICROPY_HW_ENABLE_FDCAN
939 if ((flags & MP_STREAM_POLL_WR) && (self->can.Instance->IR & FDCAN_IR_TFE))
940 #else
941 if ((flags & MP_STREAM_POLL_WR) && (self->can.Instance->TSR & CAN_TSR_TME))
942 #endif
943 {
944 ret |= MP_STREAM_POLL_WR;
945 }
946 } else {
947 *errcode = MP_EINVAL;
948 ret = -1;
949 }
950 return ret;
951 }
952
pyb_can_handle_callback(pyb_can_obj_t * self,uint fifo_id,mp_obj_t callback,mp_obj_t irq_reason)953 void pyb_can_handle_callback(pyb_can_obj_t *self, uint fifo_id, mp_obj_t callback, mp_obj_t irq_reason) {
954 if (callback != mp_const_none) {
955 mp_sched_lock();
956 gc_lock();
957 nlr_buf_t nlr;
958 if (nlr_push(&nlr) == 0) {
959 mp_call_function_2(callback, MP_OBJ_FROM_PTR(self), irq_reason);
960 nlr_pop();
961 } else {
962 // Uncaught exception; disable the callback so it doesn't run again.
963 pyb_can_rxcallback(MP_OBJ_FROM_PTR(self), MP_OBJ_NEW_SMALL_INT(fifo_id), mp_const_none);
964 mp_printf(MICROPY_ERROR_PRINTER, "uncaught exception in CAN(%u) rx interrupt handler\n", self->can_id);
965 mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
966 }
967 gc_unlock();
968 mp_sched_unlock();
969 }
970 }
971
972 STATIC const mp_stream_p_t can_stream_p = {
973 // .read = can_read, // is read sensible for CAN?
974 // .write = can_write, // is write sensible for CAN?
975 .ioctl = can_ioctl,
976 .is_text = false,
977 };
978
979 const mp_obj_type_t pyb_can_type = {
980 { &mp_type_type },
981 .name = MP_QSTR_CAN,
982 .print = pyb_can_print,
983 .make_new = pyb_can_make_new,
984 .protocol = &can_stream_p,
985 .locals_dict = (mp_obj_dict_t *)&pyb_can_locals_dict,
986 };
987
988 #endif // MICROPY_HW_ENABLE_CAN
989