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); +}