stm32/pyb_can: Add support for bus with mixed Classic/FD nodes.
A CAN bus can have mixed classic/FD nodes. Prior to this patch the CAN API could be configured for either standard or extended ID, but not both/mixed operation. This patch allows extended IDs to be filtered and enabled on a per-message basis, in send(), setfilter() and clearfilter(). This is a breaking change to the API: init() no longer accepts the extframe keyword argument.
This commit is contained in:
parent
3320ec44ed
commit
e7264e9532
|
@ -67,7 +67,6 @@ typedef struct _pyb_can_obj_t {
|
||||||
mp_obj_t rxcallback1;
|
mp_obj_t rxcallback1;
|
||||||
mp_uint_t can_id : 8;
|
mp_uint_t can_id : 8;
|
||||||
bool is_enabled : 1;
|
bool is_enabled : 1;
|
||||||
bool extframe : 1;
|
|
||||||
byte rx_state0;
|
byte rx_state0;
|
||||||
byte rx_state1;
|
byte rx_state1;
|
||||||
uint16_t num_error_warning;
|
uint16_t num_error_warning;
|
||||||
|
|
|
@ -133,10 +133,9 @@ STATIC void pyb_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
|
||||||
mode = MP_QSTR_SILENT_LOOPBACK;
|
mode = MP_QSTR_SILENT_LOOPBACK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mp_printf(print, "CAN(%u, CAN.%q, extframe=%q, auto_restart=%q)",
|
mp_printf(print, "CAN(%u, CAN.%q, auto_restart=%q)",
|
||||||
self->can_id,
|
self->can_id,
|
||||||
mode,
|
mode,
|
||||||
self->extframe ? MP_QSTR_True : MP_QSTR_False,
|
|
||||||
#if MICROPY_HW_ENABLE_FDCAN
|
#if MICROPY_HW_ENABLE_FDCAN
|
||||||
(self->can.Instance->CCCR & FDCAN_CCCR_DAR) ? MP_QSTR_True : MP_QSTR_False
|
(self->can.Instance->CCCR & FDCAN_CCCR_DAR) ? MP_QSTR_True : MP_QSTR_False
|
||||||
#else
|
#else
|
||||||
|
@ -200,13 +199,12 @@ STATIC void pyb_can_get_bit_timing(mp_uint_t baudrate, mp_uint_t sample_point,
|
||||||
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("couldn't match baudrate and sample point"));
|
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("couldn't match baudrate and sample point"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// init(mode, extframe=False, prescaler=100, *, sjw=1, bs1=6, bs2=8)
|
// init(mode, prescaler=100, *, sjw=1, bs1=6, bs2=8)
|
||||||
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) {
|
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) {
|
||||||
enum { ARG_mode, ARG_extframe, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, ARG_auto_restart, ARG_baudrate, ARG_sample_point,
|
enum { ARG_mode, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, ARG_auto_restart, ARG_baudrate, ARG_sample_point,
|
||||||
ARG_brs_prescaler, ARG_brs_sjw, ARG_brs_bs1, ARG_brs_bs2, ARG_brs_baudrate, ARG_brs_sample_point };
|
ARG_brs_prescaler, ARG_brs_sjw, ARG_brs_bs1, ARG_brs_bs2, ARG_brs_baudrate, ARG_brs_sample_point };
|
||||||
static const mp_arg_t allowed_args[] = {
|
static const mp_arg_t allowed_args[] = {
|
||||||
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} },
|
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} },
|
||||||
{ MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} },
|
|
||||||
{ MP_QSTR_prescaler, MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} },
|
{ MP_QSTR_prescaler, MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} },
|
||||||
{ MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} },
|
{ MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} },
|
||||||
{ MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} },
|
{ MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} },
|
||||||
|
@ -228,8 +226,6 @@ STATIC mp_obj_t pyb_can_init_helper(pyb_can_obj_t *self, size_t n_args, const mp
|
||||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||||
|
|
||||||
self->extframe = args[ARG_extframe].u_bool;
|
|
||||||
|
|
||||||
// set the CAN configuration values
|
// set the CAN configuration values
|
||||||
memset(&self->can, 0, sizeof(self->can));
|
memset(&self->can, 0, sizeof(self->can));
|
||||||
|
|
||||||
|
@ -475,15 +471,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_any_obj, pyb_can_any);
|
||||||
|
|
||||||
// send(send, addr, *, timeout=5000)
|
// send(send, addr, *, timeout=5000)
|
||||||
STATIC mp_obj_t pyb_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
STATIC mp_obj_t pyb_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||||
enum { ARG_data, ARG_id, ARG_timeout, ARG_rtr, ARG_fdf, ARG_brs };
|
enum { ARG_data, ARG_id, ARG_timeout, ARG_rtr, ARG_extframe, ARG_fdf, ARG_brs };
|
||||||
static const mp_arg_t allowed_args[] = {
|
static const mp_arg_t allowed_args[] = {
|
||||||
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||||
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||||
{ MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
{ MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||||
|
{ MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} },
|
||||||
#if MICROPY_HW_ENABLE_FDCAN
|
#if MICROPY_HW_ENABLE_FDCAN
|
||||||
{ MP_QSTR_fdf, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
{ MP_QSTR_fdf, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||||
{ MP_QSTR_brs, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
{ MP_QSTR_brs, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -512,7 +509,7 @@ STATIC mp_obj_t pyb_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
|
||||||
tx_msg.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
|
tx_msg.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
|
||||||
tx_msg.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
|
tx_msg.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
|
||||||
|
|
||||||
if (self->extframe) {
|
if (args[ARG_extframe].u_bool == true) {
|
||||||
tx_msg.Identifier = args[ARG_id].u_int & 0x1FFFFFFF;
|
tx_msg.Identifier = args[ARG_id].u_int & 0x1FFFFFFF;
|
||||||
tx_msg.IdType = FDCAN_EXTENDED_ID;
|
tx_msg.IdType = FDCAN_EXTENDED_ID;
|
||||||
} else {
|
} else {
|
||||||
|
@ -545,7 +542,7 @@ STATIC mp_obj_t pyb_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
|
||||||
tx_msg.DLC = bufinfo.len;
|
tx_msg.DLC = bufinfo.len;
|
||||||
uint8_t *tx_data = tx_msg.Data; // Data is uint32_t but holds only 1 byte
|
uint8_t *tx_data = tx_msg.Data; // Data is uint32_t but holds only 1 byte
|
||||||
|
|
||||||
if (self->extframe) {
|
if (args[ARG_extframe].u_bool == true) {
|
||||||
tx_msg.ExtId = args[ARG_id].u_int & 0x1FFFFFFF;
|
tx_msg.ExtId = args[ARG_id].u_int & 0x1FFFFFFF;
|
||||||
tx_msg.IDE = CAN_ID_EXT;
|
tx_msg.IDE = CAN_ID_EXT;
|
||||||
} else {
|
} else {
|
||||||
|
@ -739,11 +736,20 @@ STATIC mp_obj_t pyb_can_initfilterbanks(mp_obj_t self_in, mp_obj_t bank_in) {
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_initfilterbanks_fun_obj, pyb_can_initfilterbanks);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_initfilterbanks_fun_obj, pyb_can_initfilterbanks);
|
||||||
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pyb_can_initfilterbanks_obj, MP_ROM_PTR(&pyb_can_initfilterbanks_fun_obj));
|
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pyb_can_initfilterbanks_obj, MP_ROM_PTR(&pyb_can_initfilterbanks_fun_obj));
|
||||||
|
|
||||||
STATIC mp_obj_t pyb_can_clearfilter(mp_obj_t self_in, mp_obj_t bank_in) {
|
STATIC mp_obj_t pyb_can_clearfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||||
pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
enum { ARG_extframe };
|
||||||
mp_int_t f = mp_obj_get_int(bank_in);
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{ MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} },
|
||||||
|
};
|
||||||
|
|
||||||
|
// parse args
|
||||||
|
pyb_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||||
|
mp_int_t f = mp_obj_get_int(pos_args[1]);
|
||||||
|
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||||
|
mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||||
|
|
||||||
#if MICROPY_HW_ENABLE_FDCAN
|
#if MICROPY_HW_ENABLE_FDCAN
|
||||||
can_clearfilter(self, f, self->extframe);
|
can_clearfilter(self, f, args[ARG_extframe].u_bool);
|
||||||
#else
|
#else
|
||||||
if (self->can_id == 2) {
|
if (self->can_id == 2) {
|
||||||
f += can2_start_bank;
|
f += can2_start_bank;
|
||||||
|
@ -752,18 +758,19 @@ STATIC mp_obj_t pyb_can_clearfilter(mp_obj_t self_in, mp_obj_t bank_in) {
|
||||||
#endif
|
#endif
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_clearfilter_obj, pyb_can_clearfilter);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_can_clearfilter_obj, 2, pyb_can_clearfilter);
|
||||||
|
|
||||||
// setfilter(bank, mode, fifo, params, *, rtr)
|
// setfilter(bank, mode, fifo, params, *, rtr)
|
||||||
#define EXTENDED_ID_TO_16BIT_FILTER(id) (((id & 0xC00000) >> 13) | ((id & 0x38000) >> 15)) | 8
|
#define EXTENDED_ID_TO_16BIT_FILTER(id) (((id & 0xC00000) >> 13) | ((id & 0x38000) >> 15)) | 8
|
||||||
STATIC mp_obj_t pyb_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
STATIC mp_obj_t pyb_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||||
enum { ARG_bank, ARG_mode, ARG_fifo, ARG_params, ARG_rtr };
|
enum { ARG_bank, ARG_mode, ARG_fifo, ARG_params, ARG_rtr, ARG_extframe };
|
||||||
static const mp_arg_t allowed_args[] = {
|
static const mp_arg_t allowed_args[] = {
|
||||||
{ MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
{ MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||||
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||||
{ MP_QSTR_fifo, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_FILTER_FIFO0} },
|
{ MP_QSTR_fifo, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_FILTER_FIFO0} },
|
||||||
{ MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
{ MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||||
{ MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
{ MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||||
|
{ MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} },
|
||||||
};
|
};
|
||||||
|
|
||||||
// parse args
|
// parse args
|
||||||
|
@ -773,7 +780,7 @@ STATIC mp_obj_t pyb_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_ma
|
||||||
|
|
||||||
#if MICROPY_HW_ENABLE_FDCAN
|
#if MICROPY_HW_ENABLE_FDCAN
|
||||||
FDCAN_FilterTypeDef filter = {0};
|
FDCAN_FilterTypeDef filter = {0};
|
||||||
if (self->extframe) {
|
if (args[ARG_extframe].u_bool == true) {
|
||||||
filter.IdType = FDCAN_EXTENDED_ID;
|
filter.IdType = FDCAN_EXTENDED_ID;
|
||||||
} else {
|
} else {
|
||||||
filter.IdType = FDCAN_STANDARD_ID;
|
filter.IdType = FDCAN_STANDARD_ID;
|
||||||
|
@ -831,7 +838,7 @@ STATIC mp_obj_t pyb_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_ma
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
filter.FilterScale = CAN_FILTERSCALE_16BIT;
|
filter.FilterScale = CAN_FILTERSCALE_16BIT;
|
||||||
if (self->extframe) {
|
if (args[ARG_extframe].u_bool == true) {
|
||||||
if (args[ARG_rtr].u_obj != MP_OBJ_NULL) {
|
if (args[ARG_rtr].u_obj != MP_OBJ_NULL) {
|
||||||
if (args[ARG_mode].u_int == MASK16) {
|
if (args[ARG_mode].u_int == MASK16) {
|
||||||
rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x02 : 0;
|
rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x02 : 0;
|
||||||
|
|
Loading…
Reference in New Issue