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