drivers: can: rework support for manual bus-off recovery
Since all CAN controllers drivers seem to support automatic recovery (for any future drivers for hardware without this hardware capability this can easily be implemented in the driver), change the Zephyr CAN controller API policy to: - Always enable automatic bus recovery upon driver initialization, regardless of Kconfig options. Since CAN controllers are initialized in "stopped" state, no unwanted bus-off recovery will be started at this point. - Invert and rename the Kconfig CONFIG_CAN_AUTO_BUS_OFF_RECOVERY, which is enabled by default, to CONFIG_CAN_MANUAL_RECOVERY_MODE, which is disabled by default. Enabling CONFIG_CAN_MANUAL_RECOVERY_MODE=y enables support for the can_recover() API function and a new manual recovery mode (see next bullet). Keeping this guarded by Kconfig allows keeping the flash footprint down for applications not using manual bus-off recovery. - Introduce a new CAN controller operational mode CAN_MODE_MANUAL_RECOVERY. Support for this is only enabled if CONFIG_CAN_MANUAL_RECOVERY_MODE=y. Having this as a mode allows applications to inquire whether the CAN controller supports manual recovery mode via the can_get_capabilities() API function and either fail or rely on automatic recovery - and it allows CAN controller drivers not supporting manual recovery mode to fail early in can_set_mode() during application startup instead of failing when can_recover() is called at a later point in time. Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
parent
118f1592ff
commit
a57db0ddcb
|
@ -33,8 +33,7 @@ The following :ref:`Kconfig <kconfig>` options enable additional subcommands and
|
|||
* :kconfig:option:`CONFIG_CAN_STATS` enables printing of various statistics for the CAN controller
|
||||
in the ``can show`` subcommand. This depends on :kconfig:option:`CONFIG_STATS` being enabled as
|
||||
well.
|
||||
* :kconfig:option:`CONFIG_CAN_AUTO_BUS_OFF_RECOVERY` enables the ``can recover`` subcommand when
|
||||
disabled.
|
||||
* :kconfig:option:`CONFIG_CAN_MANUAL_RECOVERY_MODE` enables the ``can recover`` subcommand.
|
||||
|
||||
For example, building the :ref:`hello_world` sample for the :ref:`frdm_k64f` with the CAN shell and
|
||||
CAN statistics enabled:
|
||||
|
@ -253,8 +252,8 @@ details on the supported arguments.
|
|||
Bus Recovery
|
||||
************
|
||||
|
||||
The ``can recover`` subcommand can be used for initiating recovery from a CAN bus-off event as shown
|
||||
below:
|
||||
The ``can recover`` subcommand can be used for initiating manual recovery from a CAN bus-off event
|
||||
as shown below:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
|
@ -265,5 +264,5 @@ The subcommand accepts an optional bus recovery timeout in milliseconds. If no t
|
|||
the command will wait indefinitely for the bus recovery to succeed.
|
||||
|
||||
.. note::
|
||||
The ``recover`` subcommand is only available if
|
||||
:kconfig:option:`CONFIG_CAN_AUTO_BUS_OFF_RECOVERY` is disabled.
|
||||
The ``recover`` subcommand is only available if :kconfig:option:`CONFIG_CAN_MANUAL_RECOVERY_MODE`
|
||||
is enabled.
|
||||
|
|
|
@ -62,10 +62,16 @@ config CAN_ACCEPT_RTR
|
|||
level.
|
||||
|
||||
config CAN_FD_MODE
|
||||
bool "CAN FD"
|
||||
bool "CAN FD support"
|
||||
help
|
||||
Enable CAN FD support. Not all CAN controllers support CAN FD.
|
||||
|
||||
config CAN_MANUAL_RECOVERY_MODE
|
||||
bool "Manual bus-off recovery support"
|
||||
help
|
||||
Enable support for manual (non-automatic) recovery from bus-off state. Not all CAN
|
||||
controllers support manual recovery mode.
|
||||
|
||||
config CAN_RX_TIMESTAMP
|
||||
bool "Receiving timestamps"
|
||||
help
|
||||
|
@ -73,15 +79,6 @@ config CAN_RX_TIMESTAMP
|
|||
The value is incremented every bit time and starts when the controller
|
||||
is initialized. Not all CAN controllers support timestamps.
|
||||
|
||||
config CAN_AUTO_BUS_OFF_RECOVERY
|
||||
bool "Automatic recovery from bus-off"
|
||||
default y
|
||||
help
|
||||
This option enables the automatic bus-off recovery according to
|
||||
ISO 11898-1 (recovery after 128 occurrences of 11 consecutive
|
||||
recessive bits). When this option is enabled, the recovery API is not
|
||||
available.
|
||||
|
||||
config CAN_QEMU_IFACE_NAME
|
||||
string "SocketCAN interface name for QEMU"
|
||||
default ""
|
||||
|
|
|
@ -224,9 +224,9 @@ const struct can_driver_api can_esp32_twai_driver_api = {
|
|||
.set_state_change_callback = can_sja1000_set_state_change_callback,
|
||||
.get_core_clock = can_esp32_twai_get_core_clock,
|
||||
.get_max_filters = can_sja1000_get_max_filters,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = can_sja1000_recover,
|
||||
#endif /* !CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
.timing_min = CAN_SJA1000_TIMING_MIN_INITIALIZER,
|
||||
#ifdef CONFIG_SOC_SERIES_ESP32
|
||||
.timing_max = CAN_SJA1000_TIMING_MAX_INITIALIZER,
|
||||
|
|
|
@ -103,9 +103,9 @@ static const struct can_driver_api fake_can_driver_api = {
|
|||
.add_rx_filter = fake_can_add_rx_filter,
|
||||
.remove_rx_filter = fake_can_remove_rx_filter,
|
||||
.get_state = fake_can_get_state,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = fake_can_recover,
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
.set_state_change_callback = fake_can_set_state_change_callback,
|
||||
.get_core_clock = fake_can_get_core_clock,
|
||||
.get_max_filters = fake_can_get_max_filters,
|
||||
|
|
|
@ -249,15 +249,16 @@ static inline int z_vrfy_can_get_state(const struct device *dev, enum can_state
|
|||
}
|
||||
#include <syscalls/can_get_state_mrsh.c>
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
static inline int z_vrfy_can_recover(const struct device *dev, k_timeout_t timeout)
|
||||
{
|
||||
K_OOPS(K_SYSCALL_DRIVER_CAN(dev, recover));
|
||||
/* Optional API function */
|
||||
K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN));
|
||||
|
||||
return z_impl_can_recover(dev, timeout);
|
||||
}
|
||||
#include <syscalls/can_recover_mrsh.c>
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
|
||||
#ifdef CONFIG_CAN_STATS
|
||||
|
||||
|
|
|
@ -143,9 +143,9 @@ const struct can_driver_api can_kvaser_pci_driver_api = {
|
|||
.set_state_change_callback = can_sja1000_set_state_change_callback,
|
||||
.get_core_clock = can_kvaser_pci_get_core_clock,
|
||||
.get_max_filters = can_sja1000_get_max_filters,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = can_sja1000_recover,
|
||||
#endif /* !CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
.timing_min = CAN_SJA1000_TIMING_MIN_INITIALIZER,
|
||||
.timing_max = CAN_SJA1000_TIMING_MAX_INITIALIZER,
|
||||
};
|
||||
|
|
|
@ -340,21 +340,6 @@ static int can_loopback_get_state(const struct device *dev, enum can_state *stat
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
static int can_loopback_recover(const struct device *dev, k_timeout_t timeout)
|
||||
{
|
||||
struct can_loopback_data *data = dev->data;
|
||||
|
||||
ARG_UNUSED(timeout);
|
||||
|
||||
if (!data->common.started) {
|
||||
return -ENETDOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
|
||||
static void can_loopback_set_state_change_callback(const struct device *dev,
|
||||
can_state_change_callback_t cb,
|
||||
void *user_data)
|
||||
|
@ -388,9 +373,6 @@ static const struct can_driver_api can_loopback_driver_api = {
|
|||
.add_rx_filter = can_loopback_add_rx_filter,
|
||||
.remove_rx_filter = can_loopback_remove_rx_filter,
|
||||
.get_state = can_loopback_get_state,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
.recover = can_loopback_recover,
|
||||
#endif
|
||||
.set_state_change_callback = can_loopback_set_state_change_callback,
|
||||
.get_core_clock = can_loopback_get_core_clock,
|
||||
.get_max_filters = can_loopback_get_max_filters,
|
||||
|
|
|
@ -258,9 +258,13 @@ int can_mcan_get_capabilities(const struct device *dev, can_mode_t *cap)
|
|||
|
||||
*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY;
|
||||
|
||||
#if CONFIG_CAN_FD_MODE
|
||||
*cap |= CAN_MODE_FD;
|
||||
#endif /* CONFIG_CAN_FD_MODE */
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
*cap |= CAN_MODE_MANUAL_RECOVERY;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_CAN_FD_MODE)) {
|
||||
*cap |= CAN_MODE_FD;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -350,22 +354,24 @@ int can_mcan_stop(const struct device *dev)
|
|||
|
||||
int can_mcan_set_mode(const struct device *dev, can_mode_t mode)
|
||||
{
|
||||
can_mode_t supported = CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY;
|
||||
struct can_mcan_data *data = dev->data;
|
||||
uint32_t cccr;
|
||||
uint32_t test;
|
||||
int err;
|
||||
|
||||
#ifdef CONFIG_CAN_FD_MODE
|
||||
if ((mode & ~(CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_FD)) != 0U) {
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
supported |= CAN_MODE_MANUAL_RECOVERY;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_CAN_FD_MODE)) {
|
||||
supported |= CAN_MODE_FD;
|
||||
}
|
||||
|
||||
if ((mode & ~(supported)) != 0U) {
|
||||
LOG_ERR("unsupported mode: 0x%08x", mode);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#else /* CONFIG_CAN_FD_MODE */
|
||||
if ((mode & ~(CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY)) != 0U) {
|
||||
LOG_ERR("unsupported mode: 0x%08x", mode);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#endif /* !CONFIG_CAN_FD_MODE */
|
||||
|
||||
if (data->common.started) {
|
||||
return -EBUSY;
|
||||
|
@ -462,7 +468,8 @@ static void can_mcan_state_change_handler(const struct device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_CAN_AUTO_BUS_OFF_RECOVERY)) {
|
||||
if (!IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE) ||
|
||||
(data->common.mode & CAN_MODE_MANUAL_RECOVERY) == 0U) {
|
||||
/*
|
||||
* Request leaving init mode, but do not take the lock (as we are in ISR
|
||||
* context), nor wait for the result.
|
||||
|
@ -847,7 +854,7 @@ int can_mcan_get_state(const struct device *dev, enum can_state *state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
int can_mcan_recover(const struct device *dev, k_timeout_t timeout)
|
||||
{
|
||||
struct can_mcan_data *data = dev->data;
|
||||
|
@ -856,9 +863,13 @@ int can_mcan_recover(const struct device *dev, k_timeout_t timeout)
|
|||
return -ENETDOWN;
|
||||
}
|
||||
|
||||
if ((data->common.mode & CAN_MODE_MANUAL_RECOVERY) == 0U) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return can_mcan_leave_init_mode(dev, timeout);
|
||||
}
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
|
||||
int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_timeout_t timeout,
|
||||
can_tx_callback_t callback, void *user_data)
|
||||
|
|
|
@ -789,21 +789,6 @@ static void mcp2515_handle_errors(const struct device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
static int mcp2515_recover(const struct device *dev, k_timeout_t timeout)
|
||||
{
|
||||
struct mcp2515_data *dev_data = dev->data;
|
||||
|
||||
ARG_UNUSED(timeout);
|
||||
|
||||
if (!dev_data->common.started) {
|
||||
return -ENETDOWN;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void mcp2515_handle_interrupts(const struct device *dev)
|
||||
{
|
||||
const struct mcp2515_config *dev_cfg = dev->config;
|
||||
|
@ -904,9 +889,6 @@ static const struct can_driver_api can_api_funcs = {
|
|||
.add_rx_filter = mcp2515_add_rx_filter,
|
||||
.remove_rx_filter = mcp2515_remove_rx_filter,
|
||||
.get_state = mcp2515_get_state,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
.recover = mcp2515_recover,
|
||||
#endif
|
||||
.set_state_change_callback = mcp2515_set_state_change_callback,
|
||||
.get_core_clock = mcp2515_get_core_clock,
|
||||
.get_max_filters = mcp2515_get_max_filters,
|
||||
|
|
|
@ -740,21 +740,6 @@ static int mcp251xfd_get_max_filters(const struct device *dev, bool ide)
|
|||
return CONFIG_CAN_MAX_FILTER;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
static int mcp251xfd_recover(const struct device *dev, k_timeout_t timeout)
|
||||
{
|
||||
struct mcp251xfd_data *dev_data = dev->data;
|
||||
|
||||
ARG_UNUSED(timeout);
|
||||
|
||||
if (!dev_data->common.started) {
|
||||
return -ENETDOWN;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int mcp251xfd_handle_fifo_read(const struct device *dev, const struct mcp251xfd_fifo *fifo,
|
||||
uint8_t fifo_type)
|
||||
{
|
||||
|
@ -1646,9 +1631,6 @@ static const struct can_driver_api mcp251xfd_api_funcs = {
|
|||
.send = mcp251xfd_send,
|
||||
.add_rx_filter = mcp251xfd_add_rx_filter,
|
||||
.remove_rx_filter = mcp251xfd_remove_rx_filter,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
.recover = mcp251xfd_recover,
|
||||
#endif
|
||||
.get_state = mcp251xfd_get_state,
|
||||
.set_state_change_callback = mcp251xfd_set_state_change_callback,
|
||||
.get_core_clock = mcp251xfd_get_core_clock,
|
||||
|
|
|
@ -177,6 +177,10 @@ static int mcux_flexcan_get_capabilities(const struct device *dev, can_mode_t *c
|
|||
|
||||
*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_3_SAMPLES;
|
||||
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
*cap |= CAN_MODE_MANUAL_RECOVERY;
|
||||
}
|
||||
|
||||
if (UTIL_AND(IS_ENABLED(CONFIG_CAN_MCUX_FLEXCAN_FD), config->flexcan_fd)) {
|
||||
*cap |= CAN_MODE_FD;
|
||||
}
|
||||
|
@ -388,6 +392,10 @@ static int mcux_flexcan_set_mode(const struct device *dev, can_mode_t mode)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
supported |= CAN_MODE_MANUAL_RECOVERY;
|
||||
}
|
||||
|
||||
if (UTIL_AND(IS_ENABLED(CONFIG_CAN_MCUX_FLEXCAN_FD), config->flexcan_fd)) {
|
||||
supported |= CAN_MODE_FD;
|
||||
}
|
||||
|
@ -431,6 +439,16 @@ static int mcux_flexcan_set_mode(const struct device *dev, can_mode_t mode)
|
|||
ctrl1 &= ~(CAN_CTRL1_SMP_MASK);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
if ((mode & CAN_MODE_MANUAL_RECOVERY) != 0) {
|
||||
/* Disable auto-recovery from bus-off */
|
||||
ctrl1 |= CAN_CTRL1_BOFFREC_MASK;
|
||||
} else {
|
||||
/* Enable auto-recovery from bus-off */
|
||||
ctrl1 &= ~(CAN_CTRL1_BOFFREC_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
|
||||
if (config->flexcan_fd) {
|
||||
if ((mode & CAN_MODE_FD) != 0) {
|
||||
|
@ -819,7 +837,7 @@ static void mcux_flexcan_set_state_change_callback(const struct device *dev,
|
|||
data->common.state_change_cb_user_data = user_data;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
static int mcux_flexcan_recover(const struct device *dev, k_timeout_t timeout)
|
||||
{
|
||||
const struct mcux_flexcan_config *config = dev->config;
|
||||
|
@ -832,6 +850,10 @@ static int mcux_flexcan_recover(const struct device *dev, k_timeout_t timeout)
|
|||
return -ENETDOWN;
|
||||
}
|
||||
|
||||
if ((data->common.mode & CAN_MODE_MANUAL_RECOVERY) == 0U) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
(void)mcux_flexcan_get_state(dev, &state, NULL);
|
||||
if (state != CAN_STATE_BUS_OFF) {
|
||||
return 0;
|
||||
|
@ -857,7 +879,7 @@ static int mcux_flexcan_recover(const struct device *dev, k_timeout_t timeout)
|
|||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
|
||||
static void mcux_flexcan_remove_rx_filter(const struct device *dev, int filter_id)
|
||||
{
|
||||
|
@ -1225,9 +1247,8 @@ static int mcux_flexcan_init(const struct device *dev)
|
|||
|
||||
config->irq_config_func(dev);
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
config->base->CTRL1 |= CAN_CTRL1_BOFFREC_MASK;
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
/* Enable auto-recovery from bus-off */
|
||||
config->base->CTRL1 &= ~(CAN_CTRL1_BOFFREC_MASK);
|
||||
|
||||
(void)mcux_flexcan_get_state(dev, &data->state, NULL);
|
||||
|
||||
|
@ -1244,9 +1265,9 @@ __maybe_unused static const struct can_driver_api mcux_flexcan_driver_api = {
|
|||
.add_rx_filter = mcux_flexcan_add_rx_filter,
|
||||
.remove_rx_filter = mcux_flexcan_remove_rx_filter,
|
||||
.get_state = mcux_flexcan_get_state,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = mcux_flexcan_recover,
|
||||
#endif
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
.set_state_change_callback = mcux_flexcan_set_state_change_callback,
|
||||
.get_core_clock = mcux_flexcan_get_core_clock,
|
||||
.get_max_filters = mcux_flexcan_get_max_filters,
|
||||
|
@ -1287,9 +1308,9 @@ static const struct can_driver_api mcux_flexcan_fd_driver_api = {
|
|||
.add_rx_filter = mcux_flexcan_add_rx_filter,
|
||||
.remove_rx_filter = mcux_flexcan_remove_rx_filter,
|
||||
.get_state = mcux_flexcan_get_state,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = mcux_flexcan_recover,
|
||||
#endif
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
.set_state_change_callback = mcux_flexcan_set_state_change_callback,
|
||||
.get_core_clock = mcux_flexcan_get_core_clock,
|
||||
.get_max_filters = mcux_flexcan_get_max_filters,
|
||||
|
|
|
@ -132,9 +132,9 @@ static const struct can_driver_api mcux_mcan_driver_api = {
|
|||
.send = can_mcan_send,
|
||||
.add_rx_filter = can_mcan_add_rx_filter,
|
||||
.remove_rx_filter = can_mcan_remove_rx_filter,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = can_mcan_recover,
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
.get_state = can_mcan_get_state,
|
||||
.set_state_change_callback = can_mcan_set_state_change_callback,
|
||||
.get_core_clock = mcux_mcan_get_core_clock,
|
||||
|
|
|
@ -373,21 +373,6 @@ static int can_native_linux_get_state(const struct device *dev, enum can_state *
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
static int can_native_linux_recover(const struct device *dev, k_timeout_t timeout)
|
||||
{
|
||||
struct can_native_linux_data *data = dev->data;
|
||||
|
||||
ARG_UNUSED(timeout);
|
||||
|
||||
if (!data->common.started) {
|
||||
return -ENETDOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
|
||||
static void can_native_linux_set_state_change_callback(const struct device *dev,
|
||||
can_state_change_callback_t cb,
|
||||
void *user_data)
|
||||
|
@ -422,9 +407,6 @@ static const struct can_driver_api can_native_linux_driver_api = {
|
|||
.add_rx_filter = can_native_linux_add_rx_filter,
|
||||
.remove_rx_filter = can_native_linux_remove_rx_filter,
|
||||
.get_state = can_native_linux_get_state,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
.recover = can_native_linux_recover,
|
||||
#endif
|
||||
.set_state_change_callback = can_native_linux_set_state_change_callback,
|
||||
.get_core_clock = can_native_linux_get_core_clock,
|
||||
.get_max_filters = can_native_linux_get_max_filters,
|
||||
|
|
|
@ -169,9 +169,9 @@ static const struct can_driver_api can_numaker_driver_api = {
|
|||
.send = can_mcan_send,
|
||||
.add_rx_filter = can_mcan_add_rx_filter,
|
||||
.remove_rx_filter = can_mcan_remove_rx_filter,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = can_mcan_recover,
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
.get_state = can_mcan_get_state,
|
||||
.set_state_change_callback = can_mcan_set_state_change_callback,
|
||||
.get_core_clock = can_numaker_get_core_clock,
|
||||
|
|
|
@ -123,9 +123,13 @@ static int can_nxp_s32_get_capabilities(const struct device *dev, can_mode_t *ca
|
|||
|
||||
*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY;
|
||||
|
||||
#ifdef CAN_NXP_S32_FD_MODE
|
||||
*cap |= CAN_MODE_FD;
|
||||
#endif
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
*cap |= CAN_MODE_MANUAL_RECOVERY;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CAN_NXP_S32_FD_MODE)) {
|
||||
*cap |= CAN_MODE_FD;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -271,6 +275,7 @@ static int can_nxp_s32_stop(const struct device *dev)
|
|||
|
||||
static int can_nxp_s32_set_mode(const struct device *dev, can_mode_t mode)
|
||||
{
|
||||
can_mode_t supported = CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY;
|
||||
const struct can_nxp_s32_config *config = dev->config;
|
||||
struct can_nxp_s32_data *data = dev->data;
|
||||
Canexcel_Ip_ModesType can_nxp_s32_mode = CAN_MODE_NORMAL;
|
||||
|
@ -280,11 +285,16 @@ static int can_nxp_s32_set_mode(const struct device *dev, can_mode_t mode)
|
|||
if (data->common.started) {
|
||||
return -EBUSY;
|
||||
}
|
||||
#ifdef CAN_NXP_S32_FD_MODE
|
||||
if ((mode & ~(CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_FD)) != 0) {
|
||||
#else
|
||||
if ((mode & ~(CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY)) != 0) {
|
||||
#endif
|
||||
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
supported |= CAN_MODE_MANUAL_RECOVERY;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CAN_NXP_S32_FD_MODE)) {
|
||||
supported |= CAN_MODE_FD;
|
||||
}
|
||||
|
||||
if ((mode & ~(supported)) != 0) {
|
||||
LOG_ERR("unsupported mode: 0x%08x", mode);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
@ -309,6 +319,20 @@ static int can_nxp_s32_set_mode(const struct device *dev, can_mode_t mode)
|
|||
|
||||
CanXL_SetFDEnabled(config->base_sic, canfd, brs);
|
||||
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
Canexcel_Ip_StatusType status;
|
||||
uint32_t options = 0U;
|
||||
|
||||
if ((mode & CAN_MODE_MANUAL_RECOVERY) == 0U) {
|
||||
options = CANXL_IP_BUSOFF_RECOVERY_U32;
|
||||
}
|
||||
|
||||
status = CanXL_ConfigCtrlOptions(config->base_sic, options);
|
||||
if (status != CANEXCEL_STATUS_SUCCESS) {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
CanXL_SetOperationMode(config->base_sic, can_nxp_s32_mode);
|
||||
|
||||
Canexcel_Ip_ExitFreezeMode(config->instance);
|
||||
|
@ -377,7 +401,7 @@ static void can_nxp_s32_set_state_change_callback(const struct device *dev,
|
|||
data->common.state_change_cb_user_data = user_data;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
static int can_nxp_s32_recover(const struct device *dev, k_timeout_t timeout)
|
||||
{
|
||||
const struct can_nxp_s32_config *config = dev->config;
|
||||
|
@ -390,6 +414,10 @@ static int can_nxp_s32_recover(const struct device *dev, k_timeout_t timeout)
|
|||
return -ENETDOWN;
|
||||
}
|
||||
|
||||
if ((data->common.mode & CAN_MODE_MANUAL_RECOVERY) == 0U) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
can_nxp_s32_get_state(dev, &state, NULL);
|
||||
if (state != CAN_STATE_BUS_OFF) {
|
||||
return 0;
|
||||
|
@ -415,7 +443,7 @@ static int can_nxp_s32_recover(const struct device *dev, k_timeout_t timeout)
|
|||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
|
||||
static void can_nxp_s32_remove_rx_filter(const struct device *dev, int filter_id)
|
||||
{
|
||||
|
@ -1024,9 +1052,9 @@ static const struct can_driver_api can_nxp_s32_driver_api = {
|
|||
.add_rx_filter = can_nxp_s32_add_rx_filter,
|
||||
.remove_rx_filter = can_nxp_s32_remove_rx_filter,
|
||||
.get_state = can_nxp_s32_get_state,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = can_nxp_s32_recover,
|
||||
#endif
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
.set_state_change_callback = can_nxp_s32_set_state_change_callback,
|
||||
.get_core_clock = can_nxp_s32_get_core_clock,
|
||||
.get_max_filters = can_nxp_s32_get_max_filters,
|
||||
|
@ -1102,12 +1130,6 @@ static const struct can_driver_api can_nxp_s32_driver_api = {
|
|||
#define CAN_NXP_S32_BRS 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#define CAN_NXP_S32_CTRL_OPTIONS CANXL_IP_BUSOFF_RECOVERY_U32
|
||||
#else
|
||||
#define CAN_NXP_S32_CTRL_OPTIONS 0
|
||||
#endif
|
||||
|
||||
#define CAN_NXP_S32_HW_INSTANCE_CHECK(i, n) \
|
||||
((DT_INST_REG_ADDR(n) == IP_CANXL_##i##__SIC_BASE) ? i : 0)
|
||||
|
||||
|
@ -1135,7 +1157,7 @@ static const struct can_driver_api can_nxp_s32_driver_api = {
|
|||
.CanxlMode = CANEXCEL_LISTEN_ONLY_MODE, \
|
||||
.fd_enable = (boolean)IS_ENABLED(CAN_NXP_S32_FD_MODE), \
|
||||
.bitRateSwitch = (boolean)CAN_NXP_S32_BRS, \
|
||||
.ctrlOptions = (uint32)CAN_NXP_S32_CTRL_OPTIONS, \
|
||||
.ctrlOptions = CANXL_IP_BUSOFF_RECOVERY_U32, \
|
||||
.Callback = nxp_s32_can_##n##_ctrl_callback, \
|
||||
.ErrorCallback = nxp_s32_can_##n##_err_callback, \
|
||||
IF_ENABLED(CONFIG_CAN_NXP_S32_RX_FIFO, \
|
||||
|
|
|
@ -653,12 +653,17 @@ static int can_rcar_stop(const struct device *dev)
|
|||
|
||||
static int can_rcar_set_mode(const struct device *dev, can_mode_t mode)
|
||||
{
|
||||
can_mode_t supported = CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY;
|
||||
const struct can_rcar_cfg *config = dev->config;
|
||||
struct can_rcar_data *data = dev->data;
|
||||
uint8_t tcr = 0;
|
||||
int ret = 0;
|
||||
|
||||
if ((mode & ~(CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY)) != 0) {
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
supported |= CAN_MODE_MANUAL_RECOVERY;
|
||||
}
|
||||
|
||||
if ((mode & ~(supported)) != 0) {
|
||||
LOG_ERR("Unsupported mode: 0x%08x", mode);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
@ -687,6 +692,20 @@ static int can_rcar_set_mode(const struct device *dev, can_mode_t mode)
|
|||
|
||||
sys_write8(tcr, config->reg_addr + RCAR_CAN_TCR);
|
||||
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
uint16_t ctlr = can_rcar_read16(config, RCAR_CAN_CTLR);
|
||||
|
||||
if ((mode & CAN_MODE_MANUAL_RECOVERY) != 0U) {
|
||||
/* Set entry to halt automatically at bus-off */
|
||||
ctlr |= RCAR_CAN_CTLR_BOM_ENT;
|
||||
} else {
|
||||
/* Clear entry to halt automatically at bus-off */
|
||||
ctlr &= ~RCAR_CAN_CTLR_BOM_ENT;
|
||||
}
|
||||
|
||||
can_rcar_write16(config, RCAR_CAN_CTLR, ctlr);
|
||||
}
|
||||
|
||||
data->common.mode = mode;
|
||||
|
||||
unlock:
|
||||
|
@ -805,7 +824,7 @@ static int can_rcar_get_state(const struct device *dev, enum can_state *state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
static int can_rcar_recover(const struct device *dev, k_timeout_t timeout)
|
||||
{
|
||||
const struct can_rcar_cfg *config = dev->config;
|
||||
|
@ -817,6 +836,10 @@ static int can_rcar_recover(const struct device *dev, k_timeout_t timeout)
|
|||
return -ENETDOWN;
|
||||
}
|
||||
|
||||
if ((data->common.mode & CAN_MODE_MANUAL_RECOVERY) == 0U) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (data->state != CAN_STATE_BUS_OFF) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -843,7 +866,7 @@ done:
|
|||
k_mutex_unlock(&data->inst_mutex);
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
|
||||
static int can_rcar_send(const struct device *dev, const struct can_frame *frame,
|
||||
k_timeout_t timeout, can_tx_callback_t callback,
|
||||
|
@ -1078,9 +1101,7 @@ static int can_rcar_init(const struct device *dev)
|
|||
|
||||
ctlr = can_rcar_read16(config, RCAR_CAN_CTLR);
|
||||
ctlr |= RCAR_CAN_CTLR_IDFM_MIXED; /* Select mixed ID mode */
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
ctlr |= RCAR_CAN_CTLR_BOM_ENT; /* Entry to halt mode automatically at bus-off */
|
||||
#endif
|
||||
ctlr &= ~RCAR_CAN_CTLR_BOM_ENT; /* Clear entry to halt automatically at bus-off */
|
||||
ctlr |= RCAR_CAN_CTLR_MBM; /* Select FIFO mailbox mode */
|
||||
ctlr |= RCAR_CAN_CTLR_MLM; /* Overrun mode */
|
||||
ctlr &= ~RCAR_CAN_CTLR_SLPM; /* Clear CAN Sleep mode */
|
||||
|
@ -1142,9 +1163,9 @@ static const struct can_driver_api can_rcar_driver_api = {
|
|||
.add_rx_filter = can_rcar_add_rx_filter,
|
||||
.remove_rx_filter = can_rcar_remove_rx_filter,
|
||||
.get_state = can_rcar_get_state,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = can_rcar_recover,
|
||||
#endif
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
.set_state_change_callback = can_rcar_set_state_change_callback,
|
||||
.get_core_clock = can_rcar_get_core_clock,
|
||||
.get_max_filters = can_rcar_get_max_filters,
|
||||
|
|
|
@ -126,9 +126,9 @@ static const struct can_driver_api can_sam_driver_api = {
|
|||
.add_rx_filter = can_mcan_add_rx_filter,
|
||||
.remove_rx_filter = can_mcan_remove_rx_filter,
|
||||
.get_state = can_mcan_get_state,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = can_mcan_recover,
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
.get_core_clock = can_sam_get_core_clock,
|
||||
.get_max_filters = can_mcan_get_max_filters,
|
||||
.set_state_change_callback = can_mcan_set_state_change_callback,
|
||||
|
|
|
@ -171,9 +171,9 @@ static const struct can_driver_api can_sam0_driver_api = {
|
|||
.add_rx_filter = can_mcan_add_rx_filter,
|
||||
.remove_rx_filter = can_mcan_remove_rx_filter,
|
||||
.get_state = can_mcan_get_state,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = can_mcan_recover,
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
.get_core_clock = can_sam0_get_core_clock,
|
||||
.get_max_filters = can_mcan_get_max_filters,
|
||||
.set_state_change_callback = can_mcan_set_state_change_callback,
|
||||
|
|
|
@ -35,6 +35,7 @@ static const struct can_shell_mode_mapping can_shell_mode_map[] = {
|
|||
CAN_SHELL_MODE_MAPPING("normal", CAN_MODE_NORMAL),
|
||||
CAN_SHELL_MODE_MAPPING("one-shot", CAN_MODE_ONE_SHOT),
|
||||
CAN_SHELL_MODE_MAPPING("triple-sampling", CAN_MODE_3_SAMPLES),
|
||||
CAN_SHELL_MODE_MAPPING("manual-recovery", CAN_MODE_MANUAL_RECOVERY),
|
||||
};
|
||||
|
||||
K_MSGQ_DEFINE(can_shell_tx_msgq, sizeof(struct can_shell_tx_event),
|
||||
|
@ -1054,9 +1055,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_can_cmds,
|
|||
"CAN rx filter commands\n"
|
||||
"Usage: can filter <add|remove> <device> ...",
|
||||
NULL),
|
||||
SHELL_EXPR_CMD_ARG(!IS_ENABLED(CONFIG_CAN_AUTO_BUS_OFF_RECOVERY),
|
||||
SHELL_COND_CMD_ARG(CONFIG_CAN_MANUAL_RECOVERY_MODE,
|
||||
recover, &dsub_can_device_name,
|
||||
"Recover CAN controller from bus-off state\n"
|
||||
"Manually recover CAN controller from bus-off state\n"
|
||||
"Usage: can recover <device> [timeout ms]",
|
||||
cmd_can_recover, 2, 1),
|
||||
SHELL_SUBCMD_SET_END
|
||||
|
|
|
@ -141,6 +141,10 @@ int can_sja1000_get_capabilities(const struct device *dev, can_mode_t *cap)
|
|||
*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY |
|
||||
CAN_MODE_ONE_SHOT | CAN_MODE_3_SAMPLES;
|
||||
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
*cap |= CAN_MODE_MANUAL_RECOVERY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -213,12 +217,17 @@ int can_sja1000_stop(const struct device *dev)
|
|||
|
||||
int can_sja1000_set_mode(const struct device *dev, can_mode_t mode)
|
||||
{
|
||||
can_mode_t supported = CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_ONE_SHOT |
|
||||
CAN_MODE_3_SAMPLES;
|
||||
struct can_sja1000_data *data = dev->data;
|
||||
uint8_t btr1;
|
||||
uint8_t mod;
|
||||
|
||||
if ((mode & ~(CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_ONE_SHOT |
|
||||
CAN_MODE_3_SAMPLES)) != 0) {
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
supported |= CAN_MODE_MANUAL_RECOVERY;
|
||||
}
|
||||
|
||||
if ((mode & ~(supported)) != 0) {
|
||||
LOG_ERR("unsupported mode: 0x%08x", mode);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
@ -464,7 +473,7 @@ void can_sja1000_remove_rx_filter(const struct device *dev, int filter_id)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
int can_sja1000_recover(const struct device *dev, k_timeout_t timeout)
|
||||
{
|
||||
struct can_sja1000_data *data = dev->data;
|
||||
|
@ -476,6 +485,10 @@ int can_sja1000_recover(const struct device *dev, k_timeout_t timeout)
|
|||
return -ENETDOWN;
|
||||
}
|
||||
|
||||
if ((data->common.mode & CAN_MODE_MANUAL_RECOVERY) == 0U) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
sr = can_sja1000_read_reg(dev, CAN_SJA1000_SR);
|
||||
if ((sr & CAN_SJA1000_SR_BS) == 0) {
|
||||
return 0;
|
||||
|
@ -509,7 +522,7 @@ int can_sja1000_recover(const struct device *dev, k_timeout_t timeout)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif /* !CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
|
||||
int can_sja1000_get_state(const struct device *dev, enum can_state *state,
|
||||
struct can_bus_err_cnt *err_cnt)
|
||||
|
@ -659,11 +672,11 @@ static void can_sja1000_handle_error_warning_irq(const struct device *dev)
|
|||
if ((sr & CAN_SJA1000_SR_BS) != 0) {
|
||||
data->state = CAN_STATE_BUS_OFF;
|
||||
can_sja1000_tx_done(dev, -ENETUNREACH);
|
||||
#ifdef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
if (data->common.started) {
|
||||
|
||||
if (data->common.started &&
|
||||
(data->common.mode & CAN_MODE_MANUAL_RECOVERY) == 0U) {
|
||||
can_sja1000_leave_reset_mode_nowait(dev);
|
||||
}
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
} else if ((sr & CAN_SJA1000_SR_ES) != 0) {
|
||||
data->state = CAN_STATE_ERROR_WARNING;
|
||||
} else {
|
||||
|
|
|
@ -380,6 +380,10 @@ static int can_stm32_get_capabilities(const struct device *dev, can_mode_t *cap)
|
|||
|
||||
*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_ONE_SHOT;
|
||||
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
*cap |= CAN_MODE_MANUAL_RECOVERY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -473,13 +477,18 @@ unlock:
|
|||
|
||||
static int can_stm32_set_mode(const struct device *dev, can_mode_t mode)
|
||||
{
|
||||
can_mode_t supported = CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_ONE_SHOT;
|
||||
const struct can_stm32_config *cfg = dev->config;
|
||||
CAN_TypeDef *can = cfg->can;
|
||||
struct can_stm32_data *data = dev->data;
|
||||
|
||||
LOG_DBG("Set mode %d", mode);
|
||||
|
||||
if ((mode & ~(CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_ONE_SHOT)) != 0) {
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
supported |= CAN_MODE_MANUAL_RECOVERY;
|
||||
}
|
||||
|
||||
if ((mode & ~(supported)) != 0) {
|
||||
LOG_ERR("unsupported mode: 0x%08x", mode);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
@ -511,6 +520,15 @@ static int can_stm32_set_mode(const struct device *dev, can_mode_t mode)
|
|||
can->MCR &= ~CAN_MCR_NART;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
|
||||
if ((mode & CAN_MODE_MANUAL_RECOVERY) != 0) {
|
||||
/* No automatic recovery from bus-off */
|
||||
can->MCR &= ~CAN_MCR_ABOM;
|
||||
} else {
|
||||
can->MCR |= CAN_MCR_ABOM;
|
||||
}
|
||||
}
|
||||
|
||||
data->common.mode = mode;
|
||||
|
||||
k_mutex_unlock(&data->inst_mutex);
|
||||
|
@ -637,9 +655,10 @@ static int can_stm32_init(const struct device *dev)
|
|||
#ifdef CONFIG_CAN_RX_TIMESTAMP
|
||||
can->MCR |= CAN_MCR_TTCM;
|
||||
#endif
|
||||
#ifdef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
|
||||
/* Enable automatic bus-off recovery */
|
||||
can->MCR |= CAN_MCR_ABOM;
|
||||
#endif
|
||||
|
||||
ret = can_calc_timing(dev, &timing, cfg->common.bus_speed,
|
||||
cfg->common.sample_point);
|
||||
if (ret == -EINVAL) {
|
||||
|
@ -686,7 +705,7 @@ static void can_stm32_set_state_change_callback(const struct device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
static int can_stm32_recover(const struct device *dev, k_timeout_t timeout)
|
||||
{
|
||||
const struct can_stm32_config *cfg = dev->config;
|
||||
|
@ -699,6 +718,10 @@ static int can_stm32_recover(const struct device *dev, k_timeout_t timeout)
|
|||
return -ENETDOWN;
|
||||
}
|
||||
|
||||
if ((data->common.mode & CAN_MODE_MANUAL_RECOVERY) == 0U) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (!(can->ESR & CAN_ESR_BOFF)) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -729,8 +752,7 @@ done:
|
|||
k_mutex_unlock(&data->inst_mutex);
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
|
||||
static int can_stm32_send(const struct device *dev, const struct can_frame *frame,
|
||||
k_timeout_t timeout, can_tx_callback_t callback,
|
||||
|
@ -1053,9 +1075,9 @@ static const struct can_driver_api can_api_funcs = {
|
|||
.add_rx_filter = can_stm32_add_rx_filter,
|
||||
.remove_rx_filter = can_stm32_remove_rx_filter,
|
||||
.get_state = can_stm32_get_state,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = can_stm32_recover,
|
||||
#endif
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
.set_state_change_callback = can_stm32_set_state_change_callback,
|
||||
.get_core_clock = can_stm32_get_core_clock,
|
||||
.get_max_filters = can_stm32_get_max_filters,
|
||||
|
|
|
@ -586,9 +586,9 @@ static const struct can_driver_api can_stm32fd_driver_api = {
|
|||
.add_rx_filter = can_mcan_add_rx_filter,
|
||||
.remove_rx_filter = can_mcan_remove_rx_filter,
|
||||
.get_state = can_mcan_get_state,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = can_mcan_recover,
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
.get_core_clock = can_stm32fd_get_core_clock,
|
||||
.get_max_filters = can_mcan_get_max_filters,
|
||||
.set_state_change_callback = can_mcan_set_state_change_callback,
|
||||
|
|
|
@ -204,9 +204,9 @@ static const struct can_driver_api can_stm32h7_driver_api = {
|
|||
.add_rx_filter = can_mcan_add_rx_filter,
|
||||
.remove_rx_filter = can_mcan_remove_rx_filter,
|
||||
.get_state = can_mcan_get_state,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = can_mcan_recover,
|
||||
#endif
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE*/
|
||||
.get_core_clock = can_stm32h7_get_core_clock,
|
||||
.get_max_filters = can_mcan_get_max_filters,
|
||||
.set_state_change_callback = can_mcan_set_state_change_callback,
|
||||
|
|
|
@ -722,9 +722,9 @@ static const struct can_driver_api tcan4x5x_driver_api = {
|
|||
.send = can_mcan_send,
|
||||
.add_rx_filter = can_mcan_add_rx_filter,
|
||||
.remove_rx_filter = can_mcan_remove_rx_filter,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
.recover = can_mcan_recover,
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
.get_state = can_mcan_get_state,
|
||||
.set_state_change_callback = can_mcan_set_state_change_callback,
|
||||
.get_core_clock = tcan4x5x_get_core_clock,
|
||||
|
|
|
@ -514,21 +514,6 @@ static int can_xmc4xxx_get_max_filters(const struct device *dev, bool ide)
|
|||
return CONFIG_CAN_MAX_FILTER;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
static int can_xmc4xxx_recover(const struct device *dev, k_timeout_t timeout)
|
||||
{
|
||||
struct can_xmc4xxx_data *dev_data = dev->data;
|
||||
|
||||
ARG_UNUSED(timeout);
|
||||
|
||||
if (!dev_data->common.started) {
|
||||
return -ENETDOWN;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void can_xmc4xxx_reset_tx_fifos(const struct device *dev, int status)
|
||||
{
|
||||
struct can_xmc4xxx_data *dev_data = dev->data;
|
||||
|
@ -908,9 +893,6 @@ static const struct can_driver_api can_xmc4xxx_api_funcs = {
|
|||
.send = can_xmc4xxx_send,
|
||||
.add_rx_filter = can_xmc4xxx_add_rx_filter,
|
||||
.remove_rx_filter = can_xmc4xxx_remove_rx_filter,
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
.recover = can_xmc4xxx_recover,
|
||||
#endif
|
||||
.get_state = can_xmc4xxx_get_state,
|
||||
.set_state_change_callback = can_xmc4xxx_set_state_change_callback,
|
||||
.get_core_clock = can_xmc4xxx_get_core_clock,
|
||||
|
|
|
@ -89,19 +89,22 @@ extern "C" {
|
|||
#define CAN_MODE_NORMAL 0
|
||||
|
||||
/** Controller is in loopback mode (receives own frames). */
|
||||
#define CAN_MODE_LOOPBACK BIT(0)
|
||||
#define CAN_MODE_LOOPBACK BIT(0)
|
||||
|
||||
/** Controller is not allowed to send dominant bits. */
|
||||
#define CAN_MODE_LISTENONLY BIT(1)
|
||||
#define CAN_MODE_LISTENONLY BIT(1)
|
||||
|
||||
/** Controller allows transmitting/receiving CAN FD frames. */
|
||||
#define CAN_MODE_FD BIT(2)
|
||||
#define CAN_MODE_FD BIT(2)
|
||||
|
||||
/** Controller does not retransmit in case of lost arbitration or missing ACK */
|
||||
#define CAN_MODE_ONE_SHOT BIT(3)
|
||||
#define CAN_MODE_ONE_SHOT BIT(3)
|
||||
|
||||
/** Controller uses triple sampling mode */
|
||||
#define CAN_MODE_3_SAMPLES BIT(4)
|
||||
#define CAN_MODE_3_SAMPLES BIT(4)
|
||||
|
||||
/** Controller requires manual recovery after entering bus-off state */
|
||||
#define CAN_MODE_MANUAL_RECOVERY BIT(5)
|
||||
|
||||
/** @} */
|
||||
|
||||
|
@ -450,7 +453,7 @@ typedef int (*can_add_rx_filter_t)(const struct device *dev,
|
|||
typedef void (*can_remove_rx_filter_t)(const struct device *dev, int filter_id);
|
||||
|
||||
/**
|
||||
* @brief Callback API upon recovering the CAN bus
|
||||
* @brief Optional callback API upon manually recovering the CAN controller from bus-off state
|
||||
* See @a can_recover() for argument description
|
||||
*/
|
||||
typedef int (*can_recover_t)(const struct device *dev, k_timeout_t timeout);
|
||||
|
@ -491,9 +494,9 @@ __subsystem struct can_driver_api {
|
|||
can_send_t send;
|
||||
can_add_rx_filter_t add_rx_filter;
|
||||
can_remove_rx_filter_t remove_rx_filter;
|
||||
#if !defined(CONFIG_CAN_AUTO_BUS_OFF_RECOVERY) || defined(__DOXYGEN__)
|
||||
#if defined(CONFIG_CAN_MANUAL_RECOVERY_MODE) || defined(__DOXYGEN__)
|
||||
can_recover_t recover;
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
can_get_state_t get_state;
|
||||
can_set_state_change_callback_t set_state_change_callback;
|
||||
can_get_core_clock_t get_core_clock;
|
||||
|
@ -1413,34 +1416,32 @@ static inline int z_impl_can_get_state(const struct device *dev, enum can_state
|
|||
*
|
||||
* Recover the CAN controller from bus-off state to error-active state.
|
||||
*
|
||||
* @note @kconfig{CONFIG_CAN_AUTO_BUS_OFF_RECOVERY} must be deselected for this
|
||||
* @note @kconfig{CONFIG_CAN_MANUAL_RECOVERY_MODE} must be enabled for this
|
||||
* function to be available.
|
||||
*
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param timeout Timeout for waiting for the recovery or ``K_FOREVER``.
|
||||
*
|
||||
* @retval 0 on success.
|
||||
* @retval -ENOTSUP if the CAN controller is not in manual recovery mode.
|
||||
* @retval -ENETDOWN if the CAN controller is in stopped state.
|
||||
* @retval -EAGAIN on timeout.
|
||||
* @retval -ENOSYS If this function is not implemented by the driver.
|
||||
*/
|
||||
#if !defined(CONFIG_CAN_AUTO_BUS_OFF_RECOVERY) || defined(__DOXYGEN__)
|
||||
__syscall int can_recover(const struct device *dev, k_timeout_t timeout);
|
||||
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
static inline int z_impl_can_recover(const struct device *dev, k_timeout_t timeout)
|
||||
{
|
||||
const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
|
||||
|
||||
if (api->recover == NULL) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return api->recover(dev, timeout);
|
||||
}
|
||||
#else /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
/* This implementation prevents inking errors for auto recovery */
|
||||
static inline int z_impl_can_recover(const struct device *dev, k_timeout_t timeout)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
ARG_UNUSED(timeout);
|
||||
return 0;
|
||||
}
|
||||
#endif /* !CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
|
||||
/**
|
||||
* @brief Set a callback for CAN controller state change events
|
||||
|
|
|
@ -1653,13 +1653,13 @@ int can_mcan_set_timing(const struct device *dev, const struct can_timing *timin
|
|||
*/
|
||||
int can_mcan_set_timing_data(const struct device *dev, const struct can_timing *timing_data);
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
/**
|
||||
* @brief Bosch M_CAN driver callback API upon recovering the CAN bus
|
||||
* See @a can_recover() for argument description
|
||||
*/
|
||||
int can_mcan_recover(const struct device *dev, k_timeout_t timeout);
|
||||
#endif /* !CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
|
||||
int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_timeout_t timeout,
|
||||
can_tx_callback_t callback, void *user_data);
|
||||
|
|
|
@ -227,13 +227,13 @@ int can_sja1000_add_rx_filter(const struct device *dev, can_rx_callback_t callba
|
|||
*/
|
||||
void can_sja1000_remove_rx_filter(const struct device *dev, int filter_id);
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
|
||||
/**
|
||||
* @brief SJA1000 callback API upon recovering the CAN bus
|
||||
* See @a can_recover() for argument description
|
||||
*/
|
||||
int can_sja1000_recover(const struct device *dev, k_timeout_t timeout);
|
||||
#endif /* !CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
|
||||
|
||||
/**
|
||||
* @brief SJA1000 callback API upon getting the CAN controller state
|
||||
|
|
|
@ -173,16 +173,6 @@ void state_change_work_handler(struct k_work *work)
|
|||
"tx error count: %d\n",
|
||||
state_to_str(current_state),
|
||||
current_err_cnt.rx_err_cnt, current_err_cnt.tx_err_cnt);
|
||||
|
||||
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
|
||||
if (current_state == CAN_STATE_BUS_OFF) {
|
||||
printf("Recover from bus-off\n");
|
||||
|
||||
if (can_recover(can_dev, K_MSEC(100)) != 0) {
|
||||
printf("Recovery timed out\n");
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||
}
|
||||
|
||||
void state_change_callback(const struct device *dev, enum can_state state,
|
||||
|
|
|
@ -3,4 +3,4 @@ CONFIG_TEST_USERSPACE=y
|
|||
CONFIG_GPIO=y
|
||||
CONFIG_CAN=y
|
||||
CONFIG_CAN_FD_MODE=y
|
||||
CONFIG_CAN_AUTO_BUS_OFF_RECOVERY=n
|
||||
CONFIG_CAN_MANUAL_RECOVERY_MODE=y
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
CONFIG_CAN=y
|
||||
CONFIG_CAN_FD_MODE=y
|
||||
CONFIG_CAN_AUTO_BUS_OFF_RECOVERY=n
|
||||
CONFIG_CAN_MANUAL_RECOVERY_MODE=y
|
||||
CONFIG_STATS=y
|
||||
CONFIG_CAN_STATS=y
|
||||
CONFIG_TEST_USERSPACE=y
|
||||
|
|
|
@ -853,18 +853,55 @@ ZTEST_USER(can_classic, test_send_fd_format)
|
|||
|
||||
/**
|
||||
* @brief Test CAN controller bus recovery.
|
||||
*
|
||||
* It is not possible to provoke a bus off state, but verify the API call return codes.
|
||||
*/
|
||||
ZTEST_USER(can_classic, test_recover)
|
||||
{
|
||||
can_mode_t cap;
|
||||
int err;
|
||||
|
||||
/* It is not possible to provoke a bus off state, but test the API call */
|
||||
err = can_recover(can_dev, TEST_RECOVER_TIMEOUT);
|
||||
if (err == -ENOTSUP) {
|
||||
ztest_test_skip();
|
||||
Z_TEST_SKIP_IFNDEF(CONFIG_CAN_MANUAL_RECOVERY_MODE);
|
||||
|
||||
err = can_get_capabilities(can_dev, &cap);
|
||||
zassert_equal(err, 0, "failed to get CAN capabilities (err %d)", err);
|
||||
|
||||
if ((cap & CAN_MODE_MANUAL_RECOVERY) != 0U) {
|
||||
/* Check that manual recovery fails when not in manual recovery mode */
|
||||
err = can_recover(can_dev, TEST_RECOVER_TIMEOUT);
|
||||
zassert_equal(err, -ENOTSUP, "wrong error return code (err %d)", err);
|
||||
|
||||
err = can_stop(can_dev);
|
||||
zassert_equal(err, 0, "failed to stop CAN controller (err %d)", err);
|
||||
|
||||
/* Enter manual recovery mode */
|
||||
err = can_set_mode(can_dev, CAN_MODE_NORMAL | CAN_MODE_MANUAL_RECOVERY);
|
||||
zassert_equal(err, 0, "failed to set manual recovery mode (err %d)", err);
|
||||
zassert_equal(CAN_MODE_NORMAL | CAN_MODE_MANUAL_RECOVERY, can_get_mode(can_dev));
|
||||
|
||||
err = can_start(can_dev);
|
||||
zassert_equal(err, 0, "failed to start CAN controller (err %d)", err);
|
||||
}
|
||||
|
||||
zassert_equal(err, 0, "failed to recover (err %d)", err);
|
||||
err = can_recover(can_dev, TEST_RECOVER_TIMEOUT);
|
||||
|
||||
if ((cap & CAN_MODE_MANUAL_RECOVERY) != 0U) {
|
||||
zassert_equal(err, 0, "failed to recover (err %d)", err);
|
||||
|
||||
err = can_stop(can_dev);
|
||||
zassert_equal(err, 0, "failed to stop CAN controller (err %d)", err);
|
||||
|
||||
/* Restore loopback mode */
|
||||
err = can_set_mode(can_dev, CAN_MODE_LOOPBACK);
|
||||
zassert_equal(err, 0, "failed to set loopback-mode (err %d)", err);
|
||||
zassert_equal(CAN_MODE_LOOPBACK, can_get_mode(can_dev));
|
||||
|
||||
err = can_start(can_dev);
|
||||
zassert_equal(err, 0, "failed to start CAN controller (err %d)", err);
|
||||
} else {
|
||||
/* Check that manual recovery fails when not supported */
|
||||
zassert_equal(err, -ENOSYS, "wrong error return code (err %d)", err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1036,8 +1073,18 @@ ZTEST_USER(can_classic, test_start_while_started)
|
|||
*/
|
||||
ZTEST_USER(can_classic, test_recover_while_stopped)
|
||||
{
|
||||
can_mode_t cap;
|
||||
int err;
|
||||
|
||||
Z_TEST_SKIP_IFNDEF(CONFIG_CAN_MANUAL_RECOVERY_MODE);
|
||||
|
||||
err = can_get_capabilities(can_dev, &cap);
|
||||
zassert_equal(err, 0, "failed to get CAN capabilities (err %d)", err);
|
||||
|
||||
if ((cap & CAN_MODE_MANUAL_RECOVERY) == 0U) {
|
||||
ztest_test_skip();
|
||||
}
|
||||
|
||||
err = can_stop(can_dev);
|
||||
zassert_equal(err, 0, "failed to stop CAN controller (err %d)", err);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ CONFIG_SHELL=y
|
|||
CONFIG_SHELL_BACKEND_SERIAL=n
|
||||
CONFIG_SHELL_BACKEND_DUMMY=y
|
||||
CONFIG_CAN=y
|
||||
CONFIG_CAN_AUTO_BUS_OFF_RECOVERY=n
|
||||
CONFIG_CAN_MANUAL_RECOVERY_MODE=y
|
||||
CONFIG_CAN_FD_MODE=y
|
||||
CONFIG_CAN_SHELL=y
|
||||
CONFIG_ZTEST=y
|
||||
|
|
|
@ -572,7 +572,7 @@ static void can_shell_test_recover(const char *cmd, k_timeout_t expected)
|
|||
const struct shell *sh = shell_backend_dummy_get_ptr();
|
||||
int err;
|
||||
|
||||
Z_TEST_SKIP_IFDEF(CONFIG_CAN_AUTO_BUS_OFF_RECOVERY);
|
||||
Z_TEST_SKIP_IFNDEF(CONFIG_CAN_MANUAL_RECOVERY_MODE);
|
||||
|
||||
err = shell_execute_cmd(sh, cmd);
|
||||
zassert_ok(err, "failed to execute shell command (err %d)", err);
|
||||
|
|
Loading…
Reference in a new issue