summaryrefslogtreecommitdiff
path: root/board/discovery-stm32f072/echo.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/discovery-stm32f072/echo.c')
-rw-r--r--board/discovery-stm32f072/echo.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/board/discovery-stm32f072/echo.c b/board/discovery-stm32f072/echo.c
new file mode 100644
index 0000000000..ec7353e43e
--- /dev/null
+++ b/board/discovery-stm32f072/echo.c
@@ -0,0 +1,173 @@
+/* Copyright (c) 2014 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.
+ */
+/*
+ * Task to echo any characters from the three non-console USARTs back to all
+ * non-console USARTs.
+ */
+
+#include "atomic.h"
+#include "common.h"
+#include "compile_time_macros.h"
+#include "console.h"
+#include "panic.h"
+#include "task.h"
+#include "timer.h"
+#include "usart-stm32f0.h"
+#include "usb-stream.h"
+#include "util.h"
+
+static void in_ready(struct in_stream const *stream)
+{
+ task_wake(TASK_ID_ECHO);
+}
+
+static void out_ready(struct out_stream const *stream)
+{
+ task_wake(TASK_ID_ECHO);
+}
+
+USART_CONFIG(usart1, usart1_hw, 115200, 64, 64, in_ready, NULL)
+USART_CONFIG(usart3, usart3_hw, 115200, 64, 64, in_ready, NULL)
+USART_CONFIG(usart4, usart4_hw, 115200, 64, 64, in_ready, NULL)
+USB_STREAM_CONFIG(usb_stream1,
+ USB_IFACE_STREAM,
+ USB_EP_STREAM,
+ 256,
+ 256,
+ in_ready,
+ out_ready)
+
+const void *const usb_strings[] = {
+ [USB_STR_DESC] = usb_string_desc,
+ [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."),
+ [USB_STR_PRODUCT] = USB_STRING_DESC("discovery-stm32f072"),
+ [USB_STR_VERSION] = USB_STRING_DESC("v1.0"),
+};
+
+BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT);
+
+struct stream_console_state {
+ size_t wrote;
+};
+
+struct stream_console_config {
+ struct stream_console_state *state;
+
+ struct in_stream const *in;
+ struct out_stream const *out;
+};
+
+#define STREAM_CONSOLE_CONFIG(NAME, IN, OUT) \
+ static struct stream_console_state NAME##_state; \
+ struct stream_console_config const NAME = { \
+ .state = &NAME##_state, \
+ .in = IN, \
+ .out = OUT, \
+ };
+
+STREAM_CONSOLE_CONFIG(usart1_stream_console, &usart1.in, &usart1.out)
+STREAM_CONSOLE_CONFIG(usart3_stream_console, &usart3.in, &usart3.out)
+STREAM_CONSOLE_CONFIG(usart4_stream_console, &usart4.in, &usart4.out)
+STREAM_CONSOLE_CONFIG(usb_stream1_console, &usb_stream1.in, &usb_stream1.out)
+
+static struct stream_console_config const *const consoles[] = {
+ &usart1_stream_console,
+ &usart3_stream_console,
+ &usart4_stream_console,
+ &usb_stream1_console,
+};
+
+static size_t echo(struct stream_console_config const *const consoles[],
+ size_t consoles_count)
+{
+ size_t total = 0;
+ size_t i;
+
+ for (i = 0; i < consoles_count; ++i) {
+ size_t j;
+ uint8_t buffer[64];
+ size_t remaining = 0;
+ size_t count = in_stream_read(consoles[i]->in,
+ buffer,
+ sizeof(buffer));
+
+ if (count == 0)
+ continue;
+
+ for (j = 0; j < consoles_count; ++j)
+ consoles[j]->state->wrote = 0;
+
+ do {
+ remaining = 0;
+
+ for (j = 0; j < consoles_count; ++j) {
+ size_t wrote = consoles[j]->state->wrote;
+
+ if (count == wrote)
+ continue;
+
+ wrote += out_stream_write(consoles[j]->out,
+ buffer + wrote,
+ count - wrote);
+
+ consoles[j]->state->wrote = wrote;
+
+ remaining += count - wrote;
+ }
+ } while (remaining);
+
+ total += count;
+ }
+
+ return total;
+}
+
+void echo_task(void)
+{
+ usart_init(&usart1);
+ usart_init(&usart3);
+ usart_init(&usart4);
+
+ while (1) {
+ while (echo(consoles, ARRAY_SIZE(consoles))) {
+ /*
+ * Make sure other tasks, like the HOOKS get to run.
+ */
+ msleep(1);
+ }
+
+ /*
+ * There was nothing left to echo, go to sleep and be
+ * woken up by the next input.
+ */
+ task_wait_event(-1);
+ }
+}
+
+static int command_echo_info(int argc, char **argv)
+{
+ char const message[] = "Hello World!\r\n";
+ size_t i;
+
+ ccprintf("USART1 RX dropped %d bytes\n",
+ atomic_read_clear((uint32_t *) &(usart1.state->rx_dropped)));
+
+ ccprintf("USART3 RX dropped %d bytes\n",
+ atomic_read_clear((uint32_t *) &(usart3.state->rx_dropped)));
+
+ ccprintf("USART4 RX dropped %d bytes\n",
+ atomic_read_clear((uint32_t *) &(usart4.state->rx_dropped)));
+
+ for (i = 0; i < ARRAY_SIZE(consoles); ++i)
+ out_stream_write(consoles[i]->out, message, strlen(message));
+
+ return EC_SUCCESS;
+}
+
+DECLARE_CONSOLE_COMMAND(echo_info,
+ command_echo_info,
+ NULL,
+ "Dump echo task debug info",
+ NULL);