Skip to content

Commit acb92c1

Browse files
HenrikSolverdpgeorge
authored andcommitted
Adding CAN filter management
1 parent 20d239c commit acb92c1

3 files changed

Lines changed: 173 additions & 17 deletions

File tree

stmhal/can.c

Lines changed: 152 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@
4343

4444
#if MICROPY_HW_ENABLE_CAN
4545

46+
#define MASK16 (0)
47+
#define LIST16 (1)
48+
#define MASK32 (2)
49+
#define LIST32 (3)
50+
4651
/// \moduleref pyb
4752
/// \class CAN - controller area network communication bus
4853
///
@@ -71,6 +76,8 @@ typedef struct _pyb_can_obj_t {
7176
CAN_HandleTypeDef can;
7277
} pyb_can_obj_t;
7378

79+
STATIC uint8_t can2_start_bank = 14;
80+
7481
// assumes Init parameters have been set up correctly
7582
STATIC bool can_init(pyb_can_obj_t *can_obj) {
7683
CAN_TypeDef *CANx = NULL;
@@ -136,6 +143,23 @@ STATIC void can_deinit(pyb_can_obj_t *can_obj) {
136143
}
137144
}
138145

146+
STATIC void can_clearfilter(uint32_t f) {
147+
CAN_FilterConfTypeDef filter;
148+
149+
filter.FilterIdHigh = 0;
150+
filter.FilterIdLow = 0;
151+
filter.FilterMaskIdHigh = 0;
152+
filter.FilterMaskIdLow = 0;
153+
filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
154+
filter.FilterNumber = f;
155+
filter.FilterMode = CAN_FILTERMODE_IDMASK;
156+
filter.FilterScale = CAN_FILTERSCALE_16BIT;
157+
filter.FilterActivation = DISABLE;
158+
filter.BankNumber = can2_start_bank;
159+
160+
HAL_CAN_ConfigFilter(NULL, &filter);
161+
}
162+
139163
/******************************************************************************/
140164
// Micro Python bindings
141165

@@ -199,20 +223,6 @@ STATIC mp_obj_t pyb_can_init_helper(pyb_can_obj_t *self, mp_uint_t n_args, const
199223
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN port %d does not exist", self->can_id));
200224
}
201225

202-
// set CAN filter to accept everything
203-
CAN_FilterConfTypeDef filter;
204-
filter.FilterIdHigh = 0;
205-
filter.FilterIdLow = 0;
206-
filter.FilterMaskIdHigh = 0;
207-
filter.FilterMaskIdLow = 0;
208-
filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
209-
filter.FilterNumber = 0; // 0-27
210-
filter.FilterMode = CAN_FILTERMODE_IDMASK;
211-
filter.FilterScale = CAN_FILTERSCALE_32BIT;
212-
filter.FilterActivation = ENABLE;
213-
filter.BankNumber = 0; // what's this for?
214-
HAL_CAN_ConfigFilter(&self->can, &filter);
215-
216226
return mp_const_none;
217227
}
218228

@@ -399,13 +409,136 @@ STATIC mp_obj_t pyb_can_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
399409
}
400410
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_can_recv_obj, 1, pyb_can_recv);
401411

412+
/// \class method initfilterbanks
413+
///
414+
/// Set up the filterbanks. All filter will be disabled and set to their reset states.
415+
///
416+
/// - `banks` is an integer that sets how many filter banks that are reserved for CAN1.
417+
/// 0 -> no filters assigned for CAN1
418+
/// 28 -> all filters are assigned to CAN1
419+
/// CAN2 will get the rest of the 28 available.
420+
///
421+
/// Return value: none.
422+
STATIC mp_obj_t pyb_can_initfilterbanks(mp_obj_t self, mp_obj_t bank_in) {
423+
can2_start_bank = mp_obj_get_int(bank_in);
424+
425+
for (int f = 0; f < 28; f++) {
426+
can_clearfilter(f);
427+
}
428+
429+
return mp_const_none;
430+
}
431+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_initfilterbanks_fun_obj, pyb_can_initfilterbanks);
432+
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pyb_can_initfilterbanks_obj, (const mp_obj_t)&pyb_can_initfilterbanks_fun_obj);
433+
434+
STATIC mp_obj_t pyb_can_clearfilter(mp_obj_t self_in, mp_obj_t bank_in) {
435+
pyb_can_obj_t *self = self_in;
436+
mp_int_t f = mp_obj_get_int(bank_in);
437+
if (self->can_id == 2) {
438+
f += can2_start_bank;
439+
}
440+
can_clearfilter(f);
441+
return mp_const_none;
442+
}
443+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_clearfilter_obj, pyb_can_clearfilter);
444+
445+
/// Configures a filterbank
446+
/// Return value: `None`.
447+
#define EXTENDED_ID_TO_16BIT_FILTER(id) (((id & 0xC00000) >> 13) | ((id & 0x38000) >> 15)) | 8
448+
STATIC mp_obj_t pyb_can_setfilter(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
449+
static const mp_arg_t allowed_args[] = {
450+
{ MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
451+
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
452+
{ MP_QSTR_fifo, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_FILTER_FIFO0} },
453+
{ MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
454+
};
455+
456+
// parse args
457+
pyb_can_obj_t *self = pos_args[0];
458+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
459+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
460+
461+
mp_uint_t len;
462+
mp_obj_t *params;
463+
mp_obj_get_array(args[3].u_obj, &len, &params);
464+
465+
CAN_FilterConfTypeDef filter;
466+
if (args[1].u_int == MASK16 || args[1].u_int == LIST16) {
467+
if (len != 4) {
468+
goto error;
469+
}
470+
filter.FilterScale = CAN_FILTERSCALE_16BIT;
471+
if (self->extframe) {
472+
filter.FilterIdLow = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[0])); // id1
473+
filter.FilterMaskIdLow = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[1])); // mask1
474+
filter.FilterIdHigh = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[2])); // id2
475+
filter.FilterMaskIdHigh = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[3])); // mask2
476+
} else {
477+
filter.FilterIdLow = mp_obj_get_int(params[0]) << 5; // id1
478+
filter.FilterMaskIdLow = mp_obj_get_int(params[1]) << 5; // mask1
479+
filter.FilterIdHigh = mp_obj_get_int(params[2]) << 5; // id2
480+
filter.FilterMaskIdHigh = mp_obj_get_int(params[3]) << 5; // mask2
481+
}
482+
if (args[1].u_int == MASK16) {
483+
filter.FilterMode = CAN_FILTERMODE_IDMASK;
484+
}
485+
if (args[1].u_int == LIST16) {
486+
filter.FilterMode = CAN_FILTERMODE_IDLIST;
487+
}
488+
}
489+
else if (args[1].u_int == MASK32 || args[1].u_int == LIST32) {
490+
if (len != 2) {
491+
goto error;
492+
}
493+
filter.FilterScale = CAN_FILTERSCALE_32BIT;
494+
495+
filter.FilterIdHigh = (mp_obj_get_int(params[0]) & 0xFF00) >> 13;
496+
filter.FilterIdLow = ((mp_obj_get_int(params[0]) & 0x00FF) << 3) | 4;
497+
filter.FilterMaskIdHigh = (mp_obj_get_int(params[1]) & 0xFF00 ) >> 13;
498+
filter.FilterMaskIdLow = ((mp_obj_get_int(params[1]) & 0x00FF) << 3) | 4;
499+
if (args[1].u_int == MASK32) {
500+
filter.FilterMode = CAN_FILTERMODE_IDMASK;
501+
}
502+
if (args[1].u_int == LIST32) {
503+
filter.FilterMode = CAN_FILTERMODE_IDLIST;
504+
}
505+
} else {
506+
goto error;
507+
}
508+
509+
filter.FilterFIFOAssignment = args[2].u_int; // fifo
510+
filter.FilterNumber = args[0].u_int; // bank
511+
if (self->can_id == 1) {
512+
if (filter.FilterNumber >= can2_start_bank) {
513+
goto error;
514+
}
515+
} else {
516+
filter.FilterNumber = filter.FilterNumber + can2_start_bank;
517+
if (filter.FilterNumber > 27) {
518+
goto error;
519+
}
520+
}
521+
filter.FilterActivation = ENABLE;
522+
filter.BankNumber = can2_start_bank;
523+
HAL_CAN_ConfigFilter(&self->can, &filter);
524+
525+
return mp_const_none;
526+
527+
error:
528+
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN filter parameter error"));
529+
}
530+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_can_setfilter_obj, 1, pyb_can_setfilter);
531+
402532
STATIC const mp_map_elem_t pyb_can_locals_dict_table[] = {
403533
// instance methods
404534
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_can_init_obj },
405535
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_can_deinit_obj },
406536
{ MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&pyb_can_any_obj },
407537
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_can_send_obj },
408538
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_can_recv_obj },
539+
{ MP_OBJ_NEW_QSTR(MP_QSTR_initfilterbanks), (mp_obj_t)&pyb_can_initfilterbanks_obj },
540+
{ MP_OBJ_NEW_QSTR(MP_QSTR_setfilter), (mp_obj_t)&pyb_can_setfilter_obj },
541+
{ MP_OBJ_NEW_QSTR(MP_QSTR_clearfilter), (mp_obj_t)&pyb_can_clearfilter_obj },
409542

410543
// class constants
411544
// 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[] = {
414547
{ MP_OBJ_NEW_QSTR(MP_QSTR_LOOPBACK), MP_OBJ_NEW_SMALL_INT(CAN_MODE_LOOPBACK >> 4) },
415548
{ MP_OBJ_NEW_QSTR(MP_QSTR_SILENT), MP_OBJ_NEW_SMALL_INT(CAN_MODE_SILENT >> 4) },
416549
{ MP_OBJ_NEW_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_OBJ_NEW_SMALL_INT(CAN_MODE_SILENT_LOOPBACK >> 4) },
550+
551+
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASK16), MP_OBJ_NEW_SMALL_INT(MASK16) },
552+
{ MP_OBJ_NEW_QSTR(MP_QSTR_LIST16), MP_OBJ_NEW_SMALL_INT(LIST16) },
553+
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASK32), MP_OBJ_NEW_SMALL_INT(MASK32) },
554+
{ MP_OBJ_NEW_QSTR(MP_QSTR_LIST32), MP_OBJ_NEW_SMALL_INT(LIST32) },
417555
};
418556

419557
STATIC MP_DEFINE_CONST_DICT(pyb_can_locals_dict, pyb_can_locals_dict_table);

stmhal/qstrdefsport.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ Q(RTS)
160160
Q(CTS)
161161

162162
// for CAN class
163+
#if MICROPY_HW_ENABLE_CAN
163164
Q(CAN)
164165
Q(prescaler)
165166
Q(init)
@@ -174,10 +175,20 @@ Q(extframe)
174175
Q(sjw)
175176
Q(bs1)
176177
Q(bs2)
178+
Q(bank)
179+
Q(params)
180+
Q(initfilterbanks)
181+
Q(clearfilter)
182+
Q(setfilter)
177183
Q(NORMAL)
178184
Q(LOOPBACK)
179185
Q(SILENT)
180186
Q(SILENT_LOOPBACK)
187+
Q(MASK16)
188+
Q(LIST16)
189+
Q(MASK32)
190+
Q(LIST32)
191+
#endif
181192

182193
// for Timer class
183194
Q(Timer)

tests/pyb/can.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
from pyb import CAN
22

3+
CAN.initfilterbanks(14)
34
can = CAN(1)
45
print(can)
56

67
can.init(CAN.LOOPBACK)
78
print(can)
89
print(can.any(0))
910

11+
# Catch all filter
12+
can.setfilter(0, CAN.MASK16, 0, (0, 0, 0, 0))
13+
1014
can.send('abcd', 123)
1115
print(can.any(0))
1216
print(can.recv(0))
@@ -17,7 +21,7 @@
1721
can.send('abcd', 0x7FF + 1)
1822
print(can.recv(0))
1923

20-
#Test too long message
24+
# Test too long message
2125
try:
2226
can.send('abcdefghi', 0x7FF)
2327
except ValueError:
@@ -27,14 +31,17 @@
2731

2832
del can
2933

30-
#Testing extended IDs
34+
# Testing extended IDs
3135
can = CAN(1, CAN.LOOPBACK, extframe = True)
36+
# Catch all filter
37+
can.setfilter(0, CAN.MASK32, 0, (0, 0))
38+
3239
print(can)
3340

3441
try:
3542
can.send('abcde', 0x7FF + 1)
3643
except ValueError:
37-
print('failed')
44+
print('failed')
3845
else:
3946
r = can.recv(0)
4047
if r[0] == 0x7FF+1 and r[3] == b'abcde':

0 commit comments

Comments
 (0)