drivers: can: stm32: abort transfers after entering init mode
Abort any pending transmissions after entering init mode and notify the senders. Fixes: #50545 Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
parent
6cf34d0d33
commit
f239c3d0e9
2 changed files with 33 additions and 24 deletions
|
@ -54,9 +54,15 @@ LOG_MODULE_REGISTER(can_stm32, CONFIG_CAN_LOG_LEVEL);
|
||||||
*/
|
*/
|
||||||
static struct k_mutex filter_mutex;
|
static struct k_mutex filter_mutex;
|
||||||
|
|
||||||
static void can_stm32_signal_tx_complete(const struct device *dev, struct can_stm32_mailbox *mb)
|
static void can_stm32_signal_tx_complete(const struct device *dev, struct can_stm32_mailbox *mb,
|
||||||
|
int status)
|
||||||
{
|
{
|
||||||
mb->tx_callback(dev, mb->error, mb->callback_arg);
|
can_tx_callback_t callback = mb->tx_callback;
|
||||||
|
|
||||||
|
if (callback != NULL) {
|
||||||
|
callback(dev, status, mb->callback_arg);
|
||||||
|
mb->tx_callback = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void can_stm32_rx_fifo_pop(CAN_FIFOMailBox_TypeDef *mbox, struct can_frame *frame)
|
static void can_stm32_rx_fifo_pop(CAN_FIFOMailBox_TypeDef *mbox, struct can_frame *frame)
|
||||||
|
@ -206,43 +212,41 @@ static inline void can_stm32_tx_isr_handler(const struct device *dev)
|
||||||
const struct can_stm32_config *cfg = dev->config;
|
const struct can_stm32_config *cfg = dev->config;
|
||||||
CAN_TypeDef *can = cfg->can;
|
CAN_TypeDef *can = cfg->can;
|
||||||
uint32_t bus_off;
|
uint32_t bus_off;
|
||||||
|
int status;
|
||||||
|
|
||||||
bus_off = can->ESR & CAN_ESR_BOFF;
|
bus_off = can->ESR & CAN_ESR_BOFF;
|
||||||
|
|
||||||
if ((can->TSR & CAN_TSR_RQCP0) | bus_off) {
|
if ((can->TSR & CAN_TSR_RQCP0) | bus_off) {
|
||||||
data->mb0.error =
|
status = can->TSR & CAN_TSR_TXOK0 ? 0 :
|
||||||
can->TSR & CAN_TSR_TXOK0 ? 0 :
|
|
||||||
can->TSR & CAN_TSR_TERR0 ? -EIO :
|
can->TSR & CAN_TSR_TERR0 ? -EIO :
|
||||||
can->TSR & CAN_TSR_ALST0 ? -EBUSY :
|
can->TSR & CAN_TSR_ALST0 ? -EBUSY :
|
||||||
bus_off ? -ENETUNREACH :
|
bus_off ? -ENETUNREACH :
|
||||||
-EIO;
|
-EIO;
|
||||||
/* clear the request. */
|
/* clear the request. */
|
||||||
can->TSR |= CAN_TSR_RQCP0;
|
can->TSR |= CAN_TSR_RQCP0;
|
||||||
can_stm32_signal_tx_complete(dev, &data->mb0);
|
can_stm32_signal_tx_complete(dev, &data->mb0, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((can->TSR & CAN_TSR_RQCP1) | bus_off) {
|
if ((can->TSR & CAN_TSR_RQCP1) | bus_off) {
|
||||||
data->mb1.error =
|
status = can->TSR & CAN_TSR_TXOK1 ? 0 :
|
||||||
can->TSR & CAN_TSR_TXOK1 ? 0 :
|
|
||||||
can->TSR & CAN_TSR_TERR1 ? -EIO :
|
can->TSR & CAN_TSR_TERR1 ? -EIO :
|
||||||
can->TSR & CAN_TSR_ALST1 ? -EBUSY :
|
can->TSR & CAN_TSR_ALST1 ? -EBUSY :
|
||||||
bus_off ? -ENETUNREACH :
|
bus_off ? -ENETUNREACH :
|
||||||
-EIO;
|
-EIO;
|
||||||
/* clear the request. */
|
/* clear the request. */
|
||||||
can->TSR |= CAN_TSR_RQCP1;
|
can->TSR |= CAN_TSR_RQCP1;
|
||||||
can_stm32_signal_tx_complete(dev, &data->mb1);
|
can_stm32_signal_tx_complete(dev, &data->mb1, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((can->TSR & CAN_TSR_RQCP2) | bus_off) {
|
if ((can->TSR & CAN_TSR_RQCP2) | bus_off) {
|
||||||
data->mb2.error =
|
status = can->TSR & CAN_TSR_TXOK2 ? 0 :
|
||||||
can->TSR & CAN_TSR_TXOK2 ? 0 :
|
|
||||||
can->TSR & CAN_TSR_TERR2 ? -EIO :
|
can->TSR & CAN_TSR_TERR2 ? -EIO :
|
||||||
can->TSR & CAN_TSR_ALST2 ? -EBUSY :
|
can->TSR & CAN_TSR_ALST2 ? -EBUSY :
|
||||||
bus_off ? -ENETUNREACH :
|
bus_off ? -ENETUNREACH :
|
||||||
-EIO;
|
-EIO;
|
||||||
/* clear the request. */
|
/* clear the request. */
|
||||||
can->TSR |= CAN_TSR_RQCP2;
|
can->TSR |= CAN_TSR_RQCP2;
|
||||||
can_stm32_signal_tx_complete(dev, &data->mb2);
|
can_stm32_signal_tx_complete(dev, &data->mb2, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (can->TSR & CAN_TSR_TME) {
|
if (can->TSR & CAN_TSR_TME) {
|
||||||
|
@ -415,6 +419,12 @@ static int can_stm32_stop(const struct device *dev)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Abort any pending transmissions */
|
||||||
|
can_stm32_signal_tx_complete(dev, &data->mb0, -ENETDOWN);
|
||||||
|
can_stm32_signal_tx_complete(dev, &data->mb1, -ENETDOWN);
|
||||||
|
can_stm32_signal_tx_complete(dev, &data->mb2, -ENETDOWN);
|
||||||
|
can->TSR |= CAN_TSR_ABRQ2 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ0;
|
||||||
|
|
||||||
if (cfg->phy != NULL) {
|
if (cfg->phy != NULL) {
|
||||||
ret = can_transceiver_disable(cfg->phy);
|
ret = can_transceiver_disable(cfg->phy);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
struct can_stm32_mailbox {
|
struct can_stm32_mailbox {
|
||||||
can_tx_callback_t tx_callback;
|
can_tx_callback_t tx_callback;
|
||||||
void *callback_arg;
|
void *callback_arg;
|
||||||
int error;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct can_stm32_data {
|
struct can_stm32_data {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue