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

linguini pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new d6a169d6dd2 arch/arm64/src/imx9/imx9_flexcan.c: add CAN ID filtering.
d6a169d6dd2 is described below

commit d6a169d6dd2e7e8f3665f76b2215babf244c7787
Author: haitomatic <[email protected]>
AuthorDate: Wed Oct 8 06:48:24 2025 +0000

    arch/arm64/src/imx9/imx9_flexcan.c: add CAN ID filtering.
    
    Add simple single ID mask filter. Only pkts with set CAN ID are accepted. 
This works for both STD and EXT CAN ID.
    
    Signed-off-by: haitomatic <[email protected]>
---
 arch/arm64/src/imx9/imx9_flexcan.c | 230 +++++++++++++++++++++++++++++++++++--
 1 file changed, 221 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/src/imx9/imx9_flexcan.c 
b/arch/arm64/src/imx9/imx9_flexcan.c
index a25e3d35011..8d2e3359d84 100644
--- a/arch/arm64/src/imx9/imx9_flexcan.c
+++ b/arch/arm64/src/imx9/imx9_flexcan.c
@@ -552,6 +552,17 @@ static int  imx9_ioctl(struct net_driver_s *dev, int cmd,
                        unsigned long arg);
 #endif
 
+/* CAN ID filtering */
+
+#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL
+static uint32_t imx9_add_filter(struct imx9_driver_s *priv,
+                                 uint8_t filter_type,
+                                 bool ext_id,
+                                 uint32_t filter_id1,
+                                 uint32_t filter_id2);
+static uint8_t imx9_reset_filter(struct imx9_driver_s *priv);
+#endif
+
 /* Initialization */
 
 static int  imx9_initialize(struct imx9_driver_s *priv);
@@ -646,7 +657,7 @@ static int imx9_transmit(struct imx9_driver_s *priv)
     {
       nwarn("No TX MB available mbi %" PRIi32 "\n", mbi);
       NETDEV_TXERRORS(&priv->dev);
-      return ERROR;
+      return -EBUSY;
     }
 
 #ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
@@ -663,7 +674,7 @@ static int imx9_transmit(struct imx9_driver_s *priv)
                  + ((tv->tv_usec - ts.tv_nsec / 1000)*CLK_TCK) / 1000000;
       if (timeout < 0)
         {
-          return ERROR;
+          return -ETIMEDOUT;
         }
     }
   else
@@ -1426,7 +1437,7 @@ static volatile struct mb_s *flexcan_get_mb(struct 
imx9_driver_s *priv,
  *   dev  - Reference to the NuttX driver state structure
  *
  * Returned Value:
- *   OK or ERROR
+ *   return OK on success, negated error number on failure
  *
  * Assumptions:
  *
@@ -1439,7 +1450,7 @@ static int imx9_ifup(struct net_driver_s *dev)
   if (imx9_initialize(priv) != OK)
     {
       canerr("initialize failed");
-      return ERROR;
+      return -EIO;
     }
 
   priv->bifup = true;
@@ -1463,7 +1474,7 @@ static int imx9_ifup(struct net_driver_s *dev)
  *   dev  - Reference to the NuttX driver state structure
  *
  * Returned Value:
- *   None
+ *   return OK on success, negated error number on failure
  *
  * Assumptions:
  *
@@ -1645,6 +1656,45 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd,
         }
         break;
 #endif
+
+#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL
+      case SIOCACANSTDFILTER: /* Set STD ID CAN filter */
+        {
+          struct imx9_driver_s *priv = (struct imx9_driver_s *)dev;
+          struct can_ioctl_filter_s *req =
+            (struct can_ioctl_filter_s *)((uintptr_t)arg);
+          if (!req)
+            {
+              return -EINVAL;
+            }
+
+            ret = imx9_add_filter(priv, req->ftype, 0, req->fid1, req->fid2);
+        }
+        break;
+
+      case SIOCACANEXTFILTER: /* Set EXT ID CAN filter */
+        {
+          struct imx9_driver_s *priv = (struct imx9_driver_s *)dev;
+          struct can_ioctl_filter_s *req =
+            (struct can_ioctl_filter_s *)((uintptr_t)arg);
+          if (!req)
+            {
+              return -EINVAL;
+            }
+
+            ret = imx9_add_filter(priv, req->ftype, 1, req->fid1, req->fid2);
+        }
+        break;
+
+      case SIOCDCANSTDFILTER: /* Reset STD ID CAN filter */
+      case SIOCDCANEXTFILTER: /* Reset EXT ID CAN filter */
+        {
+          struct imx9_driver_s *priv = (struct imx9_driver_s *)dev;
+          ret = imx9_reset_filter(priv);
+        }
+        break;
+#endif
+
       default:
         ret = -ENOTTY;
         break;
@@ -1654,6 +1704,168 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd,
 }
 #endif /* CONFIG_NETDEV_IOCTL */
 
+/****************************************************************************
+ * Name: imx9_add_filter
+ *
+ * Description:
+ *   Add new MB filter. Currently only support single ID mask filter.
+ *   TODO: add support for multiple ID mask filters
+ *
+ * Input Parameters:
+ *   priv          - Pointer to the private CAN driver state structure
+ *   filter_type   - The type of the filter: mask, range or dual filter
+ *   ext_id        - true: extended id, false: standard id
+ *   filter_id1    - filter id 1 (refer to can_ioctl_filter_s in if.h)
+ *   filter_id2    - filter id 2 (refer to can_ioctl_filter_s in if.h)
+ *
+ * Returned Value:
+ *   return OK on success, negated error number on failure
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL
+static uint32_t imx9_add_filter(struct imx9_driver_s *priv,
+                               uint8_t filter_type,
+                               bool ext_id,
+                               uint32_t filter_id1,
+                               uint32_t filter_id2)
+{
+  volatile struct mb_s *mb;
+  uint32_t mbi = 0;
+
+  /* Enter freeze mode */
+
+  if (!imx9_setfreeze(priv->base, true))
+    {
+      canerr("FLEXCAN: freeze fail\n");
+      return -EIO;
+    }
+
+  switch (filter_type)
+    {
+      case CAN_FILTER_MASK:
+        {
+          if (ext_id)
+            {
+              for (mbi = 0; mbi < RXMBCOUNT; mbi++)
+                {
+                  /* Set individual mask register */
+
+                  putreg32(filter_id2 & CAN_MB_ID_ID_MASK,
+                           priv->base + IMX9_CAN_RXIMR_OFFSET(mbi));
+
+                  /* Set the acceptance EXT ID filter in MB */
+
+                  mb = flexcan_get_mb(priv, mbi);
+                  mb->id = filter_id1 & CAN_MB_ID_ID_MASK;
+                }
+            }
+          else
+            {
+              for (mbi = 0; mbi < RXMBCOUNT; mbi++)
+                {
+                  /* Set individual mask register */
+
+                  putreg32(((filter_id2 & CAN_SFF_MASK)
+                           << CAN_MB_ID_ID_STD_SHIFT)
+                           & CAN_MB_ID_ID_STD_MASK,
+                           priv->base + IMX9_CAN_RXIMR_OFFSET(mbi));
+
+                  /* Set the acceptance STD ID filter in MB */
+
+                  mb = flexcan_get_mb(priv, mbi);
+                  mb->id = ((filter_id1 & CAN_SFF_MASK)
+                           << CAN_MB_ID_ID_STD_SHIFT)
+                           & CAN_MB_ID_ID_STD_MASK;
+                }
+            }
+        }
+        break;
+
+      case CAN_FILTER_RANGE:
+        {
+          canerr("Range filter type not supported\n");
+          return -EINVAL;
+        }
+        break;
+
+      case CAN_FILTER_DUAL:
+        {
+          canerr("Dual filter type not supported\n");
+          return -EINVAL;
+        }
+        break;
+
+      default:
+        {
+          canerr("FLEXCAN: invalid filter type\n");
+          return -EINVAL;
+        }
+        break;
+    }
+
+  /* Exit freeze mode */
+
+  if (!imx9_setfreeze(priv->base, false))
+    {
+      canerr("FLEXCAN: unfreeze fail\n");
+      return -EIO;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: imx9_reset_filter
+ *
+ * Description:
+ *   Clear all ID filters in the MBs
+ *
+ * Input Parameters:
+ *   priv - Reference to the private FLEXCAN driver state structure
+ *
+ * Returned Value:
+ *   return OK on success, negated error number on failure
+ *
+ ****************************************************************************/
+
+static uint8_t imx9_reset_filter(struct imx9_driver_s *priv)
+{
+  volatile struct mb_s *mb;
+  uint32_t mbi = 0;
+
+  /* Enter freeze mode */
+
+  if (!imx9_setfreeze(priv->base, true))
+    {
+      canerr("FLEXCAN: freeze fail\n");
+      return -EIO;
+    }
+
+  for (mbi = 0; mbi < RXMBCOUNT; mbi++)
+    {
+      /* Clear individual mask register */
+
+      putreg32(0, priv->base + IMX9_CAN_RXIMR_OFFSET(mbi));
+
+      /* clear the acceptance ID filter */
+
+      mb = flexcan_get_mb(priv, mbi);
+      mb->id = 0;
+    }
+
+  /* Exit freeze mode */
+
+  if (!imx9_setfreeze(priv->base, false))
+    {
+      canerr("FLEXCAN: unfreeze fail\n");
+      return -EIO;
+    }
+
+  return OK;
+}
+#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */
+
 /****************************************************************************
  * Function: imx9_init_eccram
  *
@@ -1753,7 +1965,7 @@ static int imx9_init_eccram(struct imx9_driver_s *priv)
  *   priv - Reference to the private FLEXCAN driver state structure
  *
  * Returned Value:
- *   OK or ERROR
+ *   return OK on success, negated error number on failure
  *
  * Assumptions:
  *
@@ -1770,7 +1982,7 @@ static int imx9_initialize(struct imx9_driver_s *priv)
   if (!imx9_setenable(priv->base, true))
     {
       canerr("FLEXCAN: enable fail\n");
-      return ERROR;
+      return -EIO;
     }
 
   /* Enter freeze mode */
@@ -1778,7 +1990,7 @@ static int imx9_initialize(struct imx9_driver_s *priv)
   if (!imx9_setfreeze(priv->base, true))
     {
       canerr("FLEXCAN: freeze fail\n");
-      return ERROR;
+      return -EIO;
     }
 
   /* Initialize memory buffers */
@@ -1888,7 +2100,7 @@ static int imx9_initialize(struct imx9_driver_s *priv)
   if (!imx9_setfreeze(priv->base, false))
     {
       canerr("FLEXCAN: unfreeze fail\n");
-      return ERROR;
+      return -EIO;
     }
 
   return OK;

Reply via email to