From 3b94669b7f06fa7cf7a028ca43663d1dc75ce020 Mon Sep 17 00:00:00 2001 From: Peter van der Perk Date: Wed, 9 Jun 2021 17:14:40 +0200 Subject: [PATCH] FlexCAN Fix TX abort process --- arch/arm/src/imxrt/imxrt_flexcan.c | 19 +++++++++++++++++-- arch/arm/src/kinetis/kinetis_flexcan.c | 17 ++++++++++++++++- arch/arm/src/s32k1xx/s32k1xx_flexcan.c | 17 ++++++++++++++++- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/arch/arm/src/imxrt/imxrt_flexcan.c b/arch/arm/src/imxrt/imxrt_flexcan.c index dfd4e0b95f0..b2ef5dacda7 100644 --- a/arch/arm/src/imxrt/imxrt_flexcan.c +++ b/arch/arm/src/imxrt/imxrt_flexcan.c @@ -1006,10 +1006,13 @@ static void imxrt_txdone(FAR struct imxrt_driver_s *priv) NETDEV_TXDONE(&priv->dev); #ifdef TX_TIMEOUT_WQ /* We are here because a transmission completed, so the - * corresponding watchdog can be canceled. + * corresponding watchdog can be canceled + * mailbox be set to inactive */ - wd_cancel(priv->txtimeout[mbi]); + wd_cancel(&priv->txtimeout[mbi]); + struct mb_s *mb = &priv->tx[mbi]; + mb->cs.code = CAN_TXMB_INACTIVE; #endif } @@ -1129,7 +1132,9 @@ static int imxrt_flexcan_interrupt(int irq, FAR void *context, static void imxrt_txtimeout_work(FAR void *arg) { FAR struct imxrt_driver_s *priv = (FAR struct imxrt_driver_s *)arg; + uint32_t flags; uint32_t mbi; + uint32_t mb_bit; struct timespec ts; struct timeval *now = (struct timeval *)&ts; @@ -1140,6 +1145,8 @@ static void imxrt_txtimeout_work(FAR void *arg) * transmit function transmitted a new frame */ + flags = getreg32(priv->base + IMXRT_CAN_IFLAG1_OFFSET); + for (mbi = 0; mbi < TXMBCOUNT; mbi++) { if (priv->txmb[mbi].deadline.tv_sec != 0 @@ -1147,6 +1154,14 @@ static void imxrt_txtimeout_work(FAR void *arg) || now->tv_usec > priv->txmb[mbi].deadline.tv_usec)) { NETDEV_TXTIMEOUTS(&priv->dev); + + mb_bit = 1 << (RXMBCOUNT + mbi); + + if (flags & mb_bit) + { + putreg32(mb_bit, priv->base + IMXRT_CAN_IFLAG1_OFFSET); + } + struct mb_s *mb = &priv->tx[mbi]; mb->cs.code = CAN_TXMB_ABORT; priv->txmb[mbi].pending = TX_ABORT; diff --git a/arch/arm/src/kinetis/kinetis_flexcan.c b/arch/arm/src/kinetis/kinetis_flexcan.c index 3bf358027eb..9aacc05a87c 100644 --- a/arch/arm/src/kinetis/kinetis_flexcan.c +++ b/arch/arm/src/kinetis/kinetis_flexcan.c @@ -1005,10 +1005,13 @@ static void kinetis_txdone(FAR struct kinetis_driver_s *priv) NETDEV_TXDONE(&priv->dev); #ifdef TX_TIMEOUT_WQ /* We are here because a transmission completed, so the - * corresponding watchdog can be canceled. + * corresponding watchdog can be canceled + * mailbox be set to inactive */ wd_cancel(&priv->txtimeout[mbi]); + struct mb_s *mb = &priv->tx[mbi]; + mb->cs.code = CAN_TXMB_INACTIVE; #endif } @@ -1128,7 +1131,9 @@ static int kinetis_flexcan_interrupt(int irq, FAR void *context, static void kinetis_txtimeout_work(FAR void *arg) { FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg; + uint32_t flags; uint32_t mbi; + uint32_t mb_bit; struct timespec ts; struct timeval *now = (struct timeval *)&ts; @@ -1139,6 +1144,8 @@ static void kinetis_txtimeout_work(FAR void *arg) * transmit function transmitted a new frame */ + flags = getreg32(priv->base + KINETIS_CAN_IFLAG1_OFFSET); + for (mbi = 0; mbi < TXMBCOUNT; mbi++) { if (priv->txmb[mbi].deadline.tv_sec != 0 @@ -1146,6 +1153,14 @@ static void kinetis_txtimeout_work(FAR void *arg) || now->tv_usec > priv->txmb[mbi].deadline.tv_usec)) { NETDEV_TXTIMEOUTS(&priv->dev); + + mb_bit = 1 << (RXMBCOUNT + mbi); + + if (flags & mb_bit) + { + putreg32(mb_bit, priv->base + KINETIS_CAN_IFLAG1_OFFSET); + } + struct mb_s *mb = &priv->tx[mbi]; mb->cs.code = CAN_TXMB_ABORT; priv->txmb[mbi].pending = TX_ABORT; diff --git a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c index 9f8f08b36aa..5e8a894e0b9 100644 --- a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c +++ b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c @@ -1006,10 +1006,13 @@ static void s32k1xx_txdone(FAR struct s32k1xx_driver_s *priv) NETDEV_TXDONE(&priv->dev); #ifdef TX_TIMEOUT_WQ /* We are here because a transmission completed, so the - * corresponding watchdog can be canceled. + * corresponding watchdog can be canceled + * mailbox be set to inactive */ wd_cancel(&priv->txtimeout[mbi]); + struct mb_s *mb = &priv->tx[mbi]; + mb->cs.code = CAN_TXMB_INACTIVE; #endif } @@ -1129,7 +1132,9 @@ static int s32k1xx_flexcan_interrupt(int irq, FAR void *context, static void s32k1xx_txtimeout_work(FAR void *arg) { FAR struct s32k1xx_driver_s *priv = (FAR struct s32k1xx_driver_s *)arg; + uint32_t flags; uint32_t mbi; + uint32_t mb_bit; struct timespec ts; struct timeval *now = (struct timeval *)&ts; @@ -1140,6 +1145,8 @@ static void s32k1xx_txtimeout_work(FAR void *arg) * transmit function transmitted a new frame */ + flags = getreg32(priv->base + S32K1XX_CAN_IFLAG1_OFFSET); + for (mbi = 0; mbi < TXMBCOUNT; mbi++) { if (priv->txmb[mbi].deadline.tv_sec != 0 @@ -1147,6 +1154,14 @@ static void s32k1xx_txtimeout_work(FAR void *arg) || now->tv_usec > priv->txmb[mbi].deadline.tv_usec)) { NETDEV_TXTIMEOUTS(&priv->dev); + + mb_bit = 1 << (RXMBCOUNT + mbi); + + if (flags & mb_bit) + { + putreg32(mb_bit, priv->base + S32K1XX_CAN_IFLAG1_OFFSET); + } + struct mb_s *mb = &priv->tx[mbi]; mb->cs.code = CAN_TXMB_ABORT; priv->txmb[mbi].pending = TX_ABORT;