1 /*
2 * Copyright (c) 2020 Tridonic GmbH & Co KG
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define LOG_LEVEL CONFIG_OPENTHREAD_LOG_LEVEL
8 #define LOG_MODULE_NAME net_otPlat_uart
9
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
12
13 #include <zephyr/kernel.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16
17 #include <zephyr/drivers/uart.h>
18
19 #include <zephyr/sys/ring_buffer.h>
20 #include <zephyr/sys/atomic.h>
21
22 #include <zephyr/usb/usb_device.h>
23
24 #include <openthread/ncp.h>
25 #include <openthread-system.h>
26 #include <utils/uart.h>
27
28 #include "platform-zephyr.h"
29
30 struct openthread_uart {
31 struct ring_buf *rx_ringbuf;
32 const struct device *dev;
33 atomic_t tx_busy;
34 atomic_t tx_finished;
35 };
36
37 #define OT_UART_DEFINE(_name, _ringbuf_size) \
38 RING_BUF_DECLARE(_name##_rx_ringbuf, _ringbuf_size); \
39 static struct openthread_uart _name = { \
40 .rx_ringbuf = &_name##_rx_ringbuf, \
41 }
42
43 OT_UART_DEFINE(ot_uart, CONFIG_OPENTHREAD_COPROCESSOR_UART_RING_BUFFER_SIZE);
44
45 #define RX_FIFO_SIZE 128
46
47 static bool is_panic_mode;
48 static const uint8_t *write_buffer;
49 static uint16_t write_length;
50
uart_rx_handle(const struct device * dev)51 static void uart_rx_handle(const struct device *dev)
52 {
53 uint8_t *data;
54 uint32_t len;
55 uint32_t rd_len;
56 bool new_data = false;
57
58 do {
59 len = ring_buf_put_claim(
60 ot_uart.rx_ringbuf, &data,
61 ot_uart.rx_ringbuf->size);
62 if (len > 0) {
63 rd_len = uart_fifo_read(dev, data, len);
64 if (rd_len > 0) {
65 new_data = true;
66 }
67
68 int err = ring_buf_put_finish(
69 ot_uart.rx_ringbuf, rd_len);
70 (void)err;
71 __ASSERT_NO_MSG(err == 0);
72 } else {
73 uint8_t dummy;
74
75 /* No space in the ring buffer - consume byte. */
76 LOG_WRN("RX ring buffer full.");
77
78 rd_len = uart_fifo_read(dev, &dummy, 1);
79 }
80 } while (rd_len && (rd_len == len));
81
82 if (new_data) {
83 otSysEventSignalPending();
84 }
85 }
86
uart_tx_handle(const struct device * dev)87 static void uart_tx_handle(const struct device *dev)
88 {
89 uint32_t len;
90
91 if (write_length) {
92 len = uart_fifo_fill(dev, write_buffer, write_length);
93 write_buffer += len;
94 write_length -= len;
95 } else {
96 uart_irq_tx_disable(dev);
97 ot_uart.tx_busy = 0;
98 atomic_set(&(ot_uart.tx_finished), 1);
99 otSysEventSignalPending();
100 }
101 }
102
uart_callback(const struct device * dev,void * user_data)103 static void uart_callback(const struct device *dev, void *user_data)
104 {
105 ARG_UNUSED(user_data);
106
107 while (uart_irq_update(dev) && uart_irq_is_pending(dev)) {
108
109 if (uart_irq_rx_ready(dev)) {
110 uart_rx_handle(dev);
111 }
112
113 if (uart_irq_tx_ready(dev) &&
114 atomic_get(&ot_uart.tx_busy) == 1) {
115 uart_tx_handle(dev);
116 }
117 }
118 }
119
otPlatUartReceived(const uint8_t * aBuf,uint16_t aBufLength)120 void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength)
121 {
122 otNcpHdlcReceive(aBuf, aBufLength);
123 }
124
otPlatUartSendDone(void)125 void otPlatUartSendDone(void)
126 {
127 otNcpHdlcSendDone();
128 }
129
platformUartProcess(otInstance * aInstance)130 void platformUartProcess(otInstance *aInstance)
131 {
132 uint32_t len = 0;
133 const uint8_t *data;
134
135 /* Process UART RX */
136 while ((len = ring_buf_get_claim(
137 ot_uart.rx_ringbuf,
138 (uint8_t **)&data,
139 ot_uart.rx_ringbuf->size)) > 0) {
140 int err;
141
142 otPlatUartReceived(data, len);
143 err = ring_buf_get_finish(
144 ot_uart.rx_ringbuf,
145 len);
146 (void)err;
147 __ASSERT_NO_MSG(err == 0);
148 }
149
150 /* Process UART TX */
151 if (ot_uart.tx_finished) {
152 LOG_DBG("UART TX done");
153 otPlatUartSendDone();
154 ot_uart.tx_finished = 0;
155 }
156 }
157
otPlatUartEnable(void)158 otError otPlatUartEnable(void)
159 {
160 ot_uart.dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_ot_uart));
161
162 if (!device_is_ready(ot_uart.dev)) {
163 LOG_ERR("UART device not ready");
164 return OT_ERROR_FAILED;
165 }
166
167 uart_irq_callback_user_data_set(ot_uart.dev,
168 uart_callback,
169 (void *)&ot_uart);
170
171 if (DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_ot_uart), zephyr_cdc_acm_uart)) {
172 int ret;
173 uint32_t dtr = 0U;
174
175 ret = usb_enable(NULL);
176 if (ret != 0 && ret != -EALREADY) {
177 LOG_ERR("Failed to enable USB");
178 return OT_ERROR_FAILED;
179 }
180
181 LOG_INF("Waiting for host to be ready to communicate");
182
183 /* Data Terminal Ready - check if host is ready to communicate */
184 while (!dtr) {
185 ret = uart_line_ctrl_get(ot_uart.dev,
186 UART_LINE_CTRL_DTR, &dtr);
187 if (ret) {
188 LOG_ERR("Failed to get Data Terminal Ready line state: %d",
189 ret);
190 continue;
191 }
192 k_msleep(100);
193 }
194
195 /* Data Carrier Detect Modem - mark connection as established */
196 (void)uart_line_ctrl_set(ot_uart.dev, UART_LINE_CTRL_DCD, 1);
197 /* Data Set Ready - the NCP SoC is ready to communicate */
198 (void)uart_line_ctrl_set(ot_uart.dev, UART_LINE_CTRL_DSR, 1);
199 }
200
201 uart_irq_rx_enable(ot_uart.dev);
202
203 return OT_ERROR_NONE;
204 }
205
otPlatUartDisable(void)206 otError otPlatUartDisable(void)
207 {
208 if (DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_ot_uart), zephyr_cdc_acm_uart)) {
209 int ret = usb_disable();
210
211 if (ret) {
212 LOG_WRN("Failed to disable USB (%d)", ret);
213 }
214 }
215
216 uart_irq_tx_disable(ot_uart.dev);
217 uart_irq_rx_disable(ot_uart.dev);
218 return OT_ERROR_NONE;
219 }
220
otPlatUartSend(const uint8_t * aBuf,uint16_t aBufLength)221 otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
222 {
223 if (aBuf == NULL) {
224 return OT_ERROR_FAILED;
225 }
226
227 if (atomic_cas(&(ot_uart.tx_busy), 0, 1)) {
228 write_buffer = aBuf;
229 write_length = aBufLength;
230
231 if (is_panic_mode) {
232 /* In panic mode all data have to be send immediately
233 * without using interrupts
234 */
235 otPlatUartFlush();
236 } else {
237 uart_irq_tx_enable(ot_uart.dev);
238 }
239 return OT_ERROR_NONE;
240 }
241
242 return OT_ERROR_BUSY;
243 }
244
otPlatUartFlush(void)245 otError otPlatUartFlush(void)
246 {
247 otError result = OT_ERROR_NONE;
248
249 if (write_length) {
250 for (size_t i = 0; i < write_length; i++) {
251 uart_poll_out(ot_uart.dev, *(write_buffer+i));
252 }
253 }
254
255 ot_uart.tx_busy = 0;
256 atomic_set(&(ot_uart.tx_finished), 1);
257 otSysEventSignalPending();
258 return result;
259 }
260
platformUartPanic(void)261 void platformUartPanic(void)
262 {
263 is_panic_mode = true;
264 /* In panic mode data are send without using interrupts.
265 * Reception in this mode is not supported.
266 */
267 uart_irq_tx_disable(ot_uart.dev);
268 uart_irq_rx_disable(ot_uart.dev);
269 }
270