From ebc9f6554382ec9d6c141673ccd3c33bfb66bfbd Mon Sep 17 00:00:00 2001 From: Jacob Dahl Date: Sun, 30 Aug 2026 14:38:00 -0600 Subject: [PATCH 1/4] arch/arm/src/stm32h7: Remove broken FDCAN filter ioctl stubs. The SIOCxCANxxFILTER cases in fdcan_netdev_ioctl() call stm32_addextfilter(), stm32_delextfilter(), stm32_addstdfilter() and stm32_delstdfilter(), none of which exist anywhere in the tree. The block only ever compiled because no stm32h7 config enables NETDEV_CAN_FILTER_IOCTL; enabling it breaks the link. The commands now fall through to the existing -ENOTSUP default, which is also what a caller observed before. Assisted-by: Claude:claude-fable-5 Signed-off-by: Jacob Dahl --- arch/arm/src/stm32h7/stm32_fdcan_sock.c | 34 ------------------------- 1 file changed, 34 deletions(-) diff --git a/arch/arm/src/stm32h7/stm32_fdcan_sock.c b/arch/arm/src/stm32h7/stm32_fdcan_sock.c index 15eecf55a7ec6..8585bc01d3773 100644 --- a/arch/arm/src/stm32h7/stm32_fdcan_sock.c +++ b/arch/arm/src/stm32h7/stm32_fdcan_sock.c @@ -1987,40 +1987,6 @@ static int fdcan_netdev_ioctl(struct net_driver_s *dev, int cmd, break; #endif /* CONFIG_NETDEV_CAN_BITRATE_IOCTL */ -#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL - case SIOCACANEXTFILTER: - { - /* TODO: Add hardware-level filter... */ - - stm32_addextfilter(priv, (struct canioc_extfilter_s *)arg); - } - break; - - case SIOCDCANEXTFILTER: - { - /* TODO: Delete hardware-level filter... */ - - stm32_delextfilter(priv, (struct canioc_extfilter_s *)arg); - } - break; - - case SIOCACANSTDFILTER: - { - /* TODO: Add hardware-level filter... */ - - stm32_addstdfilter(priv, (struct canioc_stdfilter_s *)arg); - } - break; - - case SIOCDCANSTDFILTER: - { - /* TODO: Delete hardware-level filter... */ - - stm32_delstdfilter(priv, (struct canioc_stdfilter_s *)arg); - } - break; -#endif - default: ret = -ENOTSUP; break; From 7ab7535df092f48c9324478aff2915e1c006d497 Mon Sep 17 00:00:00 2001 From: Jacob Dahl Date: Sun, 30 Aug 2026 14:38:34 -0600 Subject: [PATCH 2/4] net/netdev: Combine the per-command CAN ioctl options into NETDEV_CAN_IOCTL NETDEV_CAN_BITRATE_IOCTL, NETDEV_CAN_FILTER_IOCTL and NETDEV_CAN_STATE_IOCTL guarded identical option blocks, and every SIOCxCANxxx case in netdev_ifr_ioctl() forwarded a member of the same ifr_ifru union to d_ioctl(). One option and one case block now cover all of the CAN commands; drivers and defconfigs are updated to the new name. Assisted-by: Claude:claude-fable-5 Signed-off-by: Jacob Dahl --- arch/arm/src/imx9/imx9_flexcan.c | 2 +- arch/arm/src/imxrt/imxrt_flexcan.c | 2 +- arch/arm/src/kinetis/kinetis_flexcan.c | 2 +- arch/arm/src/s32k1xx/s32k1xx_flexcan.c | 2 +- arch/arm/src/s32k3xx/s32k3xx_flexcan.c | 2 +- arch/arm/src/stm32h7/stm32_fdcan_sock.c | 4 +- arch/arm64/src/imx9/imx9_flexcan.c | 10 ++-- arch/risc-v/src/mpfs/mpfs_can.c | 21 ++++----- .../configs/can_socket/defconfig | 2 +- .../arm/imx9/imx95-evk/configs/can/defconfig | 2 +- .../configs/socketcan/defconfig | 2 +- .../configs/socketcan/defconfig | 2 +- .../nucleo-h753zi/configs/socketcan/defconfig | 2 +- boards/sim/sim/sim/configs/dynconns/defconfig | 3 +- net/netdev/Kconfig | 26 ++--------- net/netdev/netdev_ioctl.c | 46 ++++--------------- 16 files changed, 40 insertions(+), 90 deletions(-) diff --git a/arch/arm/src/imx9/imx9_flexcan.c b/arch/arm/src/imx9/imx9_flexcan.c index 9550597b84f4e..c362866a7db38 100644 --- a/arch/arm/src/imx9/imx9_flexcan.c +++ b/arch/arm/src/imx9/imx9_flexcan.c @@ -1544,7 +1544,7 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, switch (cmd) { -#ifdef CONFIG_NETDEV_CAN_BITRATE_IOCTL +#ifdef CONFIG_NETDEV_CAN_IOCTL case SIOCGCANBITRATE: /* Get bitrate from a CAN controller */ { struct can_ioctl_data_s *req = diff --git a/arch/arm/src/imxrt/imxrt_flexcan.c b/arch/arm/src/imxrt/imxrt_flexcan.c index 6ce94a58bb1ff..598f438dabfd9 100644 --- a/arch/arm/src/imxrt/imxrt_flexcan.c +++ b/arch/arm/src/imxrt/imxrt_flexcan.c @@ -1591,7 +1591,7 @@ static int imxrt_ioctl(struct net_driver_s *dev, int cmd, switch (cmd) { -#ifdef CONFIG_NETDEV_CAN_BITRATE_IOCTL +#ifdef CONFIG_NETDEV_CAN_IOCTL case SIOCGCANBITRATE: /* Get bitrate from a CAN controller */ { struct can_ioctl_data_s *req = diff --git a/arch/arm/src/kinetis/kinetis_flexcan.c b/arch/arm/src/kinetis/kinetis_flexcan.c index e93a41bb3ebc4..e36bb9a19493b 100644 --- a/arch/arm/src/kinetis/kinetis_flexcan.c +++ b/arch/arm/src/kinetis/kinetis_flexcan.c @@ -1477,7 +1477,7 @@ static int kinetis_txavail(struct net_driver_s *dev) * ****************************************************************************/ -#ifdef CONFIG_NETDEV_CAN_BITRATE_IOCTL +#ifdef CONFIG_NETDEV_CAN_IOCTL static int kinetis_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { diff --git a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c index 519ade4919ea8..bb124873c61df 100644 --- a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c +++ b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c @@ -1460,7 +1460,7 @@ static int s32k1xx_txavail(struct net_driver_s *dev) * ****************************************************************************/ -#ifdef CONFIG_NETDEV_CAN_BITRATE_IOCTL +#ifdef CONFIG_NETDEV_CAN_IOCTL static int s32k1xx_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { diff --git a/arch/arm/src/s32k3xx/s32k3xx_flexcan.c b/arch/arm/src/s32k3xx/s32k3xx_flexcan.c index f5aa309dea61b..340acbb5a8924 100644 --- a/arch/arm/src/s32k3xx/s32k3xx_flexcan.c +++ b/arch/arm/src/s32k3xx/s32k3xx_flexcan.c @@ -1658,7 +1658,7 @@ static int s32k3xx_ioctl(struct net_driver_s *dev, int cmd, switch (cmd) { -#ifdef CONFIG_NETDEV_CAN_BITRATE_IOCTL +#ifdef CONFIG_NETDEV_CAN_IOCTL case SIOCGCANBITRATE: /* Get bitrate from a CAN controller */ { struct can_ioctl_data_s *req = diff --git a/arch/arm/src/stm32h7/stm32_fdcan_sock.c b/arch/arm/src/stm32h7/stm32_fdcan_sock.c index 8585bc01d3773..e8e0ea6bc776f 100644 --- a/arch/arm/src/stm32h7/stm32_fdcan_sock.c +++ b/arch/arm/src/stm32h7/stm32_fdcan_sock.c @@ -1956,7 +1956,7 @@ static int fdcan_netdev_ioctl(struct net_driver_s *dev, int cmd, switch (cmd) { -#ifdef CONFIG_NETDEV_CAN_BITRATE_IOCTL +#ifdef CONFIG_NETDEV_CAN_IOCTL case SIOCGCANBITRATE: /* Get bitrate from a CAN controller */ { struct can_ioctl_data_s *req = @@ -1985,7 +1985,7 @@ static int fdcan_netdev_ioctl(struct net_driver_s *dev, int cmd, ret = OK; } break; -#endif /* CONFIG_NETDEV_CAN_BITRATE_IOCTL */ +#endif default: ret = -ENOTSUP; diff --git a/arch/arm64/src/imx9/imx9_flexcan.c b/arch/arm64/src/imx9/imx9_flexcan.c index 7936477dce5d2..620dc5c6f8e2a 100644 --- a/arch/arm64/src/imx9/imx9_flexcan.c +++ b/arch/arm64/src/imx9/imx9_flexcan.c @@ -554,7 +554,7 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, /* CAN ID filtering */ -#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL +#ifdef CONFIG_NETDEV_CAN_IOCTL static uint32_t imx9_add_filter(struct imx9_driver_s *priv, uint8_t filter_type, bool ext_id, @@ -1607,7 +1607,7 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, switch (cmd) { -#ifdef CONFIG_NETDEV_CAN_BITRATE_IOCTL +#ifdef CONFIG_NETDEV_CAN_IOCTL case SIOCGCANBITRATE: /* Get bitrate from a CAN controller */ { struct imx9_driver_s *priv = (struct imx9_driver_s *)dev; @@ -1660,9 +1660,7 @@ 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; @@ -1728,7 +1726,7 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, * ****************************************************************************/ -#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL +#ifdef CONFIG_NETDEV_CAN_IOCTL static uint32_t imx9_add_filter(struct imx9_driver_s *priv, uint8_t filter_type, bool ext_id, @@ -1869,7 +1867,7 @@ static uint8_t imx9_reset_filter(struct imx9_driver_s *priv) return OK; } -#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ +#endif /* CONFIG_NETDEV_CAN_IOCTL */ /**************************************************************************** * Function: imx9_init_eccram diff --git a/arch/risc-v/src/mpfs/mpfs_can.c b/arch/risc-v/src/mpfs/mpfs_can.c index 7c2cd99af5c80..faa0c6d4eaf20 100644 --- a/arch/risc-v/src/mpfs/mpfs_can.c +++ b/arch/risc-v/src/mpfs/mpfs_can.c @@ -474,12 +474,12 @@ static int mpfs_interrupt(int irq, void *context, void *arg); /* RX SW/HW filter related functions */ -#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL +#ifdef CONFIG_NETDEV_CAN_IOCTL static uint8_t mpfs_can_add_filter(mpfs_can_instance_t *priv, uint8_t filter_type, uint32_t filter_id1, uint32_t filter_id2); -#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ +#endif /* CONFIG_NETDEV_CAN_IOCTL */ static uint8_t mpfs_can_reset_filter(mpfs_can_instance_t *priv); @@ -523,7 +523,7 @@ static uint32_t mpfs_can_canid_to_msgid(uint32_t canid); static uint32_t mpfs_can_msgid_to_canid(uint32_t id, bool ide, bool rtr); static uint8_t mpfs_can_set_bitrate(mpfs_can_instance_t *priv, uint32_t bitrate); -#if defined(CONFIG_DEBUG_NET_INFO) || defined(CONFIG_NETDEV_CAN_BITRATE_IOCTL) +#if defined(CONFIG_DEBUG_NET_INFO) || defined(CONFIG_NETDEV_CAN_IOCTL) static uint32_t mpfs_can_get_sample_point(mpfs_can_instance_t *priv); #endif @@ -1081,7 +1081,7 @@ static int mpfs_interrupt(int irq, void *context, void *arg) * ****************************************************************************/ -#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL +#ifdef CONFIG_NETDEV_CAN_IOCTL static uint8_t mpfs_can_add_filter(mpfs_can_instance_t *priv, uint8_t filter_type, uint32_t filter_id1, @@ -1137,7 +1137,7 @@ static uint8_t mpfs_can_add_filter(mpfs_can_instance_t *priv, return CAN_OK; } -#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ +#endif /* CONFIG_NETDEV_CAN_IOCTL */ /**************************************************************************** * Name: mpfs_can_reset_filter @@ -1734,7 +1734,7 @@ static uint8_t mpfs_can_set_bitrate(mpfs_can_instance_t *priv, return CAN_OK; } -#if defined(CONFIG_DEBUG_NET_INFO) || defined(CONFIG_NETDEV_CAN_BITRATE_IOCTL) +#if defined(CONFIG_DEBUG_NET_INFO) || defined(CONFIG_NETDEV_CAN_IOCTL) /**************************************************************************** * Name: mpfs_can_get_sample_point * @@ -2299,8 +2299,7 @@ static int mpfs_ioctl(struct netdev_lowerhalf_s *dev, int cmd, { ninfo("IOCTL received | cmd: %d arg: %ld\n", cmd, arg); -#if defined(CONFIG_NETDEV_CAN_BITRATE_IOCTL) || \ -defined(CONFIG_NETDEV_CAN_FILTER_IOCTL) +#ifdef CONFIG_NETDEV_CAN_IOCTL mpfs_can_instance_t *priv = (mpfs_can_instance_t *)dev; #endif @@ -2308,7 +2307,7 @@ defined(CONFIG_NETDEV_CAN_FILTER_IOCTL) switch (cmd) { -#ifdef CONFIG_NETDEV_CAN_BITRATE_IOCTL +#ifdef CONFIG_NETDEV_CAN_IOCTL case SIOCGCANBITRATE: /* Get bitrate from the CAN controller */ @@ -2340,9 +2339,7 @@ defined(CONFIG_NETDEV_CAN_FILTER_IOCTL) ret = CAN_OK; } break; -#endif /* CONFIG_NETDEV_CAN_BITRATE_IOCTL */ -#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL case SIOCACANSTDFILTER: case SIOCACANEXTFILTER: @@ -2370,7 +2367,7 @@ defined(CONFIG_NETDEV_CAN_FILTER_IOCTL) ret = CAN_OK; } break; -#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ +#endif /* CONFIG_NETDEV_CAN_IOCTL */ default: ret = -ENOTTY; diff --git a/boards/arm/at32/at32f437-mini/configs/can_socket/defconfig b/boards/arm/at32/at32f437-mini/configs/can_socket/defconfig index a35c092537e33..7d2f6556e37eb 100644 --- a/boards/arm/at32/at32f437-mini/configs/can_socket/defconfig +++ b/boards/arm/at32/at32f437-mini/configs/can_socket/defconfig @@ -38,7 +38,7 @@ CONFIG_INIT_ENTRYPOINT="nsh_main" CONFIG_INTELHEX_BINARY=y CONFIG_LINE_MAX=64 CONFIG_NET=y -CONFIG_NETDEV_CAN_BITRATE_IOCTL=y +CONFIG_NETDEV_CAN_IOCTL=y CONFIG_NETDEV_IFINDEX=y CONFIG_NET_CAN=y CONFIG_NET_CAN_SOCK_OPTS=y diff --git a/boards/arm/imx9/imx95-evk/configs/can/defconfig b/boards/arm/imx9/imx95-evk/configs/can/defconfig index 7510776e90a63..fb147108d64f1 100644 --- a/boards/arm/imx9/imx95-evk/configs/can/defconfig +++ b/boards/arm/imx9/imx95-evk/configs/can/defconfig @@ -54,7 +54,7 @@ CONFIG_IOB_THROTTLE=8 CONFIG_LIBC_LOCALTIME=y CONFIG_LPUART3_SERIAL_CONSOLE=y CONFIG_NET=y -CONFIG_NETDEV_CAN_BITRATE_IOCTL=y +CONFIG_NETDEV_CAN_IOCTL=y CONFIG_NETDEV_IFINDEX=y CONFIG_NETDEV_LATEINIT=y CONFIG_NET_CAN=y diff --git a/boards/arm/stm32h7/linum-stm32h753bi/configs/socketcan/defconfig b/boards/arm/stm32h7/linum-stm32h753bi/configs/socketcan/defconfig index 7ef37a7cbf763..0e9a1e41a1a7a 100644 --- a/boards/arm/stm32h7/linum-stm32h753bi/configs/socketcan/defconfig +++ b/boards/arm/stm32h7/linum-stm32h753bi/configs/socketcan/defconfig @@ -44,7 +44,7 @@ CONFIG_INTELHEX_BINARY=y CONFIG_LINE_MAX=64 CONFIG_MM_REGIONS=4 CONFIG_NET=y -CONFIG_NETDEV_CAN_BITRATE_IOCTL=y +CONFIG_NETDEV_CAN_IOCTL=y CONFIG_NETDEV_IFINDEX=y CONFIG_NETDEV_LATEINIT=y CONFIG_NET_CAN=y diff --git a/boards/arm/stm32h7/nucleo-h743zi2/configs/socketcan/defconfig b/boards/arm/stm32h7/nucleo-h743zi2/configs/socketcan/defconfig index 68c89eacc79d3..66d1e74be6618 100644 --- a/boards/arm/stm32h7/nucleo-h743zi2/configs/socketcan/defconfig +++ b/boards/arm/stm32h7/nucleo-h743zi2/configs/socketcan/defconfig @@ -40,7 +40,7 @@ CONFIG_INTELHEX_BINARY=y CONFIG_LINE_MAX=64 CONFIG_MM_REGIONS=4 CONFIG_NET=y -CONFIG_NETDEV_CAN_BITRATE_IOCTL=y +CONFIG_NETDEV_CAN_IOCTL=y CONFIG_NETDEV_IFINDEX=y CONFIG_NETDEV_LATEINIT=y CONFIG_NET_CAN=y diff --git a/boards/arm/stm32h7/nucleo-h753zi/configs/socketcan/defconfig b/boards/arm/stm32h7/nucleo-h753zi/configs/socketcan/defconfig index f9643ef1a1a8f..61cc0fe7c178b 100644 --- a/boards/arm/stm32h7/nucleo-h753zi/configs/socketcan/defconfig +++ b/boards/arm/stm32h7/nucleo-h753zi/configs/socketcan/defconfig @@ -40,7 +40,7 @@ CONFIG_INTELHEX_BINARY=y CONFIG_LINE_MAX=64 CONFIG_MM_REGIONS=4 CONFIG_NET=y -CONFIG_NETDEV_CAN_BITRATE_IOCTL=y +CONFIG_NETDEV_CAN_IOCTL=y CONFIG_NETDEV_IFINDEX=y CONFIG_NETDEV_LATEINIT=y CONFIG_NET_CAN=y diff --git a/boards/sim/sim/sim/configs/dynconns/defconfig b/boards/sim/sim/sim/configs/dynconns/defconfig index c009442b847d6..df646edceb3a0 100644 --- a/boards/sim/sim/sim/configs/dynconns/defconfig +++ b/boards/sim/sim/sim/configs/dynconns/defconfig @@ -35,8 +35,7 @@ CONFIG_MM_FILL_ALLOCATIONS=y CONFIG_NAME_MAX=64 CONFIG_NET=y CONFIG_NETDB_DNSCLIENT=y -CONFIG_NETDEV_CAN_BITRATE_IOCTL=y -CONFIG_NETDEV_CAN_FILTER_IOCTL=y +CONFIG_NETDEV_CAN_IOCTL=y CONFIG_NETDEV_LATEINIT=y CONFIG_NETDEV_PHY_IOCTL=y CONFIG_NETDOWN_NOTIFIER=y diff --git a/net/netdev/Kconfig b/net/netdev/Kconfig index 227b5c2d58f54..5570cd1602734 100644 --- a/net/netdev/Kconfig +++ b/net/netdev/Kconfig @@ -16,31 +16,15 @@ config NETDEV_PHY_IOCTL ---help--- Enable support for ioctl() commands to access PHY registers -config NETDEV_CAN_BITRATE_IOCTL - bool "Enable CAN bitrate ioctl()" +config NETDEV_CAN_IOCTL + bool "Enable CAN ioctl()" default n select NETDEV_IOCTL depends on NET_CAN ---help--- - Enable support for ioctl() commands to change CAN bitrate - -config NETDEV_CAN_FILTER_IOCTL - bool "Enable CAN filter ioctl()" - default n - select NETDEV_IOCTL - depends on NET_CAN - ---help--- - Enable support for ioctl() commands to add/remove CAN hardware-level - filters (NOTE: Not supported by all drivers) - -config NETDEV_CAN_STATE_IOCTL - bool "Enable CAN state ioctl()" - default n - select NETDEV_IOCTL - depends on NET_CAN - ---help--- - Enable support for ioctl() commands to set/see CAN or LIN controller-state - (NOTE: Not supported by all drivers) + Enable support for the CAN network device ioctl() commands: + bitrate, hardware-level filters and CAN/LIN controller state + (NOTE: Not every command is supported by every driver) config NETDEV_WIRELESS_IOCTL bool "Enable Wireless ioctl()" diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c index 038ca7f1a5d54..e49e449390c39 100644 --- a/net/netdev/netdev_ioctl.c +++ b/net/netdev/netdev_ioctl.c @@ -1244,7 +1244,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, break; #endif -#if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NETDEV_CAN_BITRATE_IOCTL) +#if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NETDEV_CAN_IOCTL) case SIOCSCANBITRATE: /* Set bitrate of a CAN controller */ if (dev->d_flags & IFF_UP) { @@ -1254,52 +1254,24 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, break; } - /* If down, fall-through to common code in SIOCGCANBITRATE. */ + /* If down, fall-through to the common CAN ioctl code. */ - case SIOCGCANBITRATE: /* Get bitrate from a CAN controller */ - if (dev->d_ioctl) - { - FAR struct can_ioctl_data_s *can_bitrate_data = - &req->ifr_ifru.ifru_can_data; - ret = dev->d_ioctl(dev, cmd, - (unsigned long)(uintptr_t)can_bitrate_data); - } - else - { - ret = -ENOSYS; - } - break; -#endif - -#if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NETDEV_CAN_FILTER_IOCTL) + case SIOCGCANBITRATE: /* Get bitrate from a CAN controller */ case SIOCACANEXTFILTER: /* Add an extended-ID filter */ case SIOCDCANEXTFILTER: /* Delete an extended-ID filter */ case SIOCACANSTDFILTER: /* Add a standard-ID filter */ case SIOCDCANSTDFILTER: /* Delete a standard-ID filter */ case SIOCCANRECOVERY: /* Recovery can controller when bus-off */ + case SIOCGCANSTATE: /* Get state from a CAN/LIN controller */ + case SIOCSCANSTATE: /* Set the LIN/CAN controller state */ if (dev->d_ioctl) { - FAR struct can_ioctl_filter_s *can_filter = - &req->ifr_ifru.ifru_can_filter; - ret = dev->d_ioctl(dev, cmd, - (unsigned long)(uintptr_t)can_filter); - } - else - { - ret = -ENOSYS; - } - break; -#endif + /* Every CAN ioctl argument struct is a member of the + * ifr_ifru union, so cmd's struct is at its address. + */ -#if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NETDEV_CAN_STATE_IOCTL) - case SIOCGCANSTATE: /* Get state from a CAN/LIN controller */ - case SIOCSCANSTATE: /* Set the LIN/CAN controller state */ - if (dev->d_ioctl) - { - FAR struct can_ioctl_state_s *can_state = - &req->ifr_ifru.ifru_can_state; ret = dev->d_ioctl(dev, cmd, - (unsigned long)(uintptr_t)can_state); + (unsigned long)(uintptr_t)&req->ifr_ifru); } else { From c8c736fb8a475076a5cdd872324f3a035c3005a6 Mon Sep 17 00:00:00 2001 From: Jacob Dahl Date: Sun, 30 Aug 2026 14:38:34 -0600 Subject: [PATCH 3/4] arch/arm/src/imxrt: Unify FlexCAN TX work and add SIOCGCANERRORS. TX-complete and the deadline watchdog each queued their own callback on the same work_s, and work_queue() cancels whatever is pending when a work_s is reused, so whichever ran second was dropped: deadlines were left set, the TX interrupt mask stayed off, or expired frames were never aborted. Both now queue imxrt_tx_work(), which retires completions before it aborts expired mailboxes. Add SIOCGCANERRORS so a socket can read fault confinement, TEC/REC, a monotonic bus error count and the RX mailbox overrun count. SIOCGCANSTATE reports sleep/operational, not fault confinement, hence a new command. The error count is sampled from the clear-on-read ESR1 error flags at every driver entry rather than from ERRINT, which fires per error frame and storms at bus rate once the bus is dead. Frames the CAN socket layer drops for want of an IOB now count as rx_dropped in the netdev statistics as well as in the global CAN statistics. Tested on an i.MX RT1176 (ARK FMU-v6XRT) running PX4 with two DroneCAN nodes: unplugging one node the ioctl reports error-passive, TEC 128, REC 0 and a monotonic error count, matching ECR/ESR1 read over SWD at 20 Hz, while the other interface stays error-active with zero errors. Assisted-by: Claude:claude-fable-5 Signed-off-by: Jacob Dahl --- arch/arm/src/imxrt/hardware/imxrt_flexcan.h | 7 + arch/arm/src/imxrt/imxrt_flexcan.c | 170 ++++++++++++++++---- include/net/if.h | 21 +++ include/nuttx/net/ioctl.h | 2 + net/can/can_callback.c | 1 + net/netdev/Kconfig | 3 +- net/netdev/netdev_ioctl.c | 2 + 7 files changed, 172 insertions(+), 34 deletions(-) diff --git a/arch/arm/src/imxrt/hardware/imxrt_flexcan.h b/arch/arm/src/imxrt/hardware/imxrt_flexcan.h index d55ac68ee1c77..a1e7df4c594f1 100644 --- a/arch/arm/src/imxrt/hardware/imxrt_flexcan.h +++ b/arch/arm/src/imxrt/hardware/imxrt_flexcan.h @@ -435,6 +435,13 @@ #define CAN_FDCRC_FD_MBCRC(x) (((uint32_t)(((uint32_t)(x)) << CAN_FDCRC_FD_MBCRC_SHIFT)) & CAN_FDCRC_FD_MBCRC_MASK) /* Bit 31: Reserved */ +/* CAN MB RX codes */ + +#define CAN_RXMB_INACTIVE 0x0 /* MB is not active. */ +#define CAN_RXMB_FULL 0x2 /* MB is full. */ +#define CAN_RXMB_EMPTY 0x4 /* MB is empty. */ +#define CAN_RXMB_OVERRUN 0x6 /* MB is overwritten into a full buffer. */ + /* CAN MB TX codes */ #define CAN_TXMB_INACTIVE 0x8 /* MB is not active. */ #define CAN_TXMB_ABORT 0x9 /* MB is aborted. */ diff --git a/arch/arm/src/imxrt/imxrt_flexcan.c b/arch/arm/src/imxrt/imxrt_flexcan.c index 598f438dabfd9..d1e8f4ef14930 100644 --- a/arch/arm/src/imxrt/imxrt_flexcan.c +++ b/arch/arm/src/imxrt/imxrt_flexcan.c @@ -298,6 +298,9 @@ struct imxrt_driver_s #ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE struct txmbstats txmb[TXMBRINGSIZE]; #endif + + uint32_t bus_errors; /* ESR1 error flags observed, monotonic */ + uint32_t rx_overruns; /* RX mailbox CODE=OVERRUN count */ }; /**************************************************************************** @@ -488,7 +491,7 @@ static struct mb_s *flexcan_get_mb(struct imxrt_driver_s *priv, static void imxrt_receive(struct imxrt_driver_s *priv, uint32_t flags); -static void imxrt_txdone_work(void *arg); +static void imxrt_tx_work(void *arg); static void imxrt_txdone(struct imxrt_driver_s *priv); static int imxrt_flexcan_interrupt(int irq, void *context, @@ -497,7 +500,7 @@ static void imxrt_flexcan_interrupt_work(void *arg); /* Watchdog timer expirations */ #ifdef TX_TIMEOUT_WQ -static void imxrt_txtimeout_work(void *arg); +static void imxrt_txtimeout_abort(struct imxrt_driver_s *priv); static void imxrt_txtimeout_expiry(wdparm_t arg); #endif @@ -523,6 +526,54 @@ static void imxrt_reset(struct imxrt_driver_s *priv); * Private Functions ****************************************************************************/ +/* ESR1 error flags. Every one is set by the protocol engine on the matching + * bus error and cleared when ESR1 is read, so a read reports the error + * types seen since the previous read. Sampling them at every driver entry + * gives a monotonic error count without the ERRINT interrupt, which fires + * once per error frame and storms at bus rate on a dead bus. + */ + +#define ESR1_ERRFLAGS (CAN_ESR1_STFERR | CAN_ESR1_FRMERR | CAN_ESR1_CRCERR | \ + CAN_ESR1_ACKERR | CAN_ESR1_BIT0ERR | CAN_ESR1_BIT1ERR | \ + CAN_ESR1_STFERRFAST | CAN_ESR1_FRMERRFAST | \ + CAN_ESR1_CRCERRFAST | CAN_ESR1_BIT0ERRFAST | \ + CAN_ESR1_BIT1ERRFAST) + +/**************************************************************************** + * Function: imxrt_sample_errors + * + * Description: + * Read ESR1, clearing its error flags, and add the number of set flags + * to the bus error count. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * The ESR1 value that was read. + * + ****************************************************************************/ + +static uint32_t imxrt_sample_errors(struct imxrt_driver_s *priv) +{ + irqstate_t flags; + uint32_t esr1; + uint32_t errs; + + flags = spin_lock_irqsave(NULL); + + esr1 = getreg32(priv->base + IMXRT_CAN_ESR1_OFFSET); + + for (errs = esr1 & ESR1_ERRFLAGS; errs != 0; errs &= errs - 1) + { + priv->bus_errors++; + } + + spin_unlock_irqrestore(NULL, flags); + + return esr1; +} + /**************************************************************************** * Function: imxrt_txmb_next * @@ -895,6 +946,13 @@ static void imxrt_receive(struct imxrt_driver_s *priv, rf = flexcan_get_mb(priv, mbi); + /* CODE is in CS; read it before unlocking the mailbox via IFLAG. */ + + if (rf->cs.code == CAN_RXMB_OVERRUN) + { + priv->rx_overruns++; + } + /* Read the frame contents */ #ifdef CONFIG_NET_CAN_CANFD @@ -1067,7 +1125,7 @@ static void imxrt_txdone(struct imxrt_driver_s *priv) /* Retire the deadline with the frame. Left behind it sits in the * past forever, and the next expiry of any other mailbox's - * watchdog makes imxrt_txtimeout_work() abort whatever frame has + * watchdog makes imxrt_txtimeout_abort() abort whatever frame has * since been loaded here. */ @@ -1089,35 +1147,48 @@ static void imxrt_txdone(struct imxrt_driver_s *priv) } /**************************************************************************** - * Function: imxrt_txdone_work + * Function: imxrt_tx_work * * Description: - * An interrupt was received indicating that the last TX packet(s) is done + * Process TX completions and deadline aborts on the worker thread, then + * poll for more data. TX-complete IRQs and the deadline watchdog both + * queue this function on the same work_s; work_queue() cancels a pending + * callback when that work_s is reused, so splitting them lost whichever + * ran second (deadlines left set, TX IMASK left off, expired frames + * never aborted). * * Input Parameters: - * priv - Reference to the driver state structure + * arg - Reference to the driver state structure * * Returned Value: * None * - * Assumptions: - * Global interrupts are disabled by the watchdog logic. - * We are not in an interrupt context so that we can lock the network. - * ****************************************************************************/ -static void imxrt_txdone_work(void *arg) +static void imxrt_tx_work(void *arg) { struct imxrt_driver_s *priv = (struct imxrt_driver_s *)arg; + imxrt_sample_errors(priv); imxrt_txdone(priv); - /* There should be space for a new TX in any event. Poll the network for - * new XMIT data +#ifdef TX_TIMEOUT_WQ + imxrt_txtimeout_abort(priv); +#endif + + /* The TX IRQ masked every TX mailbox to stop the interrupt storm. + * Restore the mask so abort completions and later transmits can + * interrupt. txdone() already cleared completion flags. */ + modifyreg32(priv->base + IMXRT_CAN_IMASK1_OFFSET, 0, IFLAG1_TX); + net_lock(); - devif_poll(&priv->dev, imxrt_txpoll); + if (priv->bifup) + { + devif_poll(&priv->dev, imxrt_txpoll); + } + net_unlock(); } @@ -1150,6 +1221,8 @@ static void imxrt_flexcan_interrupt_work(void *arg) flags = getreg32(priv->base + IMXRT_CAN_IFLAG1_OFFSET); flags &= IFLAG1_RX; + imxrt_sample_errors(priv); + net_lock(); imxrt_receive(priv, flags); net_unlock(); @@ -1208,7 +1281,7 @@ static int imxrt_flexcan_interrupt(int irq, void *context, */ modifyreg32(priv->base + IMXRT_CAN_IMASK1_OFFSET, IFLAG1_TX, 0); - work_queue(CANWORK, &priv->irqwork, imxrt_txdone_work, priv, 0); + work_queue(CANWORK, &priv->irqwork, imxrt_tx_work, priv, 0); } } @@ -1216,25 +1289,24 @@ static int imxrt_flexcan_interrupt(int irq, void *context, } /**************************************************************************** - * Function: imxrt_txtimeout_work + * Function: imxrt_txtimeout_abort * * Description: - * Perform TX timeout related work from the worker thread + * Abort TX mailboxes whose deadline has passed. Called from + * imxrt_tx_work() after completions have been retired so a just-finished + * mailbox is not aborted on a stale deadline. * * Input Parameters: - * arg - The argument passed when work_queue() as called. + * priv - Reference to the driver state structure * * Returned Value: - * OK on success - * - * Assumptions: + * None * ****************************************************************************/ #ifdef TX_TIMEOUT_WQ -static void imxrt_txtimeout_work(void *arg) +static void imxrt_txtimeout_abort(struct imxrt_driver_s *priv) { - struct imxrt_driver_s *priv = (struct imxrt_driver_s *)arg; uint32_t flags; uint32_t mbi; uint32_t mb_bit; @@ -1246,10 +1318,6 @@ static void imxrt_txtimeout_work(void *arg) now.tv_sec = ts.tv_sec; now.tv_usec = ts.tv_nsec / 1000; - /* The watchdog timed out, yet we still check mailboxes in case the - * transmit function transmitted a new frame - */ - flags = getreg32(priv->base + IMXRT_CAN_IFLAG1_OFFSET); for (mbi = 0; mbi < TXMBRINGSIZE; mbi++) @@ -1288,7 +1356,6 @@ static void imxrt_txtimeout_work(void *arg) mb = flexcan_get_mb(priv, RXMBCOUNT + 1 + mbi); mb->cs.code = CAN_TXMB_ABORT; - priv->txmb[mbi].pending = TX_ABORT; } } @@ -1297,7 +1364,8 @@ static void imxrt_txtimeout_work(void *arg) * * Description: * Our TX watchdog timed out. Called from the timer interrupt handler. - * The last TX never completed. Reset the hardware and start again. + * Queue the same TX worker as the completion IRQ so the two cannot + * cancel each other. * * Input Parameters: * arg - The argument @@ -1314,10 +1382,7 @@ static void imxrt_txtimeout_expiry(wdparm_t arg) { struct imxrt_driver_s *priv = (struct imxrt_driver_s *)arg; - /* Schedule to perform the TX timeout processing on the worker thread - */ - - work_queue(CANWORK, &priv->irqwork, imxrt_txtimeout_work, priv, 0); + work_queue(CANWORK, &priv->irqwork, imxrt_tx_work, priv, 0); } #endif @@ -1428,6 +1493,8 @@ static int imxrt_ifup(struct net_driver_s *dev) } priv->bifup = true; + priv->bus_errors = 0; + priv->rx_overruns = 0; priv->txdesc = (struct can_frame *)&g_tx_pool; priv->rxdesc = (struct can_frame *)&g_rx_pool; if (priv->canfd_capable) @@ -1660,7 +1727,44 @@ static int imxrt_ioctl(struct net_driver_s *dev, int cmd, } } break; + + case SIOCGCANERRORS: + { + struct can_ioctl_errors_s *req = + (struct can_ioctl_errors_s *)((uintptr_t)arg); + uint32_t esr1 = imxrt_sample_errors(priv); + uint32_t ecr = getreg32(priv->base + IMXRT_CAN_ECR_OFFSET); + uint32_t flt = (esr1 & CAN_ESR1_FLTCONF_MASK) >> + CAN_ESR1_FLTCONF_SHIFT; + + if (flt >= 2) + { + req->state = CAN_ERRSTATE_BUSOFF; + } + else if (flt == 1) + { + req->state = CAN_ERRSTATE_PASSIVE; + } + else if (esr1 & (CAN_ESR1_TXWRN | CAN_ESR1_RXWRN)) + { + req->state = CAN_ERRSTATE_WARNING; + } + else + { + req->state = CAN_ERRSTATE_ACTIVE; + } + + req->txerr = (ecr & CAN_ECR_TXERRCNT_MASK) >> + CAN_ECR_TXERRCNT_SHIFT; + req->rxerr = (ecr & CAN_ECR_RXERRCNT_MASK) >> + CAN_ECR_RXERRCNT_SHIFT; + req->errors = priv->bus_errors; + req->rx_overruns = priv->rx_overruns; + ret = OK; + } + break; #endif + default: ret = -ENOTTY; break; diff --git a/include/net/if.h b/include/net/if.h index db49af71b25ae..3f7174e46b9c1 100644 --- a/include/net/if.h +++ b/include/net/if.h @@ -237,6 +237,25 @@ struct can_ioctl_state_s enum can_ioctl_state_e state; }; +/* Fault confinement and error counters, SIOCGCANERRORS ioctl command. + * WARNING is error-active with either error counter at or above 96; + * PASSIVE and BUSOFF follow the controller's own state. + */ + +#define CAN_ERRSTATE_ACTIVE 0 +#define CAN_ERRSTATE_WARNING 1 +#define CAN_ERRSTATE_PASSIVE 2 +#define CAN_ERRSTATE_BUSOFF 3 + +struct can_ioctl_errors_s +{ + uint8_t state; /* CAN_ERRSTATE_* */ + uint8_t txerr; /* Transmit error counter (TEC) */ + uint8_t rxerr; /* Receive error counter (REC) */ + uint32_t errors; /* Bus errors observed since ifup, monotonic */ + uint32_t rx_overruns; /* RX frames the controller overwrote unread */ +}; + /* There are two forms of the I/F request structure. * One for IPv6 and one for IPv4. * Notice that they are (and must be) cast compatible and really different @@ -264,6 +283,7 @@ struct lifreq struct can_ioctl_data_s lifru_can_data; /* CAN bitrate request data */ struct can_ioctl_filter_s lifru_can_filter; /* CAN filter request data */ struct can_ioctl_state_s lifru_can_state; /* CAN/LIN controller state */ + struct can_ioctl_errors_s lifru_can_errors; /* CAN error counters */ } lifr_ifru; }; @@ -322,6 +342,7 @@ struct ifreq struct can_ioctl_data_s ifru_can_data; /* CAN bitrate request data */ struct can_ioctl_filter_s ifru_can_filter; /* CAN filter request data */ struct can_ioctl_state_s ifru_can_state; /* CAN/LIN controller state */ + struct can_ioctl_errors_s ifru_can_errors; /* CAN error counters */ FAR void *ifru_data; /* For use by interface */ } ifr_ifru; }; diff --git a/include/nuttx/net/ioctl.h b/include/nuttx/net/ioctl.h index 75bf689f9d565..b1519dddff570 100644 --- a/include/nuttx/net/ioctl.h +++ b/include/nuttx/net/ioctl.h @@ -127,6 +127,8 @@ #define SIOCCANRECOVERY _SIOC(0x0032) /* Recovery can, work only when bus-off state */ #define SIOCGCANSTATE _SIOC(0x0041) /* Get state from a CAN/LIN controller */ #define SIOCSCANSTATE _SIOC(0x0042) /* Set the LIN/CAN controller state */ +#define SIOCGCANERRORS _SIOC(0x0045) /* Get CAN error counters and fault + * confinement state */ /* Network socket control ***************************************************/ diff --git a/net/can/can_callback.c b/net/can/can_callback.c index 323e93893a0c0..667f1061496d0 100644 --- a/net/can/can_callback.c +++ b/net/can/can_callback.c @@ -92,6 +92,7 @@ can_data_event(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn, #ifdef CONFIG_NET_STATISTICS g_netstats.can.drop++; #endif + NETDEV_RXDROPPED(dev); } /* In any event, the new data has now been handled */ diff --git a/net/netdev/Kconfig b/net/netdev/Kconfig index 5570cd1602734..a040c471c2ca9 100644 --- a/net/netdev/Kconfig +++ b/net/netdev/Kconfig @@ -23,7 +23,8 @@ config NETDEV_CAN_IOCTL depends on NET_CAN ---help--- Enable support for the CAN network device ioctl() commands: - bitrate, hardware-level filters and CAN/LIN controller state + bitrate, hardware-level filters, CAN/LIN controller state and + error counters (NOTE: Not every command is supported by every driver) config NETDEV_WIRELESS_IOCTL diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c index e49e449390c39..64b6a04f3cdf2 100644 --- a/net/netdev/netdev_ioctl.c +++ b/net/netdev/netdev_ioctl.c @@ -775,6 +775,7 @@ static ssize_t net_ioctl_ifreq_arglen(uint8_t domain, int cmd) case SIOCCANRECOVERY: case SIOCGCANSTATE: case SIOCSCANSTATE: + case SIOCGCANERRORS: case SIOCSIFNAME: case SIOCGIFNAME: case SIOCGIFINDEX: @@ -1264,6 +1265,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, case SIOCCANRECOVERY: /* Recovery can controller when bus-off */ case SIOCGCANSTATE: /* Get state from a CAN/LIN controller */ case SIOCSCANSTATE: /* Set the LIN/CAN controller state */ + case SIOCGCANERRORS: /* Get CAN error counters and state */ if (dev->d_ioctl) { /* Every CAN ioctl argument struct is a member of the From 1a8dfc8469568a1ade9a82ca4ea0820cb52cef7a Mon Sep 17 00:00:00 2001 From: Jacob Dahl Date: Sun, 30 Aug 2026 14:38:42 -0600 Subject: [PATCH 4/4] net, arch: Fix nxstyle errors in files the CAN ioctl merge touches. Whitespace only: blank lines after declarations, misindented switch bodies and brace alignment. nxstyle runs over the whole of any file a change touches, and merging the CAN ioctl options renames a config in every SocketCAN driver. Assisted-by: Claude:claude-fable-5 Signed-off-by: Jacob Dahl --- arch/arm/src/imx9/imx9_flexcan.c | 231 +++++++++++++----------- arch/arm/src/kinetis/kinetis_flexcan.c | 108 ++++++----- arch/arm/src/s32k1xx/s32k1xx_flexcan.c | 95 +++++----- arch/arm/src/s32k3xx/s32k3xx_flexcan.c | 195 ++++++++++---------- arch/arm/src/stm32h7/stm32_fdcan_sock.c | 95 ++++++---- arch/arm64/src/imx9/imx9_flexcan.c | 44 +++-- arch/risc-v/src/mpfs/mpfs_can.c | 136 +++++++------- net/can/can_callback.c | 38 ++-- net/netdev/netdev_ioctl.c | 20 +- 9 files changed, 538 insertions(+), 424 deletions(-) diff --git a/arch/arm/src/imx9/imx9_flexcan.c b/arch/arm/src/imx9/imx9_flexcan.c index c362866a7db38..1bdaa09fdfbdc 100644 --- a/arch/arm/src/imx9/imx9_flexcan.c +++ b/arch/arm/src/imx9/imx9_flexcan.c @@ -628,6 +628,7 @@ static int imx9_transmit(struct imx9_driver_s *priv) /* Check whether message buffer is not currently transmitting */ struct mb_s *mb = flexcan_get_mb(priv, mbi); + if (mb->cs.code != CAN_TXMB_DATAORREMOTE) { putreg32(mb_bit, priv->base + IMX9_CAN_IFLAG1_OFFSET); @@ -650,12 +651,14 @@ static int imx9_transmit(struct imx9_driver_s *priv) #ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE struct timespec ts; + clock_systime_timespec(&ts); if (priv->dev.d_sndlen > priv->dev.d_len) { struct timeval *tv = (struct timeval *)(priv->dev.d_buf + priv->dev.d_len); + priv->txmb[txmb].deadline = *tv; timeout = (tv->tv_sec - ts.tv_sec)*CLK_TCK + ((tv->tv_usec - ts.tv_nsec / 1000)*CLK_TCK) / 1000000; @@ -690,9 +693,11 @@ static int imx9_transmit(struct imx9_driver_s *priv) (peak_tx_mailbox_index_ > mbi ? peak_tx_mailbox_index_ : mbi); union cs_e cs; + cs.cs = 0; cs.code = CAN_TXMB_DATAORREMOTE; struct mb_s *mb = flexcan_get_mb(priv, mbi); + mb->cs.code = CAN_TXMB_INACTIVE; if (priv->dev.d_len == sizeof(struct can_frame)) @@ -755,6 +760,7 @@ static int imx9_transmit(struct imx9_driver_s *priv) */ struct mb_s *buffer = flexcan_get_mb(priv, RXMBCOUNT); + buffer->cs.code = 0x3; buffer->cs.code = 0x3; @@ -878,11 +884,13 @@ static void imx9_receive(struct imx9_driver_s *priv, mbj = mbi = arm_lsb(f); rf = flexcan_get_mb(priv, mbi); uint32_t t = rf->cs.time_stamp; + while ((f &= ~(1 << mbj)) != 0) { mbj = arm_lsb(f); struct mb_s *rf_next = flexcan_get_mb(priv, mbj); uint16_t t_next = rf_next->cs.time_stamp; + if ((int16_t)(t - t_next) > 0) { t = t_next; @@ -897,7 +905,7 @@ static void imx9_receive(struct imx9_driver_s *priv, #ifdef CONFIG_NET_CAN_CANFD if (rf->cs.edl) /* CAN FD frame */ { - struct canfd_frame *frame = (struct canfd_frame *)priv->rxdesc_fd; + struct canfd_frame *frame = (struct canfd_frame *)priv->rxdesc_fd; if (rf->cs.ide) { @@ -938,7 +946,7 @@ static void imx9_receive(struct imx9_driver_s *priv, else /* CAN 2.0 Frame */ #endif { - struct can_frame *frame = (struct can_frame *)priv->rxdesc; + struct can_frame *frame = (struct can_frame *)priv->rxdesc; if (rf->cs.ide) { @@ -1058,6 +1066,7 @@ static void imx9_txdone(struct imx9_driver_s *priv) wd_cancel(&priv->txtimeout[txmb]); struct mb_s *mb = flexcan_get_mb(priv, mbi); + mb->cs.code = CAN_TXMB_INACTIVE; #endif } @@ -1128,6 +1137,7 @@ static void imx9_flexcan_interrupt_work(void *arg) struct imx9_driver_s *priv = (struct imx9_driver_s *)arg; uint32_t flags; + flags = getreg32(priv->base + IMX9_CAN_IFLAG1_OFFSET); flags &= IFLAG1_RX; @@ -1168,6 +1178,7 @@ static int imx9_flexcan_interrupt(int irq, void *context, if (irq == priv->config->irq) { uint32_t flags; + flags = getreg32(priv->base + IMX9_CAN_IFLAG1_OFFSET); flags &= IFLAG1_RX; @@ -1221,6 +1232,7 @@ static void imx9_txtimeout_work(void *arg) struct timespec ts; struct timeval *now = (struct timeval *)&ts; + clock_systime_timespec(&ts); now->tv_usec = ts.tv_nsec / 1000; /* timespec to timeval conversion */ @@ -1246,6 +1258,7 @@ static void imx9_txtimeout_work(void *arg) } struct mb_s *mb = flexcan_get_mb(priv, mbi + RXMBCOUNT); + mb->cs.code = CAN_TXMB_ABORT; priv->txmb[mbi].pending = TX_ABORT; } @@ -1305,6 +1318,7 @@ static void imx9_setenable(uint32_t base, uint32_t enable) static void imx9_setfreeze(uint32_t base, uint32_t freeze) { uint32_t regval; + if (freeze) { /* Enter freeze mode */ @@ -1333,6 +1347,7 @@ static uint32_t imx9_waitmcr_change(uint32_t base, uint32_t mask, { const bool state = (getreg32(base + IMX9_CAN_MCR_OFFSET) & mask) != 0; + if (state == target_state) { return true; @@ -1549,6 +1564,7 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, { struct can_ioctl_data_s *req = (struct can_ioctl_data_s *)((uintptr_t)arg); + req->arbi_bitrate = priv->arbi_timing.bitrate; req->arbi_samplep = priv->arbi_timing.samplep; if (priv->canfd_capable) @@ -1572,6 +1588,7 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, (struct can_ioctl_data_s *)((uintptr_t)arg); struct flexcan_timeseg arbi_timing; + arbi_timing.bitrate = req->arbi_bitrate; arbi_timing.samplep = req->arbi_samplep; @@ -1585,19 +1602,19 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, } if (priv->canfd_capable) - { - data_timing.bitrate = req->data_bitrate; - data_timing.samplep = req->data_samplep; - - if (ret == OK && imx9_bitratetotimeseg(&data_timing, 10, 1)) - { - ret = OK; - } - else - { - ret = -EINVAL; - } - } + { + data_timing.bitrate = req->data_bitrate; + data_timing.samplep = req->data_samplep; + + if (ret == OK && imx9_bitratetotimeseg(&data_timing, 10, 1)) + { + ret = OK; + } + else + { + ret = -EINVAL; + } + } if (ret == OK) { @@ -1605,9 +1622,9 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, priv->arbi_timing = arbi_timing; if (priv->canfd_capable) - { - priv->data_timing = data_timing; - } + { + priv->data_timing = data_timing; + } } } break; @@ -1782,12 +1799,14 @@ static int imx9_initialize(struct imx9_driver_s *priv) * transmitting the package, hence we write 0x3. */ - struct mb_s *buffer = flexcan_get_mb(priv, RXMBCOUNT); - buffer->cs.code = 0x3; + struct mb_s *buffer = flexcan_get_mb(priv, RXMBCOUNT); + + buffer->cs.code = 0x3; for (i = RXMBCOUNT + 1; i < TOTALMBCOUNT; i++) { struct mb_s *rx = flexcan_get_mb(priv, i); + rx->id.w = 0x0; /* FIXME sometimes we get a hard fault here */ @@ -1803,6 +1822,7 @@ static int imx9_initialize(struct imx9_driver_s *priv) for (i = 0; i < RXMBCOUNT; i++) { struct mb_s *rx = flexcan_get_mb(priv, i); + ninfo("Set MB%" PRIi32 " to receive %p\n", i, rx); rx->cs.edl = 0x1; rx->cs.brs = 0x1; @@ -1868,6 +1888,7 @@ static void imx9_reset(struct imx9_driver_s *priv) for (i = 0; i < TOTALMBCOUNT; i++) { struct mb_s *rx = flexcan_get_mb(priv, i); + ninfo("MB %" PRIi32 " %p\n", i, rx); ninfo("MB %" PRIi32 " %p\n", i, &rx->id.w); rx->cs.cs = 0x0; @@ -1928,143 +1949,143 @@ int imx9_caninitialize(int intf) switch (intf) { #ifdef CONFIG_IMX9_FLEXCAN1 - case 1: - priv = &g_flexcan1; - memset(priv, 0, sizeof(struct imx9_driver_s)); - priv->base = IMX9_CAN1_BASE; - priv->config = &imx9_flexcan1_config; + case 1: + priv = &g_flexcan1; + memset(priv, 0, sizeof(struct imx9_driver_s)); + priv->base = IMX9_CAN1_BASE; + priv->config = &imx9_flexcan1_config; # if defined(CONFIG_NET_CAN_CANFD) - priv->canfd_capable = true; - priv->mb_address_offset = 14; + priv->canfd_capable = true; + priv->mb_address_offset = 14; #endif - /* Default bitrate configuration */ + /* Default bitrate configuration */ # if defined(CONFIG_NET_CAN_CANFD) - priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN1_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN1_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN1_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN1_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN1_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN1_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN1_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN1_SAMPLEP; # endif - break; + break; #endif #ifdef CONFIG_IMX9_FLEXCAN2 - case 2: - priv = &g_flexcan2; - memset(priv, 0, sizeof(struct imx9_driver_s)); - priv->base = IMX9_CAN2_BASE; - priv->config = &imx9_flexcan2_config; + case 2: + priv = &g_flexcan2; + memset(priv, 0, sizeof(struct imx9_driver_s)); + priv->base = IMX9_CAN2_BASE; + priv->config = &imx9_flexcan2_config; # if defined(CONFIG_NET_CAN_CANFD) - priv->canfd_capable = true; - priv->mb_address_offset = 14; + priv->canfd_capable = true; + priv->mb_address_offset = 14; # else - priv->canfd_capable = false; - priv->mb_address_offset = 0; + priv->canfd_capable = false; + priv->mb_address_offset = 0; # endif - /* Default bitrate configuration */ + /* Default bitrate configuration */ # if defined(CONFIG_NET_CAN_CANFD) - priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN2_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN2_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN2_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN2_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN2_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN2_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN2_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN2_SAMPLEP; # endif - break; + break; #endif #ifdef CONFIG_IMX9_FLEXCAN3 - case 3: - priv = &g_flexcan3; - memset(priv, 0, sizeof(struct imx9_driver_s)); - priv->base = IMX9_CAN3_BASE; - priv->config = &imx9_flexcan3_config; + case 3: + priv = &g_flexcan3; + memset(priv, 0, sizeof(struct imx9_driver_s)); + priv->base = IMX9_CAN3_BASE; + priv->config = &imx9_flexcan3_config; # ifdef CONFIG_NET_CAN_CANFD - priv->canfd_capable = true; - priv->mb_address_offset = 14; + priv->canfd_capable = true; + priv->mb_address_offset = 14; # else - priv->canfd_capable = false; - priv->mb_address_offset = 0; + priv->canfd_capable = false; + priv->mb_address_offset = 0; # endif - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN3_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN3_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN3_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN3_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN3_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN3_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN3_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN3_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN3_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN3_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN3_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN3_SAMPLEP; # endif - break; + break; #endif #ifdef CONFIG_IMX9_FLEXCAN4 - case 4: - priv = &g_flexcan4; - memset(priv, 0, sizeof(struct imx9_driver_s)); - priv->base = IMX9_CAN4_BASE; - priv->config = &imx9_flexcan4_config; + case 4: + priv = &g_flexcan4; + memset(priv, 0, sizeof(struct imx9_driver_s)); + priv->base = IMX9_CAN4_BASE; + priv->config = &imx9_flexcan4_config; # ifdef CONFIG_NET_CAN_CANFD - priv->canfd_capable = true; - priv->mb_address_offset = 14; + priv->canfd_capable = true; + priv->mb_address_offset = 14; # else - priv->canfd_capable = false; - priv->mb_address_offset = 0; + priv->canfd_capable = false; + priv->mb_address_offset = 0; # endif - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN4_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN4_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN4_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN4_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN4_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN4_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN4_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN4_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN4_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN4_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN4_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN4_SAMPLEP; # endif - break; + break; #endif #ifdef CONFIG_IMX9_FLEXCAN5 - case 5: - priv = &g_flexcan5; - memset(priv, 0, sizeof(struct imx9_driver_s)); - priv->base = IMX9_CAN5_BASE; - priv->config = &imx9_flexcan5_config; + case 5: + priv = &g_flexcan5; + memset(priv, 0, sizeof(struct imx9_driver_s)); + priv->base = IMX9_CAN5_BASE; + priv->config = &imx9_flexcan5_config; # ifdef CONFIG_NET_CAN_CANFD - priv->canfd_capable = true; - priv->mb_address_offset = 14; + priv->canfd_capable = true; + priv->mb_address_offset = 14; # else - priv->canfd_capable = false; - priv->mb_address_offset = 0; + priv->canfd_capable = false; + priv->mb_address_offset = 0; # endif - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN5_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN5_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN5_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN5_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN5_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN5_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN5_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN5_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN5_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN5_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN5_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN5_SAMPLEP; # endif - break; + break; #endif - default: - return -ENODEV; + default: + return -ENODEV; } imx9_configure_clock(priv->config->clk_root, true); diff --git a/arch/arm/src/kinetis/kinetis_flexcan.c b/arch/arm/src/kinetis/kinetis_flexcan.c index e36bb9a19493b..48db88f287df7 100644 --- a/arch/arm/src/kinetis/kinetis_flexcan.c +++ b/arch/arm/src/kinetis/kinetis_flexcan.c @@ -643,12 +643,14 @@ static int kinetis_transmit(struct kinetis_driver_s *priv) #ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE struct timespec ts; + clock_systime_timespec(&ts); if (priv->dev.d_sndlen > priv->dev.d_len) { struct timeval *tv = (struct timeval *)(priv->dev.d_buf + priv->dev.d_len); + priv->txmb[mbi].deadline = *tv; timeout = (tv->tv_sec - ts.tv_sec)*CLK_TCK + ((tv->tv_usec - ts.tv_nsec / 1000)*CLK_TCK) / 1000000; @@ -683,9 +685,11 @@ static int kinetis_transmit(struct kinetis_driver_s *priv) (peak_tx_mailbox_index_ > mbi ? peak_tx_mailbox_index_ : mbi); union cs_e cs; + cs.cs = 0; cs.code = CAN_TXMB_DATAORREMOTE; struct mb_s *mb = &priv->tx[mbi]; + mb->cs.code = CAN_TXMB_INACTIVE; if (priv->dev.d_len == sizeof(struct can_frame)) @@ -1015,6 +1019,7 @@ static void kinetis_txdone(struct kinetis_driver_s *priv) wd_cancel(&priv->txtimeout[mbi]); struct mb_s *mb = &priv->tx[mbi]; + mb->cs.code = CAN_TXMB_INACTIVE; #endif } @@ -1084,6 +1089,7 @@ static int kinetis_flexcan_interrupt(int irq, void *context, if (irq == priv->config->mb_irq) { uint32_t flags; + flags = getreg32(priv->base + KINETIS_CAN_IFLAG1_OFFSET); flags &= IFLAG1_RX; @@ -1141,6 +1147,7 @@ static void kinetis_txtimeout_work(void *arg) struct timespec ts; struct timeval *now = (struct timeval *)&ts; + clock_systime_timespec(&ts); now->tv_usec = ts.tv_nsec / 1000; /* timespec to timeval conversion */ @@ -1166,6 +1173,7 @@ static void kinetis_txtimeout_work(void *arg) } struct mb_s *mb = &priv->tx[mbi]; + mb->cs.code = CAN_TXMB_ABORT; priv->txmb[mbi].pending = TX_ABORT; } @@ -1230,6 +1238,7 @@ static uint32_t kinetis_waitesr2_change(uint32_t base, uint32_t mask, for (wait_ack = 0; wait_ack < timeout; wait_ack++) { uint32_t state = (getreg32(base + KINETIS_CAN_ESR2_OFFSET) & mask); + if (state == target_state) { return true; @@ -1244,6 +1253,7 @@ static uint32_t kinetis_waitesr2_change(uint32_t base, uint32_t mask, static void kinetis_setfreeze(uint32_t base, uint32_t freeze) { uint32_t regval; + if (freeze) { /* Enter freeze mode */ @@ -1272,6 +1282,7 @@ static uint32_t kinetis_waitmcr_change(uint32_t base, uint32_t mask, { const bool state = (getreg32(base + KINETIS_CAN_MCR_OFFSET) & mask) != 0; + if (state == target_state) { return true; @@ -1492,6 +1503,7 @@ static int kinetis_ioctl(struct net_driver_s *dev, int cmd, { struct can_ioctl_data_s *req = (struct can_ioctl_data_s *)((uintptr_t)arg); + req->arbi_bitrate = priv->arbi_timing.bitrate; req->arbi_samplep = priv->arbi_timing.samplep; #ifdef CONFIG_NET_CAN_CANFD @@ -1511,6 +1523,7 @@ static int kinetis_ioctl(struct net_driver_s *dev, int cmd, (struct can_ioctl_data_s *)((uintptr_t)arg); struct flexcan_timeseg arbi_timing; + arbi_timing.bitrate = req->arbi_bitrate; arbi_timing.samplep = req->arbi_samplep; @@ -1525,6 +1538,7 @@ static int kinetis_ioctl(struct net_driver_s *dev, int cmd, #ifdef CONFIG_NET_CAN_CANFD struct flexcan_timeseg data_timing; + data_timing.bitrate = req->data_bitrate; data_timing.samplep = req->data_samplep; @@ -1803,76 +1817,76 @@ int kinetis_caninitialize(int intf) switch (intf) { #ifdef CONFIG_KINETIS_FLEXCAN0 - case 0: - priv = &g_flexcan0; - memset(priv, 0, sizeof(struct kinetis_driver_s)); - priv->base = KINETIS_CAN0_BASE; - priv->config = &kinetis_flexcan0_config; + case 0: + priv = &g_flexcan0; + memset(priv, 0, sizeof(struct kinetis_driver_s)); + priv->base = KINETIS_CAN0_BASE; + priv->config = &kinetis_flexcan0_config; - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN0_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN0_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN0_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN0_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN0_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN0_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN0_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN0_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN0_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN0_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN0_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN0_SAMPLEP; # endif - regval = getreg32(KINETIS_SIM_SCGC6); - regval |= SIM_SCGC6_FLEXCAN0; - putreg32(regval, KINETIS_SIM_SCGC6); - break; + regval = getreg32(KINETIS_SIM_SCGC6); + regval |= SIM_SCGC6_FLEXCAN0; + putreg32(regval, KINETIS_SIM_SCGC6); + break; #endif #ifdef CONFIG_KINETIS_FLEXCAN1 - case 1: - priv = &g_flexcan1; - memset(priv, 0, sizeof(struct kinetis_driver_s)); - priv->base = KINETIS_CAN1_BASE; - priv->config = &kinetis_flexcan1_config; + case 1: + priv = &g_flexcan1; + memset(priv, 0, sizeof(struct kinetis_driver_s)); + priv->base = KINETIS_CAN1_BASE; + priv->config = &kinetis_flexcan1_config; - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN1_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN1_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN1_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN1_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN1_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN1_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN1_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN1_SAMPLEP; # endif - regval = getreg32(KINETIS_SIM_SCGC3); - regval |= SIM_SCGC3_FLEXCAN1; - putreg32(regval, KINETIS_SIM_SCGC3); - break; + regval = getreg32(KINETIS_SIM_SCGC3); + regval |= SIM_SCGC3_FLEXCAN1; + putreg32(regval, KINETIS_SIM_SCGC3); + break; #endif #ifdef CONFIG_KINETIS_FLEXCAN2 - case 2: - priv = &g_flexcan2; - memset(priv, 0, sizeof(struct kinetis_driver_s)); - priv->base = KINETIS_CAN2_BASE; - priv->config = &kinetis_flexcan2_config; + case 2: + priv = &g_flexcan2; + memset(priv, 0, sizeof(struct kinetis_driver_s)); + priv->base = KINETIS_CAN2_BASE; + priv->config = &kinetis_flexcan2_config; - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN2_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN2_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN2_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN2_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN2_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN2_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN2_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN2_SAMPLEP; # endif - break; + break; #endif - default: - return -ENODEV; + default: + return -ENODEV; } if (!kinetis_bitratetotimeseg(&priv->arbi_timing, 1, 0)) diff --git a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c index bb124873c61df..69061ab5370d2 100644 --- a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c +++ b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c @@ -645,12 +645,14 @@ static int s32k1xx_transmit(struct s32k1xx_driver_s *priv) #ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE struct timespec ts; + clock_systime_timespec(&ts); if (priv->dev.d_sndlen > priv->dev.d_len) { struct timeval *tv = (struct timeval *)(priv->dev.d_buf + priv->dev.d_len); + priv->txmb[mbi].deadline = *tv; timeout = (tv->tv_sec - ts.tv_sec)*CLK_TCK + ((tv->tv_usec - ts.tv_nsec / 1000)*CLK_TCK) / 1000000; @@ -685,9 +687,11 @@ static int s32k1xx_transmit(struct s32k1xx_driver_s *priv) (peak_tx_mailbox_index_ > mbi ? peak_tx_mailbox_index_ : mbi); union cs_e cs; + cs.cs = 0; cs.code = CAN_TXMB_DATAORREMOTE; struct mb_s *mb = &priv->tx[mbi]; + mb->cs.code = CAN_TXMB_INACTIVE; if (priv->dev.d_len <= sizeof(struct can_frame)) @@ -1019,6 +1023,7 @@ static void s32k1xx_txdone(struct s32k1xx_driver_s *priv) wd_cancel(&priv->txtimeout[mbi]); struct mb_s *mb = &priv->tx[mbi]; + mb->cs.code = CAN_TXMB_INACTIVE; #endif } @@ -1088,6 +1093,7 @@ static int s32k1xx_flexcan_interrupt(int irq, void *context, if (irq == priv->config->mb_irq) { uint32_t flags; + flags = getreg32(priv->base + S32K1XX_CAN_IFLAG1_OFFSET); flags &= IFLAG1_RX; @@ -1145,6 +1151,7 @@ static void s32k1xx_txtimeout_work(void *arg) struct timespec ts; struct timeval *now = (struct timeval *)&ts; + clock_systime_timespec(&ts); now->tv_usec = ts.tv_nsec / 1000; /* timespec to timeval conversion */ @@ -1170,6 +1177,7 @@ static void s32k1xx_txtimeout_work(void *arg) } struct mb_s *mb = &priv->tx[mbi]; + mb->cs.code = CAN_TXMB_ABORT; priv->txmb[mbi].pending = TX_ABORT; } @@ -1229,6 +1237,7 @@ static void s32k1xx_setenable(uint32_t base, uint32_t enable) static void s32k1xx_setfreeze(uint32_t base, uint32_t freeze) { uint32_t regval; + if (freeze) { /* Enter freeze mode */ @@ -1257,6 +1266,7 @@ static uint32_t s32k1xx_waitmcr_change(uint32_t base, uint32_t mask, { const bool state = (getreg32(base + S32K1XX_CAN_MCR_OFFSET) & mask) != 0; + if (state == target_state) { return true; @@ -1475,6 +1485,7 @@ static int s32k1xx_ioctl(struct net_driver_s *dev, int cmd, { struct can_ioctl_data_s *req = (struct can_ioctl_data_s *)((uintptr_t)arg); + req->arbi_bitrate = priv->arbi_timing.bitrate; req->arbi_samplep = priv->arbi_timing.samplep; #ifdef CONFIG_NET_CAN_CANFD @@ -1494,6 +1505,7 @@ static int s32k1xx_ioctl(struct net_driver_s *dev, int cmd, (struct can_ioctl_data_s *)((uintptr_t)arg); struct flexcan_timeseg arbi_timing; + arbi_timing.bitrate = req->arbi_bitrate; arbi_timing.samplep = req->arbi_samplep; @@ -1508,6 +1520,7 @@ static int s32k1xx_ioctl(struct net_driver_s *dev, int cmd, #ifdef CONFIG_NET_CAN_CANFD struct flexcan_timeseg data_timing; + data_timing.bitrate = req->data_bitrate; data_timing.samplep = req->data_samplep; @@ -1794,70 +1807,70 @@ int s32k1xx_caninitialize(int intf) switch (intf) { #ifdef CONFIG_S32K1XX_FLEXCAN0 - case 0: - priv = &g_flexcan0; - memset(priv, 0, sizeof(struct s32k1xx_driver_s)); - priv->base = S32K1XX_FLEXCAN0_BASE; - priv->config = &s32k1xx_flexcan0_config; + case 0: + priv = &g_flexcan0; + memset(priv, 0, sizeof(struct s32k1xx_driver_s)); + priv->base = S32K1XX_FLEXCAN0_BASE; + priv->config = &s32k1xx_flexcan0_config; - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN0_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN0_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN0_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN0_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN0_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN0_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN0_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN0_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN0_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN0_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN0_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN0_SAMPLEP; # endif - break; + break; #endif #ifdef CONFIG_S32K1XX_FLEXCAN1 - case 1: - priv = &g_flexcan1; - memset(priv, 0, sizeof(struct s32k1xx_driver_s)); - priv->base = S32K1XX_FLEXCAN1_BASE; - priv->config = &s32k1xx_flexcan1_config; + case 1: + priv = &g_flexcan1; + memset(priv, 0, sizeof(struct s32k1xx_driver_s)); + priv->base = S32K1XX_FLEXCAN1_BASE; + priv->config = &s32k1xx_flexcan1_config; - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN1_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN1_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN1_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN1_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN1_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN1_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN1_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN1_SAMPLEP; # endif - break; + break; #endif #ifdef CONFIG_S32K1XX_FLEXCAN2 - case 2: - priv = &g_flexcan2; - memset(priv, 0, sizeof(struct s32k1xx_driver_s)); - priv->base = S32K1XX_FLEXCAN2_BASE; - priv->config = &s32k1xx_flexcan2_config; + case 2: + priv = &g_flexcan2; + memset(priv, 0, sizeof(struct s32k1xx_driver_s)); + priv->base = S32K1XX_FLEXCAN2_BASE; + priv->config = &s32k1xx_flexcan2_config; - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN2_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN2_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN2_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN2_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN2_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN2_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN2_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN2_SAMPLEP; # endif - break; + break; #endif - default: - return -ENODEV; + default: + return -ENODEV; } if (!s32k1xx_bitratetotimeseg(&priv->arbi_timing, 1, 0)) diff --git a/arch/arm/src/s32k3xx/s32k3xx_flexcan.c b/arch/arm/src/s32k3xx/s32k3xx_flexcan.c index 340acbb5a8924..f3deaf6083af9 100644 --- a/arch/arm/src/s32k3xx/s32k3xx_flexcan.c +++ b/arch/arm/src/s32k3xx/s32k3xx_flexcan.c @@ -805,12 +805,14 @@ static int s32k3xx_transmit(struct s32k3xx_driver_s *priv) #ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE struct timespec ts; + clock_systime_timespec(&ts); if (priv->dev.d_sndlen > priv->dev.d_len) { struct timeval *tv = (struct timeval *)(priv->dev.d_buf + priv->dev.d_len); + priv->txmb[mbi].deadline = *tv; timeout = (tv->tv_sec - ts.tv_sec)*CLK_TCK + ((tv->tv_usec - ts.tv_nsec / 1000)*CLK_TCK) / 1000000; @@ -845,9 +847,11 @@ static int s32k3xx_transmit(struct s32k3xx_driver_s *priv) (peak_tx_mailbox_index_ > mbi ? peak_tx_mailbox_index_ : mbi); union cs_e cs; + cs.cs = 0; cs.code = CAN_TXMB_DATAORREMOTE; struct mb_s *mb = &priv->tx[mbi]; + mb->cs.code = CAN_TXMB_INACTIVE; if (priv->dev.d_len <= sizeof(struct can_frame)) @@ -1067,7 +1071,7 @@ static void s32k3xx_receive(struct s32k3xx_driver_s *priv, uint32_t flags) else /* CAN 2.0 Frame */ #endif { - struct can_frame *frame = (struct can_frame *)priv->rxdesc; + struct can_frame *frame = (struct can_frame *)priv->rxdesc; if (rf->cs.ide) { @@ -1175,6 +1179,7 @@ static void s32k3xx_txdone(struct s32k3xx_driver_s *priv) wd_cancel(&priv->txtimeout[mbi]); struct mb_s *mb = &priv->tx[mbi]; + mb->cs.code = CAN_TXMB_INACTIVE; #endif } @@ -1243,6 +1248,7 @@ static int s32k3xx_flexcan_interrupt(int irq, void *context, void *arg) if (irq == priv->config->mb_irq) { uint32_t flags; + flags = getreg32(priv->base + S32K3XX_CAN_IFLAG1_OFFSET); flags &= IFLAG1_RX; @@ -1300,6 +1306,7 @@ static void s32k3xx_txtimeout_work(void *arg) struct timespec ts; struct timeval *now = (struct timeval *)&ts; + clock_systime_timespec(&ts); now->tv_usec = ts.tv_nsec / 1000; /* timespec to timeval conversion */ @@ -1325,6 +1332,7 @@ static void s32k3xx_txtimeout_work(void *arg) } struct mb_s *mb = &priv->tx[mbi]; + mb->cs.code = CAN_TXMB_ABORT; priv->txmb[mbi].pending = TX_ABORT; } @@ -1384,6 +1392,7 @@ static void s32k3xx_setenable(uint32_t base, uint32_t enable) static void s32k3xx_setfreeze(uint32_t base, uint32_t freeze) { uint32_t regval; + if (freeze) { /* Enter freeze mode */ @@ -1412,6 +1421,7 @@ static uint32_t s32k3xx_waitmcr_change(uint32_t base, uint32_t mask, { const bool state = (getreg32(base + S32K3XX_CAN_MCR_OFFSET) & mask) != 0; + if (state == target_state) { return true; @@ -1663,6 +1673,7 @@ static int s32k3xx_ioctl(struct net_driver_s *dev, int cmd, { struct can_ioctl_data_s *req = (struct can_ioctl_data_s *)((uintptr_t)arg); + req->arbi_bitrate = priv->arbi_timing.bitrate; req->arbi_samplep = priv->arbi_timing.samplep; #ifdef CONFIG_NET_CAN_CANFD @@ -1682,6 +1693,7 @@ static int s32k3xx_ioctl(struct net_driver_s *dev, int cmd, (struct can_ioctl_data_s *)((uintptr_t)arg); struct flexcan_timeseg arbi_timing; + arbi_timing.bitrate = req->arbi_bitrate; arbi_timing.samplep = req->arbi_samplep; @@ -1697,6 +1709,7 @@ static int s32k3xx_ioctl(struct net_driver_s *dev, int cmd, #ifdef CONFIG_NET_CAN_CANFD struct flexcan_timeseg data_timing; + data_timing.bitrate = req->data_bitrate; data_timing.samplep = req->data_samplep; @@ -2019,139 +2032,139 @@ int s32k3xx_caninitialize(int intf) switch (intf) { #ifdef CONFIG_S32K3XX_FLEXCAN0 - case 0: - priv = &g_flexcan0; - memset(priv, 0, sizeof(struct s32k3xx_driver_s)); - priv->base = S32K3XX_FLEXCAN0_BASE; - priv->config = &s32k3xx_flexcan0_config; - priv->clk_freq = s32k3xx_get_freq(FLEXCAN0_CLK); + case 0: + priv = &g_flexcan0; + memset(priv, 0, sizeof(struct s32k3xx_driver_s)); + priv->base = S32K3XX_FLEXCAN0_BASE; + priv->config = &s32k3xx_flexcan0_config; + priv->clk_freq = s32k3xx_get_freq(FLEXCAN0_CLK); - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN0_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN0_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN0_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN0_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN0_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN0_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN0_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN0_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN0_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN0_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN0_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN0_SAMPLEP; # endif - break; + break; #endif #ifdef CONFIG_S32K3XX_FLEXCAN1 - case 1: - priv = &g_flexcan1; - memset(priv, 0, sizeof(struct s32k3xx_driver_s)); - priv->base = S32K3XX_FLEXCAN1_BASE; - priv->config = &s32k3xx_flexcan1_config; - priv->clk_freq = s32k3xx_get_freq(FLEXCAN1_CLK); + case 1: + priv = &g_flexcan1; + memset(priv, 0, sizeof(struct s32k3xx_driver_s)); + priv->base = S32K3XX_FLEXCAN1_BASE; + priv->config = &s32k3xx_flexcan1_config; + priv->clk_freq = s32k3xx_get_freq(FLEXCAN1_CLK); - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN1_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN1_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN1_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN1_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN1_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN1_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN1_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN1_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN1_SAMPLEP; # endif - break; + break; #endif #ifdef CONFIG_S32K3XX_FLEXCAN2 - case 2: - priv = &g_flexcan2; - memset(priv, 0, sizeof(struct s32k3xx_driver_s)); - priv->base = S32K3XX_FLEXCAN2_BASE; - priv->config = &s32k3xx_flexcan2_config; - priv->clk_freq = s32k3xx_get_freq(FLEXCAN2_CLK); + case 2: + priv = &g_flexcan2; + memset(priv, 0, sizeof(struct s32k3xx_driver_s)); + priv->base = S32K3XX_FLEXCAN2_BASE; + priv->config = &s32k3xx_flexcan2_config; + priv->clk_freq = s32k3xx_get_freq(FLEXCAN2_CLK); - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN2_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN2_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN2_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN2_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN2_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN2_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN2_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN2_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN2_SAMPLEP; # endif - break; + break; #endif #ifdef CONFIG_S32K3XX_FLEXCAN3 - case 3: - priv = &g_flexcan3; - memset(priv, 0, sizeof(struct s32k3xx_driver_s)); - priv->base = S32K3XX_FLEXCAN3_BASE; - priv->config = &s32k3xx_flexcan3_config; - priv->clk_freq = s32k3xx_get_freq(FLEXCAN3_CLK); + case 3: + priv = &g_flexcan3; + memset(priv, 0, sizeof(struct s32k3xx_driver_s)); + priv->base = S32K3XX_FLEXCAN3_BASE; + priv->config = &s32k3xx_flexcan3_config; + priv->clk_freq = s32k3xx_get_freq(FLEXCAN3_CLK); - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN3_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN3_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN3_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN3_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN3_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN3_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN3_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN3_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN3_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN3_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN3_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN3_SAMPLEP; # endif - break; + break; #endif #ifdef CONFIG_S32K3XX_FLEXCAN4 - case 4: - priv = &g_flexcan4; - memset(priv, 0, sizeof(struct s32k3xx_driver_s)); - priv->base = S32K3XX_FLEXCAN4_BASE; - priv->config = &s32k3xx_flexcan4_config; - priv->clk_freq = s32k3xx_get_freq(FLEXCAN4_CLK); + case 4: + priv = &g_flexcan4; + memset(priv, 0, sizeof(struct s32k3xx_driver_s)); + priv->base = S32K3XX_FLEXCAN4_BASE; + priv->config = &s32k3xx_flexcan4_config; + priv->clk_freq = s32k3xx_get_freq(FLEXCAN4_CLK); - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN4_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN4_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN4_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN4_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN4_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN4_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN4_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN4_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN4_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN4_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN4_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN4_SAMPLEP; # endif - break; + break; #endif #ifdef CONFIG_S32K3XX_FLEXCAN5 - case 5: - priv = &g_flexcan5; - memset(priv, 0, sizeof(struct s32k3xx_driver_s)); - priv->base = S32K3XX_FLEXCAN5_BASE; - priv->config = &s32k3xx_flexcan5_config; - priv->clk_freq = s32k3xx_get_freq(FLEXCAN5_CLK); + case 5: + priv = &g_flexcan5; + memset(priv, 0, sizeof(struct s32k3xx_driver_s)); + priv->base = S32K3XX_FLEXCAN5_BASE; + priv->config = &s32k3xx_flexcan5_config; + priv->clk_freq = s32k3xx_get_freq(FLEXCAN5_CLK); - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FLEXCAN5_ARBI_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN5_ARBI_SAMPLEP; - priv->data_timing.bitrate = CONFIG_FLEXCAN5_DATA_BITRATE; - priv->data_timing.samplep = CONFIG_FLEXCAN5_DATA_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN5_ARBI_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN5_ARBI_SAMPLEP; + priv->data_timing.bitrate = CONFIG_FLEXCAN5_DATA_BITRATE; + priv->data_timing.samplep = CONFIG_FLEXCAN5_DATA_SAMPLEP; # else - priv->arbi_timing.bitrate = CONFIG_FLEXCAN5_BITRATE; - priv->arbi_timing.samplep = CONFIG_FLEXCAN5_SAMPLEP; + priv->arbi_timing.bitrate = CONFIG_FLEXCAN5_BITRATE; + priv->arbi_timing.samplep = CONFIG_FLEXCAN5_SAMPLEP; # endif - break; + break; #endif - default: - return -ENODEV; + default: + return -ENODEV; } if (!s32k3xx_bitratetotimeseg(&priv->arbi_timing, 1, 0, priv->clk_freq)) @@ -2187,7 +2200,7 @@ int s32k3xx_caninitialize(int intf) /* Attach the flexcan interrupt handler */ if (priv->config->bus_irq > 0) - { + { if (irq_attach(priv->config->bus_irq, s32k3xx_flexcan_interrupt, priv)) { /* We could not attach the ISR to the interrupt */ @@ -2195,10 +2208,10 @@ int s32k3xx_caninitialize(int intf) nerr("ERROR: Failed to attach CAN bus IRQ\n"); return -EAGAIN; } - } + } if (priv->config->error_irq > 0) - { + { if (irq_attach(priv->config->error_irq, s32k3xx_flexcan_interrupt, priv)) { @@ -2207,7 +2220,7 @@ int s32k3xx_caninitialize(int intf) nerr("ERROR: Failed to attach CAN error IRQ\n"); return -EAGAIN; } - } + } if (priv->config->lprx_irq > 0) { diff --git a/arch/arm/src/stm32h7/stm32_fdcan_sock.c b/arch/arm/src/stm32h7/stm32_fdcan_sock.c index e8e0ea6bc776f..1ae369be865fa 100644 --- a/arch/arm/src/stm32h7/stm32_fdcan_sock.c +++ b/arch/arm/src/stm32h7/stm32_fdcan_sock.c @@ -518,6 +518,7 @@ static void fdcan_dumpregs(struct fdcan_driver_s *priv) printf("CAN%d Base: 0x%lx\n", priv->iface_idx, priv->base); uint32_t regval; + regval = getreg32(priv->base + STM32_FDCAN_CCCR_OFFSET); printf("CCCR = 0x%lx\n", regval); regval = getreg32(priv->base + STM32_FDCAN_ECR_OFFSET); @@ -721,6 +722,7 @@ static bool fdcan_txringfull(struct fdcan_driver_s *priv) */ uint32_t regval = getreg32(priv->base + STM32_FDCAN_TXBC_OFFSET); + if ((regval & FDCAN_TXBC_TFQS) == 0) { nerr("No Tx FIFO buffers assigned? Check your message RAM config\n"); @@ -765,6 +767,7 @@ static int fdcan_transmit(struct fdcan_driver_s *priv) /* First, check if there are any slots available in the queue */ uint32_t regval = getreg32(priv->base + STM32_FDCAN_TXFQS_OFFSET); + if ((regval & FDCAN_TXFQS_TFQF) == FDCAN_TXFQS_TFQF) { /* Tx FIFO / Queue is full */ @@ -795,6 +798,7 @@ static int fdcan_transmit(struct fdcan_driver_s *priv) #ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE int32_t timeout = 0; struct timespec ts; + clock_systime_timespec(&ts); if (priv->dev.d_sndlen > priv->dev.d_len) @@ -803,6 +807,7 @@ static int fdcan_transmit(struct fdcan_driver_s *priv) struct timeval *tv = (struct timeval *)(priv->dev.d_buf + priv->dev.d_len); + priv->txmb[mbi].deadline = *tv; timeout = (tv->tv_sec - ts.tv_sec)*CLK_TCK + ((tv->tv_usec - ts.tv_nsec / 1000)*CLK_TCK) / 1000000; @@ -1251,13 +1256,13 @@ static void fdcan_receive_work(void *arg) fdcan_check_errors(priv); #ifdef CONFIG_NET_CAN_ERRORS - uint32_t regval; + uint32_t regval; - /* Turning back on all configured RX error interrupts */ + /* Turning back on all configured RX error interrupts */ - regval = getreg32(priv->base + STM32_FDCAN_IE_OFFSET); - regval |= FDCAN_RXERR_INTS; - putreg32(regval, priv->base + STM32_FDCAN_IE_OFFSET); + regval = getreg32(priv->base + STM32_FDCAN_IE_OFFSET); + regval |= FDCAN_RXERR_INTS; + putreg32(regval, priv->base + STM32_FDCAN_IE_OFFSET); #endif leave_critical_section(flags); @@ -1285,6 +1290,7 @@ static void fdcan_txdone(struct fdcan_driver_s *priv) /* Read and reset the interrupt flag */ uint32_t ir = getreg32(priv->base + STM32_FDCAN_IR_OFFSET); + if (ir & FDCAN_IR_TC) { putreg32(FDCAN_IR_TC, priv->base + STM32_FDCAN_IR_OFFSET); @@ -1524,6 +1530,7 @@ static void fdcan_txtimeout_work(void *arg) struct timespec ts; struct timeval *now = (struct timeval *)&ts; + clock_systime_timespec(&ts); now->tv_usec = ts.tv_nsec / 1000; /* timespec to timeval conversion */ @@ -1697,9 +1704,11 @@ static bool fdcan_waitccr_change(uint32_t base, uint32_t mask, uint32_t target_state) { const unsigned timeout = 1000; + for (unsigned wait_ack = 0; wait_ack < timeout; wait_ack++) { const bool state = (getreg32(base + STM32_FDCAN_CCCR_OFFSET) & mask); + if (state == target_state) { return true; @@ -1730,6 +1739,7 @@ static void fdcan_enable_interrupts(struct fdcan_driver_s *priv) /* Enable both interrupt lines at the device level */ const uint32_t ile = FDCAN_ILE_EINT0 | FDCAN_ILE_EINT1; + modifyreg32(priv->base + STM32_FDCAN_ILE_OFFSET, 0, ile); /* Enable both lines at the NVIC level */ @@ -1762,6 +1772,7 @@ static void fdcan_disable_interrupts(struct fdcan_driver_s *priv) /* Disable both interrupt lines at the device level */ const uint32_t ile = FDCAN_ILE_EINT0 | FDCAN_ILE_EINT1; + modifyreg32(priv->base + STM32_FDCAN_ILE_OFFSET, ile, 0); } @@ -1961,6 +1972,7 @@ static int fdcan_netdev_ioctl(struct net_driver_s *dev, int cmd, { struct can_ioctl_data_s *req = (struct can_ioctl_data_s *)((uintptr_t)arg); + req->arbi_bitrate = priv->arbi_timing.bitrate; #ifdef CONFIG_NET_CAN_CANFD req->data_bitrate = priv->data_timing.bitrate; @@ -2060,6 +2072,7 @@ int fdcan_initialize(struct fdcan_driver_s *priv) #ifdef CONFIG_STM32_FDCAN_REGDEBUG const struct fdcan_bitseg *tim = &priv->arbi_timing; + ninfo("[fdcan][arbi] Timings: presc=%u sjw=%u bs1=%u bs2=%u\r\n", tim->prescaler, tim->sjw, tim->bs1, tim->bs2); #endif @@ -2210,6 +2223,7 @@ int fdcan_initialize(struct fdcan_driver_s *priv) /* Standard ID Filters: Allow space for 128 filters (128 words) */ const uint8_t n_stdid = 128; + priv->message_ram.filt_stdid_addr = gl_ram_base + ram_offset * WORD_LENGTH; regval = (n_stdid << FDCAN_SIDFC_LSS_SHIFT) & FDCAN_SIDFC_LSS_MASK; @@ -2237,6 +2251,7 @@ int fdcan_initialize(struct fdcan_driver_s *priv) */ const uint8_t n_extid = 128; + priv->message_ram.filt_extid_addr = gl_ram_base + ram_offset * WORD_LENGTH; regval = (n_extid << FDCAN_XIDFC_LSE_SHIFT) & FDCAN_XIDFC_LSE_MASK; @@ -2425,64 +2440,64 @@ int stm32_fdcansockinitialize(int intf) switch (intf) { #ifdef CONFIG_STM32_FDCAN1 - case 0: - priv = &g_fdcan0; - memset(priv, 0, sizeof(struct fdcan_driver_s)); - priv->base = STM32_FDCAN1_BASE; - priv->iface_idx = 0; - priv->config = &stm32_fdcan0_config; + case 0: + priv = &g_fdcan0; + memset(priv, 0, sizeof(struct fdcan_driver_s)); + priv->base = STM32_FDCAN1_BASE; + priv->iface_idx = 0; + priv->config = &stm32_fdcan0_config; - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FDCAN1_ARBI_BITRATE; - priv->data_timing.bitrate = CONFIG_FDCAN1_DATA_BITRATE; + priv->arbi_timing.bitrate = CONFIG_FDCAN1_ARBI_BITRATE; + priv->data_timing.bitrate = CONFIG_FDCAN1_DATA_BITRATE; # else - priv->arbi_timing.bitrate = CONFIG_FDCAN1_BITRATE; + priv->arbi_timing.bitrate = CONFIG_FDCAN1_BITRATE; # endif - break; + break; #endif #ifdef CONFIG_STM32_FDCAN2 - case 1: - priv = &g_fdcan1; - memset(priv, 0, sizeof(struct fdcan_driver_s)); - priv->base = STM32_FDCAN2_BASE; - priv->iface_idx = 1; - priv->config = &stm32_fdcan1_config; + case 1: + priv = &g_fdcan1; + memset(priv, 0, sizeof(struct fdcan_driver_s)); + priv->base = STM32_FDCAN2_BASE; + priv->iface_idx = 1; + priv->config = &stm32_fdcan1_config; - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FDCAN2_ARBI_BITRATE; - priv->data_timing.bitrate = CONFIG_FDCAN2_DATA_BITRATE; + priv->arbi_timing.bitrate = CONFIG_FDCAN2_ARBI_BITRATE; + priv->data_timing.bitrate = CONFIG_FDCAN2_DATA_BITRATE; # else - priv->arbi_timing.bitrate = CONFIG_FDCAN2_BITRATE; + priv->arbi_timing.bitrate = CONFIG_FDCAN2_BITRATE; # endif - break; + break; #endif #ifdef CONFIG_STM32_FDCAN3 - case 2: - priv = &g_fdcan2; - memset(priv, 0, sizeof(struct fdcan_driver_s)); - priv->base = STM32_FDCAN3_BASE; - priv->iface_idx = 2; - priv->config = &stm32_fdcan2_config; + case 2: + priv = &g_fdcan2; + memset(priv, 0, sizeof(struct fdcan_driver_s)); + priv->base = STM32_FDCAN3_BASE; + priv->iface_idx = 2; + priv->config = &stm32_fdcan2_config; - /* Default bitrate configuration */ + /* Default bitrate configuration */ # ifdef CONFIG_NET_CAN_CANFD - priv->arbi_timing.bitrate = CONFIG_FDCAN3_ARBI_BITRATE; - priv->data_timing.bitrate = CONFIG_FDCAN3_DATA_BITRATE; + priv->arbi_timing.bitrate = CONFIG_FDCAN3_ARBI_BITRATE; + priv->data_timing.bitrate = CONFIG_FDCAN3_DATA_BITRATE; # else - priv->arbi_timing.bitrate = CONFIG_FDCAN3_BITRATE; + priv->arbi_timing.bitrate = CONFIG_FDCAN3_BITRATE; # endif - break; + break; #endif - default: - return -ENODEV; + default: + return -ENODEV; } if (fdcan_bittiming(&priv->arbi_timing) != OK) diff --git a/arch/arm64/src/imx9/imx9_flexcan.c b/arch/arm64/src/imx9/imx9_flexcan.c index 620dc5c6f8e2a..7ca08ee1b8435 100644 --- a/arch/arm64/src/imx9/imx9_flexcan.c +++ b/arch/arm64/src/imx9/imx9_flexcan.c @@ -594,6 +594,7 @@ static bool imx9_txringfull(struct imx9_driver_s *priv) for (mbi = RXMBCOUNT; mbi < TOTALMBCOUNT; mbi++) { volatile struct mb_s *mb = flexcan_get_mb(priv, mbi); + if (CAN_MB_CS_CODE(mb->cs) != CAN_TXMB_DATAORREMOTE) { return false; @@ -662,6 +663,7 @@ static int imx9_transmit(struct imx9_driver_s *priv) #ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE struct timespec ts; + clock_systime_timespec(&ts); if (priv->dev.d_sndlen > priv->dev.d_len) @@ -702,6 +704,7 @@ static int imx9_transmit(struct imx9_driver_s *priv) if (priv->dev.d_len == sizeof(struct can_frame)) { struct can_frame *frame = (struct can_frame *)priv->dev.d_buf; + can_id = frame->can_id; len = 8; can_dlc = frame->can_dlc; @@ -711,6 +714,7 @@ static int imx9_transmit(struct imx9_driver_s *priv) else { struct canfd_frame *frame = (struct canfd_frame *)priv->dev.d_buf; + cs |= CAN_MB_CS_EDL; cs |= frame->flags & CANFD_BRS ? CAN_MB_CS_BRS : 0; can_id = frame->can_id; @@ -898,6 +902,7 @@ static void imx9_receive(struct imx9_driver_s *priv) size_t frame_len; uint32_t flags = getreg32(priv->base + IMX9_CAN_IFLAG1_OFFSET); + flags &= IFLAG1_RX; while (flags != 0) @@ -1278,6 +1283,7 @@ static void imx9_txtimeout_work(void *arg) volatile struct mb_s *mb; struct timespec ts; struct timeval *now = (struct timeval *)&ts; + clock_systime_timespec(&ts); now->tv_usec = ts.tv_nsec / 1000; /* timespec to timeval conversion */ @@ -1613,6 +1619,7 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, struct imx9_driver_s *priv = (struct imx9_driver_s *)dev; struct can_ioctl_data_s *req = (struct can_ioctl_data_s *)((uintptr_t)arg); + req->arbi_bitrate = priv->arbi_timing.bitrate; req->arbi_samplep = priv->arbi_timing.samplep; if (priv->canfd_capable) @@ -1654,9 +1661,9 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, priv->arbi_timing = arbi_timing; if (priv->canfd_capable) - { - priv->data_timing = data_timing; - } + { + priv->data_timing = data_timing; + } } } break; @@ -1666,12 +1673,13 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, 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); + ret = imx9_add_filter(priv, req->ftype, 0, req->fid1, req->fid2); } break; @@ -1680,12 +1688,13 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, 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); + ret = imx9_add_filter(priv, req->ftype, 1, req->fid1, req->fid2); } break; @@ -1693,6 +1702,7 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, case SIOCDCANEXTFILTER: /* Reset EXT ID CAN filter */ { struct imx9_driver_s *priv = (struct imx9_driver_s *)dev; + ret = imx9_reset_filter(priv); } break; @@ -2214,23 +2224,23 @@ int imx9_caninitialize(int intf) switch (intf) { #ifdef CONFIG_IMX9_FLEXCAN1 - case 1: - imx9_ccm_configure_root_clock(CCM_CR_CAN1, SYS_PLL1PFD1DIV2, 5); - imx9_ccm_gate_on(CCM_LPCG_CAN1, true); - priv = &g_flexcan1; - break; + case 1: + imx9_ccm_configure_root_clock(CCM_CR_CAN1, SYS_PLL1PFD1DIV2, 5); + imx9_ccm_gate_on(CCM_LPCG_CAN1, true); + priv = &g_flexcan1; + break; #endif #ifdef CONFIG_IMX9_FLEXCAN2 - case 2: - imx9_ccm_configure_root_clock(CCM_CR_CAN2, SYS_PLL1PFD1DIV2, 5); - imx9_ccm_gate_on(CCM_LPCG_CAN2, true); - priv = &g_flexcan2; - break; + case 2: + imx9_ccm_configure_root_clock(CCM_CR_CAN2, SYS_PLL1PFD1DIV2, 5); + imx9_ccm_gate_on(CCM_LPCG_CAN2, true); + priv = &g_flexcan2; + break; #endif - default: - return -ENODEV; + default: + return -ENODEV; } /* Get and store the clock (should be 80 MHz now) */ diff --git a/arch/risc-v/src/mpfs/mpfs_can.c b/arch/risc-v/src/mpfs/mpfs_can.c index faa0c6d4eaf20..e8e814526ee5d 100644 --- a/arch/risc-v/src/mpfs/mpfs_can.c +++ b/arch/risc-v/src/mpfs/mpfs_can.c @@ -1371,6 +1371,7 @@ static void mpfs_can_set_int_ebl(mpfs_can_instance_t *priv, uint32_t flag) { uint32_t reg = mpfs_can_get_int_ebl(priv); + putreg32(reg | flag, priv->reg_base + MPFS_CAN_INT_ENABLE_OFFSET); } @@ -1414,6 +1415,7 @@ static void mpfs_can_clear_int_ebl(mpfs_can_instance_t *priv, uint32_t flag) { uint32_t reg = mpfs_can_get_int_ebl(priv); + putreg32(reg & ~flag, priv->reg_base + MPFS_CAN_INT_ENABLE_OFFSET); } @@ -1530,6 +1532,7 @@ static uint32_t mpfs_can_get_int_status(mpfs_can_instance_t *priv) static uint8_t mpfs_can_get_error_status(mpfs_can_instance_t *priv) { uint32_t reg = getreg32(priv->reg_base + MPFS_CAN_ERROR_STATUS_OFFSET); + reg = ((reg & MPFS_CAN_ERROR_STATUS_ERROR_STATE) >> MPFS_CAN_ERROR_STATUS_ERROR_STATE_SHIFT); return (uint8_t)reg; @@ -1760,12 +1763,14 @@ static uint8_t mpfs_can_set_bitrate(mpfs_can_instance_t *priv, static uint32_t mpfs_can_get_sample_point(mpfs_can_instance_t *priv) { uint32_t reg; + reg = getreg32(priv->reg_base + MPFS_CAN_CAN_CONFIG_OFFSET); uint32_t tseg1 = ((reg & MPFS_CAN_CAN_CONFIG_CFG_TSEG1) >> MPFS_CAN_CAN_CONFIG_CFG_TSEG1_SHIFT) + 1; uint32_t tseg2 = ((reg & MPFS_CAN_CAN_CONFIG_CFG_TSEG2) >> MPFS_CAN_CAN_CONFIG_CFG_TSEG2_SHIFT) + 1; const uint32_t sync_seg = 1; + return (sync_seg + tseg1) * 100 / (sync_seg + tseg1 + tseg2); } #endif @@ -1838,7 +1843,7 @@ static uint8_t mpfs_can_config_buffer(mpfs_can_instance_t *priv) mpfs_can_config_buffer_n(priv, buffer_number, &canrxobj); } - success = CAN_OK; + success = CAN_OK; } return success; @@ -1945,6 +1950,7 @@ mpfs_can_get_rx_buffer_status(mpfs_can_instance_t *priv) static uint32_t mpfs_can_get_rx_error_count(mpfs_can_instance_t *priv) { uint32_t reg = getreg32(priv->reg_base + MPFS_CAN_ERROR_STATUS_OFFSET); + reg = ((reg & MPFS_CAN_ERROR_STATUS_RX_ERR_CNT) >> MPFS_CAN_ERROR_STATUS_RX_ERR_CNT_SHIFT); return reg; @@ -1976,6 +1982,7 @@ static uint32_t mpfs_can_get_rx_error_count(mpfs_can_instance_t *priv) static inline bool mpfs_can_get_rx_gte96(mpfs_can_instance_t *priv) { uint32_t reg = getreg32(priv->reg_base + MPFS_CAN_ERROR_STATUS_OFFSET); + reg &= MPFS_CAN_ERROR_STATUS_RXGTE96; return (bool)reg; } @@ -2088,6 +2095,7 @@ static uint32_t mpfs_can_get_tx_buffer_status(mpfs_can_instance_t *priv) static uint32_t mpfs_can_get_tx_error_count(mpfs_can_instance_t *priv) { uint32_t reg = getreg32(priv->reg_base + MPFS_CAN_ERROR_STATUS_OFFSET); + reg = ((reg & MPFS_CAN_ERROR_STATUS_TX_ERR_CNT) >> MPFS_CAN_ERROR_STATUS_TX_ERR_CNT_SHIFT); return reg; @@ -2119,6 +2127,7 @@ static uint32_t mpfs_can_get_tx_error_count(mpfs_can_instance_t *priv) static inline bool mpfs_can_get_tx_gte96(mpfs_can_instance_t *priv) { uint32_t reg = getreg32(priv->reg_base + MPFS_CAN_ERROR_STATUS_OFFSET); + reg &= MPFS_CAN_ERROR_STATUS_TXGTE96; return (bool)reg; } @@ -2308,70 +2317,71 @@ static int mpfs_ioctl(struct netdev_lowerhalf_s *dev, int cmd, switch (cmd) { #ifdef CONFIG_NETDEV_CAN_IOCTL - case SIOCGCANBITRATE: - - /* Get bitrate from the CAN controller */ - - { - struct can_ioctl_data_s *req = - (struct can_ioctl_data_s *)((uintptr_t)arg); - req->arbi_bitrate = priv->bitrate_value; - req->arbi_samplep = mpfs_can_get_sample_point(priv); - ret = CAN_OK; - } - break; - - case SIOCSCANBITRATE: - - /* Set bitrate of the CAN controller */ - - { - struct can_ioctl_data_s *req = - (struct can_ioctl_data_s *)((uintptr_t)arg); - - if (CAN_OK != mpfs_can_set_bitrate(priv, req->arbi_bitrate)) - { - nerr("CAN controller bitrate set failed"); - ret = -EAGAIN; - break; - } - - ret = CAN_OK; - } - break; - - case SIOCACANSTDFILTER: - case SIOCACANEXTFILTER: - - { - struct can_ioctl_filter_s *req = - (struct can_ioctl_filter_s *)((uintptr_t)arg); - - if (CAN_OK != mpfs_can_add_filter(priv, req->ftype, - req->fid1, req->fid2)) - { - nerr("CAN filter add failed"); - ret = -EINVAL; - break; - } - - ret = CAN_OK; - } - break; - - case SIOCDCANSTDFILTER: - case SIOCDCANEXTFILTER: - - { - mpfs_can_reset_filter(priv); - ret = CAN_OK; - } - break; + case SIOCGCANBITRATE: + + /* Get bitrate from the CAN controller */ + + { + struct can_ioctl_data_s *req = + (struct can_ioctl_data_s *)((uintptr_t)arg); + + req->arbi_bitrate = priv->bitrate_value; + req->arbi_samplep = mpfs_can_get_sample_point(priv); + ret = CAN_OK; + } + break; + + case SIOCSCANBITRATE: + + /* Set bitrate of the CAN controller */ + + { + struct can_ioctl_data_s *req = + (struct can_ioctl_data_s *)((uintptr_t)arg); + + if (CAN_OK != mpfs_can_set_bitrate(priv, req->arbi_bitrate)) + { + nerr("CAN controller bitrate set failed"); + ret = -EAGAIN; + break; + } + + ret = CAN_OK; + } + break; + + case SIOCACANSTDFILTER: + case SIOCACANEXTFILTER: + + { + struct can_ioctl_filter_s *req = + (struct can_ioctl_filter_s *)((uintptr_t)arg); + + if (CAN_OK != mpfs_can_add_filter(priv, req->ftype, + req->fid1, req->fid2)) + { + nerr("CAN filter add failed"); + ret = -EINVAL; + break; + } + + ret = CAN_OK; + } + break; + + case SIOCDCANSTDFILTER: + case SIOCDCANEXTFILTER: + + { + mpfs_can_reset_filter(priv); + ret = CAN_OK; + } + break; #endif /* CONFIG_NETDEV_CAN_IOCTL */ - default: - ret = -ENOTTY; - break; + default: + ret = -ENOTTY; + break; } return ret; diff --git a/net/can/can_callback.c b/net/can/can_callback.c index 667f1061496d0..b06302e0e6c14 100644 --- a/net/can/can_callback.c +++ b/net/can/can_callback.c @@ -127,28 +127,28 @@ uint32_t can_callback(FAR struct net_driver_s *dev, if (conn) { #ifdef CONFIG_NET_TIMESTAMP - /* TIMESTAMP sockopt is activated, - * create timestamp and copy to iob - */ + /* TIMESTAMP sockopt is activated, + * create timestamp and copy to iob + */ + + if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) && + (dev->d_iob != NULL)) + { + struct timeval tv; + FAR struct timespec *ts = (FAR struct timespec *)&tv; + int len; - if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) && - (dev->d_iob != NULL)) + clock_systime_timespec(ts); + tv.tv_usec = ts->tv_nsec / 1000; + + len = iob_trycopyin(dev->d_iob, (FAR uint8_t *)&tv, + sizeof(struct timeval), + -CONFIG_NET_LL_GUARDSIZE, false); + if (len == sizeof(struct timeval)) { - struct timeval tv; - FAR struct timespec *ts = (FAR struct timespec *)&tv; - int len; - - clock_systime_timespec(ts); - tv.tv_usec = ts->tv_nsec / 1000; - - len = iob_trycopyin(dev->d_iob, (FAR uint8_t *)&tv, - sizeof(struct timeval), - -CONFIG_NET_LL_GUARDSIZE, false); - if (len == sizeof(struct timeval)) - { - dev->d_len += len; - } + dev->d_len += len; } + } #endif conn_lock(&conn->sconn); diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c index 64b6a04f3cdf2..4f6610f43963a 100644 --- a/net/netdev/netdev_ioctl.c +++ b/net/netdev/netdev_ioctl.c @@ -270,6 +270,7 @@ static void ioctl_get_ipv4addr(FAR struct sockaddr *outaddr, in_addr_t inaddr) { FAR struct sockaddr_in *dest = (FAR struct sockaddr_in *)outaddr; + dest->sin_family = AF_INET; dest->sin_port = 0; dest->sin_addr.s_addr = inaddr; @@ -295,6 +296,7 @@ static void ioctl_get_ipv4broadcast(FAR struct sockaddr *outaddr, in_addr_t inaddr, in_addr_t netmask) { FAR struct sockaddr_in *dest = (FAR struct sockaddr_in *)outaddr; + dest->sin_family = AF_INET; dest->sin_port = 0; dest->sin_addr.s_addr = net_ipv4addr_broadcast(inaddr, netmask); @@ -319,6 +321,7 @@ static void ioctl_get_ipv6addr(FAR struct sockaddr_storage *outaddr, FAR const net_ipv6addr_t inaddr) { FAR struct sockaddr_in6 *dest = (FAR struct sockaddr_in6 *)outaddr; + dest->sin6_family = AF_INET6; dest->sin6_port = 0; memcpy(dest->sin6_addr.in6_u.u6_addr8, inaddr, 16); @@ -343,6 +346,7 @@ static void ioctl_set_ipv4addr(FAR in_addr_t *outaddr, FAR const struct sockaddr *inaddr) { FAR const struct sockaddr_in *src = (FAR const struct sockaddr_in *)inaddr; + *outaddr = src->sin_addr.s_addr; } #endif @@ -366,6 +370,7 @@ static void ioctl_set_ipv6addr(FAR net_ipv6addr_t outaddr, { FAR const struct sockaddr_in6 *src = (FAR const struct sockaddr_in6 *)inaddr; + memcpy(outaddr, src->sin6_addr.in6_u.u6_addr8, 16); } #endif @@ -854,6 +859,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, case SIOCSIFNAME: /* Set interface name */ { FAR struct net_driver_s *tmpdev; + tmpdev = netdev_findbyindex(req->ifr_ifindex); if (tmpdev != NULL) { @@ -869,6 +875,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, case SIOCGIFNAME: /* Get interface name */ { FAR struct net_driver_s *tmpdev; + tmpdev = netdev_findbyindex(req->ifr_ifindex); if (tmpdev != NULL) { @@ -898,6 +905,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, == (ssize_t)sizeof(struct in6_ifreq)) { FAR struct in6_ifreq *ifr6 = (FAR struct in6_ifreq *)req; + dev = netdev_findbyindex(ifr6->ifr6_ifindex); } @@ -954,6 +962,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, case SIOCGLIFADDR: /* Get IP address */ { FAR struct lifreq *lreq = (FAR struct lifreq *)req; + idx = MIN(idx, CONFIG_NETDEV_MAX_IPv6_ADDR - 1); ioctl_get_ipv6addr(&lreq->lifr_addr, dev->d_ipv6[idx].addr); } @@ -962,6 +971,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, case SIOCSLIFADDR: /* Set IP address */ { FAR struct lifreq *lreq = (FAR struct lifreq *)req; + idx = MIN(idx, CONFIG_NETDEV_MAX_IPv6_ADDR - 1); netdev_ipv6_removemcastmac(dev, dev->d_ipv6[idx].addr); @@ -976,6 +986,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, case SIOCGLIFDSTADDR: /* Get P-to-P address */ { FAR struct lifreq *lreq = (FAR struct lifreq *)req; + ioctl_get_ipv6addr(&lreq->lifr_dstaddr, dev->d_ipv6draddr); } break; @@ -983,6 +994,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, case SIOCSLIFDSTADDR: /* Set P-to-P address */ { FAR struct lifreq *lreq = (FAR struct lifreq *)req; + ioctl_set_ipv6addr(dev->d_ipv6draddr, &lreq->lifr_dstaddr); } break; @@ -995,6 +1007,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, case SIOCGLIFNETMASK: /* Get network mask */ { FAR struct lifreq *lreq = (FAR struct lifreq *)req; + idx = MIN(idx, CONFIG_NETDEV_MAX_IPv6_ADDR - 1); ioctl_get_ipv6addr(&lreq->lifr_addr, dev->d_ipv6[idx].mask); } @@ -1003,6 +1016,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, case SIOCSLIFNETMASK: /* Set network mask */ { FAR struct lifreq *lreq = (FAR struct lifreq *)req; + idx = MIN(idx, CONFIG_NETDEV_MAX_IPv6_ADDR - 1); ioctl_set_ipv6addr(dev->d_ipv6[idx].mask, &lreq->lifr_addr); } @@ -1176,6 +1190,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, if (psock->s_domain == PF_INET6) { FAR struct in6_ifreq *ifr6 = (FAR struct in6_ifreq *)req; + ret = netdev_ipv6_add(dev, ifr6->ifr6_addr.in6_u.u6_addr16, ifr6->ifr6_prefixlen); if (ret == OK) @@ -1201,6 +1216,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, if (psock->s_domain == PF_INET6) { FAR struct in6_ifreq *ifr6 = (FAR struct in6_ifreq *)req; + ret = netdev_ipv6_del(dev, ifr6->ifr6_addr.in6_u.u6_addr16, ifr6->ifr6_prefixlen); if (ret == OK) @@ -1219,6 +1235,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, { FAR struct mii_ioctl_notify_s *notify = &req->ifr_ifru.ifru_mii_notify; + ret = dev->d_ioctl(dev, cmd, (unsigned long)(uintptr_t)notify); } else @@ -1235,6 +1252,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, { FAR struct mii_ioctl_data_s *mii_data = &req->ifr_ifru.ifru_mii_data; + ret = dev->d_ioctl(dev, cmd, (unsigned long)(uintptr_t)mii_data); } @@ -1714,7 +1732,7 @@ static int netdev_ioctl(FAR struct socket *psock, int cmd, break; - default: + default: break; }