Skip to content

Commit a25e6c6

Browse files
committed
stm32/can: Add CAN.info() method to retrieve error and tx/rx buf info.
1 parent d7e67fb commit a25e6c6

4 files changed

Lines changed: 97 additions & 0 deletions

File tree

docs/library/pyb.CAN.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,28 @@ Methods
113113
- ``CAN.BUS_OFF`` -- the controller is on but not participating in bus activity
114114
(TEC overflowed beyond 255).
115115

116+
.. method:: CAN.info([list])
117+
118+
Get information about the controller's error states and TX and RX buffers.
119+
If *list* is provided then it should be a list object with at least 8 entries,
120+
which will be filled in with the information. Otherwise a new list will be
121+
created and filled in. In both cases the return value of the method is the
122+
populated list.
123+
124+
The values in the list are:
125+
126+
- TEC value
127+
- REC value
128+
- number of times the controller enterted the Error Warning state (wrapped
129+
around to 0 after 65535)
130+
- number of times the controller enterted the Error Passive state (wrapped
131+
around to 0 after 65535)
132+
- number of times the controller enterted the Bus Off state (wrapped
133+
around to 0 after 65535)
134+
- number of pending TX messages
135+
- number of pending RX messages on fifo 0
136+
- number of pending RX messages on fifo 1
137+
116138
.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr)
117139

118140
Configure a filter bank:

ports/stm32/can.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ typedef struct _pyb_can_obj_t {
8989
bool extframe : 1;
9090
byte rx_state0;
9191
byte rx_state1;
92+
uint16_t num_error_warning;
93+
uint16_t num_error_passive;
94+
uint16_t num_bus_off;
9295
CAN_HandleTypeDef can;
9396
} pyb_can_obj_t;
9497

@@ -103,6 +106,7 @@ STATIC bool can_init(pyb_can_obj_t *can_obj) {
103106
uint32_t GPIO_Pin = 0;
104107
uint8_t GPIO_AF_CANx = 0;
105108
GPIO_TypeDef* GPIO_Port = NULL;
109+
uint32_t sce_irq = 0;
106110

107111
switch (can_obj->can_id) {
108112
// CAN1 is on RX,TX = Y3,Y4 = PB9,PB9
@@ -111,6 +115,7 @@ STATIC bool can_init(pyb_can_obj_t *can_obj) {
111115
GPIO_AF_CANx = GPIO_AF9_CAN1;
112116
GPIO_Port = GPIOB;
113117
GPIO_Pin = GPIO_PIN_8 | GPIO_PIN_9;
118+
sce_irq = CAN1_SCE_IRQn;
114119
__CAN1_CLK_ENABLE();
115120
break;
116121

@@ -121,6 +126,7 @@ STATIC bool can_init(pyb_can_obj_t *can_obj) {
121126
GPIO_AF_CANx = GPIO_AF9_CAN2;
122127
GPIO_Port = GPIOB;
123128
GPIO_Pin = GPIO_PIN_12 | GPIO_PIN_13;
129+
sce_irq = CAN2_SCE_IRQn;
124130
__CAN1_CLK_ENABLE(); // CAN2 is a "slave" and needs CAN1 enabled as well
125131
__CAN2_CLK_ENABLE();
126132
break;
@@ -144,6 +150,14 @@ STATIC bool can_init(pyb_can_obj_t *can_obj) {
144150
HAL_CAN_Init(&can_obj->can);
145151

146152
can_obj->is_enabled = true;
153+
can_obj->num_error_warning = 0;
154+
can_obj->num_error_passive = 0;
155+
can_obj->num_bus_off = 0;
156+
157+
__HAL_CAN_ENABLE_IT(&can_obj->can, CAN_IT_ERR | CAN_IT_BOF | CAN_IT_EPV | CAN_IT_EWG);
158+
159+
HAL_NVIC_SetPriority(sce_irq, IRQ_PRI_CAN, IRQ_SUBPRI_CAN);
160+
HAL_NVIC_EnableIRQ(sce_irq);
147161

148162
return true;
149163
}
@@ -459,13 +473,15 @@ STATIC mp_obj_t pyb_can_deinit(mp_obj_t self_in) {
459473
if (self->can.Instance == CAN1) {
460474
HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn);
461475
HAL_NVIC_DisableIRQ(CAN1_RX1_IRQn);
476+
HAL_NVIC_DisableIRQ(CAN1_SCE_IRQn);
462477
__CAN1_FORCE_RESET();
463478
__CAN1_RELEASE_RESET();
464479
__CAN1_CLK_DISABLE();
465480
#if defined(CAN2)
466481
} else if (self->can.Instance == CAN2) {
467482
HAL_NVIC_DisableIRQ(CAN2_RX0_IRQn);
468483
HAL_NVIC_DisableIRQ(CAN2_RX1_IRQn);
484+
HAL_NVIC_DisableIRQ(CAN2_SCE_IRQn);
469485
__CAN2_FORCE_RESET();
470486
__CAN2_RELEASE_RESET();
471487
__CAN2_CLK_DISABLE();
@@ -512,6 +528,36 @@ STATIC mp_obj_t pyb_can_state(mp_obj_t self_in) {
512528
}
513529
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_can_state_obj, pyb_can_state);
514530

531+
// Get info about error states and TX/RX buffers
532+
STATIC mp_obj_t pyb_can_info(size_t n_args, const mp_obj_t *args) {
533+
pyb_can_obj_t *self = MP_OBJ_TO_PTR(args[0]);
534+
mp_obj_list_t *list;
535+
if (n_args == 1) {
536+
list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL));
537+
} else {
538+
if (!MP_OBJ_IS_TYPE(args[1], &mp_type_list)) {
539+
mp_raise_TypeError(NULL);
540+
}
541+
list = MP_OBJ_TO_PTR(args[1]);
542+
if (list->len < 8) {
543+
mp_raise_ValueError(NULL);
544+
}
545+
}
546+
CAN_TypeDef *can = self->can.Instance;
547+
uint32_t esr = can->ESR;
548+
list->items[0] = MP_OBJ_NEW_SMALL_INT(esr >> CAN_ESR_TEC_Pos & 0xff);
549+
list->items[1] = MP_OBJ_NEW_SMALL_INT(esr >> CAN_ESR_REC_Pos & 0xff);
550+
list->items[2] = MP_OBJ_NEW_SMALL_INT(self->num_error_warning);
551+
list->items[3] = MP_OBJ_NEW_SMALL_INT(self->num_error_passive);
552+
list->items[4] = MP_OBJ_NEW_SMALL_INT(self->num_bus_off);
553+
int n_tx_pending = 0x01121223 >> ((can->TSR >> CAN_TSR_TME_Pos & 7) << 2) & 0xf;
554+
list->items[5] = MP_OBJ_NEW_SMALL_INT(n_tx_pending);
555+
list->items[6] = MP_OBJ_NEW_SMALL_INT(can->RF0R >> CAN_RF0R_FMP0_Pos & 3);
556+
list->items[7] = MP_OBJ_NEW_SMALL_INT(can->RF1R >> CAN_RF1R_FMP1_Pos & 3);
557+
return MP_OBJ_FROM_PTR(list);
558+
}
559+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_can_info_obj, 1, 2, pyb_can_info);
560+
515561
/// \method any(fifo)
516562
/// Return `True` if any message waiting on the FIFO, else `False`.
517563
STATIC mp_obj_t pyb_can_any(mp_obj_t self_in, mp_obj_t fifo_in) {
@@ -871,6 +917,7 @@ STATIC const mp_rom_map_elem_t pyb_can_locals_dict_table[] = {
871917
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_can_deinit_obj) },
872918
{ MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&pyb_can_restart_obj) },
873919
{ MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&pyb_can_state_obj) },
920+
{ MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&pyb_can_info_obj) },
874921
{ MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_can_any_obj) },
875922
{ MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pyb_can_send_obj) },
876923
{ MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&pyb_can_recv_obj) },
@@ -979,6 +1026,21 @@ void can_rx_irq_handler(uint can_id, uint fifo_id) {
9791026
}
9801027
}
9811028

1029+
void can_sce_irq_handler(uint can_id) {
1030+
pyb_can_obj_t *self = MP_STATE_PORT(pyb_can_obj_all)[can_id - 1];
1031+
if (self) {
1032+
self->can.Instance->MSR = CAN_MSR_ERRI;
1033+
uint32_t esr = self->can.Instance->ESR;
1034+
if (esr & CAN_ESR_BOFF) {
1035+
++self->num_bus_off;
1036+
} else if (esr & CAN_ESR_EPVF) {
1037+
++self->num_error_passive;
1038+
} else if (esr & CAN_ESR_EWGF) {
1039+
++self->num_error_warning;
1040+
}
1041+
}
1042+
}
1043+
9821044
STATIC const mp_stream_p_t can_stream_p = {
9831045
//.read = can_read, // is read sensible for CAN?
9841046
//.write = can_write, // is write sensible for CAN?

ports/stm32/can.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@ extern const mp_obj_type_t pyb_can_type;
3434
void can_init0(void);
3535
void can_deinit(void);
3636
void can_rx_irq_handler(uint can_id, uint fifo_id);
37+
void can_sce_irq_handler(uint can_id);
3738

3839
#endif // MICROPY_INCLUDED_STM32_CAN_H

ports/stm32/stm32_it.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,12 @@ void CAN1_RX1_IRQHandler(void) {
749749
IRQ_EXIT(CAN1_RX1_IRQn);
750750
}
751751

752+
void CAN1_SCE_IRQHandler(void) {
753+
IRQ_ENTER(CAN1_SCE_IRQn);
754+
can_sce_irq_handler(PYB_CAN_1);
755+
IRQ_EXIT(CAN1_SCE_IRQn);
756+
}
757+
752758
void CAN2_RX0_IRQHandler(void) {
753759
IRQ_ENTER(CAN2_RX0_IRQn);
754760
can_rx_irq_handler(PYB_CAN_2, CAN_FIFO0);
@@ -760,6 +766,12 @@ void CAN2_RX1_IRQHandler(void) {
760766
can_rx_irq_handler(PYB_CAN_2, CAN_FIFO1);
761767
IRQ_EXIT(CAN2_RX1_IRQn);
762768
}
769+
770+
void CAN2_SCE_IRQHandler(void) {
771+
IRQ_ENTER(CAN2_SCE_IRQn);
772+
can_sce_irq_handler(PYB_CAN_2);
773+
IRQ_EXIT(CAN2_SCE_IRQn);
774+
}
763775
#endif // MICROPY_HW_ENABLE_CAN
764776

765777
#if defined(MICROPY_HW_I2C1_SCL)

0 commit comments

Comments
 (0)