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 
174 		ret = usb_enable(NULL);
175 		if (ret != 0 && ret != -EALREADY) {
176 			LOG_ERR("Failed to enable USB");
177 			return OT_ERROR_FAILED;
178 		}
179 
180 		/* Data Carrier Detect Modem - mark connection as established */
181 		(void)uart_line_ctrl_set(ot_uart.dev, UART_LINE_CTRL_DCD, 1);
182 		/* Data Set Ready - the NCP SoC is ready to communicate */
183 		(void)uart_line_ctrl_set(ot_uart.dev, UART_LINE_CTRL_DSR, 1);
184 	}
185 
186 	uart_irq_rx_enable(ot_uart.dev);
187 
188 	return OT_ERROR_NONE;
189 }
190 
otPlatUartDisable(void)191 otError otPlatUartDisable(void)
192 {
193 	if (DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_ot_uart), zephyr_cdc_acm_uart)) {
194 		int ret = usb_disable();
195 
196 		if (ret) {
197 			LOG_WRN("Failed to disable USB (%d)", ret);
198 		}
199 	}
200 
201 	uart_irq_tx_disable(ot_uart.dev);
202 	uart_irq_rx_disable(ot_uart.dev);
203 	return OT_ERROR_NONE;
204 }
205 
otPlatUartSend(const uint8_t * aBuf,uint16_t aBufLength)206 otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
207 {
208 	if (aBuf == NULL) {
209 		return OT_ERROR_FAILED;
210 	}
211 
212 	if (atomic_cas(&(ot_uart.tx_busy), 0, 1)) {
213 		write_buffer = aBuf;
214 		write_length = aBufLength;
215 
216 		if (is_panic_mode) {
217 			/* In panic mode all data have to be send immediately
218 			 * without using interrupts
219 			 */
220 			otPlatUartFlush();
221 		} else {
222 			uart_irq_tx_enable(ot_uart.dev);
223 		}
224 		return OT_ERROR_NONE;
225 	}
226 
227 	return OT_ERROR_BUSY;
228 }
229 
otPlatUartFlush(void)230 otError otPlatUartFlush(void)
231 {
232 	otError result = OT_ERROR_NONE;
233 
234 	if (write_length) {
235 		for (size_t i = 0; i < write_length; i++) {
236 			uart_poll_out(ot_uart.dev, *(write_buffer+i));
237 		}
238 	}
239 
240 	ot_uart.tx_busy = 0;
241 	atomic_set(&(ot_uart.tx_finished), 1);
242 	otSysEventSignalPending();
243 	return result;
244 }
245 
platformUartPanic(void)246 void platformUartPanic(void)
247 {
248 	is_panic_mode = true;
249 	/* In panic mode data are send without using interrupts.
250 	 * Reception in this mode is not supported.
251 	 */
252 	uart_irq_tx_disable(ot_uart.dev);
253 	uart_irq_rx_disable(ot_uart.dev);
254 }
255