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;