diff options
author | Namyoon Woo <namyoon@chromium.org> | 2019-08-08 09:46:43 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-09-19 03:03:34 +0000 |
commit | 16d2b24ac05f7a5654bddcf9cb61f0f6684d1806 (patch) | |
tree | 6d20d184c6b3752376d4492bd925f367bf8ef87c | |
parent | 580a54658ad27550a1da5cd6077b901a12d447f2 (diff) | |
download | chrome-ec-16d2b24ac05f7a5654bddcf9cb61f0f6684d1806.tar.gz |
g: re-implement usb console with usb-stream configuration.
This patch introduces CONFIG_USB_CONSOLE_STREAM, which implements
usb-console with usb-stream configuration, intending to remove
code redundancy between the previous implementation (usb_console.c)
and usb_stream.c.
Flash usage decreases by 224 bytes, and RAM usage by 40 bytes.
BUG=b:138447451
BRANCH=cr50
TEST=Checked cr50 USB console and cr50 UART console respectively.
Key-in response and output are working well:
./util/uart_stress_tester.py /dev/ttyUSB0 -t 300 --debug
Change-Id: I305038e1db83dc49bb12a8afdbfcc2a8135d50f5
Signed-off-by: Namyoon Woo <namyoon@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1741302
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
-rw-r--r-- | board/cr50/board.h | 4 | ||||
-rw-r--r-- | chip/g/usb-stream.c | 4 | ||||
-rw-r--r-- | chip/g/usb-stream.h | 8 | ||||
-rw-r--r-- | common/build.mk | 3 | ||||
-rw-r--r-- | common/usb_console_stream.c | 233 | ||||
-rw-r--r-- | include/config.h | 7 | ||||
-rw-r--r-- | include/usb_console.h | 2 |
7 files changed, 257 insertions, 4 deletions
diff --git a/board/cr50/board.h b/board/cr50/board.h index 5a0dc1e330..130ac2320a 100644 --- a/board/cr50/board.h +++ b/board/cr50/board.h @@ -98,7 +98,9 @@ /* USB configuration */ #define CONFIG_USB -#define CONFIG_USB_CONSOLE +#define CONFIG_USB_CONSOLE_STREAM +#undef CONFIG_USB_CONSOLE_TX_BUF_SIZE +#define CONFIG_USB_CONSOLE_TX_BUF_SIZE 4096 #define CONFIG_USB_I2C #define CONFIG_USB_INHIBIT_INIT #define CONFIG_USB_SPI diff --git a/chip/g/usb-stream.c b/chip/g/usb-stream.c index b929cf7d4e..ae3b42e5c2 100644 --- a/chip/g/usb-stream.c +++ b/chip/g/usb-stream.c @@ -117,7 +117,7 @@ void usb_stream_rx(struct usb_stream_config const *config) } /* True if the Tx/IN FIFO can take some bytes from us. */ -static inline int tx_fifo_is_ready(struct usb_stream_config const *config) +int tx_fifo_is_ready(struct usb_stream_config const *config) { uint32_t status; struct g_usb_desc *in_desc = config->in_desc; @@ -290,6 +290,8 @@ void usb_stream_reset(struct usb_stream_config const *config) GR_USB_DAINTMSK |= DAINT_INEP(config->endpoint) | DAINT_OUTEP(config->endpoint); + *config->is_reset = 1; + /* Flush any queued data */ tx_stream_handler(config); hook_call_deferred(config->deferred_rx, 0); diff --git a/chip/g/usb-stream.h b/chip/g/usb-stream.h index 6e01c3341c..49048a6d9c 100644 --- a/chip/g/usb-stream.h +++ b/chip/g/usb-stream.h @@ -33,6 +33,7 @@ struct usb_stream_config { /* USB TX transfer is in progress */ uint8_t *tx_in_progress; uint8_t *kicker_running; + uint8_t *is_reset; /* * Deferred function to call to handle USB and Queue request. @@ -126,6 +127,7 @@ extern struct producer_ops const usb_stream_producer_ops; static uint8_t CONCAT2(NAME, _buf_rx_)[RX_SIZE]; \ static uint8_t CONCAT2(NAME, _tx_in_progress_); \ static uint8_t CONCAT2(NAME, _kicker_running_); \ + static uint8_t CONCAT2(NAME, _is_reset_); \ static void CONCAT2(NAME, _deferred_rx_)(void); \ static void CONCAT2(NAME, _tx_kicker_)(void); \ DECLARE_DEFERRED(CONCAT2(NAME, _deferred_rx_)); \ @@ -135,9 +137,11 @@ extern struct producer_ops const usb_stream_producer_ops; struct usb_stream_config const NAME = { \ .endpoint = ENDPOINT, \ .is_uart_console = ((ENDPOINT == USB_EP_EC) || \ + (ENDPOINT == USB_EP_CONSOLE) || \ (ENDPOINT == USB_EP_AP)), \ .tx_in_progress = &CONCAT2(NAME, _tx_in_progress_), \ .kicker_running = &CONCAT2(NAME, _kicker_running_), \ + .is_reset = &CONCAT2(NAME, _is_reset_), \ .in_desc = &CONCAT2(NAME, _in_desc_)[0], \ .out_desc = &CONCAT2(NAME, _out_desc_), \ .deferred_rx = &CONCAT2(NAME, _deferred_rx__data), \ @@ -242,4 +246,8 @@ void usb_stream_tx(struct usb_stream_config const *config); void usb_stream_rx(struct usb_stream_config const *config); void usb_stream_reset(struct usb_stream_config const *config); +/* + * Return non-zero if the USB stream is reset, or 0 otherwise + */ +int tx_fifo_is_ready(struct usb_stream_config const *config); #endif /* __CROS_EC_USB_STREAM_H */ diff --git a/common/build.mk b/common/build.mk index 72288730f3..19a55699d1 100644 --- a/common/build.mk +++ b/common/build.mk @@ -134,8 +134,9 @@ common-$(CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT)+=throttle_ap.o common-$(CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE)+=throttle_ap.o common-$(CONFIG_TPM_I2CS)+=i2cs_tpm.o common-$(CONFIG_U2F)+=u2f.o -common-$(CONFIG_USB_I2C)+=usb_i2c.o common-$(CONFIG_USB_CHARGER)+=usb_charger.o +common-$(CONFIG_USB_CONSOLE_STREAM)+=usb_console_stream.o +common-$(CONFIG_USB_I2C)+=usb_i2c.o common-$(CONFIG_USB_PORT_POWER_DUMB)+=usb_port_power_dumb.o common-$(CONFIG_USB_PORT_POWER_SMART)+=usb_port_power_smart.o common-$(CONFIG_USB_POWER_DELIVERY)+=usb_common.o diff --git a/common/usb_console_stream.c b/common/usb_console_stream.c new file mode 100644 index 0000000000..40bbc07e3c --- /dev/null +++ b/common/usb_console_stream.c @@ -0,0 +1,233 @@ +/* Copyright 2019 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" +#include "config.h" +#include "console.h" +#include "crc.h" +#include "link_defs.h" +#include "printf.h" +#include "queue.h" +#include "task.h" +#include "timer.h" +#include "usb-stream.h" + +#ifdef CONFIG_USB_CONSOLE +/* + * CONFIG_USB_CONSOLE and CONFIG_USB_CONSOLE_STREAM should be defined + * exclusively each other. + */ +#error "Do not enable CONFIG_USB_CONSOLE." +#endif + +/* Console output macro */ +#define USB_CONSOLE_TIMEOUT_US (30 * MSEC) + +#define QUEUE_SIZE_USB_TX CONFIG_USB_CONSOLE_TX_BUF_SIZE +#define QUEUE_SIZE_USB_RX USB_MAX_PACKET_SIZE + +static void usb_console_wr(struct queue_policy const *policy, size_t count); +static void uart_console_rd(struct queue_policy const *policy, size_t count); + + +static int last_tx_ok = 1; + +/* + * Start enabled, so we can queue early debug output before the board gets + * around to calling usb_console_enable(). + */ +static int is_enabled = 1; + +/* + * But start read-only, so we don't accept console input until we explicitly + * decide that we're ready for it. + */ +static int is_readonly = 1; + +/* + * This is a usb_console producer policy, which wakes up CONSOLE task whenever + * rx_q gets new data added. This shall be called by rx_stream_handler() in + * usb-stream.c. + */ +static struct queue_policy const usb_console_policy = { + .add = usb_console_wr, + .remove = uart_console_rd, +}; + +static struct queue const tx_q = QUEUE_NULL(QUEUE_SIZE_USB_TX, uint8_t); +static struct queue const rx_q = QUEUE(QUEUE_SIZE_USB_RX, uint8_t, + usb_console_policy); + +struct usb_stream_config const usb_console; + +USB_STREAM_CONFIG(usb_console, + USB_IFACE_CONSOLE, + USB_STR_CONSOLE_NAME, + USB_EP_CONSOLE, + USB_MAX_PACKET_SIZE, + USB_MAX_PACKET_SIZE, + rx_q, + tx_q) + +static void usb_console_wr(struct queue_policy const *policy, size_t count) +{ + console_has_input(); +} + +static void uart_console_rd(struct queue_policy const *policy, size_t count) +{ + /* do nothing */ +} + +static void handle_output(void) +{ + /* Wake up the Tx FIFO handler */ + usb_console.consumer.ops->written(&usb_console.consumer, 1); +} + +static int usb_wait_console(void) +{ + timestamp_t deadline = get_time(); + int wait_time_us = 1; + + if (!is_enabled || !tx_fifo_is_ready(&usb_console)) + return EC_SUCCESS; + + deadline.val += USB_CONSOLE_TIMEOUT_US; + + /* + * If the USB console is not used, Tx buffer would never free up. + * In this case, let's drop characters immediately instead of sitting + * for some time just to time out. On the other hand, if the last + * Tx is good, it's likely the host is there to receive data, and + * we should wait so that we don't clobber the buffer. + */ + if (last_tx_ok) { + while (queue_space(&tx_q) < USB_MAX_PACKET_SIZE || + !*usb_console.is_reset) { + if (timestamp_expired(deadline, NULL) || + in_interrupt_context()) { + last_tx_ok = 0; + return EC_ERROR_TIMEOUT; + } + if (wait_time_us < MSEC) + udelay(wait_time_us); + else + usleep(wait_time_us); + wait_time_us *= 2; + } + } else { + last_tx_ok = queue_space(&tx_q); + } + + return EC_SUCCESS; +} + +#ifdef CONFIG_USB_CONSOLE_CRC +static uint32_t usb_tx_crc_ctx; + +void usb_console_crc_init(void) +{ + crc32_ctx_init(&usb_tx_crc_ctx); +} + +uint32_t usb_console_crc(void) +{ + return crc32_ctx_result(&usb_tx_crc_ctx); +} +#endif + +static int __tx_char(void *context, int c) +{ + int ret; + + if (c == '\n') { + ret = __tx_char(NULL, '\r'); + if (ret) + return ret; + } + +#ifdef CONFIG_USB_CONSOLE_CRC + crc32_ctx_hash8(&usb_tx_crc_ctx, c); + + while (queue_add_unit(&tx_q, &c) != 1) + usleep(500); + + return EC_SUCCESS; +#else + /* Return 0 on success */ + return queue_add_unit(&tx_q, &c) ? EC_SUCCESS : EC_ERROR_OVERFLOW; +#endif +} + +/* + * Public USB console implementation below. + */ +int usb_getc(void) +{ + int c; + + if (is_readonly || !is_enabled) + return -1; + + if (!queue_remove_unit(&rx_q, &c)) + return -1; + + return c; +} + +int usb_puts(const char *outstr) +{ + int ret; + + if (!is_enabled) + return EC_SUCCESS; + + ret = usb_wait_console(); + if (ret) + return ret; + + while (*outstr) { + ret = __tx_char(NULL, *outstr++); + if (ret) + break; + } + handle_output(); + + return ret; +} + +int usb_putc(int c) +{ + static char string[2] = { 0, '\0' }; + + string[0] = c; + + return usb_puts(string); +} + +int usb_vprintf(const char *format, va_list args) +{ + int ret; + + if (!is_enabled) + return EC_SUCCESS; + + ret = usb_wait_console(); + if (ret) + return ret; + + ret = vfnprintf(__tx_char, NULL, format, args); + + handle_output(); + + return ret; +} + +void usb_console_enable(int enabled, int readonly) +{ + is_enabled = enabled; + is_readonly = readonly; +} diff --git a/include/config.h b/include/config.h index 5b3d99d37b..53db82d683 100644 --- a/include/config.h +++ b/include/config.h @@ -3944,6 +3944,13 @@ /* Enable USB serial console module. */ #undef CONFIG_USB_CONSOLE +/* + * Enable USB serial console module using usb stream config. + * NOTE: CONFIG_USB_CONSOLE and CONFIG_USB_CONSOLE_STREAM should be defined + * exclusively each other. + */ +#undef CONFIG_USB_CONSOLE_STREAM + /* USB serial console transmit buffer size in bytes. */ #define CONFIG_USB_CONSOLE_TX_BUF_SIZE 2048 diff --git a/include/usb_console.h b/include/usb_console.h index 4505ed5c34..296829ff9c 100644 --- a/include/usb_console.h +++ b/include/usb_console.h @@ -8,7 +8,7 @@ #ifndef __CROS_EC_USB_CONSOLE_H #define __CROS_EC_USB_CONSOLE_H -#ifdef CONFIG_USB_CONSOLE +#if defined(CONFIG_USB_CONSOLE) || defined(CONFIG_USB_CONSOLE_STREAM) #include <stdarg.h> |