samples: canbus: isotp: Add sample code for the ISO-TP lib
This commit adds sample-code for the ISO-TP library Signed-off-by: Alexander Wachter <alexander@wachter.cloud>
This commit is contained in:
parent
10ed5d55d0
commit
7c3a4e6baa
5 changed files with 273 additions and 0 deletions
8
samples/subsys/canbus/isotp/CMakeLists.txt
Normal file
8
samples/subsys/canbus/isotp/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.13.1)
|
||||
|
||||
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||
project(ISOTP)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
48
samples/subsys/canbus/isotp/README.rst
Normal file
48
samples/subsys/canbus/isotp/README.rst
Normal file
|
@ -0,0 +1,48 @@
|
|||
.. _isotp-sample:
|
||||
|
||||
ISO-TP library
|
||||
##############
|
||||
|
||||
Overview
|
||||
********
|
||||
This sample demonstrates how to use the ISO-TP library.
|
||||
Messages are exchanged between two boards. A long message, that is sent with
|
||||
a block-size (BS) of eight frames, and a short one that has an minimal
|
||||
separation-time (STmin) of five milliseconds.
|
||||
The send function call for the short message is non-blocking, and the send
|
||||
function call for the long message is blocking.
|
||||
|
||||
Building and Running
|
||||
********************
|
||||
Use these instructions with integrated CAN controller like in the NXP TWR-KE18F
|
||||
or Nucleo-F746ZG board.
|
||||
|
||||
For the NXP TWR-KE18F board:
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/drivers/CAN
|
||||
:board: twr_ke18f
|
||||
:goals: build flash
|
||||
|
||||
Requirements
|
||||
************
|
||||
|
||||
* Two boards with CAN bus support, connected together
|
||||
|
||||
Sample output
|
||||
=============
|
||||
.. code-block:: console
|
||||
|
||||
Start sending data
|
||||
[00:00:00.000,000] <inf> can_driver: Init of CAN_1 done
|
||||
========================================
|
||||
| ____ ___ ____ ____ ____ |
|
||||
| |_ _|/ __|| | ___ |_ _|| _ \ |
|
||||
| _||_ \__ \| || | ___ || | ___/ |
|
||||
| |____||___/|____| || |_| |
|
||||
========================================
|
||||
Got 248 bytes in total
|
||||
This is the sample test for the short payload
|
||||
TX complete cb [0]
|
||||
|
||||
.. note:: The values shown above might differ.
|
12
samples/subsys/canbus/isotp/prj.conf
Normal file
12
samples/subsys/canbus/isotp/prj.conf
Normal file
|
@ -0,0 +1,12 @@
|
|||
CONFIG_LOG=y
|
||||
|
||||
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.
|
||||
CONFIG_ISOTP_RX_SF_FF_BUF_COUNT=2
|
11
samples/subsys/canbus/isotp/sample.yaml
Normal file
11
samples/subsys/canbus/isotp/sample.yaml
Normal file
|
@ -0,0 +1,11 @@
|
|||
sample:
|
||||
name: ISO-TP lib sample
|
||||
tests:
|
||||
sample.subsys.canbus.isotp:
|
||||
tags: CAN
|
||||
depends_on: can
|
||||
harness: console
|
||||
harness_config:
|
||||
type: one_line
|
||||
regex:
|
||||
- "(.*)Got 248 bytes in total"
|
194
samples/subsys/canbus/isotp/src/main.c
Normal file
194
samples/subsys/canbus/isotp/src/main.c
Normal file
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Alexander Wachter
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <canbus/isotp.h>
|
||||
|
||||
|
||||
#define RX_THREAD_STACK_SIZE 512
|
||||
#define RX_THREAD_PRIORITY 2
|
||||
|
||||
const struct isotp_fc_opts fc_opts_8_0 = {.bs = 8, .stmin = 0};
|
||||
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,
|
||||
.id_type = CAN_STANDARD_IDENTIFIER,
|
||||
.use_ext_addr = 0
|
||||
};
|
||||
const struct isotp_msg_id tx_addr_8_0 = {
|
||||
.std_id = 0x180,
|
||||
.id_type = CAN_STANDARD_IDENTIFIER,
|
||||
.use_ext_addr = 0
|
||||
};
|
||||
const struct isotp_msg_id rx_addr_0_5 = {
|
||||
.std_id = 0x01,
|
||||
.id_type = CAN_STANDARD_IDENTIFIER,
|
||||
.use_ext_addr = 0
|
||||
};
|
||||
const struct isotp_msg_id tx_addr_0_5 = {
|
||||
.std_id = 0x101,
|
||||
.id_type = CAN_STANDARD_IDENTIFIER,
|
||||
.use_ext_addr = 0
|
||||
};
|
||||
|
||||
struct device *can_dev;
|
||||
struct isotp_recv_ctx recv_ctx_8_0;
|
||||
struct isotp_recv_ctx recv_ctx_0_5;
|
||||
|
||||
K_THREAD_STACK_DEFINE(rx_8_0_thread_stack, RX_THREAD_STACK_SIZE);
|
||||
K_THREAD_STACK_DEFINE(rx_0_5_thread_stack, RX_THREAD_STACK_SIZE);
|
||||
struct k_thread rx_8_0_thread_data;
|
||||
struct k_thread rx_0_5_thread_data;
|
||||
|
||||
const char tx_data_large[] =
|
||||
"========================================\n"
|
||||
"| ____ ___ ____ ____ ____ |\n"
|
||||
"| |_ _|/ __|| | ___ |_ _|| _ \\ |\n"
|
||||
"| _||_ \\__ \\| || | ___ || | ___/ |\n"
|
||||
"| |____||___/|____| || |_| |\n"
|
||||
"========================================\n";
|
||||
|
||||
const char tx_data_small[] = "This is the sample test for the short payload\n";
|
||||
|
||||
void rx_8_0_thread(void *arg1, void *arg2, void *arg3)
|
||||
{
|
||||
ARG_UNUSED(arg1);
|
||||
ARG_UNUSED(arg2);
|
||||
ARG_UNUSED(arg3);
|
||||
int ret, rem_len, received_len;
|
||||
struct net_buf *buf;
|
||||
static u8_t rx_buffer[7];
|
||||
|
||||
|
||||
ret = isotp_bind(&recv_ctx_8_0, can_dev,
|
||||
&tx_addr_8_0, &rx_addr_8_0,
|
||||
&fc_opts_8_0, K_FOREVER);
|
||||
if (ret != ISOTP_N_OK) {
|
||||
printk("Failed to bind to rx ID %d [%d]\n",
|
||||
rx_addr_8_0.std_id, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
received_len = 0;
|
||||
do {
|
||||
rem_len = isotp_recv_net(&recv_ctx_8_0, &buf,
|
||||
K_MSEC(2000));
|
||||
if (rem_len < 0) {
|
||||
printk("Receiving erreor [%d]\n", rem_len);
|
||||
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");
|
||||
}
|
||||
net_buf_unref(buf);
|
||||
} while (rem_len);
|
||||
printk("Got %d bytes in total\n", received_len);
|
||||
}
|
||||
}
|
||||
|
||||
void rx_0_5_thread(void *arg1, void *arg2, void *arg3)
|
||||
{
|
||||
ARG_UNUSED(arg1);
|
||||
ARG_UNUSED(arg2);
|
||||
ARG_UNUSED(arg3);
|
||||
int ret, received_len;
|
||||
static u8_t rx_buffer[32];
|
||||
|
||||
ret = isotp_bind(&recv_ctx_0_5, can_dev,
|
||||
&tx_addr_0_5, &rx_addr_0_5,
|
||||
&fc_opts_0_5, K_FOREVER);
|
||||
if (ret != ISOTP_N_OK) {
|
||||
printk("Failed to bind to rx ID %d [%d]\n",
|
||||
rx_addr_0_5.std_id, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
received_len = isotp_recv(&recv_ctx_0_5, rx_buffer,
|
||||
sizeof(rx_buffer)-1U, K_MSEC(2000));
|
||||
if (received_len < 0) {
|
||||
printk("Receiving erreor [%d]\n", received_len);
|
||||
continue;
|
||||
}
|
||||
|
||||
rx_buffer[received_len] = '\0';
|
||||
printk("%s", rx_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void send_complette_cb(int error_nr, void *arg)
|
||||
{
|
||||
ARG_UNUSED(arg);
|
||||
printk("TX complete cb [%d]\n", error_nr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Main application entry point.
|
||||
*
|
||||
*/
|
||||
void main(void)
|
||||
{
|
||||
k_tid_t tid;
|
||||
static struct isotp_send_ctx send_ctx_8_0;
|
||||
static struct isotp_send_ctx send_ctx_0_5;
|
||||
int ret = 0;
|
||||
|
||||
can_dev = device_get_binding(DT_ALIAS_CAN_PRIMARY_LABEL);
|
||||
if (!can_dev) {
|
||||
printk("CAN: Device driver not found.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
tid = k_thread_create(&rx_8_0_thread_data, rx_8_0_thread_stack,
|
||||
K_THREAD_STACK_SIZEOF(rx_8_0_thread_stack),
|
||||
rx_8_0_thread, NULL, NULL, NULL,
|
||||
RX_THREAD_PRIORITY, 0, K_NO_WAIT);
|
||||
if (!tid) {
|
||||
printk("ERROR spawning rx thread\n");
|
||||
}
|
||||
|
||||
tid = k_thread_create(&rx_0_5_thread_data, rx_0_5_thread_stack,
|
||||
K_THREAD_STACK_SIZEOF(rx_0_5_thread_stack),
|
||||
rx_0_5_thread, NULL, NULL, NULL,
|
||||
RX_THREAD_PRIORITY, 0, K_NO_WAIT);
|
||||
if (!tid) {
|
||||
printk("ERROR spawning rx thread\n");
|
||||
}
|
||||
|
||||
printk("Start sending data\n");
|
||||
|
||||
while (1) {
|
||||
k_sleep(K_MSEC(1000));
|
||||
ret = isotp_send(&send_ctx_0_5, can_dev,
|
||||
tx_data_small, sizeof(tx_data_small),
|
||||
&tx_addr_0_5, &rx_addr_0_5,
|
||||
send_complette_cb, NULL);
|
||||
if (ret != ISOTP_N_OK) {
|
||||
printk("Error while sending data to ID %d [%d]\n",
|
||||
tx_addr_0_5.std_id, ret);
|
||||
}
|
||||
|
||||
ret = isotp_send(&send_ctx_8_0, can_dev,
|
||||
tx_data_large, sizeof(tx_data_large),
|
||||
&tx_addr_8_0, &rx_addr_8_0, NULL, NULL);
|
||||
if (ret != ISOTP_N_OK) {
|
||||
printk("Error while sending data to ID %d [%d]\n",
|
||||
tx_addr_8_0.std_id, ret);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue