aboutsummaryrefslogtreecommitdiff
path: root/ports/stm32/can.c
diff options
context:
space:
mode:
Diffstat (limited to 'ports/stm32/can.c')
-rw-r--r--ports/stm32/can.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/ports/stm32/can.c b/ports/stm32/can.c
index 563d15dab..b1bcd1c3e 100644
--- a/ports/stm32/can.c
+++ b/ports/stm32/can.c
@@ -89,6 +89,9 @@ typedef struct _pyb_can_obj_t {
bool extframe : 1;
byte rx_state0;
byte rx_state1;
+ uint16_t num_error_warning;
+ uint16_t num_error_passive;
+ uint16_t num_bus_off;
CAN_HandleTypeDef can;
} pyb_can_obj_t;
@@ -103,6 +106,7 @@ STATIC bool can_init(pyb_can_obj_t *can_obj) {
uint32_t GPIO_Pin = 0;
uint8_t GPIO_AF_CANx = 0;
GPIO_TypeDef* GPIO_Port = NULL;
+ uint32_t sce_irq = 0;
switch (can_obj->can_id) {
// CAN1 is on RX,TX = Y3,Y4 = PB9,PB9
@@ -111,6 +115,7 @@ STATIC bool can_init(pyb_can_obj_t *can_obj) {
GPIO_AF_CANx = GPIO_AF9_CAN1;
GPIO_Port = GPIOB;
GPIO_Pin = GPIO_PIN_8 | GPIO_PIN_9;
+ sce_irq = CAN1_SCE_IRQn;
__CAN1_CLK_ENABLE();
break;
@@ -121,6 +126,7 @@ STATIC bool can_init(pyb_can_obj_t *can_obj) {
GPIO_AF_CANx = GPIO_AF9_CAN2;
GPIO_Port = GPIOB;
GPIO_Pin = GPIO_PIN_12 | GPIO_PIN_13;
+ sce_irq = CAN2_SCE_IRQn;
__CAN1_CLK_ENABLE(); // CAN2 is a "slave" and needs CAN1 enabled as well
__CAN2_CLK_ENABLE();
break;
@@ -144,6 +150,14 @@ STATIC bool can_init(pyb_can_obj_t *can_obj) {
HAL_CAN_Init(&can_obj->can);
can_obj->is_enabled = true;
+ can_obj->num_error_warning = 0;
+ can_obj->num_error_passive = 0;
+ can_obj->num_bus_off = 0;
+
+ __HAL_CAN_ENABLE_IT(&can_obj->can, CAN_IT_ERR | CAN_IT_BOF | CAN_IT_EPV | CAN_IT_EWG);
+
+ HAL_NVIC_SetPriority(sce_irq, IRQ_PRI_CAN, IRQ_SUBPRI_CAN);
+ HAL_NVIC_EnableIRQ(sce_irq);
return true;
}
@@ -459,6 +473,7 @@ STATIC mp_obj_t pyb_can_deinit(mp_obj_t self_in) {
if (self->can.Instance == CAN1) {
HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn);
HAL_NVIC_DisableIRQ(CAN1_RX1_IRQn);
+ HAL_NVIC_DisableIRQ(CAN1_SCE_IRQn);
__CAN1_FORCE_RESET();
__CAN1_RELEASE_RESET();
__CAN1_CLK_DISABLE();
@@ -466,6 +481,7 @@ STATIC mp_obj_t pyb_can_deinit(mp_obj_t self_in) {
} else if (self->can.Instance == CAN2) {
HAL_NVIC_DisableIRQ(CAN2_RX0_IRQn);
HAL_NVIC_DisableIRQ(CAN2_RX1_IRQn);
+ HAL_NVIC_DisableIRQ(CAN2_SCE_IRQn);
__CAN2_FORCE_RESET();
__CAN2_RELEASE_RESET();
__CAN2_CLK_DISABLE();
@@ -512,6 +528,36 @@ STATIC mp_obj_t pyb_can_state(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_can_state_obj, pyb_can_state);
+// Get info about error states and TX/RX buffers
+STATIC mp_obj_t pyb_can_info(size_t n_args, const mp_obj_t *args) {
+ pyb_can_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ mp_obj_list_t *list;
+ if (n_args == 1) {
+ list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL));
+ } else {
+ if (!MP_OBJ_IS_TYPE(args[1], &mp_type_list)) {
+ mp_raise_TypeError(NULL);
+ }
+ list = MP_OBJ_TO_PTR(args[1]);
+ if (list->len < 8) {
+ mp_raise_ValueError(NULL);
+ }
+ }
+ CAN_TypeDef *can = self->can.Instance;
+ uint32_t esr = can->ESR;
+ list->items[0] = MP_OBJ_NEW_SMALL_INT(esr >> CAN_ESR_TEC_Pos & 0xff);
+ list->items[1] = MP_OBJ_NEW_SMALL_INT(esr >> CAN_ESR_REC_Pos & 0xff);
+ list->items[2] = MP_OBJ_NEW_SMALL_INT(self->num_error_warning);
+ list->items[3] = MP_OBJ_NEW_SMALL_INT(self->num_error_passive);
+ list->items[4] = MP_OBJ_NEW_SMALL_INT(self->num_bus_off);
+ int n_tx_pending = 0x01121223 >> ((can->TSR >> CAN_TSR_TME_Pos & 7) << 2) & 0xf;
+ list->items[5] = MP_OBJ_NEW_SMALL_INT(n_tx_pending);
+ list->items[6] = MP_OBJ_NEW_SMALL_INT(can->RF0R >> CAN_RF0R_FMP0_Pos & 3);
+ list->items[7] = MP_OBJ_NEW_SMALL_INT(can->RF1R >> CAN_RF1R_FMP1_Pos & 3);
+ return MP_OBJ_FROM_PTR(list);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_can_info_obj, 1, 2, pyb_can_info);
+
/// \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) {
@@ -871,6 +917,7 @@ STATIC const mp_rom_map_elem_t pyb_can_locals_dict_table[] = {
{ 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_info), MP_ROM_PTR(&pyb_can_info_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) },
@@ -979,6 +1026,21 @@ void can_rx_irq_handler(uint can_id, uint fifo_id) {
}
}
+void can_sce_irq_handler(uint can_id) {
+ pyb_can_obj_t *self = MP_STATE_PORT(pyb_can_obj_all)[can_id - 1];
+ if (self) {
+ self->can.Instance->MSR = CAN_MSR_ERRI;
+ uint32_t esr = self->can.Instance->ESR;
+ if (esr & CAN_ESR_BOFF) {
+ ++self->num_bus_off;
+ } else if (esr & CAN_ESR_EPVF) {
+ ++self->num_error_passive;
+ } else if (esr & CAN_ESR_EWGF) {
+ ++self->num_error_warning;
+ }
+ }
+}
+
STATIC const mp_stream_p_t can_stream_p = {
//.read = can_read, // is read sensible for CAN?
//.write = can_write, // is write sensible for CAN?