Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

can: isotp: Add CAN-FD support to ISO-TP #60323

Merged
merged 5 commits into from Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 26 additions & 3 deletions include/zephyr/canbus/isotp.h
Expand Up @@ -11,8 +11,8 @@
* ISO-TP is a transport protocol for CAN (Controller Area Network)
*/

#ifndef ZEPHYR_INCLUDE_ISOTP_H_
#define ZEPHYR_INCLUDE_ISOTP_H_
#ifndef ZEPHYR_INCLUDE_CANBUS_ISOTP_H_
#define ZEPHYR_INCLUDE_CANBUS_ISOTP_H_

/**
* @brief CAN ISO-TP Protocol
Expand All @@ -34,10 +34,16 @@
* DLC Data length code
* FC Flow Control
* FF First Frame
* SF Single Frame
* FS Flow Status
* AE Address Extension
* SN Sequence Number
* ST Separation time
* SA Source Address
* TA Target Address
* RX_DL CAN RX LL data size
* TX_DL CAN TX LL data size
* PCI Process Control Information
*/

/*
Expand Down Expand Up @@ -147,6 +153,12 @@ extern "C" {
/** Message uses extended (29-bit) CAN ID */
#define ISOTP_MSG_IDE BIT(2)

/** Message uses CAN-FD format (FDF) */
#define ISOTP_MSG_FDF BIT(3)

/** Message uses CAN-FD Baud Rate Switch (BRS). Only valid in combination with ``ISOTP_MSG_FDF``. */
#define ISOTP_MSG_BRS BIT(4)

/** @} */

/**
Expand All @@ -167,6 +179,17 @@ struct isotp_msg_id {
};
/** ISO-TP extended address (if used) */
uint8_t ext_addr;
/**
* ISO-TP frame data length (TX_DL for TX address or RX_DL for RX address).
*
* Valid values are 8 for classical CAN or 8, 12, 16, 20, 24, 32, 48 and 64 for CAN-FD.
*
* 0 will be interpreted as 8 or 64 (if ISOTP_MSG_FDF is set).
*
* The value for incoming transmissions (RX_DL) is determined automatically based on the
* received first frame and does not need to be set during initialization.
*/
uint8_t dl;
/** Flags. @see @ref ISOTP_MSG_FLAGS. */
uint8_t flags;
};
Expand Down Expand Up @@ -459,4 +482,4 @@ struct isotp_recv_ctx {
}
#endif

#endif /* ZEPHYR_INCLUDE_ISOTP_H_ */
#endif /* ZEPHYR_INCLUDE_CANBUS_ISOTP_H_ */
8 changes: 8 additions & 0 deletions samples/subsys/canbus/isotp/Kconfig
Expand Up @@ -22,4 +22,12 @@ config SAMPLE_RX_THREAD_PRIORITY
help
Priority used for the RX threads.

config SAMPLE_CAN_FD_MODE
bool "Use CAN-FD"
select CAN_FD_MODE

config ISOTP_RX_BUF_COUNT
default 4 if SAMPLE_CAN_FD_MODE
default 2

source "Kconfig.zephyr"
6 changes: 1 addition & 5 deletions samples/subsys/canbus/isotp/prj.conf
Expand Up @@ -4,9 +4,5 @@ CONFIG_CAN=y
CONFIG_CAN_MAX_FILTER=8

CONFIG_ISOTP=y
CONFIG_ISOTP_RX_BUF_COUNT=2
#A frame has 7 bytes payload, we are using a BS of 8 and need one char for the
#string termination (7 * 8 + 1 = 57)
CONFIG_ISOTP_RX_BUF_SIZE=57
#We have two receiving contexts that are bound to a single address.
# We have two receiving contexts that are bound to a single address.
CONFIG_ISOTP_RX_SF_FF_BUF_COUNT=2
16 changes: 16 additions & 0 deletions samples/subsys/canbus/isotp/sample.yaml
Expand Up @@ -14,3 +14,19 @@ tests:
type: one_line
regex:
- "(.*)Got 247 bytes in total"
sample.subsys.canbus.isotp.fd:
tags:
- can
- isotp
depends_on: can
extra_configs:
- CONFIG_SAMPLE_LOOPBACK_MODE=y
- CONFIG_SAMPLE_CAN_FD_MODE=y
platform_allow:
- native_posix
- native_posix_64
harness: console
harness_config:
type: one_line
regex:
- "(.*)Got 247 bytes in total"
40 changes: 22 additions & 18 deletions samples/subsys/canbus/isotp/src/main.c
Expand Up @@ -12,15 +12,29 @@ const struct isotp_fc_opts fc_opts_0_5 = {.bs = 0, .stmin = 5};

const struct isotp_msg_id rx_addr_8_0 = {
.std_id = 0x80,
#ifdef CONFIG_SAMPLE_CAN_FD_MODE
.flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS,
#endif
};
const struct isotp_msg_id tx_addr_8_0 = {
.std_id = 0x180,
#ifdef CONFIG_SAMPLE_CAN_FD_MODE
.dl = 64,
.flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS,
#endif
};
const struct isotp_msg_id rx_addr_0_5 = {
.std_id = 0x01,
#ifdef CONFIG_SAMPLE_CAN_FD_MODE
.flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS,
#endif
};
const struct isotp_msg_id tx_addr_0_5 = {
.std_id = 0x101,
#ifdef CONFIG_SAMPLE_CAN_FD_MODE
.dl = 64,
.flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS,
#endif
};

const struct device *can_dev;
Expand Down Expand Up @@ -49,8 +63,6 @@ void rx_8_0_thread(void *arg1, void *arg2, void *arg3)
ARG_UNUSED(arg3);
int ret, rem_len, received_len;
struct net_buf *buf;
static uint8_t rx_buffer[7];


ret = isotp_bind(&recv_ctx_8_0, can_dev,
&tx_addr_8_0, &rx_addr_8_0,
Expand All @@ -71,19 +83,11 @@ void rx_8_0_thread(void *arg1, void *arg2, void *arg3)
break;
}

received_len += buf->len;
if (net_buf_tailroom(buf) >= 1) {
net_buf_add_u8(buf, '\0');
printk("%s", buf->data);
} else if (buf->len == 6) {
/* First frame does not have tailroom.*/
memcpy(rx_buffer, buf->data, 6);
rx_buffer[6] = '\0';
printk("%s", rx_buffer);
} else {
printk("No tailroom for string termination\n");
while (buf != NULL) {
received_len += buf->len;
printk("%.*s", buf->len, buf->data);
buf = net_buf_frag_del(NULL, buf);
}
net_buf_unref(buf);
} while (rem_len);
printk("Got %d bytes in total\n", received_len);
}
Expand Down Expand Up @@ -142,13 +146,13 @@ int main(void)
return 0;
}

#ifdef CONFIG_SAMPLE_LOOPBACK_MODE
ret = can_set_mode(can_dev, CAN_MODE_LOOPBACK);
can_mode_t mode = (IS_ENABLED(CONFIG_SAMPLE_LOOPBACK_MODE) ? CAN_MODE_LOOPBACK : 0) |
(IS_ENABLED(CONFIG_SAMPLE_CAN_FD_MODE) ? CAN_MODE_FD : 0);
ret = can_set_mode(can_dev, mode);
if (ret != 0) {
printk("CAN: Failed to set loopback mode [%d]", ret);
printk("CAN: Failed to set mode [%d]", ret);
return 0;
}
#endif /* CONFIG_SAMPLE_LOOPBACK_MODE */

ret = can_start(can_dev);
if (ret != 0) {
Expand Down
6 changes: 4 additions & 2 deletions subsys/canbus/isotp/Kconfig
Expand Up @@ -5,6 +5,7 @@

menuconfig ISOTP
bool "ISO-TP Transport [EXPERIMENTAL]"
depends on CAN
select NET_BUF
select POLL
select EXPERIMENTAL
Expand Down Expand Up @@ -74,11 +75,12 @@ config ISOTP_RX_BUF_COUNT

config ISOTP_RX_BUF_SIZE
int "Size of one buffer data block"
default 63 if CAN_FD_MODE
default 56
help
This value defines the size of a single block in the pool. The number of
blocks is given by ISOTP_RX_BUF_COUNT. To be efficient use a multiple of
CAN_DL - 1 (for classic can : 8 - 1 = 7).
CAN_MAX_DLEN - 1 (for classic CAN : 8 - 1 = 7, for CAN-FD : 64 - 1 = 63).

config ISOTP_RX_SF_FF_BUF_COUNT
int "Number of SF and FF data buffers for receiving data"
Expand All @@ -87,7 +89,7 @@ config ISOTP_RX_SF_FF_BUF_COUNT
This buffer is used for first and single frames. It is extra because the
buffer has to be ready for the first reception in isr context and therefor
is allocated when binding.
Each buffer will occupy CAN_DL - 1 byte + header (sizeof(struct net_buf))
Each buffer will occupy CAN_MAX_DLEN - 1 byte + header (sizeof(struct net_buf))
amount of data.

config ISOTP_USE_TX_BUF
Expand Down