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 <hai.to@unikie.com>
This commit is contained in:
haitomatic
2025-10-08 06:48:24 +00:00
committed by Matteo Golin
parent 2b2afeec4c
commit d6a169d6dd

View File

@@ -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;