You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/06/02 14:09:47 UTC

[incubator-nuttx] 29/31: NET_CAN_RAW_TX_DEADLINE use relative time with watchdog Instead of a polling timer, also every mailbox get its own watchdog and gets cancelled when a tx interrupt for the corresponding mailbox occurs.

This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a commit to branch SocketCAN
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 0fe722cc64f6d9065aecacc924d69efd3ca16998
Author: Peter van der Perk <pe...@nxp.com>
AuthorDate: Wed Mar 18 11:33:53 2020 +0100

    NET_CAN_RAW_TX_DEADLINE use relative time with watchdog
    Instead of a polling timer, also every mailbox get its own watchdog
    and gets cancelled when a tx interrupt for the corresponding mailbox
    occurs.
---
 arch/arm/src/s32k1xx/s32k1xx_flexcan.c | 153 ++++++++++++++++-----------------
 net/can/Kconfig                        |   7 --
 2 files changed, 75 insertions(+), 85 deletions(-)

diff --git a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c
index 0325033..b1005d7 100644
--- a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c
+++ b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c
@@ -142,7 +142,6 @@ static int peak_tx_mailbox_index_ = 0;
  */
 
 #define S32K1XX_WDDELAY     (1*CLK_TCK)
-#define S32K1XX_TXTIMEOUT   ((CONFIG_NET_CAN_RAW_TX_POLL/1000)*CLK_TCK)
 
 /****************************************************************************
  * Private Types
@@ -224,30 +223,30 @@ struct txmbstats
 
 struct s32k1xx_driver_s
 {
-  bool bifup;                  /* true:ifup false:ifdown */
-  uint8_t txtail;              /* The oldest busy TX descriptor */
-  uint8_t txhead;              /* The next TX descriptor to use */
-  uint8_t rxtail;              /* The next RX descriptor to use */
-  uint8_t phyaddr;             /* Selected PHY address */
+  bool bifup;                   /* true:ifup false:ifdown */
+  uint8_t txtail;               /* The oldest busy TX descriptor */
+  uint8_t txhead;               /* The next TX descriptor to use */
+  uint8_t rxtail;               /* The next RX descriptor to use */
+  uint8_t phyaddr;              /* Selected PHY address */
 #ifdef WORK_QUEUE
-  WDOG_ID txpoll;              /* TX poll timer */
+  WDOG_ID txpoll;               /* TX poll timer */
 #endif
 #ifdef TX_TIMEOUT_WQ
-  WDOG_ID txtimeout;           /* TX timeout timer */
+  WDOG_ID txtimeout[TXMBCOUNT]; /* TX timeout timer */
 #endif
-  struct work_s irqwork;       /* For deferring interrupt work to the work queue */
-  struct work_s pollwork;      /* For deferring poll work to the work queue */
+  struct work_s irqwork;        /* For deferring interrupt work to the wq */
+  struct work_s pollwork;       /* For deferring poll work to the work wq */
 #ifdef CAN_FD
-  struct canfd_frame *txdesc;  /* A pointer to the list of TX descriptor */
-  struct canfd_frame *rxdesc;  /* A pointer to the list of RX descriptors */
+  struct canfd_frame *txdesc;   /* A pointer to the list of TX descriptor */
+  struct canfd_frame *rxdesc;   /* A pointer to the list of RX descriptors */
 #else
-  struct can_frame *txdesc;    /* A pointer to the list of TX descriptor */
-  struct can_frame *rxdesc;    /* A pointer to the list of RX descriptors */
+  struct can_frame *txdesc;     /* A pointer to the list of TX descriptor */
+  struct can_frame *rxdesc;     /* A pointer to the list of RX descriptors */
 #endif
 
   /* This holds the information visible to the NuttX network */
 
-  struct net_driver_s dev;     /* Interface understood by the network */
+  struct net_driver_s dev;      /* Interface understood by the network */
 
   struct mb_s *rx;
   struct mb_s *tx;
@@ -311,10 +310,6 @@ static void s32k1xx_setenable(uint32_t enable);
 static void s32k1xx_setfreeze(uint32_t freeze);
 static uint32_t s32k1xx_waitmcr_change(uint32_t mask,
                                        uint32_t target_state);
-#ifdef TX_TIMEOUT_WQ
-static void s32k1xx_checkandaborttx(struct s32k1xx_driver_s *priv,
-        uint32_t mbi, struct timeval *now);
-#endif
 
 /* Interrupt handling */
 
@@ -446,31 +441,41 @@ static int s32k1xx_transmit(FAR struct s32k1xx_driver_s *priv)
     }
 
 #ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
-      if (priv->dev.d_sndlen > priv->dev.d_len)
+  int32_t timeout = 0;
+  struct timespec ts;
+  clock_systimespec(&ts);
+
+  if (priv->dev.d_sndlen > priv->dev.d_len)
+    {
+      struct timeval *tv =
+             (struct timeval *)(priv->dev.d_buf + priv->dev.d_len);
+      priv->txmb[mbi].deadline = *tv;
+      timeout  = (tv->tv_sec - ts.tv_sec)*CLK_TCK
+                 + ((tv->tv_usec - ts.tv_nsec / 1000)*CLK_TCK) / 1000000;
+      if (timeout < 0)
+        {
+          return 0;       /* No transmission for you! */
+        }
+    }
+  else
+    {
+      /* Default TX deadline defined in NET_CAN_RAW_DEFAULT_TX_DEADLINE */
+
+      if (CONFIG_NET_CAN_RAW_DEFAULT_TX_DEADLINE > 0)
         {
-          struct timeval *tv =
-                 (struct timeval *)(priv->dev.d_buf + priv->dev.d_len);
-          priv->txmb[mbi].deadline = *tv;
+          timeout = ((CONFIG_NET_CAN_RAW_DEFAULT_TX_DEADLINE / 1000000)
+              *CLK_TCK);
+          priv->txmb[mbi].deadline.tv_sec = ts.tv_sec +
+              CONFIG_NET_CAN_RAW_DEFAULT_TX_DEADLINE / 1000000;
+          priv->txmb[mbi].deadline.tv_usec = (ts.tv_nsec / 1000) +
+              CONFIG_NET_CAN_RAW_DEFAULT_TX_DEADLINE % 1000000;
         }
       else
         {
-          /* Default TX deadline defined in NET_CAN_RAW_DEFAULT_TX_DEADLINE */
-
-          if (CONFIG_NET_CAN_RAW_DEFAULT_TX_DEADLINE > 0)
-            {
-              struct timespec ts;
-              clock_systimespec(&ts);
-              priv->txmb[mbi].deadline.tv_sec = ts.tv_sec +
-                      CONFIG_NET_CAN_RAW_DEFAULT_TX_DEADLINE / 1000000;
-              priv->txmb[mbi].deadline.tv_usec = (ts.tv_nsec / 1000) +
-                      CONFIG_NET_CAN_RAW_DEFAULT_TX_DEADLINE % 1000000;
-            }
-          else
-            {
-              priv->txmb[mbi].deadline.tv_sec = 0;
-              priv->txmb[mbi].deadline.tv_usec = 0;
-            }
+          priv->txmb[mbi].deadline.tv_sec = 0;
+          priv->txmb[mbi].deadline.tv_usec = 0;
         }
+    }
 #endif
 
   peak_tx_mailbox_index_ =
@@ -580,10 +585,14 @@ static int s32k1xx_transmit(FAR struct s32k1xx_driver_s *priv)
 
   NETDEV_TXPACKETS(&priv->dev);
 
-  /* Setup the TX timeout watchdog (perhaps restarting the timer) */
 #ifdef TX_TIMEOUT_WQ
-  wd_start(priv->txtimeout, S32K1XX_TXTIMEOUT, s32k1xx_txtimeout_expiry, 1,
-           (wdparm_t)priv);
+  /* Setup the TX timeout watchdog (perhaps restarting the timer) */
+
+  if (timeout > 0)
+    {
+      wd_start(priv->txtimeout[mbi], timeout + 1, s32k1xx_txtimeout_expiry,
+                1, (wdparm_t)priv);
+    }
 #endif
 
   return OK;
@@ -838,19 +847,6 @@ static void s32k1xx_txdone(FAR struct s32k1xx_driver_s *priv, uint32_t flags)
 {
   #warning Missing logic
 
-#ifdef TX_TIMEOUT_WQ
-  /* We are here because a transmission completed, so the watchdog can be
-   * canceled.
-   */
-
-  wd_cancel(priv->txtimeout);
-
-  struct timespec ts;
-  struct timeval *now = (struct timeval *)&ts;
-  clock_systimespec(&ts);
-  now->tv_usec = ts.tv_nsec / 1000; /* timespec to timeval conversion */
-#endif
-
   /* FIXME First Process Error aborts */
 
   /* Process TX completions */
@@ -863,16 +859,14 @@ static void s32k1xx_txdone(FAR struct s32k1xx_driver_s *priv, uint32_t flags)
           putreg32(mb_bit, S32K1XX_CAN0_IFLAG1);
           flags &= ~mb_bit;
           NETDEV_TXDONE(&priv->dev);
-        }
-
 #ifdef TX_TIMEOUT_WQ
-      /* MB is not done, check for timeout */
+          /* We are here because a transmission completed, so the
+           * corresponding watchdog can be canceled.
+           */
 
-      else
-        {
-       s32k1xx_checkandaborttx(priv, mbi, now);
-        }
+          wd_cancel(priv->txtimeout[mbi]);
 #endif
+        }
 
       mb_bit <<= 1;
     }
@@ -1017,19 +1011,6 @@ static void s32k1xx_polltimer_expiry(int argc, uint32_t arg, ...)
  *
  ****************************************************************************/
 #ifdef TX_TIMEOUT_WQ
-static void s32k1xx_checkandaborttx(struct s32k1xx_driver_s *priv,
-  uint32_t mbi, struct timeval *now)
-{
-  if (priv->txmb[mbi].deadline.tv_sec != 0
-      && (now->tv_sec > priv->txmb[mbi].deadline.tv_sec
-      || now->tv_usec > priv->txmb[mbi].deadline.tv_usec))
-    {
-      NETDEV_TXTIMEOUTS(&priv->dev);
-      struct mb_s *mb = &priv->tx[mbi];
-      mb->cs.code = CAN_TXMB_ABORT;
-      priv->txmb[mbi].pending = TX_ABORT;
-    }
-}
 
 static void s32k1xx_txtimeout_work(FAR void *arg)
 {
@@ -1040,9 +1021,21 @@ static void s32k1xx_txtimeout_work(FAR void *arg)
   clock_systimespec(&ts);
   now->tv_usec = ts.tv_nsec / 1000; /* timespec to timeval conversion */
 
-  for (int i = 0; i < TXMBCOUNT; i++)
+  /* The watchdog timed out, yet we still check mailboxes in case the
+   * transmit function transmitted a new frame
+   */
+
+  for (int mbi = 0; mbi < TXMBCOUNT; mbi++)
     {
-      s32k1xx_checkandaborttx(priv, i, now);
+      if (priv->txmb[mbi].deadline.tv_sec != 0
+          && (now->tv_sec > priv->txmb[mbi].deadline.tv_sec
+          || now->tv_usec > priv->txmb[mbi].deadline.tv_usec))
+        {
+          NETDEV_TXTIMEOUTS(&priv->dev);
+          struct mb_s *mb = &priv->tx[mbi];
+          mb->cs.code = CAN_TXMB_ABORT;
+          priv->txmb[mbi].pending = TX_ABORT;
+        }
     }
 }
 
@@ -1637,7 +1630,11 @@ int s32k1xx_netinitialize(int intf)
   priv->txpoll        = wd_create();       /* Create periodic poll timer */
 #endif
 #ifdef TX_TIMEOUT_WQ
-  priv->txtimeout     = wd_create();       /* Create TX timeout timer */
+  for (int i = 0; i < TXMBCOUNT; i++)
+    {
+      priv->txtimeout[i] = wd_create();    /* Create TX timeout timer */
+    }
+
 #endif
   priv->rx            = (struct mb_s *)(S32K1XX_CAN0_MB);
   priv->tx            = (struct mb_s *)(S32K1XX_CAN0_MB +
diff --git a/net/can/Kconfig b/net/can/Kconfig
index 00bfabd..731a12b 100644
--- a/net/can/Kconfig
+++ b/net/can/Kconfig
@@ -51,13 +51,6 @@ config NET_CAN_RAW_TX_DEADLINE
 		CAN frame is still in the HW TX mailbox then the CAN driver will 
 		discard the CAN frame automatically.
 		
-config NET_CAN_RAW_TX_POLL
-	int "TX deadline polling rate (ms) "
-	default 500
-	depends on NET_CAN_RAW_TX_DEADLINE
-	---help---
-		The polling rate on which the CAN driver checks whenever a TX deadline occurs
-		
 config NET_CAN_RAW_DEFAULT_TX_DEADLINE
 	int "Default TX deadline when no deadline is given (us)"
 	default 0