Skip to content

Commit 31f8809

Browse files
committed
[serial] add bypass testcase in utest
1 parent db8e2e4 commit 31f8809

File tree

10 files changed

+605
-20
lines changed

10 files changed

+605
-20
lines changed

components/drivers/serial/Kconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ menuconfig RT_USING_SERIAL
2323
default 64
2424
config RT_USING_SERIAL_BYPASS
2525
bool "Using serial bypass"
26-
default y
26+
default n
2727
endif

components/drivers/serial/dev_serial.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -1428,14 +1428,14 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
14281428

14291429
while (1)
14301430
{
1431-
rt_bool_t skip = RT_FALSE;
14321431
ch = serial->ops->getc(serial);
14331432
if (ch == -1) break;
14341433

14351434
/* disable interrupt */
14361435
#ifdef RT_USING_SERIAL_BYPASS
14371436
if (serial->bypass && serial->bypass->upper_h && (serial->bypass->upper_h->head.next != &serial->bypass->upper_h->head))
14381437
{
1438+
rt_bool_t skip = RT_FALSE;
14391439
char buf = (char)ch;
14401440
int ret;
14411441
rt_list_t* node = serial->bypass->upper_h->head.next;
@@ -1449,10 +1449,11 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
14491449
}
14501450
node = node->next;
14511451
} while (node != &serial->bypass->upper_h->head);
1452+
1453+
if (skip)
1454+
continue;
14521455
}
14531456

1454-
if (skip)
1455-
continue;
14561457
#endif
14571458
level = rt_spin_lock_irqsave(&(serial->spinlock));
14581459
rx_fifo->buffer[rx_fifo->put_index] = ch;

components/drivers/serial/serial_tty.c

+18-16
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,22 @@ static void _setup_debug_rxind_hook(void)
114114

115115
#endif /* LWP_DEBUG_INIT */
116116

117-
static void _tty_rx_notify(struct rt_device *device)
117+
#ifdef RT_USING_SERIAL_BYPASS
118+
static rt_err_t _serial_ty_bypass(struct rt_serial_device* serial, char ch,void *data)
119+
{
120+
lwp_tty_t tp;
121+
tp = (lwp_tty_t)data;
122+
123+
tty_lock(tp);
124+
ttydisc_rint(tp, ch, 0);
125+
ttydisc_rint_done(tp);
126+
tty_unlock(tp);
127+
128+
return RT_EOK;
129+
130+
}
131+
#else
132+
static void _tty_rx_notify(struct rt_device* device)
118133
{
119134
lwp_tty_t tp;
120135
struct serial_tty_context *softc;
@@ -127,8 +142,9 @@ static void _tty_rx_notify(struct rt_device *device)
127142
if (_ttyworkq)
128143
rt_workqueue_submit_work(_ttyworkq, &softc->work, 0);
129144
}
145+
#endif
130146

131-
static void _tty_rx_worker(struct rt_work *work, void *data)
147+
static void _tty_rx_worker(struct rt_work* work, void* data)
132148
{
133149
char input;
134150
rt_ssize_t readbytes;
@@ -154,21 +170,7 @@ static void _tty_rx_worker(struct rt_work *work, void *data)
154170
ttydisc_rint_done(tp);
155171
tty_unlock(tp);
156172
}
157-
#ifdef RT_USING_SERIAL_BYPASS
158-
static rt_err_t _serial_ty_bypass(struct rt_serial_device* serial, char ch,void *data)
159-
{
160-
lwp_tty_t tp;
161-
tp = (lwp_tty_t)data;
162173

163-
tty_lock(tp);
164-
ttydisc_rint(tp, ch, 0);
165-
ttydisc_rint_done(tp);
166-
tty_unlock(tp);
167-
168-
return RT_EOK;
169-
170-
}
171-
#endif
172174
rt_inline void _setup_serial(struct rt_serial_device* serial, lwp_tty_t tp,
173175
struct serial_tty_context *softc)
174176
{

examples/utest/testcases/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ rsource "utest/Kconfig"
1111
rsource "kernel/Kconfig"
1212
rsource "cpp11/Kconfig"
1313
rsource "drivers/serial_v2/Kconfig"
14+
rsource "drivers/serial_bypass/Kconfig"
1415
rsource "drivers/ipc/Kconfig"
1516
rsource "posix/Kconfig"
1617
rsource "mm/Kconfig"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
menu "Serial-Bypass Testcase"
2+
3+
config UTEST_SERIAL_BYPASS
4+
bool "Serial testcase"
5+
default n
6+
7+
endmenu
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Import('rtconfig')
2+
from building import *
3+
4+
cwd = GetCurrentDir()
5+
src = Glob('bypass*.c')
6+
7+
CPPPATH = [cwd]
8+
9+
group = DefineGroup('utestcases', src, depend = ['UTEST_SERIAL_BYPASS'], CPPPATH = CPPPATH)
10+
11+
Return('group')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
* Copyright (c) 2006-2024 RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2024-11-20 zhujiale the first version
9+
*/
10+
#include <rtthread.h>
11+
#include <rtdevice.h>
12+
#include "utest.h"
13+
14+
static struct rt_serial_device* _serial0;
15+
static struct rt_spinlock lock;
16+
static int cnt = 0;
17+
18+
#define __REG32(x) (*((volatile unsigned int*)((rt_ubase_t)x)))
19+
#define UART_FR(base) __REG32(base + 0x18)
20+
#define UART_DR(base) __REG32(base + 0x00)
21+
#define UARTFR_TXFF 0x20
22+
23+
static rt_err_t utest_get_c(struct rt_serial_device* serial, char ch, void* data)
24+
{
25+
rt_atomic_add(&cnt, 1);
26+
return RT_EOK;
27+
}
28+
29+
static int utest_getc(struct rt_serial_device* serial)
30+
{
31+
static int num = 0;
32+
33+
rt_spin_lock(&lock);
34+
if (rt_atomic_load(&num) == 10)
35+
{
36+
rt_atomic_flag_clear(&num);
37+
rt_spin_unlock(&lock);
38+
return -1;
39+
}
40+
rt_atomic_add(&num, 1);
41+
rt_spin_unlock(&lock);
42+
return 'a';
43+
}
44+
45+
struct hw_uart_device
46+
{
47+
rt_size_t hw_base;
48+
rt_size_t irqno;
49+
};
50+
51+
static int uart_putc(struct rt_serial_device* serial, char c)
52+
{
53+
struct hw_uart_device* uart;
54+
55+
RT_ASSERT(serial != RT_NULL);
56+
uart = (struct hw_uart_device*)serial->parent.user_data;
57+
58+
while (UART_FR(uart->hw_base) & UARTFR_TXFF);
59+
UART_DR(uart->hw_base) = c;
60+
61+
return 1;
62+
}
63+
64+
static const struct rt_uart_ops _utest_ops =
65+
{
66+
RT_NULL,
67+
RT_NULL,
68+
uart_putc,
69+
utest_getc,
70+
};
71+
72+
73+
static void thread_rx1(void* parameter)
74+
{
75+
for (int i = 0; i < 10; i++)
76+
{
77+
rt_hw_serial_isr(_serial0, RT_SERIAL_EVENT_RX_IND);
78+
}
79+
}
80+
81+
static void thread_rx2(void* parameter)
82+
{
83+
for (int i = 0; i < 10; i++)
84+
{
85+
rt_workqueue_dowork(_serial0->bypass->lower_workq, &_serial0->bypass->work);
86+
}
87+
}
88+
89+
static void thread_high_priority(void* parameter)
90+
{
91+
for (int i = 1; i < 10; i++)
92+
{
93+
rt_bypass_upper_register(_serial0, "test", i, utest_get_c, RT_NULL);
94+
rt_bypass_upper_unregister(_serial0, i);
95+
}
96+
}
97+
98+
static void thread_low_priority(void* parameter)
99+
{
100+
for (int i = 0; i < 20; i++)
101+
{
102+
rt_hw_serial_isr(_serial0, RT_SERIAL_EVENT_RX_IND);
103+
}
104+
}
105+
106+
static void bypass_rx_stress_003(void)
107+
{
108+
const struct rt_uart_ops* tmp = _serial0->ops;
109+
110+
rt_thread_t high = rt_thread_create("high_prio", thread_high_priority, RT_NULL, 2048, 15, 10);
111+
rt_thread_t low = rt_thread_create("low_prio", thread_low_priority, RT_NULL, 2048, 20, 10);
112+
113+
rt_atomic_flag_clear(&cnt);
114+
_serial0->ops = &_utest_ops;
115+
rt_bypass_upper_register(_serial0, "test", 0, utest_get_c, RT_NULL);
116+
117+
rt_thread_startup(high);
118+
rt_thread_startup(low);
119+
120+
rt_thread_mdelay(1000);
121+
_serial0->ops = tmp;
122+
rt_bypass_upper_unregister(_serial0, 0);
123+
uassert_true(rt_atomic_load(&cnt) == 200);
124+
}
125+
126+
static void bypass_rx_stress_002(void)
127+
{
128+
const struct rt_uart_ops* tmp = _serial0->ops;
129+
rt_thread_t rx2 = rt_thread_create("rx2", thread_rx1, RT_NULL, 2048, RT_THREAD_PRIORITY_MAX - 5, 10);
130+
rt_thread_t rx3 = rt_thread_create("rx3", thread_rx2, RT_NULL, 2048, RT_THREAD_PRIORITY_MAX - 5, 10);
131+
132+
rt_atomic_flag_clear(&cnt);
133+
_serial0->ops = &_utest_ops;
134+
rt_bypass_lower_register(_serial0, "utest", 0, utest_get_c, RT_NULL);
135+
136+
rt_thread_startup(rx2);
137+
rt_thread_startup(rx3);
138+
139+
rt_thread_mdelay(1000);
140+
141+
uassert_true(rt_atomic_load(&cnt) == 100);
142+
_serial0->ops = tmp;
143+
rt_bypass_lower_unregister(_serial0, 0);
144+
}
145+
146+
static void bypass_rx_stress_001(void)
147+
{
148+
const struct rt_uart_ops* tmp = _serial0->ops;
149+
rt_thread_t rx1 = rt_thread_create("rx1", thread_rx1, RT_NULL, 2048, RT_THREAD_PRIORITY_MAX - 5, 10);
150+
rt_thread_t rx2 = rt_thread_create("rx1", thread_rx1, RT_NULL, 2048, RT_THREAD_PRIORITY_MAX - 5, 10);
151+
152+
cnt = 0;
153+
_serial0->ops = &_utest_ops;
154+
rt_bypass_upper_register(_serial0, "utest", 0, utest_get_c, RT_NULL);
155+
156+
rt_thread_startup(rx1);
157+
rt_thread_startup(rx2);
158+
159+
rt_thread_mdelay(1000);
160+
161+
uassert_true(rt_atomic_load(&cnt) == 200);
162+
_serial0->ops = tmp;
163+
rt_bypass_upper_unregister(_serial0, 0);
164+
}
165+
166+
static rt_err_t utest_tc_init(void)
167+
{
168+
_serial0 = (struct rt_serial_device*)rt_console_get_device();
169+
rt_spin_lock_init(&lock);
170+
return RT_EOK;
171+
}
172+
173+
static rt_err_t utest_tc_cleanup(void)
174+
{
175+
return RT_EOK;
176+
}
177+
178+
static void _testcase(void)
179+
{
180+
UTEST_UNIT_RUN(bypass_rx_stress_001);
181+
UTEST_UNIT_RUN(bypass_rx_stress_002);
182+
UTEST_UNIT_RUN(bypass_rx_stress_003);
183+
}
184+
185+
UTEST_TC_EXPORT(_testcase, "testcase.bypass.conflict.001", utest_tc_init, utest_tc_cleanup, 10);

0 commit comments

Comments
 (0)