From 5f2a7787aaf9f447d1b56945ddf570a307169473 Mon Sep 17 00:00:00 2001 From: Kamil Kasperczyk Date: Thu, 16 Jul 2020 15:20:33 +0200 Subject: [PATCH] net: openthread: platform: Removed double-buffering in UART send. Putting data to local buffer before transmission was removed to optimize operation. Local buffering was not needed, as passed buffer cannot be modified until sending is finished. Signed-off-by: Kamil Kasperczyk kamil.kasperczyk@nordicsemi.no --- .../lib/openthread/platform/platform-zephyr.h | 6 ++ subsys/net/lib/openthread/platform/uart.c | 84 ++++++++++++++----- 2 files changed, 67 insertions(+), 23 deletions(-) diff --git a/subsys/net/lib/openthread/platform/platform-zephyr.h b/subsys/net/lib/openthread/platform/platform-zephyr.h index f09a2d15f0788a..e1a5ca6d3cabc7 100644 --- a/subsys/net/lib/openthread/platform/platform-zephyr.h +++ b/subsys/net/lib/openthread/platform/platform-zephyr.h @@ -54,6 +54,12 @@ void platformRadioProcess(otInstance *aInstance); */ void platformUartProcess(otInstance *aInstance); +/** + * Outer component calls this method to notify UART driver that it should + * switch to panic mode and work in synchronous way. + */ +void platformUartPanic(void); + /** * Get current channel from radio driver. * diff --git a/subsys/net/lib/openthread/platform/uart.c b/subsys/net/lib/openthread/platform/uart.c index 86ca768409ba5e..c46be97d87df5f 100644 --- a/subsys/net/lib/openthread/platform/uart.c +++ b/subsys/net/lib/openthread/platform/uart.c @@ -29,7 +29,6 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include "platform-zephyr.h" struct openthread_uart { - struct ring_buf *tx_ringbuf; struct ring_buf *rx_ringbuf; struct device *dev; atomic_t tx_busy; @@ -37,10 +36,8 @@ struct openthread_uart { }; #define OT_UART_DEFINE(_name, _ringbuf_size) \ - RING_BUF_DECLARE(_name##_tx_ringbuf, _ringbuf_size); \ RING_BUF_DECLARE(_name##_rx_ringbuf, _ringbuf_size); \ static struct openthread_uart _name = { \ - .tx_ringbuf = &_name##_tx_ringbuf, \ .rx_ringbuf = &_name##_rx_ringbuf, \ } @@ -48,6 +45,10 @@ OT_UART_DEFINE(ot_uart, CONFIG_OPENTHREAD_NCP_UART_RING_BUFFER_SIZE); #define RX_FIFO_SIZE 128 +static bool is_panic_mode; +static const uint8_t *s_write_buffer = NULL; +static uint16_t s_write_length = 0; + static void uart_rx_handle(void) { u8_t *data; @@ -90,17 +91,11 @@ static void uart_rx_handle(void) static void uart_tx_handle(void) { u32_t len; - const u8_t *data; - - len = ring_buf_get_claim(ot_uart.tx_ringbuf, (u8_t **)&data, - ot_uart.tx_ringbuf->size); - if (len) { - int err; - len = uart_fifo_fill(ot_uart.dev, data, len); - err = ring_buf_get_finish(ot_uart.tx_ringbuf, len); - (void)err; - __ASSERT_NO_MSG(err == 0); + if (s_write_length) { + len = uart_fifo_fill(ot_uart.dev, s_write_buffer, s_write_length); + s_write_buffer += len; + s_write_length -= len; } else { uart_irq_tx_disable(ot_uart.dev); ot_uart.tx_busy = 0; @@ -197,23 +192,66 @@ otError otPlatUartEnable(void) otError otPlatUartDisable(void) { - /* TODO: uninit UART */ - LOG_WRN("%s not implemented.", __func__); - return OT_ERROR_NOT_IMPLEMENTED; +#ifdef CONFIG_OPENTHREAD_NCP_SPINEL_ON_UART_ACM + int ret = usb_disable(); + + if (ret) { + LOG_WRN("Failed to disable USB, ret code %d", ret); + } +#endif + + uart_irq_tx_disable(ot_uart.dev); + uart_irq_rx_disable(ot_uart.dev); + return OT_ERROR_NONE; }; otError otPlatUartSend(const u8_t *aBuf, u16_t aBufLength) { - size_t cnt = ring_buf_put(ot_uart.tx_ringbuf, aBuf, aBufLength); + if (NULL == aBuf) { + return OT_ERROR_FAILED; + } + + s_write_buffer = aBuf; + s_write_length = aBufLength; if (atomic_set(&(ot_uart.tx_busy), 1) == 0) { - uart_irq_tx_enable(ot_uart.dev); + if (is_panic_mode) { + /* In panic mode all data have to be send immediately + * without using interrupts + */ + otPlatUartFlush(); + } else { + uart_irq_tx_enable(ot_uart.dev); + } } - if (cnt == aBufLength) { - return OT_ERROR_NONE; - } else { - return OT_ERROR_BUSY; - } + return OT_ERROR_NONE; }; + +otError otPlatUartFlush(void) +{ + u32_t len; + otError result = OT_ERROR_NONE; + + if (s_write_length) { + for (size_t i = 0; i < len; i++) { + uart_poll_out(ot_uart.dev, s_write_buffer+i); + } + } + + ot_uart.tx_busy = 0; + atomic_set(&(ot_uart.tx_finished), 1); + otSysEventSignalPending(); + return result; +} + +void platformUartPanic(void) +{ + is_panic_mode = true; + /* In panic mode data are send without using interrupts. + * Reception in this mode is not supported. + */ + uart_irq_tx_disable(ot_uart.dev); + uart_irq_rx_disable(ot_uart.dev); +}