diff --git a/drivers/include/can/candev.h b/drivers/include/can/candev.h index cddfb5f2b1..1c01ea80ed 100644 --- a/drivers/include/can/candev.h +++ b/drivers/include/can/candev.h @@ -82,6 +82,7 @@ struct candev { enum can_state state; /**< device state */ #ifdef MODULE_FDCAN struct can_bittiming fd_data_bittiming;/**< device bittimings for FD CAN only */ + uint16_t loop_delay; /**< CAN FD transceiver loop delay */ #endif }; diff --git a/sys/Kconfig b/sys/Kconfig index 4573def28c..8052d8e1f0 100644 --- a/sys/Kconfig +++ b/sys/Kconfig @@ -7,6 +7,7 @@ menu "System" rsource "auto_init/Kconfig" +rsource "can/Kconfig" rsource "chunked_ringbuffer/Kconfig" rsource "congure/Kconfig" rsource "debug_irq_disable/Kconfig" diff --git a/sys/auto_init/can/auto_init_periph_can.c b/sys/auto_init/can/auto_init_periph_can.c index b831440681..3fed0abc6e 100644 --- a/sys/auto_init/can/auto_init_periph_can.c +++ b/sys/auto_init/can/auto_init_periph_can.c @@ -48,6 +48,9 @@ void auto_init_periph_can(void) { candev_dev[i].rx_inactivity_timeout = candev_params[i].rx_inactivity_timeout; candev_dev[i].tx_wakeup_timeout = candev_params[i].tx_wakeup_timeout; #endif +#ifdef MODULE_FDCAN + candev_dev[i].loop_delay = candev_params[i].loop_delay; +#endif can_device_init(_can_stacks[i], CANDEV_STACKSIZE, CANDEV_BASE_PRIORITY + i, candev_params[i].name, &candev_dev[i]); diff --git a/sys/can/Kconfig b/sys/can/Kconfig new file mode 100644 index 0000000000..6897449f73 --- /dev/null +++ b/sys/can/Kconfig @@ -0,0 +1,36 @@ +menu "CAN" + depends on USEMODULE_CAN || USEMODULE_FDCAN + +menu "FD CAN" + +config FDCAN_DEVICE_SET_TRANSCEIVER_LOOP_DELAY + depends on USEMODULE_FDCAN + bool "FD CAN transceiver loop delay" + default n + help + Allow to set FD CAN Transceiver loop delay. + +config FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY + depends on FDCAN_DEVICE_SET_TRANSCEIVER_LOOP_DELAY + int "FD CAN transceiver loop delay value" + range 0 1000 + default 0 + help + This parameter defines the loop delay introduced by the CAN transceiver + during transmission. The loop delay represents the time taken for the + transmitted signal to be looped back to the CAN controller. This delay + is introduced by the physical transceiver circuitry and may vary + depending on the transceiver model and other physical factors. + + The value is typically measured in nanoseconds and should be set + according to the specifications provided by the transceiver manufacturer. + A higher loop delay can affect the timing of CAN message transmissions + and may need to be adjusted in systems with tight timing requirements. + + If unsure, leave this value as 0 or refer to the hardware documentation + for the correct delay value. + + +endmenu # FD CAN + +endmenu # CAN diff --git a/sys/can/device.c b/sys/can/device.c index 4dd092c47e..7a654cc4e2 100644 --- a/sys/can/device.c +++ b/sys/can/device.c @@ -35,6 +35,16 @@ #define ENABLE_DEBUG 0 #include "debug.h" +#ifdef MODULE_FDCAN +/** + * The loop delay in CAN, especially in CAN FD with bitrate switching, affects synchronization due to increased data rates. + * The unit is nanoseconds. + */ +#ifndef CONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY +#error "CONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY must be defined. This property can be found in the datasheet of the CAN transceiver in use. The unit is nanoseconds." +#endif /* CONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY */ +#endif /* MODULE_FDCAN */ + #ifndef CAN_DEVICE_MSG_QUEUE_SIZE #define CAN_DEVICE_MSG_QUEUE_SIZE 64 #endif @@ -236,6 +246,13 @@ static void *_can_device_thread(void *args) candev_dev->ifnum = can_dll_register_candev(candev_dev); +#if defined(MODULE_FDCAN) + if (candev_dev->loop_delay == 0) { + candev_dev->loop_delay = CONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY; + } + dev->loop_delay = candev_dev->loop_delay; +#endif + dev->driver->init(dev); power_up(candev_dev); diff --git a/sys/include/can/device.h b/sys/include/can/device.h index be3d858f30..3972119d5b 100644 --- a/sys/include/can/device.h +++ b/sys/include/can/device.h @@ -57,6 +57,9 @@ typedef struct candev_params { #if defined(MODULE_CAN_TRX) || defined(DOXYGEN) can_trx_t *trx; /**< transceiver to set */ #endif +#if defined(MODULE_FDCAN) + uint16_t loop_delay; /**< CAN FD transceiver loop delay */ +#endif #if defined(MODULE_CAN_PM) || defined(DOXYGEN) uint32_t rx_inactivity_timeout; /**< power management rx timeout value */ uint32_t tx_wakeup_timeout; /**< power management tx wake up value */ @@ -74,6 +77,9 @@ typedef struct candev_dev { #if defined(MODULE_CAN_TRX) || defined(DOXYGEN) can_trx_t *trx; /**< transceiver attached to the device */ #endif +#if defined(MODULE_FDCAN) + uint16_t loop_delay; /**< CAN FD transceiver loop delay */ +#endif #if defined(MODULE_CAN_PM) || defined(DOXYGEN) uint32_t rx_inactivity_timeout; /**< Min timeout loaded when a frame is received */ uint32_t tx_wakeup_timeout; /**< Min timeout loaded when a frame is sent */