diff --git a/docs/library/pyb.CAN.rst b/docs/library/pyb.CAN.rst index f90e7a8a7e..484a00f364 100644 --- a/docs/library/pyb.CAN.rst +++ b/docs/library/pyb.CAN.rst @@ -99,6 +99,20 @@ Methods and the controller will follow the CAN protocol to leave the bus-off state and go into the error active state. +.. method:: CAN.state() + + Return the state of the controller. The return value can be one of: + + - ``CAN.STOPPED`` -- the controller is completely off and reset; + - ``CAN.ERROR_ACTIVE`` -- the controller is on and in the Error Active state + (both TEC and REC are less than 96); + - ``CAN.ERROR_WARNING`` -- the controller is on and in the Error Warning state + (at least one of TEC or REC is 96 or greater); + - ``CAN.ERROR_PASSIVE`` -- the controller is on and in the Error Passive state + (at least one of TEC or REC is 128 or greater); + - ``CAN.BUS_OFF`` -- the controller is on but not participating in bus activity + (TEC overflowed beyond 255). + .. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) Configure a filter bank: @@ -229,6 +243,14 @@ Constants the mode of the CAN bus +.. data:: CAN.STOPPED + CAN.ERROR_ACTIVE + CAN.ERROR_WARNING + CAN.ERROR_PASSIVE + CAN.BUS_OFF + + Possible states of the CAN controller. + .. data:: CAN.LIST16 .. data:: CAN.MASK16 .. data:: CAN.LIST32 diff --git a/ports/stm32/can.c b/ports/stm32/can.c index d5702f6d1b..563d15dab3 100644 --- a/ports/stm32/can.c +++ b/ports/stm32/can.c @@ -45,6 +45,14 @@ #define MASK32 (2) #define LIST32 (3) +enum { + CAN_STATE_STOPPED, + CAN_STATE_ERROR_ACTIVE, + CAN_STATE_ERROR_WARNING, + CAN_STATE_ERROR_PASSIVE, + CAN_STATE_BUS_OFF, +}; + /// \moduleref pyb /// \class CAN - controller area network communication bus /// @@ -484,6 +492,26 @@ STATIC mp_obj_t pyb_can_restart(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_can_restart_obj, pyb_can_restart); +// Get the state of the controller +STATIC mp_obj_t pyb_can_state(mp_obj_t self_in) { + pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_int_t state = CAN_STATE_STOPPED; + if (self->is_enabled) { + CAN_TypeDef *can = self->can.Instance; + if (can->ESR & CAN_ESR_BOFF) { + state = CAN_STATE_BUS_OFF; + } else if (can->ESR & CAN_ESR_EPVF) { + state = CAN_STATE_ERROR_PASSIVE; + } else if (can->ESR & CAN_ESR_EWGF) { + state = CAN_STATE_ERROR_WARNING; + } else { + state = CAN_STATE_ERROR_ACTIVE; + } + } + return MP_OBJ_NEW_SMALL_INT(state); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_can_state_obj, pyb_can_state); + /// \method any(fifo) /// Return `True` if any message waiting on the FIFO, else `False`. STATIC mp_obj_t pyb_can_any(mp_obj_t self_in, mp_obj_t fifo_in) { @@ -842,6 +870,7 @@ STATIC const mp_rom_map_elem_t pyb_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_can_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_can_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&pyb_can_restart_obj) }, + { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&pyb_can_state_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_can_any_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pyb_can_send_obj) }, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&pyb_can_recv_obj) }, @@ -861,6 +890,13 @@ STATIC const mp_rom_map_elem_t pyb_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_LIST16), MP_ROM_INT(LIST16) }, { MP_ROM_QSTR(MP_QSTR_MASK32), MP_ROM_INT(MASK32) }, { MP_ROM_QSTR(MP_QSTR_LIST32), MP_ROM_INT(LIST32) }, + + // values for CAN.state() + { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, + { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_ERROR_ACTIVE) }, + { MP_ROM_QSTR(MP_QSTR_ERROR_WARNING), MP_ROM_INT(CAN_STATE_ERROR_WARNING) }, + { MP_ROM_QSTR(MP_QSTR_ERROR_PASSIVE), MP_ROM_INT(CAN_STATE_ERROR_PASSIVE) }, + { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_can_locals_dict, pyb_can_locals_dict_table);