From aea94d9525699d3619ff29c2fa876b573b262e6a Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 7 Aug 2015 08:23:21 -0600 Subject: [PATCH] SAMV7 MCAN: Add support for all filter modes --- arch/arm/src/samv7/chip/sam_mcan.h | 2 +- arch/arm/src/samv7/sam_mcan.c | 113 ++++++++++++++++++++++------- 2 files changed, 86 insertions(+), 29 deletions(-) diff --git a/arch/arm/src/samv7/chip/sam_mcan.h b/arch/arm/src/samv7/chip/sam_mcan.h index 24dd73fe9d9..b3951aef703 100644 --- a/arch/arm/src/samv7/chip/sam_mcan.h +++ b/arch/arm/src/samv7/chip/sam_mcan.h @@ -776,7 +776,7 @@ # define EXTFILTER_F0_EFEC_REJECT (3 << EXTFILTER_F0_EFEC_SHIFT) /* Reject ID on match */ # define EXTFILTER_F0_EFEC_PRIORITY (4 << EXTFILTER_F0_EFEC_SHIFT) /* Set priority on match */ # define EXTFILTER_F0_EFEC_PRIOFIFO0 (5 << EXTFILTER_F0_EFEC_SHIFT) /* Set priority and store in FIFO 0 on match */ -# define EXTFILTER_F0_EFEC_PRIOFIFO1 (6 << EXTFILTER_F0_EFEC_SHIFT) /* Set priority and store in FIFO 1 on match */ +# define EXTFILTER_F0_EFEC_PRIOFIFO1 (6 << EXTFILTER_F0_EFEC_SHIFT) /* Set priority and store in FIFO 1 on match */ # define EXTFILTER_F0_EFEC_BUFFER (7 << EXTFILTER_F0_EFEC_SHIFT) /* Store into Rx Buffer or as debug message */ #define EXTFILTER_F1_EFID2_SHIFT (0) /* Bits 0-28: Extended Filter ID 2 */ diff --git a/arch/arm/src/samv7/sam_mcan.c b/arch/arm/src/samv7/sam_mcan.c index f7bed8ed912..3d0a1851d88 100644 --- a/arch/arm/src/samv7/sam_mcan.c +++ b/arch/arm/src/samv7/sam_mcan.c @@ -920,11 +920,12 @@ static uint8_t mcan_bytes2dlc(FAR struct sam_mcan_s *priv, uint8_t nbytes); #endif #ifdef CONFIG_CAN_EXTID -static int mcan_add_extfilter(FAR struct sam_mcan_s *priv, uint32_t id, - uint32_t mask); +static int mcan_add_extfilter(FAR struct sam_mcan_s *priv, + FAR struct canioc_stdfilter_s *extconfig); static int mcan_del_extfilter(FAR struct sam_mcan_s *priv, int ndx); #else -static int mcan_add_stdfilter(FAR struct sam_mcan_s *priv, uint16_t id); +static int mcan_add_stdfilter(FAR struct sam_mcan_s *priv, + FAR struct canioc_stdfilter_s *stdconfig); static int mcan_del_stdfilter(FAR struct sam_mcan_s *priv, int ndx); #endif /* CAN driver methods */ @@ -1538,9 +1539,8 @@ static uint8_t mcan_bytes2dlc(FAR struct sam_mcan_s *priv, uint8_t nbytes) * Add an address filter for a extended 29 bit address. * * Input Parameters: - * priv - An instance of the MCAN driver state structure. - * id - The 29-bit extended address to filter - * mask - A 29-bit extended address mask + * priv - An instance of the MCAN driver state structure. + * extconfig - The configuration of the extended filter * * Returned Value: * A non-negative filter ID is returned on success. Otherwise a negated @@ -1549,8 +1549,8 @@ static uint8_t mcan_bytes2dlc(FAR struct sam_mcan_s *priv, uint8_t nbytes) ****************************************************************************/ #ifdef CONFIG_CAN_EXTID -static int mcan_add_extfilter(FAR struct sam_mcan_s *priv, uint32_t id, - uint32_t mask) +static int mcan_add_extfilter(FAR struct sam_mcan_s *priv, + FAR struct canioc_stdfilter_s *extconfig) { FAR const struct sam_config_s *config; FAR uint32_t *extfilter; @@ -1559,8 +1559,7 @@ static int mcan_add_extfilter(FAR struct sam_mcan_s *priv, uint32_t id, int bit; int ndx; - DEBUGASSERT(priv != NULL && priv->config != NULL && - id < (1 << 29) && mask < (1 << 29)); + DEBUGASSERT(priv != NULL && priv->config != NULL && extconfig != NULL); config = priv->config; /* Get exclusive excess to the MCAN hardware */ @@ -1586,10 +1585,43 @@ static int mcan_add_extfilter(FAR struct sam_mcan_s *priv, uint32_t id, extfilter = config->msgram.extfilters + (ndx << 1); - /* REVISIT: Here we use only FIFO0. */ + /* Format and write filter word F0 */ - extfilter[0] = EXTFILTER_F0_EFEC_FIFO0 | EXTFILTER_F0_EFID1(id); - extfilter[1] = EXTFILTER_F1_EFT_CLASSIC | mask; + DEBUGASSERT(extconfig->xf_id1 < (1 << 29)); + regval = EXTFILTER_F0_EFID1(extconfig->xf_id1); + + if (extconfig->xf_prio == 0) + { + regval |= EXTFILTER_F0_EFEC_FIFO0; + } + else + { + regval |= EXTFILTER_F0_EFEC_FIFO0; + } + + extfilter[0] = regval; + + /* Format and write filter word F1 */ + + DEBUGASSERT(extconfig->xf_id2 < (1 << 29)); + regval = EXTFILTER_F1_EFID2(extconfig->xf_id2); + + switch (extconfig->xf_type) + { + default: + case CAN_FILTER_DUAL: + regval |= EXTFILTER_F1_EFT_DUAL; + break; + + case CAN_FILTER_MASK: + regval |= EXTFILTER_F1_EFT_CLASSIC; + break; + case CAN_FILTER_RANGE: + regval |= EXTFILTER_F1_EFT_RANGE; + break; + } + + extfilter[1] = regval; /* Flush the filter entry into physical RAM */ @@ -1700,8 +1732,8 @@ static int mcan_del_extfilter(FAR struct sam_mcan_s *priv, int ndx) * Add an address filter for a standard 11 bit address. * * Input Parameters: - * priv - An instance of the MCAN driver state structure. - * id - The 11-bit extended address to filter + * priv - An instance of the MCAN driver state structure. + * stdconfig - The configuration of the standard filter * * Returned Value: * A non-negative filter ID is returned on success. Otherwise a negated @@ -1710,7 +1742,8 @@ static int mcan_del_extfilter(FAR struct sam_mcan_s *priv, int ndx) ****************************************************************************/ #ifndef CONFIG_CAN_EXTID -static int mcan_add_stdfilter(FAR struct sam_mcan_s *priv, uint16_t id) +static int mcan_add_stdfilter(FAR struct sam_mcan_s *priv, + FAR struct canioc_stdfilter_s *stdconfig) { FAR const struct sam_config_s *config; FAR uint32_t *stdfilter; @@ -1719,7 +1752,7 @@ static int mcan_add_stdfilter(FAR struct sam_mcan_s *priv, uint16_t id) int bit; int ndx; - DEBUGASSERT(priv != NULL && priv->config != NULL && id < (1 << 11)); + DEBUGASSERT(priv != NULL && priv->config != NULL); config = priv->config; /* Get exclusive excess to the MCAN hardware */ @@ -1743,12 +1776,40 @@ static int mcan_add_stdfilter(FAR struct sam_mcan_s *priv, uint16_t id) priv->stdfilters[word] |= (1 << bit); priv->nstdalloc++; + /* Format and write filter word S0 */ + stdfilter = config->msgram.stdfilters + ndx; - regval = STDFILTER_S0_SFT_CLASSIC | STDFILTER_S0_SFID1(id); - /* REVISIT: Here we use only FIFO0. */ + DEBUGASSERT(stdconfig->sf_id1 < (1 << 29)); + regval = STDFILTER_S0_SFID1(stdconfig->sf_id1); + + DEBUGASSERT(stdconfig->sf_id2 < (1 << 29)); + regval |= STDFILTER_S0_SFID2(stdconfig->sf_id2); + + if (stdconfig->sf_prio == 0) + { + regval |= STDFILTER_S0_SFEC_FIFO0; + } + else + { + regval |= STDFILTER_S0_SFEC_FIFO1; + } + + switch (stdconfig->sf_type) + { + default: + case CAN_FILTER_DUAL: + regval |= STDFILTER_S0_SFT_DUAL; + break; + + case CAN_FILTER_MASK: + regval |= STDFILTER_S0_SFT_CLASSIC; + break; + case CAN_FILTER_RANGE: + regval |= STDFILTER_S0_SFT_RANGE; + break; + } - regval |= STDFILTER_S0_SFEC_FIFO0; *stdfilter = regval; /* Flush the filter entry into physical RAM */ @@ -2147,10 +2208,8 @@ static int mcan_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg) case CANIOC_ADD_EXTFILTER: { - FAR struct canioc_extfilter_s *extfilter = - (FAR struct canioc_extfilter_s *)arg; - - ret = mcan_add_extfilter(priv, extfilter->xf_id, extfilter->xf_mask); + DEBUGASSERT(arg != 0); + ret = mcan_add_extfilter(priv, (FAR struct canioc_extfilter_s *)arg); } break; @@ -2182,10 +2241,8 @@ static int mcan_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg) case CANIOC_ADD_STDFILTER: { - FAR struct canioc_stdfilter_s *stdfilter = - (FAR struct canioc_stdfilter_s *)arg; - - ret = mcan_add_stdfilter(priv, stdfilter->sf_id); + DEBUGASSERT(arg != 0); + ret = mcan_add_stdfilter(priv, (FAR struct canioc_stdfilter_s *)arg); } break;