drivers: can: loopback: add CAN-FD loopback support
Add support for CAN-FD frames in the CAN loopback driver. Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
parent
4b30008f5b
commit
b407b5697f
2 changed files with 56 additions and 4 deletions
|
@ -7,6 +7,7 @@ DT_COMPAT_ZEPHYR_CAN_LOOPBACK := zephyr,can-loopback
|
||||||
|
|
||||||
config CAN_LOOPBACK
|
config CAN_LOOPBACK
|
||||||
bool "Emulated CAN loopback driver"
|
bool "Emulated CAN loopback driver"
|
||||||
|
select CAN_HAS_CANFD
|
||||||
default $(dt_compat_enabled,$(DT_COMPAT_ZEPHYR_CAN_LOOPBACK))
|
default $(dt_compat_enabled,$(DT_COMPAT_ZEPHYR_CAN_LOOPBACK))
|
||||||
help
|
help
|
||||||
This is an emulated driver that can only loopback messages.
|
This is an emulated driver that can only loopback messages.
|
||||||
|
|
|
@ -96,9 +96,10 @@ static int can_loopback_send(const struct device *dev,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct can_loopback_data *data = dev->data;
|
struct can_loopback_data *data = dev->data;
|
||||||
int ret;
|
|
||||||
struct can_loopback_frame loopback_frame;
|
struct can_loopback_frame loopback_frame;
|
||||||
|
uint8_t max_dlc = CAN_MAX_DLC;
|
||||||
struct k_sem tx_sem;
|
struct k_sem tx_sem;
|
||||||
|
int ret;
|
||||||
|
|
||||||
LOG_DBG("Sending %d bytes on %s. Id: 0x%x, ID type: %s %s",
|
LOG_DBG("Sending %d bytes on %s. Id: 0x%x, ID type: %s %s",
|
||||||
frame->dlc, dev->name, frame->id,
|
frame->dlc, dev->name, frame->id,
|
||||||
|
@ -106,8 +107,14 @@ static int can_loopback_send(const struct device *dev,
|
||||||
"standard" : "extended",
|
"standard" : "extended",
|
||||||
frame->rtr == CAN_DATAFRAME ? "" : ", RTR frame");
|
frame->rtr == CAN_DATAFRAME ? "" : ", RTR frame");
|
||||||
|
|
||||||
if (frame->dlc > CAN_MAX_DLC) {
|
#ifdef CONFIG_CAN_FD_MODE
|
||||||
LOG_ERR("DLC of %d exceeds maximum (%d)", frame->dlc, CAN_MAX_DLC);
|
if (frame->fd != 0) {
|
||||||
|
max_dlc = CANFD_MAX_DLC;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_CAN_FD_MODE */
|
||||||
|
|
||||||
|
if (frame->dlc > max_dlc) {
|
||||||
|
LOG_ERR("DLC of %d exceeds maximum (%d)", frame->dlc, max_dlc);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,6 +205,10 @@ static int can_loopback_get_capabilities(const struct device *dev, can_mode_t *c
|
||||||
|
|
||||||
*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK;
|
*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK;
|
||||||
|
|
||||||
|
#if CONFIG_CAN_FD_MODE
|
||||||
|
*cap |= CAN_MODE_FD;
|
||||||
|
#endif /* CONFIG_CAN_FD_MODE */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +216,18 @@ static int can_loopback_set_mode(const struct device *dev, can_mode_t mode)
|
||||||
{
|
{
|
||||||
struct can_loopback_data *data = dev->data;
|
struct can_loopback_data *data = dev->data;
|
||||||
|
|
||||||
|
#ifdef CONFIG_CAN_FD_MODE
|
||||||
|
if ((mode & ~(CAN_MODE_LOOPBACK | CAN_MODE_FD)) != 0) {
|
||||||
|
LOG_ERR("unsupported mode: 0x%08x", mode);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if ((mode & ~(CAN_MODE_LOOPBACK)) != 0) {
|
||||||
|
LOG_ERR("unsupported mode: 0x%08x", mode);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_CAN_FD_MODE */
|
||||||
|
|
||||||
data->loopback = (mode & CAN_MODE_LOOPBACK) != 0 ? 1 : 0;
|
data->loopback = (mode & CAN_MODE_LOOPBACK) != 0 ? 1 : 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -218,6 +241,17 @@ static int can_loopback_set_timing(const struct device *dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CAN_FD_MODE
|
||||||
|
static int can_loopback_set_timing_data(const struct device *dev,
|
||||||
|
const struct can_timing *timing)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
ARG_UNUSED(timing);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_CAN_FD_MODE */
|
||||||
|
|
||||||
static int can_loopback_get_state(const struct device *dev, enum can_state *state,
|
static int can_loopback_get_state(const struct device *dev, enum can_state *state,
|
||||||
struct can_bus_err_cnt *err_cnt)
|
struct can_bus_err_cnt *err_cnt)
|
||||||
{
|
{
|
||||||
|
@ -295,7 +329,24 @@ static const struct can_driver_api can_loopback_driver_api = {
|
||||||
.phase_seg1 = 0x0F,
|
.phase_seg1 = 0x0F,
|
||||||
.phase_seg2 = 0x0F,
|
.phase_seg2 = 0x0F,
|
||||||
.prescaler = 0xFFFF
|
.prescaler = 0xFFFF
|
||||||
}
|
},
|
||||||
|
#ifdef CONFIG_CAN_FD_MODE
|
||||||
|
.set_timing_data = can_loopback_set_timing_data,
|
||||||
|
.timing_data_min = {
|
||||||
|
.sjw = 0x1,
|
||||||
|
.prop_seg = 0x01,
|
||||||
|
.phase_seg1 = 0x01,
|
||||||
|
.phase_seg2 = 0x01,
|
||||||
|
.prescaler = 0x01
|
||||||
|
},
|
||||||
|
.timing_data_max = {
|
||||||
|
.sjw = 0x0F,
|
||||||
|
.prop_seg = 0x0F,
|
||||||
|
.phase_seg1 = 0x0F,
|
||||||
|
.phase_seg2 = 0x0F,
|
||||||
|
.prescaler = 0xFFFF
|
||||||
|
},
|
||||||
|
#endif /* CONFIG_CAN_FD_MODE */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int can_loopback_init(const struct device *dev)
|
static int can_loopback_init(const struct device *dev)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue