summaryrefslogtreecommitdiff
path: root/components/drivers/serial/dev_serial.c
diff options
context:
space:
mode:
authorzhujiale <[email protected]>2024-11-20 10:04:53 +0800
committerRbb666 <[email protected]>2024-12-17 11:08:14 +0800
commit27cf024585bee854eb032b4240f1a2390a3c29d7 (patch)
tree14632d9251b8fc7c52e4845fb09ef90a8ad42bf1 /components/drivers/serial/dev_serial.c
parentc1166e0bf16aeda85e5facd01506973afcf6e8c6 (diff)
[serial] add bypass hook to direct processing char when uart irq coming
Diffstat (limited to 'components/drivers/serial/dev_serial.c')
-rw-r--r--components/drivers/serial/dev_serial.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/components/drivers/serial/dev_serial.c b/components/drivers/serial/dev_serial.c
index 19043e2ad2..3a78ca5195 100644
--- a/components/drivers/serial/dev_serial.c
+++ b/components/drivers/serial/dev_serial.c
@@ -27,6 +27,7 @@
* 2020-12-14 Meco Man implement function of setting window's size(TIOCSWINSZ)
* 2021-08-22 Meco Man implement function of getting window's size(TIOCGWINSZ)
* 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
+ * 2024-11-25 zhujiale add bypass mode
*/
#include <rthw.h>
@@ -303,6 +304,23 @@ rt_inline int _serial_int_rx(struct rt_serial_device *serial, rt_uint8_t *data,
rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx;
RT_ASSERT(rx_fifo != RT_NULL);
+#ifdef RT_USING_SERIAL_BYPASS
+ if (serial->bypass)
+ {
+ rt_bypass_work_straight(serial);
+ while (length)
+ {
+ rt_uint8_t ch;
+ if (!rt_bypass_getchar(serial, &ch))
+ break;
+
+ *data = ch & 0xff;
+ data++; length--;
+ }
+
+ return size - length;
+ }
+#endif
/* read from software FIFO */
while (length)
{
@@ -1410,13 +1428,33 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
while (1)
{
+ rt_bool_t skip = RT_FALSE;
ch = serial->ops->getc(serial);
if (ch == -1) break;
-
/* disable interrupt */
- level = rt_spin_lock_irqsave(&(serial->spinlock));
+#ifdef RT_USING_SERIAL_BYPASS
+ if (serial->bypass && serial->bypass->upper_h && (serial->bypass->upper_h->head.next != &serial->bypass->upper_h->head))
+ {
+ char buf = (char)ch;
+ int ret;
+ rt_list_t* node = serial->bypass->upper_h->head.next;
+ do {
+ struct rt_serial_bypass_func* bypass_run = rt_container_of(node, struct rt_serial_bypass_func, node);
+ ret = bypass_run->bypass(serial, buf, bypass_run->data);
+ if (!ret)
+ {
+ skip = RT_TRUE;
+ break;
+ }
+ node = node->next;
+ } while (node != &serial->bypass->upper_h->head);
+ }
+ if (skip)
+ continue;
+#endif
+ level = rt_spin_lock_irqsave(&(serial->spinlock));
rx_fifo->buffer[rx_fifo->put_index] = ch;
rx_fifo->put_index += 1;
if (rx_fifo->put_index >= serial->config.bufsz) rx_fifo->put_index = 0;
@@ -1435,6 +1473,11 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
rt_spin_unlock_irqrestore(&(serial->spinlock), level);
}
+#ifdef RT_USING_SERIAL_BYPASS
+ if (serial->bypass && serial->bypass->lower_h)
+ rt_workqueue_dowork(serial->bypass->lower_workq, &serial->bypass->work);
+#endif
+
/**
* Invoke callback.
* First try notify if any, and if notify is existed, rx_indicate()