diff --git a/arch/arm/src/sama5/sam_mcan.c b/arch/arm/src/sama5/sam_mcan.c index 54c2a2d76d..7126e033cd 100644 --- a/arch/arm/src/sama5/sam_mcan.c +++ b/arch/arm/src/sama5/sam_mcan.c @@ -2652,18 +2652,39 @@ static int mcan_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg) DEBUGASSERT(bt != NULL); - regval = mcan_getreg(priv, SAM_MCAN_BTP_OFFSET); - bt->bt_sjw = ((regval & MCAN_BTP_SJW_MASK) >> - MCAN_BTP_SJW_SHIFT) + 1; - bt->bt_tseg1 = ((regval & MCAN_BTP_TSEG1_MASK) >> - MCAN_BTP_TSEG1_SHIFT) + 1; - bt->bt_tseg2 = ((regval & MCAN_BTP_TSEG2_MASK) >> - MCAN_BTP_TSEG2_SHIFT) + 1; +#ifdef CONFIG_CAN_FD + if (bt->type == CAN_BITTIMING_DATA) + { + regval = mcan_getreg(priv, SAM_MCAN_FBTP_OFFSET); + bt->bt_sjw = ((regval & MCAN_FBTP_FSJW_MASK) >> + MCAN_FBTP_FSJW_SHIFT) + 1; + bt->bt_tseg1 = ((regval & MCAN_FBTP_FTSEG1_MASK) >> + MCAN_FBTP_FTSEG1_SHIFT) + 1; + bt->bt_tseg2 = ((regval & MCAN_FBTP_FTSEG2_MASK) >> + MCAN_FBTP_FTSEG2_SHIFT) + 1; + + brp = ((regval & MCAN_FBTP_FBRP_MASK) >> + MCAN_FBTP_FBRP_SHIFT) + 1; + bt->bt_baud = SAMA5_MCANCLK_FREQUENCY / brp / + (bt->bt_tseg1 + bt->bt_tseg2 + 1); + } + else +#endif + { + regval = mcan_getreg(priv, SAM_MCAN_BTP_OFFSET); + bt->bt_sjw = ((regval & MCAN_BTP_SJW_MASK) >> + MCAN_BTP_SJW_SHIFT) + 1; + bt->bt_tseg1 = ((regval & MCAN_BTP_TSEG1_MASK) >> + MCAN_BTP_TSEG1_SHIFT) + 1; + bt->bt_tseg2 = ((regval & MCAN_BTP_TSEG2_MASK) >> + MCAN_BTP_TSEG2_SHIFT) + 1; + + brp = ((regval & MCAN_BTP_BRP_MASK) >> + MCAN_BTP_BRP_SHIFT) + 1; + bt->bt_baud = SAMA5_MCANCLK_FREQUENCY / brp / + (bt->bt_tseg1 + bt->bt_tseg2 + 1); + } - brp = ((regval & MCAN_BTP_BRP_MASK) >> - MCAN_BTP_BRP_SHIFT) + 1; - bt->bt_baud = SAMA5_MCANCLK_FREQUENCY / brp / - (bt->bt_tseg1 + bt->bt_tseg2 + 1); ret = OK; } break; @@ -2716,8 +2737,18 @@ static int mcan_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg) /* Save the value of the new bit timing register */ flags = enter_critical_section(); - priv->btp = MCAN_BTP_BRP(brp) | MCAN_BTP_TSEG1(tseg1) | - MCAN_BTP_TSEG2(tseg2) | MCAN_BTP_SJW(sjw); +#ifdef CONFIG_CAN_FD + if (bt->type == CAN_BITTIMING_DATA) + { + priv->fbtp = MCAN_FBTP_FBRP(brp) | MCAN_FBTP_FTSEG1(tseg1) | + MCAN_FBTP_FTSEG2(tseg2) | MCAN_FBTP_FSJW(sjw); + } + else +#endif + { + priv->btp = MCAN_BTP_BRP(brp) | MCAN_BTP_TSEG1(tseg1) | + MCAN_BTP_TSEG2(tseg2) | MCAN_BTP_SJW(sjw); + } /* We need to reset to instantiate the new timing. Save * current state information so that recover to this diff --git a/arch/arm/src/samv7/sam_mcan.c b/arch/arm/src/samv7/sam_mcan.c index 0f98953c5b..3a5d8062dd 100644 --- a/arch/arm/src/samv7/sam_mcan.c +++ b/arch/arm/src/samv7/sam_mcan.c @@ -144,10 +144,10 @@ (float)CONFIG_SAMV7_MCAN0_FBITRATE)) - 1)) # define MCAN0_DSJW (CONFIG_SAMV7_MCAN0_FFSJW - 1) -# if MCAN0_DTSEG1 > 15 +# if MCAN0_DTSEG1 > 31 # error Invalid MCAN0 DTSEG1 # endif -# if MCAN0_DTSEG2 > 7 +# if MCAN0_DTSEG2 > 15 # error Invalid MCAN0 DTSEG2 # endif # if MCAN0_DSJW > 3 @@ -429,10 +429,10 @@ (float)CONFIG_SAMV7_MCAN1_FBITRATE)) - 1)) # define MCAN1_DSJW (CONFIG_SAMV7_MCAN1_FFSJW - 1) -#if MCAN1_DTSEG1 > 15 +#if MCAN1_DTSEG1 > 31 # error Invalid MCAN1 DTSEG1 #endif -#if MCAN1_DTSEG2 > 7 +#if MCAN1_DTSEG2 > 15 # error Invalid MCAN1 DTSEG2 #endif #if MCAN1_DSJW > 3 @@ -2650,33 +2650,70 @@ static int mcan_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg) DEBUGASSERT(bt != NULL); - regval = mcan_getreg(priv, SAM_MCAN_NBTP_OFFSET); - - if (priv->rev == 0) +#ifdef CONFIG_CAN_FD + if (bt->type == CAN_BITTIMING_DATA) { - /* Revision A */ + if (priv->rev == 0) + { + /* Revision A */ - bt->bt_sjw = ((regval & MCAN_REVA_BTP_SJW_MASK) >> - MCAN_REVA_BTP_SJW_SHIFT) + 1; - bt->bt_tseg1 = ((regval & MCAN_REVA_BTP_TSEG1_MASK) >> - MCAN_REVA_BTP_TSEG1_SHIFT) + 1; - bt->bt_tseg2 = ((regval & MCAN_REVA_BTP_TSEG2_MASK) >> - MCAN_REVA_BTP_TSEG2_SHIFT) + 1; - brp = ((regval & MCAN_REVA_BTP_BRP_MASK) >> - MCAN_REVA_BTP_BRP_SHIFT) + 1; + regval = mcan_getreg(priv, + SAM_MCAN_REVA_FBTP_OFFSET); + bt->bt_sjw = ((regval & MCAN_REVA_FBTP_FSJW_MASK) >> + MCAN_REVA_FBTP_FSJW_SHIFT) + 1; + bt->bt_tseg1 = ((regval & MCAN_REVA_FBTP_FTSEG1_MASK) >> + MCAN_REVA_FBTP_FTSEG1_SHIFT) + 1; + bt->bt_tseg2 = ((regval & MCAN_REVA_FBTP_FTSEG2_MASK) >> + MCAN_REVA_FBTP_FTSEG2_SHIFT) + 1; + brp = ((regval & MCAN_REVA_FBTP_FBRP_MASK) >> + MCAN_REVA_FBTP_FBRP_SHIFT) + 1; + } + else + { + /* Revision B */ + + regval = mcan_getreg(priv, SAM_MCAN_DBTP_OFFSET); + bt->bt_sjw = ((regval & MCAN_DBTP_DSJW_MASK) >> + MCAN_DBTP_DSJW_SHIFT) + 1; + bt->bt_tseg1 = ((regval & MCAN_DBTP_DTSEG1_MASK) >> + MCAN_DBTP_DTSEG1_SHIFT) + 1; + bt->bt_tseg2 = ((regval & MCAN_DBTP_DTSEG2_MASK) >> + MCAN_DBTP_DTSEG2_SHIFT) + 1; + brp = ((regval & MCAN_DBTP_DBRP_MASK) >> + MCAN_DBTP_DBRP_SHIFT) + 1; + } } else +#endif { - /* Revision B */ + if (priv->rev == 0) + { + /* Revision A */ - bt->bt_sjw = ((regval & MCAN_NBTP_NSJW_MASK) >> - MCAN_NBTP_NSJW_SHIFT) + 1; - bt->bt_tseg1 = ((regval & MCAN_NBTP_NTSEG1_MASK) >> - MCAN_NBTP_NTSEG1_SHIFT) + 1; - bt->bt_tseg2 = ((regval & MCAN_NBTP_NTSEG2_MASK) >> - MCAN_NBTP_NTSEG2_SHIFT) + 1; - brp = ((regval & MCAN_NBTP_NBRP_MASK) >> - MCAN_NBTP_NBRP_SHIFT) + 1; + regval = mcan_getreg(priv, SAM_MCAN_REVA_BTP_OFFSET); + bt->bt_sjw = ((regval & MCAN_REVA_BTP_SJW_MASK) >> + MCAN_REVA_BTP_SJW_SHIFT) + 1; + bt->bt_tseg1 = ((regval & MCAN_REVA_BTP_TSEG1_MASK) >> + MCAN_REVA_BTP_TSEG1_SHIFT) + 1; + bt->bt_tseg2 = ((regval & MCAN_REVA_BTP_TSEG2_MASK) >> + MCAN_REVA_BTP_TSEG2_SHIFT) + 1; + brp = ((regval & MCAN_REVA_BTP_BRP_MASK) >> + MCAN_REVA_BTP_BRP_SHIFT) + 1; + } + else + { + /* Revision B */ + + regval = mcan_getreg(priv, SAM_MCAN_NBTP_OFFSET); + bt->bt_sjw = ((regval & MCAN_NBTP_NSJW_MASK) >> + MCAN_NBTP_NSJW_SHIFT) + 1; + bt->bt_tseg1 = ((regval & MCAN_NBTP_NTSEG1_MASK) >> + MCAN_NBTP_NTSEG1_SHIFT) + 1; + bt->bt_tseg2 = ((regval & MCAN_NBTP_NTSEG2_MASK) >> + MCAN_NBTP_NTSEG2_SHIFT) + 1; + brp = ((regval & MCAN_NBTP_NBRP_MASK) >> + MCAN_NBTP_NBRP_SHIFT) + 1; + } } bt->bt_baud = SAMV7_MCANCLK_FREQUENCY / brp / @@ -2733,17 +2770,41 @@ static int mcan_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg) /* Save the value of the new bit timing register */ flags = enter_critical_section(); - if (priv->rev == 0) +#ifdef CONFIG_CAN_FD + if (bt->type == CAN_BITTIMING_DATA) { - priv->btp = MCAN_REVA_BTP_BRP(brp) | - MCAN_REVA_BTP_TSEG1(tseg1) | - MCAN_REVA_BTP_TSEG2(tseg2) | - MCAN_REVA_BTP_SJW(sjw); + if (priv->rev == 0) + { + priv->fbtp = MCAN_REVA_FBTP_FBRP(brp) | + MCAN_REVA_FBTP_FTSEG1(tseg1) | + MCAN_REVA_FBTP_FTSEG2(tseg2) | + MCAN_REVA_FBTP_FSJW(sjw); + } + else + { + priv->fbtp = MCAN_DBTP_DBRP(brp) | + MCAN_DBTP_DTSEG1(tseg1) | + MCAN_DBTP_DTSEG2(tseg2) | + MCAN_DBTP_DSJW(sjw); + } } else +#endif { - priv->btp = MCAN_NBTP_NBRP(brp) | MCAN_NBTP_NTSEG1(tseg1) | - MCAN_NBTP_NTSEG2(tseg2) | MCAN_NBTP_NSJW(sjw); + if (priv->rev == 0) + { + priv->btp = MCAN_REVA_BTP_BRP(brp) | + MCAN_REVA_BTP_TSEG1(tseg1) | + MCAN_REVA_BTP_TSEG2(tseg2) | + MCAN_REVA_BTP_SJW(sjw); + } + else + { + priv->btp = MCAN_NBTP_NBRP(brp) | + MCAN_NBTP_NTSEG1(tseg1) | + MCAN_NBTP_NTSEG2(tseg2) | + MCAN_NBTP_NSJW(sjw); + } } /* We need to reset to instantiate the new timing. Save diff --git a/arch/arm/src/stm32/stm32_fdcan.c b/arch/arm/src/stm32/stm32_fdcan.c index f36ddb2236..8d573c976a 100644 --- a/arch/arm/src/stm32/stm32_fdcan.c +++ b/arch/arm/src/stm32/stm32_fdcan.c @@ -2068,18 +2068,39 @@ static int fdcan_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg) DEBUGASSERT(bt != NULL); - regval = fdcan_getreg(priv, STM32_FDCAN_NBTP_OFFSET); - bt->bt_sjw = ((regval & FDCAN_NBTP_NSJW_MASK) >> - FDCAN_NBTP_NSJW_SHIFT) + 1; - bt->bt_tseg1 = ((regval & FDCAN_NBTP_NTSEG1_MASK) >> - FDCAN_NBTP_NTSEG1_SHIFT) + 1; - bt->bt_tseg2 = ((regval & FDCAN_NBTP_NTSEG2_MASK) >> - FDCAN_NBTP_NTSEG2_SHIFT) + 1; +#ifdef CONFIG_CAN_FD + if (bt->type == CAN_BITTIMING_DATA) + { + regval = fdcan_getreg(priv, STM32_FDCAN_DBTP_OFFSET); + bt->bt_sjw = ((regval & FDCAN_DBTP_DSJW_MASK) >> + FDCAN_DBTP_DSJW_SHIFT) + 1; + bt->bt_tseg1 = ((regval & FDCAN_DBTP_DTSEG1_MASK) >> + FDCAN_DBTP_DTSEG1_SHIFT) + 1; + bt->bt_tseg2 = ((regval & FDCAN_DBTP_DTSEG2_MASK) >> + FDCAN_DBTP_DTSEG2_SHIFT) + 1; + + nbrp = ((regval & FDCAN_DBTP_DBRP_MASK) >> + FDCAN_DBTP_DBRP_SHIFT) + 1; + bt->bt_baud = STM32_FDCANCLK_FREQUENCY / nbrp / + (bt->bt_tseg1 + bt->bt_tseg2 + 1); + } + else +#endif + { + regval = fdcan_getreg(priv, STM32_FDCAN_NBTP_OFFSET); + bt->bt_sjw = ((regval & FDCAN_NBTP_NSJW_MASK) >> + FDCAN_NBTP_NSJW_SHIFT) + 1; + bt->bt_tseg1 = ((regval & FDCAN_NBTP_NTSEG1_MASK) >> + FDCAN_NBTP_NTSEG1_SHIFT) + 1; + bt->bt_tseg2 = ((regval & FDCAN_NBTP_NTSEG2_MASK) >> + FDCAN_NBTP_NTSEG2_SHIFT) + 1; + + nbrp = ((regval & FDCAN_NBTP_NBRP_MASK) >> + FDCAN_NBTP_NBRP_SHIFT) + 1; + bt->bt_baud = STM32_FDCANCLK_FREQUENCY / nbrp / + (bt->bt_tseg1 + bt->bt_tseg2 + 1); + } - nbrp = ((regval & FDCAN_NBTP_NBRP_MASK) >> - FDCAN_NBTP_NBRP_SHIFT) + 1; - bt->bt_baud = STM32_FDCANCLK_FREQUENCY / nbrp / - (bt->bt_tseg1 + bt->bt_tseg2 + 1); ret = OK; } break; @@ -2130,8 +2151,22 @@ static int fdcan_ioctl(struct can_dev_s *dev, int cmd, unsigned long arg) /* Save the value of the new bit timing register */ - priv->nbtp = FDCAN_NBTP_NBRP(nbrp) | FDCAN_NBTP_NTSEG1(ntseg1) | - FDCAN_NBTP_NTSEG2(ntseg2) | FDCAN_NBTP_NSJW(nsjw); +#ifdef CONFIG_CAN_FD + if (bt->type == CAN_BITTIMING_DATA) + { + priv->dbtp = FDCAN_NBTP_DBRP(nbrp) | + FDCAN_NBTP_DTSEG1(ntseg1) | + FDCAN_DBTP_DTSEG2(ntseg2) | + FDCAN_DBTP_DSJW(nsjw); + } + else +#endif + { + priv->nbtp = FDCAN_NBTP_NBRP(nbrp) | + FDCAN_NBTP_NTSEG1(ntseg1) | + FDCAN_NBTP_NTSEG2(ntseg2) | + FDCAN_NBTP_NSJW(nsjw); + } /* We need to reset to instantiate the new timing. Save * current state information so that recover to this diff --git a/include/nuttx/can/can.h b/include/nuttx/can/can.h index 59646b54a1..6eb7847ad7 100644 --- a/include/nuttx/can/can.h +++ b/include/nuttx/can/can.h @@ -438,6 +438,11 @@ #define CAN_FILTER_DUAL 1 /* Dual address match */ #define CAN_FILTER_RANGE 2 /* Match a range of addresses */ +/* CAN bit timing support ***************************************************/ + +#define CAN_BITTIMING_NOMINAL 0 /* Specifies nominal bittiming */ +#define CAN_BITTIMING_DATA 1 /* Specifies data bittiming */ + /**************************************************************************** * Public Types ****************************************************************************/ @@ -713,6 +718,13 @@ struct canioc_rtr_s struct canioc_bittiming_s { +#ifdef CONFIG_CAN_FD + uint8_t type; /* Nominal/Data bit timing. This is + * used to specify which bit timing + * should be set/obtained. Applies + * only if CAN FD is configured. + */ +#endif uint32_t bt_baud; /* Bit rate = 1 / bit time */ uint8_t bt_tseg1; /* TSEG1 in time quanta */ uint8_t bt_tseg2; /* TSEG2 in time quanta */