aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/drivers/uart/util.c29
-rw-r--r--src/include/console/uart.h3
2 files changed, 32 insertions, 0 deletions
diff --git a/src/drivers/uart/util.c b/src/drivers/uart/util.c
index c7b9ab21eb..d38f688da2 100644
--- a/src/drivers/uart/util.c
+++ b/src/drivers/uart/util.c
@@ -13,6 +13,8 @@
#include <console/console.h>
#include <console/uart.h>
+#include <types.h>
+#include <timer.h>
/* Calculate divisor. Do not floor but round to nearest integer. */
unsigned int uart_baudrate_divisor(unsigned int baudrate,
@@ -53,3 +55,30 @@ unsigned int uart_platform_refclk(void)
return 115200 * 16;
}
#endif
+
+/* Helper function to allow bitbanging an 8n1 UART. */
+void uart_bitbang_tx_byte(unsigned char data, void (*set_tx)(int line_state))
+{
+ const int baud_rate = get_uart_baudrate();
+ int i;
+ struct stopwatch sw;
+ stopwatch_init(&sw);
+
+ /* Send start bit */
+ set_tx(0);
+ while (stopwatch_duration_usecs(&sw) < MHz / baud_rate)
+ stopwatch_tick(&sw);
+
+ /* 'i' counts the total bits sent at the end of the loop */
+ for (i = 2; i < 10; i++) {
+ set_tx(data & 1);
+ data >>= 1;
+ while (stopwatch_duration_usecs(&sw) < i * MHz / baud_rate)
+ stopwatch_tick(&sw);
+ }
+
+ /* Send stop bit */
+ set_tx(1);
+ while (stopwatch_duration_usecs(&sw) < i * MHz / baud_rate)
+ stopwatch_tick(&sw);
+}
diff --git a/src/include/console/uart.h b/src/include/console/uart.h
index 3bd390e75b..2e9c7b815c 100644
--- a/src/include/console/uart.h
+++ b/src/include/console/uart.h
@@ -46,6 +46,9 @@ unsigned int uart_baudrate_divisor(unsigned int baudrate,
*/
unsigned int uart_input_clock_divider(void);
+/* Bitbang out one byte on an 8n1 UART through the output function set_tx(). */
+void uart_bitbang_tx_byte(unsigned char data, void (*set_tx)(int line_state));
+
void uart_init(int idx);
void uart_tx_byte(int idx, unsigned char data);
void uart_tx_flush(int idx);