Skip to content

Commit fabe118

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

File tree

13 files changed

+591
-71
lines changed

13 files changed

+591
-71
lines changed

components/drivers/include/rtdevice.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ extern "C" {
9191
#else
9292
#include "drivers/dev_serial.h"
9393
#ifdef RT_USING_SERIAL_BYPASS
94-
#include "drivers/bypass.h"
94+
#include "drivers/serial_bypass.h"
9595
#endif /* RT_USING_SERIAL_BYPASS */
9696
#endif
9797
#endif /* RT_USING_SERIAL */

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

+5-14
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;
@@ -1478,17 +1479,7 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
14781479
rt_workqueue_dowork(serial->bypass->lower_workq, &serial->bypass->work);
14791480
#endif
14801481

1481-
/**
1482-
* Invoke callback.
1483-
* First try notify if any, and if notify is existed, rx_indicate()
1484-
* is not callback. This separate the priority and makes the reuse
1485-
* of same serial device reasonable for RT console.
1486-
*/
1487-
if (serial->rx_notify.notify)
1488-
{
1489-
serial->rx_notify.notify(serial->rx_notify.dev);
1490-
}
1491-
else if (serial->parent.rx_indicate != RT_NULL)
1482+
if (serial->parent.rx_indicate != RT_NULL)
14921483
{
14931484
rt_size_t rx_length;
14941485

components/drivers/serial/serial_tty.c

+1-55
Original file line numberDiff line numberDiff line change
@@ -114,47 +114,6 @@ static void _setup_debug_rxind_hook(void)
114114

115115
#endif /* LWP_DEBUG_INIT */
116116

117-
static void _tty_rx_notify(struct rt_device *device)
118-
{
119-
lwp_tty_t tp;
120-
struct serial_tty_context *softc;
121-
122-
tp = rt_container_of(device, struct lwp_tty, parent);
123-
RT_ASSERT(tp);
124-
125-
softc = tty_softc(tp);
126-
127-
if (_ttyworkq)
128-
rt_workqueue_submit_work(_ttyworkq, &softc->work, 0);
129-
}
130-
131-
static void _tty_rx_worker(struct rt_work *work, void *data)
132-
{
133-
char input;
134-
rt_ssize_t readbytes;
135-
lwp_tty_t tp = data;
136-
struct serial_tty_context *softc;
137-
struct rt_serial_device *serial;
138-
139-
tty_lock(tp);
140-
141-
while (1)
142-
{
143-
softc = tty_softc(tp);
144-
serial = softc->parent;
145-
readbytes = rt_device_read(&serial->parent, -1, &input, 1);
146-
if (readbytes != 1)
147-
{
148-
break;
149-
}
150-
151-
ttydisc_rint(tp, input, 0);
152-
}
153-
154-
ttydisc_rint_done(tp);
155-
tty_unlock(tp);
156-
}
157-
#ifdef RT_USING_SERIAL_BYPASS
158117
static rt_err_t _serial_ty_bypass(struct rt_serial_device* serial, char ch,void *data)
159118
{
160119
lwp_tty_t tp;
@@ -168,23 +127,11 @@ static rt_err_t _serial_ty_bypass(struct rt_serial_device* serial, char ch,void
168127
return RT_EOK;
169128

170129
}
171-
#endif
130+
172131
rt_inline void _setup_serial(struct rt_serial_device* serial, lwp_tty_t tp,
173132
struct serial_tty_context *softc)
174133
{
175-
#ifndef RT_USING_SERIAL_BYPASS
176-
struct rt_device_notify notify;
177-
178-
softc->backup_notify = serial->rx_notify;
179-
notify.dev = &tp->parent;
180-
notify.notify = _tty_rx_notify;
181-
182-
rt_device_init(&serial->parent);
183-
184-
rt_device_control(&serial->parent, RT_DEVICE_CTRL_NOTIFY_SET, &notify);
185-
#else
186134
rt_bypass_lower_register(serial, "tty",RT_BYPASS_PROTECT_LEVEL_1, _serial_ty_bypass,(void *)tp);
187-
#endif
188135
}
189136

190137
rt_inline void _restore_serial(struct rt_serial_device *serial, lwp_tty_t tp,
@@ -363,7 +310,6 @@ rt_err_t rt_hw_serial_register_tty(struct rt_serial_device *serial)
363310
{
364311
_serial_tty_set_speed(tty);
365312
rc = lwp_tty_register(tty, dev_name);
366-
rt_work_init(&softc->work, _tty_rx_worker, tty);
367313

368314
if (rc != RT_EOK)
369315
{

components/lwp/terminal/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ menuconfig LWP_USING_TERMINAL
22
bool "Terminal I/O Subsystem"
33
depends on RT_USING_SMART
44
default y
5+
select RT_USING_SERIAL_BYPASS
56

67
if LWP_USING_TERMINAL
78
config LWP_PTY_MAX_PARIS_LIMIT

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)