1 /*
2 * Copyright (c) 2020 Alexander Wachter
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/canbus/isotp.h>
9
10 const struct isotp_fc_opts fc_opts_8_0 = {.bs = 8, .stmin = 0};
11 const struct isotp_fc_opts fc_opts_0_5 = {.bs = 0, .stmin = 5};
12
13 const struct isotp_msg_id rx_addr_8_0 = {
14 .std_id = 0x80,
15 #ifdef CONFIG_SAMPLE_CAN_FD_MODE
16 .flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS,
17 #endif
18 };
19 const struct isotp_msg_id tx_addr_8_0 = {
20 .std_id = 0x180,
21 #ifdef CONFIG_SAMPLE_CAN_FD_MODE
22 .dl = 64,
23 .flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS,
24 #endif
25 };
26 const struct isotp_msg_id rx_addr_0_5 = {
27 .std_id = 0x01,
28 #ifdef CONFIG_SAMPLE_CAN_FD_MODE
29 .flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS,
30 #endif
31 };
32 const struct isotp_msg_id tx_addr_0_5 = {
33 .std_id = 0x101,
34 #ifdef CONFIG_SAMPLE_CAN_FD_MODE
35 .dl = 64,
36 .flags = ISOTP_MSG_FDF | ISOTP_MSG_BRS,
37 #endif
38 };
39
40 const struct device *can_dev;
41 struct isotp_recv_ctx recv_ctx_8_0;
42 struct isotp_recv_ctx recv_ctx_0_5;
43
44 K_THREAD_STACK_DEFINE(rx_8_0_thread_stack, CONFIG_SAMPLE_RX_THREAD_STACK_SIZE);
45 K_THREAD_STACK_DEFINE(rx_0_5_thread_stack, CONFIG_SAMPLE_RX_THREAD_STACK_SIZE);
46 struct k_thread rx_8_0_thread_data;
47 struct k_thread rx_0_5_thread_data;
48
49 const char tx_data_large[] =
50 "========================================\n"
51 "| ____ ___ ____ ____ ____ |\n"
52 "| |_ _|/ __|| | ___ |_ _|| _ \\ |\n"
53 "| _||_ \\__ \\| || | ___ || | ___/ |\n"
54 "| |____||___/|____| || |_| |\n"
55 "========================================\n";
56
57 const char tx_data_small[] = "This is the sample test for the short payload\n";
58
rx_8_0_thread(void * arg1,void * arg2,void * arg3)59 void rx_8_0_thread(void *arg1, void *arg2, void *arg3)
60 {
61 ARG_UNUSED(arg1);
62 ARG_UNUSED(arg2);
63 ARG_UNUSED(arg3);
64 int ret, rem_len, received_len;
65 struct net_buf *buf;
66
67 ret = isotp_bind(&recv_ctx_8_0, can_dev,
68 &tx_addr_8_0, &rx_addr_8_0,
69 &fc_opts_8_0, K_FOREVER);
70 if (ret != ISOTP_N_OK) {
71 printk("Failed to bind to rx ID %d [%d]\n",
72 rx_addr_8_0.std_id, ret);
73 return;
74 }
75
76 while (1) {
77 received_len = 0;
78 do {
79 rem_len = isotp_recv_net(&recv_ctx_8_0, &buf,
80 K_MSEC(2000));
81 if (rem_len < 0) {
82 printk("Receiving error [%d]\n", rem_len);
83 break;
84 }
85
86 while (buf != NULL) {
87 received_len += buf->len;
88 printk("%.*s", buf->len, buf->data);
89 buf = net_buf_frag_del(NULL, buf);
90 }
91 } while (rem_len);
92 printk("Got %d bytes in total\n", received_len);
93 }
94 }
95
rx_0_5_thread(void * arg1,void * arg2,void * arg3)96 void rx_0_5_thread(void *arg1, void *arg2, void *arg3)
97 {
98 ARG_UNUSED(arg1);
99 ARG_UNUSED(arg2);
100 ARG_UNUSED(arg3);
101 int ret, received_len;
102 static uint8_t rx_buffer[32];
103
104 ret = isotp_bind(&recv_ctx_0_5, can_dev,
105 &tx_addr_0_5, &rx_addr_0_5,
106 &fc_opts_0_5, K_FOREVER);
107 if (ret != ISOTP_N_OK) {
108 printk("Failed to bind to rx ID %d [%d]\n",
109 rx_addr_0_5.std_id, ret);
110 return;
111 }
112
113 while (1) {
114 received_len = isotp_recv(&recv_ctx_0_5, rx_buffer,
115 sizeof(rx_buffer)-1U, K_MSEC(2000));
116 if (received_len < 0) {
117 printk("Receiving error [%d]\n", received_len);
118 continue;
119 }
120
121 rx_buffer[received_len] = '\0';
122 printk("%s", rx_buffer);
123 }
124 }
125
send_complette_cb(int error_nr,void * arg)126 void send_complette_cb(int error_nr, void *arg)
127 {
128 ARG_UNUSED(arg);
129 printk("TX complete cb [%d]\n", error_nr);
130 }
131
132 /**
133 * @brief Main application entry point.
134 *
135 */
main(void)136 int main(void)
137 {
138 k_tid_t tid;
139 static struct isotp_send_ctx send_ctx_8_0;
140 static struct isotp_send_ctx send_ctx_0_5;
141 int ret = 0;
142
143 can_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus));
144 if (!device_is_ready(can_dev)) {
145 printk("CAN: Device driver not ready.\n");
146 return 0;
147 }
148
149 can_mode_t mode = (IS_ENABLED(CONFIG_SAMPLE_LOOPBACK_MODE) ? CAN_MODE_LOOPBACK : 0) |
150 (IS_ENABLED(CONFIG_SAMPLE_CAN_FD_MODE) ? CAN_MODE_FD : 0);
151 ret = can_set_mode(can_dev, mode);
152 if (ret != 0) {
153 printk("CAN: Failed to set mode [%d]", ret);
154 return 0;
155 }
156
157 ret = can_start(can_dev);
158 if (ret != 0) {
159 printk("CAN: Failed to start device [%d]\n", ret);
160 return 0;
161 }
162
163 tid = k_thread_create(&rx_8_0_thread_data, rx_8_0_thread_stack,
164 K_THREAD_STACK_SIZEOF(rx_8_0_thread_stack),
165 rx_8_0_thread, NULL, NULL, NULL,
166 CONFIG_SAMPLE_RX_THREAD_PRIORITY, 0, K_NO_WAIT);
167 if (!tid) {
168 printk("ERROR spawning rx thread\n");
169 return 0;
170 }
171 k_thread_name_set(tid, "rx_8_0");
172
173 tid = k_thread_create(&rx_0_5_thread_data, rx_0_5_thread_stack,
174 K_THREAD_STACK_SIZEOF(rx_0_5_thread_stack),
175 rx_0_5_thread, NULL, NULL, NULL,
176 CONFIG_SAMPLE_RX_THREAD_PRIORITY, 0, K_NO_WAIT);
177 if (!tid) {
178 printk("ERROR spawning rx thread\n");
179 return 0;
180 }
181 k_thread_name_set(tid, "rx_0_5");
182
183 printk("Start sending data\n");
184
185 while (1) {
186 k_msleep(1000);
187 ret = isotp_send(&send_ctx_0_5, can_dev,
188 tx_data_small, sizeof(tx_data_small),
189 &tx_addr_0_5, &rx_addr_0_5,
190 send_complette_cb, NULL);
191 if (ret != ISOTP_N_OK) {
192 printk("Error while sending data to ID %d [%d]\n",
193 tx_addr_0_5.std_id, ret);
194 }
195
196 ret = isotp_send(&send_ctx_8_0, can_dev,
197 tx_data_large, sizeof(tx_data_large),
198 &tx_addr_8_0, &rx_addr_8_0, NULL, NULL);
199 if (ret != ISOTP_N_OK) {
200 printk("Error while sending data to ID %d [%d]\n",
201 tx_addr_8_0.std_id, ret);
202 }
203 }
204 }
205