Skip to content

Commit 87abf20

Browse files
committed
tests: drivers: add simple LIN driver test
Add simple LIN loopback test to check basic read/write operation Signed-off-by: The Nguyen <[email protected]>
1 parent a544108 commit 87abf20

File tree

5 files changed

+328
-0
lines changed

5 files changed

+328
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(lin_api)
6+
7+
FILE(GLOB app_sources src/*.c)
8+
target_sources(app PRIVATE ${app_sources})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright (c) 2025 Renesas Electronics Corporation
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
aliases {
9+
master = &lin_skeleton0;
10+
slave = &lin_skeleton1;
11+
};
12+
13+
lin_skeleton0: lin_skeleton0 {
14+
compatible = "zephyr,lin-skeleton";
15+
};
16+
17+
lin_skeleton1: lin_skeleton1 {
18+
compatible = "zephyr,lin-skeleton";
19+
};
20+
};

tests/drivers/lin/lin_api/prj.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
CONFIG_LIN=y
2+
CONFIG_ZTEST=y
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
/*
2+
* Copyright (c) 2025 Renesas Electronics Corporation
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @addtogroup t_lin_api
9+
* @{
10+
* @defgroup t_lin_api_basic test_lin_api_basic
11+
* @brief TestPurpose: verify LIN API basic functionality
12+
*
13+
* This test uses 2 nodes: a LIN master node and a LIN slave node for loopback testing.
14+
* @}
15+
*/
16+
17+
#include <zephyr/drivers/lin.h>
18+
#include <zephyr/kernel.h>
19+
#include <zephyr/ztest.h>
20+
21+
#if DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(master))
22+
#define LIN_MASTER DT_ALIAS(master)
23+
#else
24+
#error "Please set the correct LIN master device"
25+
#endif
26+
27+
#if DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(slave))
28+
#define LIN_SLAVE DT_ALIAS(slave)
29+
#else
30+
#error "Please set the correct LIN slave device"
31+
#endif
32+
33+
#define LIN_BUS_BAUDRATE 19200U
34+
#define LIN_BUS_BREAK_LEN 13U
35+
#define LIN_BUS_BREAK_DELIMITER_LEN 2U
36+
37+
#define LIN_MASTER_WRITE_ID 0x01
38+
#define LIN_MASTER_READ_ID 0x02
39+
40+
static const struct device *const lin_master = DEVICE_DT_GET(LIN_MASTER);
41+
static const struct device *const lin_slave = DEVICE_DT_GET(LIN_SLAVE);
42+
43+
static const struct lin_config master_cfg = {
44+
.mode = LIN_MODE_COMMANDER,
45+
.baudrate = LIN_BUS_BAUDRATE,
46+
.break_len = LIN_BUS_BREAK_LEN,
47+
.break_delimiter_len = LIN_BUS_BREAK_DELIMITER_LEN,
48+
.flags = 0,
49+
};
50+
51+
static const struct lin_config slave_cfg = {
52+
.mode = LIN_MODE_RESPONDER,
53+
.baudrate = LIN_BUS_BAUDRATE,
54+
.break_len = LIN_BUS_BREAK_LEN,
55+
.break_delimiter_len = LIN_BUS_BREAK_DELIMITER_LEN,
56+
.flags = 0,
57+
};
58+
59+
static const uint8_t data[LIN_MAX_DLEN] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
60+
static struct k_sem transmission_completed;
61+
static struct lin_msg slave_msg;
62+
63+
static void slave_evt_callback(const struct device *dev, const struct lin_event *event,
64+
void *user_data)
65+
{
66+
ARG_UNUSED(dev);
67+
ARG_UNUSED(user_data);
68+
int ret;
69+
70+
switch (event->type) {
71+
case LIN_EVT_RX_HEADER:
72+
if (event->pid == LIN_MASTER_WRITE_ID) {
73+
ret = lin_read(lin_slave, &slave_msg, K_FOREVER);
74+
if (ret) {
75+
TC_PRINT("LIN slave read failed\n");
76+
return;
77+
}
78+
} else if (event->pid == LIN_MASTER_READ_ID) {
79+
ret = lin_response(lin_slave, &slave_msg, K_FOREVER);
80+
if (ret) {
81+
TC_PRINT("LIN slave send failed\n");
82+
return;
83+
}
84+
} else {
85+
TC_PRINT("Unexpected LIN ID\n");
86+
return;
87+
}
88+
break;
89+
case LIN_EVT_TX_DATA:
90+
case LIN_EVT_RX_DATA:
91+
case LIN_EVT_RX_WAKEUP:
92+
case LIN_EVT_ERR:
93+
default:
94+
break;
95+
}
96+
}
97+
98+
static void master_evt_callback(const struct device *dev, const struct lin_event *event,
99+
void *user_data)
100+
{
101+
ARG_UNUSED(dev);
102+
ARG_UNUSED(user_data);
103+
104+
switch (event->type) {
105+
case LIN_EVT_TX_DATA:
106+
case LIN_EVT_RX_DATA:
107+
k_sem_give(&transmission_completed);
108+
break;
109+
case LIN_EVT_RX_HEADER:
110+
case LIN_EVT_RX_WAKEUP:
111+
case LIN_EVT_ERR:
112+
default:
113+
break;
114+
}
115+
}
116+
117+
static int test_lin_basic_api(struct lin_msg *master_msg, struct lin_msg *slave_msg)
118+
{
119+
int ret;
120+
121+
/* 1. Configure LIN master and slave nodes */
122+
ret = lin_configure(lin_master, &master_cfg);
123+
if (ret) {
124+
TC_PRINT("LIN configure failed\n");
125+
return TC_FAIL;
126+
}
127+
128+
ret = lin_configure(lin_slave, &slave_cfg);
129+
if (ret) {
130+
TC_PRINT("LIN slave configure failed\n");
131+
return TC_FAIL;
132+
}
133+
134+
/* 2. Allow LIN communication */
135+
ret = lin_start(lin_master);
136+
if (ret) {
137+
TC_PRINT("LIN start failed\n");
138+
return TC_FAIL;
139+
}
140+
141+
ret = lin_start(lin_slave);
142+
if (ret) {
143+
TC_PRINT("LIN slave start failed\n");
144+
return TC_FAIL;
145+
}
146+
147+
/* 3. Master send header + data frames to slave */
148+
ret = lin_send(lin_master, master_msg, K_FOREVER);
149+
if (ret) {
150+
TC_PRINT("LIN send failed\n");
151+
return TC_FAIL;
152+
}
153+
154+
/* 4. Wait for transmission completed */
155+
ret = k_sem_take(&transmission_completed, K_MSEC(100));
156+
if (ret) {
157+
TC_PRINT("Master write timeout\n");
158+
return TC_FAIL;
159+
}
160+
161+
return TC_PASS;
162+
}
163+
164+
static void *test_lin_setup(void)
165+
{
166+
k_sem_init(&transmission_completed, 0, 1);
167+
168+
return NULL;
169+
}
170+
171+
static void test_lin_before(void *f)
172+
{
173+
ARG_UNUSED(f);
174+
175+
k_sem_reset(&transmission_completed);
176+
}
177+
178+
static void test_lin_after(void *f)
179+
{
180+
ARG_UNUSED(f);
181+
182+
lin_stop(lin_master);
183+
lin_stop(lin_slave);
184+
}
185+
186+
static void test_lin_teardown(void *f)
187+
{
188+
ARG_UNUSED(f);
189+
}
190+
191+
ZTEST(lin_api_basic, test_lin_configure)
192+
{
193+
struct lin_config config_tmp;
194+
int ret;
195+
196+
zassert_true(device_is_ready(lin_master), "LIN master device is not ready");
197+
zassert_true(device_is_ready(lin_slave), "LIN slave device is not ready");
198+
199+
/* Configure LIN master */
200+
ret = lin_configure(lin_master, &master_cfg);
201+
zassert_ok(ret, "Failed to configure LIN master");
202+
203+
/* Verify LIN master configuration */
204+
ret = lin_get_config(lin_master, &config_tmp);
205+
zassert_ok(ret, "Failed to get LIN master config");
206+
zassert_mem_equal(&config_tmp, &master_cfg, sizeof(master_cfg),
207+
"LIN master config mismatch");
208+
209+
/* Configure LIN slave */
210+
ret = lin_configure(lin_slave, &slave_cfg);
211+
zassert_ok(ret, "Failed to configure LIN slave");
212+
213+
/* Verify LIN slave configuration */
214+
ret = lin_get_config(lin_slave, &config_tmp);
215+
zassert_ok(ret, "Failed to get LIN slave config");
216+
zassert_mem_equal(&config_tmp, &slave_cfg, sizeof(slave_cfg), "LIN slave config mismatch");
217+
}
218+
219+
ZTEST(lin_api_basic, test_lin_master_write)
220+
{
221+
struct lin_msg lin_master_msg = {
222+
.id = LIN_MASTER_WRITE_ID,
223+
.data_len = LIN_MAX_DLEN,
224+
.checksum_type = LIN_CHECKSUM_CLASSIC,
225+
};
226+
int ret;
227+
228+
/* Prepare master message write data */
229+
memcpy(lin_master_msg.data, data, LIN_MAX_DLEN);
230+
231+
zassert_true(device_is_ready(lin_master), "LIN master device is not ready");
232+
zassert_true(device_is_ready(lin_slave), "LIN slave device is not ready");
233+
234+
/* Set master event handler */
235+
ret = lin_set_callback(lin_master, master_evt_callback, NULL);
236+
zassert_ok(ret, "Failed to set master event callback");
237+
238+
/* Set slave event handler */
239+
ret = lin_set_callback(lin_slave, slave_evt_callback, NULL);
240+
zassert_ok(ret, "Failed to set slave event callback");
241+
242+
/* Run the LIN master write test */
243+
ret = test_lin_basic_api(&lin_master_msg, &slave_msg);
244+
zassert_ok(ret, "LIN master write test failed");
245+
246+
/* Verify LIN received data */
247+
zassert_equal(slave_msg.id, lin_master_msg.id, "LIN received ID does not match sent ID");
248+
zassert_mem_equal(slave_msg.data, lin_master_msg.data, lin_master_msg.data_len,
249+
"LIN received data does not match sent data");
250+
}
251+
252+
ZTEST(lin_api_basic, test_lin_master_read)
253+
{
254+
struct lin_msg lin_master_msg = {
255+
.id = LIN_MASTER_READ_ID,
256+
.data_len = LIN_MAX_DLEN,
257+
.checksum_type = LIN_CHECKSUM_CLASSIC,
258+
};
259+
int ret;
260+
261+
/* Prepare slave message response data */
262+
memcpy(slave_msg.data, data, LIN_MAX_DLEN);
263+
264+
zassert_true(device_is_ready(lin_master), "LIN master device is not ready");
265+
zassert_true(device_is_ready(lin_slave), "LIN slave device is not ready");
266+
267+
/* Set master event handler */
268+
ret = lin_set_callback(lin_master, master_evt_callback, NULL);
269+
zassert_ok(ret, "Failed to set master event callback");
270+
271+
/* Set slave event handler */
272+
ret = lin_set_callback(lin_slave, slave_evt_callback, NULL);
273+
zassert_ok(ret, "Failed to set slave event callback");
274+
275+
/* Run the master read test */
276+
ret = test_lin_basic_api(&lin_master_msg, &slave_msg);
277+
zassert_ok(ret, "LIN master read test failed");
278+
279+
/* Verify LIN received data */
280+
zassert_equal(lin_master_msg.id, slave_msg.id, "LIN received ID does not match sent ID");
281+
zassert_mem_equal(lin_master_msg.data, slave_msg.data, lin_master_msg.data_len,
282+
"LIN received data does not match sent data");
283+
}
284+
285+
ZTEST_SUITE(lin_api_basic, NULL, test_lin_setup, test_lin_before, test_lin_after,
286+
test_lin_teardown);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
common:
2+
tags:
3+
- lin
4+
- drivers
5+
tests:
6+
drivers.lin.api:
7+
depends_on: lin
8+
drivers.lin.api.skeleton:
9+
extra_args:
10+
- EXTRA_DTC_OVERLAY_FILE="lin_skeleton.overlay"
11+
platform_allow:
12+
- native_sim/native/64

0 commit comments

Comments
 (0)