stm32/can: Improve can.recv() so it checks for events, eg ctrl-C.

This patch provides a custom (and simple) function to receive data on the
CAN bus, instead of the HAL function.  This custom version calls
mp_handle_pending() while waiting for messages, which, among other things,
allows to interrupt the recv() method via KeyboardInterrupt.
pull/3663/head
Damien George 2018-03-15 16:34:07 +11:00
rodzic 22a9158ced
commit 2036196d71
1 zmienionych plików z 41 dodań i 6 usunięć

Wyświetl plik

@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Damien P. George
* Copyright (c) 2014-2018 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -172,6 +172,43 @@ STATIC void can_clearfilter(uint32_t f) {
HAL_CAN_ConfigFilter(NULL, &filter);
}
STATIC int can_receive(CAN_TypeDef *can, int fifo, CanRxMsgTypeDef *msg, uint32_t timeout_ms) {
volatile uint32_t *rfr;
if (fifo == CAN_FIFO0) {
rfr = &can->RF0R;
} else {
rfr = &can->RF1R;
}
// Wait for a message to become available, with timeout
uint32_t start = HAL_GetTick();
while ((*rfr & 3) == 0) {
MICROPY_EVENT_POLL_HOOK
if (HAL_GetTick() - start >= timeout_ms) {
return -MP_ETIMEDOUT;
}
}
// Read message data
CAN_FIFOMailBox_TypeDef *box = &can->sFIFOMailBox[fifo];
msg->IDE = box->RIR & 4;
if (msg->IDE == CAN_ID_STD) {
msg->StdId = box->RIR >> 21;
} else {
msg->ExtId = box->RIR >> 3;
}
msg->RTR = box->RIR & 2;
msg->DLC = box->RDTR & 0xf;
msg->FMI = box->RDTR >> 8 & 0xff;
*(uint32_t*)&msg->Data[0] = box->RDLR;
*(uint32_t*)&msg->Data[4] = box->RDHR;
// Release (free) message from FIFO
*rfr |= CAN_RF0R_RFOM0;
return 0; // success
}
// We have our own version of CAN transmit so we can handle Timeout=0 correctly.
STATIC HAL_StatusTypeDef CAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t Timeout) {
uint32_t transmitmailbox;
@ -530,11 +567,9 @@ STATIC mp_obj_t pyb_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
// receive the data
CanRxMsgTypeDef rx_msg;
self->can.pRxMsg = self->can.pRx1Msg = &rx_msg;
HAL_StatusTypeDef status = HAL_CAN_Receive(&self->can, args[0].u_int, args[1].u_int);
if (status != HAL_OK) {
mp_hal_raise(status);
int ret = can_receive(self->can.Instance, args[0].u_int, &rx_msg, args[1].u_int);
if (ret < 0) {
mp_raise_OSError(-ret);
}
// Manage the rx state machine