Skip to content

Commit c4b7b67

Browse files
committed
[serial] add bypass hook to direct processing char when uart irq coming
1 parent 07c8b57 commit c4b7b67

File tree

6 files changed

+204
-2
lines changed

6 files changed

+204
-2
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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+
11+
#ifndef __RTT_BYPASS_H__
12+
#define __RTT_BYPASS_H__
13+
#include <rtthread.h>
14+
#include <rttypes.h>
15+
#include <rtdevice.h>
16+
typedef rt_err_t (*bypass_function_t)(struct rt_serial_device* serial, char buf);
17+
struct rt_serial_bypass {
18+
/*The function pointer of the bypassed data processing*/
19+
bypass_function_t bypass;
20+
21+
/*The smaller the array of levels, the higher the priority of execution*/
22+
rt_uint8_t level;
23+
#define RT_BYPASS_LEVEL_MAX 4
24+
#define RT_BYPASS_LEVEL_1 0
25+
#define RT_BYPASS_LEVEL_2 1
26+
#define RT_BYPASS_LEVEL_3 2
27+
#define RT_BYPASS_LEVEL_4 3
28+
#define BYPASS_FUNC_MAX_4 4
29+
rt_list_t list;
30+
char name[RT_NAME_MAX];
31+
};
32+
33+
rt_err_t rt_bypass_unregister(struct rt_serial_device* serial, rt_uint8_t level);
34+
rt_err_t rt_bypass_register(struct rt_serial_device* serial, const char* name, rt_uint8_t level, bypass_function_t func);
35+
36+
#endif

components/drivers/include/drivers/dev_serial.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ struct rt_serial_device
264264
void *serial_tx;
265265

266266
struct rt_spinlock spinlock;
267-
267+
struct rt_serial_bypass *bypass;
268268
struct rt_device_notify rx_notify;
269269
};
270270
typedef struct rt_serial_device rt_serial_t;

components/drivers/include/rtdevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ extern "C" {
9090
#include "drivers/dev_serial_v2.h"
9191
#else
9292
#include "drivers/dev_serial.h"
93+
#include "drivers/bypass.h"
9394
#endif
9495
#endif /* RT_USING_SERIAL */
9596

components/drivers/serial/SConscript

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ if GetDepend(['RT_USING_SERIAL_V2']):
1515
src += ['dev_serial_v2.c']
1616
else:
1717
src += ['dev_serial.c']
18+
src += ['bypass.c']
1819

1920
if GetDepend(['RT_USING_DM']):
2021
src += ['serial_dm.c']

components/drivers/serial/bypass.c

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
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+
11+
#include<rtdevice.h>
12+
#define DBG_TAG "UART"
13+
#define DBG_LVL DBG_INFO
14+
#include <rtdbg.h>
15+
static struct rt_serial_bypass *rt_bypass_alloc(const char* name, rt_uint8_t level,bypass_function_t func)
16+
{
17+
struct rt_serial_bypass* bypass;
18+
19+
if (!func)
20+
return RT_NULL;
21+
22+
bypass = rt_malloc(sizeof(struct rt_serial_bypass));
23+
rt_memset(bypass, 0, sizeof(struct rt_serial_bypass));
24+
25+
if (rt_strlen(name) > RT_NAME_MAX - 1)
26+
rt_memcpy(bypass->name, name, RT_NAME_MAX);
27+
else
28+
rt_memcpy(bypass->name, name, rt_strlen(name) + 1);
29+
30+
bypass->level = level;
31+
rt_list_init(&bypass->list);
32+
bypass->bypass = func;
33+
34+
return bypass;
35+
}
36+
37+
rt_err_t rt_bypass_register(struct rt_serial_device* serial, const char* name, rt_uint8_t level, bypass_function_t func)
38+
{
39+
struct rt_serial_bypass* bypass = RT_NULL;
40+
struct rt_list_node* node;
41+
int flags;
42+
43+
44+
bypass = rt_bypass_alloc(name, level, func);
45+
46+
RT_ASSERT(bypass != RT_NULL);
47+
48+
flags = rt_spin_lock_irqsave(&(serial->spinlock));
49+
if (!serial->bypass)
50+
{
51+
serial->bypass = bypass;
52+
rt_spin_unlock_irqrestore(&(serial->spinlock), flags);
53+
return RT_EOK;
54+
}
55+
56+
node = &serial->bypass->list;
57+
do {
58+
struct rt_serial_bypass* temp_curr = rt_container_of(node, struct rt_serial_bypass, list);
59+
60+
if (level < temp_curr->level)
61+
{
62+
rt_list_insert_before(node, &bypass->list);
63+
if (node == &serial->bypass->list)
64+
serial->bypass = bypass;
65+
66+
rt_spin_unlock_irqrestore(&(serial->spinlock), flags);
67+
return RT_EOK;
68+
} else if (level == temp_curr->level)
69+
{
70+
rt_spin_unlock_irqrestore(&(serial->spinlock), flags);
71+
LOG_E("Conflict: bypass [%s] level conflicts with [%s] at level [%d]\n", name, temp_curr->name, level);
72+
rt_free(bypass);
73+
return -RT_ERROR;
74+
}
75+
76+
node = node -> next;
77+
78+
} while (node != &serial->bypass->list);
79+
80+
rt_list_insert_before(&serial->bypass->list, &bypass->list);
81+
82+
rt_spin_unlock_irqrestore(&(serial->spinlock), flags);
83+
return RT_EOK;
84+
85+
}
86+
87+
rt_err_t rt_bypass_unregister(struct rt_serial_device* serial, rt_uint8_t level)
88+
{
89+
struct rt_list_node* node;
90+
struct rt_serial_bypass* temp_curr = RT_NULL;
91+
int flags;
92+
93+
if (!serial->bypass)
94+
return -RT_ERROR;
95+
96+
node = &serial->bypass->list;
97+
98+
flags = rt_spin_lock_irqsave(&(serial->spinlock));
99+
100+
do {
101+
temp_curr = rt_container_of(node, struct rt_serial_bypass, list);
102+
if (level == temp_curr->level)
103+
{
104+
if (&temp_curr->list == &serial->bypass->list)
105+
{
106+
if (node->next != &serial->bypass->list)
107+
{
108+
struct rt_serial_bypass* temp_next = rt_container_of(node->next, struct rt_serial_bypass, list);
109+
serial->bypass = temp_next;
110+
} else {
111+
serial->bypass = RT_NULL;
112+
}
113+
114+
}
115+
rt_list_remove(node);
116+
rt_spin_unlock_irqrestore(&(serial->spinlock), flags);
117+
rt_free(temp_curr);
118+
return RT_EOK;
119+
}
120+
node = node -> next;
121+
} while (node != &serial->bypass->list);
122+
123+
LOG_E("Can't find bypass with level [%d]", flags);
124+
rt_spin_unlock_irqrestore(&(serial->spinlock), flags);
125+
return -RT_ERROR;
126+
}
127+
128+
int serial_bypass_list(int argc, char** argv)
129+
{
130+
struct rt_serial_device* serial;
131+
struct rt_serial_bypass* temp_curr = RT_NULL;
132+
serial = (struct rt_serial_device*)rt_console_get_device();
133+
if (!serial->bypass)
134+
{
135+
rt_kprintf("There is no bypass registered\n");
136+
return 0;
137+
}
138+
139+
rt_list_t* node = &serial->bypass->list;
140+
141+
do {
142+
temp_curr = rt_container_of(node, struct rt_serial_bypass, list);
143+
rt_kprintf("The bypass of this serial name: [%s] level: [%d]\n", temp_curr->name, temp_curr->level);
144+
node = node->next;
145+
} while (node != &serial->bypass->list);
146+
147+
return 0;
148+
149+
}
150+
MSH_CMD_EXPORT(serial_bypass_list, serial bypass list)

components/drivers/serial/dev_serial.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1413,10 +1413,24 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
14131413
ch = serial->ops->getc(serial);
14141414
if (ch == -1) break;
14151415

1416-
14171416
/* disable interrupt */
14181417
level = rt_spin_lock_irqsave(&(serial->spinlock));
14191418

1419+
if (serial->bypass)
1420+
{
1421+
char buf = (char)ch;
1422+
ssize_t size = 0;
1423+
int ret;
1424+
rt_list_t* node = &serial->bypass->list;
1425+
do {
1426+
struct rt_serial_bypass *bypass_run= rt_container_of(node, struct rt_serial_bypass, list);
1427+
ret = bypass_run->bypass(serial, buf);
1428+
if (!ret)
1429+
return;
1430+
node = node->next;
1431+
} while (node != &serial->bypass->list);
1432+
}
1433+
14201434
rx_fifo->buffer[rx_fifo->put_index] = ch;
14211435
rx_fifo->put_index += 1;
14221436
if (rx_fifo->put_index >= serial->config.bufsz) rx_fifo->put_index = 0;

0 commit comments

Comments
 (0)