diff options
Diffstat (limited to 'stmhal/can.c')
-rw-r--r-- | stmhal/can.c | 166 |
1 files changed, 152 insertions, 14 deletions
diff --git a/stmhal/can.c b/stmhal/can.c index 13b876c9f..118c4d8d9 100644 --- a/stmhal/can.c +++ b/stmhal/can.c @@ -43,6 +43,11 @@ #if MICROPY_HW_ENABLE_CAN +#define MASK16 (0) +#define LIST16 (1) +#define MASK32 (2) +#define LIST32 (3) + /// \moduleref pyb /// \class CAN - controller area network communication bus /// @@ -71,6 +76,8 @@ typedef struct _pyb_can_obj_t { CAN_HandleTypeDef can; } pyb_can_obj_t; +STATIC uint8_t can2_start_bank = 14; + // assumes Init parameters have been set up correctly STATIC bool can_init(pyb_can_obj_t *can_obj) { CAN_TypeDef *CANx = NULL; @@ -136,6 +143,23 @@ STATIC void can_deinit(pyb_can_obj_t *can_obj) { } } +STATIC void can_clearfilter(uint32_t f) { + CAN_FilterConfTypeDef filter; + + filter.FilterIdHigh = 0; + filter.FilterIdLow = 0; + filter.FilterMaskIdHigh = 0; + filter.FilterMaskIdLow = 0; + filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; + filter.FilterNumber = f; + filter.FilterMode = CAN_FILTERMODE_IDMASK; + filter.FilterScale = CAN_FILTERSCALE_16BIT; + filter.FilterActivation = DISABLE; + filter.BankNumber = can2_start_bank; + + HAL_CAN_ConfigFilter(NULL, &filter); +} + /******************************************************************************/ // Micro Python bindings @@ -199,20 +223,6 @@ STATIC mp_obj_t pyb_can_init_helper(pyb_can_obj_t *self, mp_uint_t n_args, const nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN port %d does not exist", self->can_id)); } - // set CAN filter to accept everything - CAN_FilterConfTypeDef filter; - filter.FilterIdHigh = 0; - filter.FilterIdLow = 0; - filter.FilterMaskIdHigh = 0; - filter.FilterMaskIdLow = 0; - filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; - filter.FilterNumber = 0; // 0-27 - filter.FilterMode = CAN_FILTERMODE_IDMASK; - filter.FilterScale = CAN_FILTERSCALE_32BIT; - filter.FilterActivation = ENABLE; - filter.BankNumber = 0; // what's this for? - HAL_CAN_ConfigFilter(&self->can, &filter); - return mp_const_none; } @@ -399,6 +409,126 @@ STATIC mp_obj_t pyb_can_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_ } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_can_recv_obj, 1, pyb_can_recv); +/// \class method initfilterbanks +/// +/// Set up the filterbanks. All filter will be disabled and set to their reset states. +/// +/// - `banks` is an integer that sets how many filter banks that are reserved for CAN1. +/// 0 -> no filters assigned for CAN1 +/// 28 -> all filters are assigned to CAN1 +/// CAN2 will get the rest of the 28 available. +/// +/// Return value: none. +STATIC mp_obj_t pyb_can_initfilterbanks(mp_obj_t self, mp_obj_t bank_in) { + can2_start_bank = mp_obj_get_int(bank_in); + + for (int f = 0; f < 28; f++) { + can_clearfilter(f); + } + + return mp_const_none; +} +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, (const mp_obj_t)&pyb_can_initfilterbanks_fun_obj); + +STATIC mp_obj_t pyb_can_clearfilter(mp_obj_t self_in, mp_obj_t bank_in) { + pyb_can_obj_t *self = self_in; + mp_int_t f = mp_obj_get_int(bank_in); + if (self->can_id == 2) { + f += can2_start_bank; + } + can_clearfilter(f); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_clearfilter_obj, pyb_can_clearfilter); + +/// Configures a filterbank +/// Return value: `None`. +#define EXTENDED_ID_TO_16BIT_FILTER(id) (((id & 0xC00000) >> 13) | ((id & 0x38000) >> 15)) | 8 +STATIC mp_obj_t pyb_can_setfilter(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + static const mp_arg_t allowed_args[] = { + { 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_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} }, + }; + + // parse args + pyb_can_obj_t *self = pos_args[0]; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_uint_t len; + mp_obj_t *params; + mp_obj_get_array(args[3].u_obj, &len, ¶ms); + + CAN_FilterConfTypeDef filter; + if (args[1].u_int == MASK16 || args[1].u_int == LIST16) { + if (len != 4) { + goto error; + } + filter.FilterScale = CAN_FILTERSCALE_16BIT; + if (self->extframe) { + filter.FilterIdLow = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[0])); // id1 + filter.FilterMaskIdLow = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[1])); // mask1 + filter.FilterIdHigh = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[2])); // id2 + filter.FilterMaskIdHigh = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[3])); // mask2 + } else { + filter.FilterIdLow = mp_obj_get_int(params[0]) << 5; // id1 + filter.FilterMaskIdLow = mp_obj_get_int(params[1]) << 5; // mask1 + filter.FilterIdHigh = mp_obj_get_int(params[2]) << 5; // id2 + filter.FilterMaskIdHigh = mp_obj_get_int(params[3]) << 5; // mask2 + } + if (args[1].u_int == MASK16) { + filter.FilterMode = CAN_FILTERMODE_IDMASK; + } + if (args[1].u_int == LIST16) { + filter.FilterMode = CAN_FILTERMODE_IDLIST; + } + } + else if (args[1].u_int == MASK32 || args[1].u_int == LIST32) { + if (len != 2) { + goto error; + } + filter.FilterScale = CAN_FILTERSCALE_32BIT; + + filter.FilterIdHigh = (mp_obj_get_int(params[0]) & 0xFF00) >> 13; + filter.FilterIdLow = ((mp_obj_get_int(params[0]) & 0x00FF) << 3) | 4; + filter.FilterMaskIdHigh = (mp_obj_get_int(params[1]) & 0xFF00 ) >> 13; + filter.FilterMaskIdLow = ((mp_obj_get_int(params[1]) & 0x00FF) << 3) | 4; + if (args[1].u_int == MASK32) { + filter.FilterMode = CAN_FILTERMODE_IDMASK; + } + if (args[1].u_int == LIST32) { + filter.FilterMode = CAN_FILTERMODE_IDLIST; + } + } else { + goto error; + } + + filter.FilterFIFOAssignment = args[2].u_int; // fifo + filter.FilterNumber = args[0].u_int; // bank + if (self->can_id == 1) { + if (filter.FilterNumber >= can2_start_bank) { + goto error; + } + } else { + filter.FilterNumber = filter.FilterNumber + can2_start_bank; + if (filter.FilterNumber > 27) { + goto error; + } + } + filter.FilterActivation = ENABLE; + filter.BankNumber = can2_start_bank; + HAL_CAN_ConfigFilter(&self->can, &filter); + + return mp_const_none; + +error: + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN filter parameter error")); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_can_setfilter_obj, 1, pyb_can_setfilter); + STATIC const mp_map_elem_t pyb_can_locals_dict_table[] = { // instance methods { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_can_init_obj }, @@ -406,6 +536,9 @@ STATIC const mp_map_elem_t pyb_can_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&pyb_can_any_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_can_send_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_can_recv_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_initfilterbanks), (mp_obj_t)&pyb_can_initfilterbanks_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_setfilter), (mp_obj_t)&pyb_can_setfilter_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_clearfilter), (mp_obj_t)&pyb_can_clearfilter_obj }, // class constants // Note: we use the ST constants >> 4 so they fit in a small-int. The @@ -414,6 +547,11 @@ STATIC const mp_map_elem_t pyb_can_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_LOOPBACK), MP_OBJ_NEW_SMALL_INT(CAN_MODE_LOOPBACK >> 4) }, { MP_OBJ_NEW_QSTR(MP_QSTR_SILENT), MP_OBJ_NEW_SMALL_INT(CAN_MODE_SILENT >> 4) }, { MP_OBJ_NEW_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_OBJ_NEW_SMALL_INT(CAN_MODE_SILENT_LOOPBACK >> 4) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_MASK16), MP_OBJ_NEW_SMALL_INT(MASK16) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_LIST16), MP_OBJ_NEW_SMALL_INT(LIST16) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MASK32), MP_OBJ_NEW_SMALL_INT(MASK32) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_LIST32), MP_OBJ_NEW_SMALL_INT(LIST32) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_can_locals_dict, pyb_can_locals_dict_table); |