summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNamyoon Woo <namyoon@chromium.org>2019-08-08 09:46:43 -0700
committerCommit Bot <commit-bot@chromium.org>2019-09-19 03:03:34 +0000
commit16d2b24ac05f7a5654bddcf9cb61f0f6684d1806 (patch)
tree6d20d184c6b3752376d4492bd925f367bf8ef87c
parent580a54658ad27550a1da5cd6077b901a12d447f2 (diff)
downloadchrome-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.h4
-rw-r--r--chip/g/usb-stream.c4
-rw-r--r--chip/g/usb-stream.h8
-rw-r--r--common/build.mk3
-rw-r--r--common/usb_console_stream.c233
-rw-r--r--include/config.h7
-rw-r--r--include/usb_console.h2
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>