summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2018-03-15 17:29:30 +1100
committerDamien George <damien.p.george@gmail.com>2018-03-15 17:29:30 +1100
commit1272c3c65d895e4694e0c707a98a739706667d23 (patch)
tree1967c0a44dab1177bdc8291a3520a625d4d6445b
parent823ca03008908d98671393c00b018349d18b46a2 (diff)
stm32/can: Add CAN.restart() method so controller can leave bus-off.
-rw-r--r--docs/library/pyb.CAN.rst14
-rw-r--r--ports/stm32/can.c18
2 files changed, 31 insertions, 1 deletions
diff --git a/docs/library/pyb.CAN.rst b/docs/library/pyb.CAN.rst
index 6e5b958cf..f90e7a8a7 100644
--- a/docs/library/pyb.CAN.rst
+++ b/docs/library/pyb.CAN.rst
@@ -65,7 +65,8 @@ Methods
- *bs2* defines the location of the transmit point in units of the time quanta;
it can be between 1 and 16 inclusive
- *auto_restart* sets whether the controller will automatically try and restart
- communications after entering the bus-off state
+ communications after entering the bus-off state; if this is disabled then
+ :meth:`~CAN.restart()` can be used to leave the bus-off state
The time quanta tq is the basic unit of time for the CAN bus. tq is the CAN
prescaler value divided by PCLK1 (the frequency of internal peripheral bus 1);
@@ -87,6 +88,17 @@ Methods
Turn off the CAN bus.
+.. method:: CAN.restart()
+
+ Force a software restart of the CAN controller without resetting its
+ configuration.
+
+ If the controller enters the bus-off state then it will no longer participate
+ in bus activity. If the controller is not configured to automatically restart
+ (see :meth:`~CAN.init()`) then this method can be used to trigger a restart,
+ and the controller will follow the CAN protocol to leave the bus-off state and
+ go into the error active state.
+
.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr)
Configure a filter bank:
diff --git a/ports/stm32/can.c b/ports/stm32/can.c
index fc0fa98a8..d5702f6d1 100644
--- a/ports/stm32/can.c
+++ b/ports/stm32/can.c
@@ -467,6 +467,23 @@ STATIC mp_obj_t pyb_can_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_can_deinit_obj, pyb_can_deinit);
+// Force a software restart of the controller, to allow transmission after a bus error
+STATIC mp_obj_t pyb_can_restart(mp_obj_t self_in) {
+ pyb_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (!self->is_enabled) {
+ mp_raise_ValueError(NULL);
+ }
+ CAN_TypeDef *can = self->can.Instance;
+ can->MCR |= CAN_MCR_INRQ;
+ while ((can->MSR & CAN_MSR_INAK) == 0) {
+ }
+ can->MCR &= ~CAN_MCR_INRQ;
+ while ((can->MSR & CAN_MSR_INAK)) {
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_can_restart_obj, pyb_can_restart);
+
/// \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) {
@@ -824,6 +841,7 @@ STATIC const mp_rom_map_elem_t pyb_can_locals_dict_table[] = {
// instance methods
{ 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_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) },