diff --git a/CODEOWNERS b/CODEOWNERS index 576326c014b..03b912c2156 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -151,6 +151,8 @@ /drivers/serial/*ns16550* @gnuless /drivers/serial/Kconfig.litex @mateusz-holenko @kgugala @pgielda /drivers/serial/uart_liteuart.c @mateusz-holenko @kgugala @pgielda +/drivers/serial/Kconfig.rtt @carlescufi @pkral78 +/drivers/serial/uart_rtt.c @carlescufi @pkral78 /drivers/net/ @jukkar @tbursztyka /drivers/ptp_clock/ @jukkar /drivers/spi/ @tbursztyka diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index 7473c519b3a..6f38414ec7e 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -29,6 +29,7 @@ zephyr_library_sources_if_kconfig(uart_psoc6.c) zephyr_library_sources_if_kconfig(uart_pl011.c) zephyr_library_sources_if_kconfig(uart_rv32m1_lpuart.c) zephyr_library_sources_if_kconfig(uart_liteuart.c) +zephyr_library_sources_ifdef(CONFIG_UART_RTT_DRIVER uart_rtt.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE uart_handlers.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index bb530621cf6..a93fcd98c16 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -125,4 +125,6 @@ source "drivers/serial/Kconfig.rv32m1_lpuart" source "drivers/serial/Kconfig.litex" +source "drivers/serial/Kconfig.rtt" + endif # SERIAL diff --git a/drivers/serial/Kconfig.rtt b/drivers/serial/Kconfig.rtt new file mode 100644 index 00000000000..182d8094d05 --- /dev/null +++ b/drivers/serial/Kconfig.rtt @@ -0,0 +1,105 @@ +# Kconfig - Virtual UART RTT driver option +# +# Copyright (c) 2019 omSquare s.r.o. +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig UART_RTT + bool "Enable UART RTT driver" + depends on USE_SEGGER_RTT + help + This option enables access RTT channel as UART device. + +if UART_RTT + +config UART_RTT_0 + bool "Enable UART on RTT channel 0" + depends on SEGGER_RTT_MAX_NUM_UP_BUFFERS >= 1 && SEGGER_RTT_MAX_NUM_DOWN_BUFFERS >= 1 + depends on SEGGER_RTT_MODE_NO_BLOCK_SKIP + select SERIAL_HAS_DRIVER + select UART_RTT_DRIVER + help + Enable UART on (default) RTT channel 0. Default channel has to be configured in non-blocking skip mode. + +config UART_RTT_1 + bool "Enable UART on RTT channel 1" + depends on SEGGER_RTT_MAX_NUM_UP_BUFFERS >= 2 && SEGGER_RTT_MAX_NUM_DOWN_BUFFERS >= 2 + select SERIAL_HAS_DRIVER + select UART_RTT_DRIVER + help + Enable UART on RTT channel 1 + +if UART_RTT_1 + +config UART_RTT_1_TX_BUFFER_SIZE + int "Size of RTT_1 TX buffer (up to host)" + range 1 65535 + default 1024 + help + Size of the RTT up buffer for UART 1 transmission. + +config UART_RTT_1_RX_BUFFER_SIZE + int "Size of RTT_1 RX buffer (down from host)" + range 1 65535 + default 16 + help + Size of the RTT down buffer for UART 1 reception. + +endif + +config UART_RTT_2 + bool "Enable UART on RTT channel 2" + depends on SEGGER_RTT_MAX_NUM_UP_BUFFERS >= 3 && SEGGER_RTT_MAX_NUM_DOWN_BUFFERS >= 3 + select SERIAL_HAS_DRIVER + select UART_RTT_DRIVER + help + Enable UART on RTT channel 2 + +if UART_RTT_2 + +config UART_RTT_2_TX_BUFFER_SIZE + int "Size of RTT_2 TX buffer (up to host)" + range 1 65535 + default 1024 + help + Size of the RTT up buffer for UART 2 transmission. + +config UART_RTT_2_RX_BUFFER_SIZE + int "Size of RTT_2 RX buffer (down from host)" + range 1 65535 + default 16 + help + Size of the RTT down buffer for UART 2 reception. + +endif + +config UART_RTT_3 + bool "Enable UART on RTT channel 3" + depends on SEGGER_RTT_MAX_NUM_UP_BUFFERS >= 4 && SEGGER_RTT_MAX_NUM_DOWN_BUFFERS >= 4 + select SERIAL_HAS_DRIVER + select UART_RTT_DRIVER + help + Enable UART on RTT channel 3 + +if UART_RTT_3 + +config UART_RTT_3_TX_BUFFER_SIZE + int "Size of RTT_3 TX buffer (up to host)" + range 1 65535 + default 1024 + help + Size of the RTT up buffer for UART 3 transmission. + +config UART_RTT_3_RX_BUFFER_SIZE + int "Size of RTT_3 RX buffer (down from host)" + range 1 65535 + default 16 + help + Size of the RTT down buffer for UART 3 reception. + +endif + +config UART_RTT_DRIVER + bool + +endif diff --git a/drivers/serial/uart_rtt.c b/drivers/serial/uart_rtt.c new file mode 100644 index 00000000000..de628295f08 --- /dev/null +++ b/drivers/serial/uart_rtt.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2019 omSquare s.r.o. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +struct uart_rtt_config { + void *up_buffer; + size_t up_size; + void *down_buffer; + size_t down_size; + u8_t channel; +}; + +static inline const struct uart_rtt_config *get_dev_config(struct device *dev) +{ + return dev->config->config_info; +} + +static int uart_rtt_init(struct device *dev) +{ + /* + * Channel 0 is initialized at compile-time, Kconfig ensures that + * it is configured in correct, non-blocking mode. Other channels + * need to be configured at run-time. + */ + if (get_dev_config(dev)) { + const struct uart_rtt_config *cfg = get_dev_config(dev); + + SEGGER_RTT_ConfigUpBuffer(cfg->channel, dev->config->name, + cfg->up_buffer, cfg->up_size, + SEGGER_RTT_MODE_NO_BLOCK_SKIP); + SEGGER_RTT_ConfigDownBuffer(cfg->channel, dev->config->name, + cfg->down_buffer, cfg->down_size, + SEGGER_RTT_MODE_NO_BLOCK_SKIP); + } + return 0; +} + +/** + * @brief Poll the device for input. + * + * @param dev UART device struct + * @param c Pointer to character + * + * @return 0 if a character arrived, -1 if the input buffer if empty. + */ + +static int uart_rtt_poll_in(struct device *dev, unsigned char *c) +{ + unsigned int ch = + get_dev_config(dev) ? get_dev_config(dev)->channel : 0; + unsigned int ret = SEGGER_RTT_Read(ch, c, 1); + + return ret ? 0 : -1; +} + +/** + * @brief Output a character in polled mode. + * + * @param dev UART device struct + * @param c Character to send + */ +static void uart_rtt_poll_out(struct device *dev, unsigned char c) +{ + unsigned int ch = + get_dev_config(dev) ? get_dev_config(dev)->channel : 0; + + SEGGER_RTT_Write(ch, &c, 1); +} + +static const struct uart_driver_api uart_rtt_driver_api = { + .poll_in = uart_rtt_poll_in, + .poll_out = uart_rtt_poll_out, +}; + +#if CONFIG_UART_RTT_0 + +DEVICE_DEFINE(uart_rtt0, "RTT_0", uart_rtt_init, NULL, NULL, NULL, + /* Initialize UART device after RTT init. */ + PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &uart_rtt_driver_api); + +#endif + +#define UART_RTT_CHANNEL(n) \ + static u8_t \ + uart_rtt##n##_tx_buffer[CONFIG_UART_RTT_##n##_TX_BUFFER_SIZE]; \ + static u8_t \ + uart_rtt##n##_rx_buffer[CONFIG_UART_RTT_##n##_RX_BUFFER_SIZE]; \ + \ + static const char uart_rtt##n##_name[] = "RTT_" #n "\0"; \ + \ + static const struct uart_rtt_config uart_rtt##n##_config = { \ + .channel = n, \ + .up_buffer = uart_rtt##n##_tx_buffer, \ + .up_size = sizeof(uart_rtt##n##_tx_buffer), \ + .down_buffer = uart_rtt##n##_rx_buffer, \ + .down_size = sizeof(uart_rtt##n##_rx_buffer), \ + }; \ + \ + DEVICE_DEFINE(uart_rtt##n, uart_rtt##n##_name, uart_rtt_init, NULL, \ + NULL, &uart_rtt##n##_config, PRE_KERNEL_2, \ + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &uart_rtt_driver_api) + +#if CONFIG_UART_RTT_1 +UART_RTT_CHANNEL(1); +#endif + +#if CONFIG_UART_RTT_2 +UART_RTT_CHANNEL(2); +#endif + +#if CONFIG_UART_RTT_3 +UART_RTT_CHANNEL(3); +#endif