1 /** @file
2 * @brief Pipe UART driver
3 *
4 * A pipe UART driver allowing application to handle all aspects of received
5 * protocol data.
6 */
7
8 /*
9 * Copyright (c) 2015 Intel Corporation
10 *
11 * SPDX-License-Identifier: Apache-2.0
12 */
13
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(uart_pipe);
16
17 #include <zephyr/kernel.h>
18
19 #include <zephyr/drivers/uart.h>
20
21 #include <zephyr/drivers/uart_pipe.h>
22 #include <zephyr/sys/printk.h>
23
24 static const struct device *const uart_pipe_dev =
25 DEVICE_DT_GET(DT_CHOSEN(zephyr_uart_pipe));
26
27 static uint8_t *recv_buf;
28 static size_t recv_buf_len;
29 static uart_pipe_recv_cb app_cb;
30 static size_t recv_off;
31
uart_pipe_rx(const struct device * dev)32 static void uart_pipe_rx(const struct device *dev)
33 {
34 /* As per the API, the interrupt may be an edge so keep
35 * reading from the FIFO until it's empty.
36 */
37 for (;;) {
38 int avail = recv_buf_len - recv_off;
39 int got;
40
41 got = uart_fifo_read(uart_pipe_dev, recv_buf + recv_off, avail);
42 if (got <= 0) {
43 break;
44 }
45
46 LOG_HEXDUMP_DBG(recv_buf + recv_off, got, "RX");
47
48 /*
49 * Call application callback with received data. Application
50 * may provide new buffer or alter data offset.
51 */
52 recv_off += got;
53 recv_buf = app_cb(recv_buf, &recv_off);
54 }
55 }
56
uart_pipe_isr(const struct device * dev,void * user_data)57 static void uart_pipe_isr(const struct device *dev, void *user_data)
58 {
59 ARG_UNUSED(user_data);
60
61 uart_irq_update(dev);
62
63 if (uart_irq_rx_ready(dev)) {
64 uart_pipe_rx(dev);
65 }
66 }
67
uart_pipe_send(const uint8_t * data,int len)68 int uart_pipe_send(const uint8_t *data, int len)
69 {
70 LOG_HEXDUMP_DBG(data, len, "TX");
71
72 while (len--) {
73 uart_poll_out(uart_pipe_dev, *data++);
74 }
75
76 return 0;
77 }
78
uart_pipe_setup(const struct device * uart)79 static void uart_pipe_setup(const struct device *uart)
80 {
81 uint8_t c;
82
83 uart_irq_rx_disable(uart);
84 uart_irq_tx_disable(uart);
85
86 /* Drain the fifo */
87 while (uart_fifo_read(uart, &c, 1)) {
88 continue;
89 }
90
91 uart_irq_callback_set(uart, uart_pipe_isr);
92
93 uart_irq_rx_enable(uart);
94 }
95
uart_pipe_register(uint8_t * buf,size_t len,uart_pipe_recv_cb cb)96 void uart_pipe_register(uint8_t *buf, size_t len, uart_pipe_recv_cb cb)
97 {
98 recv_buf = buf;
99 recv_buf_len = len;
100 app_cb = cb;
101
102 if (device_is_ready(uart_pipe_dev)) {
103 uart_pipe_setup(uart_pipe_dev);
104 }
105 }
106