Browse Source

stm32/can: Add CAN.info() method to retrieve error and tx/rx buf info.

pull/3663/head
Damien George 7 years ago
parent
commit
a25e6c6b65
  1. 22
      docs/library/pyb.CAN.rst
  2. 62
      ports/stm32/can.c
  3. 1
      ports/stm32/can.h
  4. 12
      ports/stm32/stm32_it.c

22
docs/library/pyb.CAN.rst

@ -113,6 +113,28 @@ Methods
- ``CAN.BUS_OFF`` -- the controller is on but not participating in bus activity
(TEC overflowed beyond 255).
.. method:: CAN.info([list])
Get information about the controller's error states and TX and RX buffers.
If *list* is provided then it should be a list object with at least 8 entries,
which will be filled in with the information. Otherwise a new list will be
created and filled in. In both cases the return value of the method is the
populated list.
The values in the list are:
- TEC value
- REC value
- number of times the controller enterted the Error Warning state (wrapped
around to 0 after 65535)
- number of times the controller enterted the Error Passive state (wrapped
around to 0 after 65535)
- number of times the controller enterted the Bus Off state (wrapped
around to 0 after 65535)
- number of pending TX messages
- number of pending RX messages on fifo 0
- number of pending RX messages on fifo 1
.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr)
Configure a filter bank:

62
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?

1
ports/stm32/can.h

@ -34,5 +34,6 @@ extern const mp_obj_type_t pyb_can_type;
void can_init0(void);
void can_deinit(void);
void can_rx_irq_handler(uint can_id, uint fifo_id);
void can_sce_irq_handler(uint can_id);
#endif // MICROPY_INCLUDED_STM32_CAN_H

12
ports/stm32/stm32_it.c

@ -749,6 +749,12 @@ void CAN1_RX1_IRQHandler(void) {
IRQ_EXIT(CAN1_RX1_IRQn);
}
void CAN1_SCE_IRQHandler(void) {
IRQ_ENTER(CAN1_SCE_IRQn);
can_sce_irq_handler(PYB_CAN_1);
IRQ_EXIT(CAN1_SCE_IRQn);
}
void CAN2_RX0_IRQHandler(void) {
IRQ_ENTER(CAN2_RX0_IRQn);
can_rx_irq_handler(PYB_CAN_2, CAN_FIFO0);
@ -760,6 +766,12 @@ void CAN2_RX1_IRQHandler(void) {
can_rx_irq_handler(PYB_CAN_2, CAN_FIFO1);
IRQ_EXIT(CAN2_RX1_IRQn);
}
void CAN2_SCE_IRQHandler(void) {
IRQ_ENTER(CAN2_SCE_IRQn);
can_sce_irq_handler(PYB_CAN_2);
IRQ_EXIT(CAN2_SCE_IRQn);
}
#endif // MICROPY_HW_ENABLE_CAN
#if defined(MICROPY_HW_I2C1_SCL)

Loading…
Cancel
Save