From ab01c11f50dcab03e33ec64ab9ad5e88cb31af89 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Fri, 21 Jan 2022 14:52:25 +0000 Subject: [PATCH] move all of uart state to a struct, preparing for save/restore --- verilator/uart-verilator.c | 168 +++++++++++++++++++------------------ 1 file changed, 86 insertions(+), 82 deletions(-) diff --git a/verilator/uart-verilator.c b/verilator/uart-verilator.c index 0346f6b..79c0556 100644 --- a/verilator/uart-verilator.c +++ b/verilator/uart-verilator.c @@ -13,23 +13,33 @@ /* Round to nearest */ #define BITWIDTH ((CLK_FREQUENCY+(BAUD/2))/BAUD) +enum state { + IDLE, START_BIT, BITS, STOP_BIT, ERROR +}; + /* * Our UART uses 16x oversampling, so at 50 MHz and 115200 baud * each sample is: 50000000/(115200*16) = 27 clock cycles. This * means each bit is off by 0.47% so for 8 bits plus a start and * stop bit the errors add to be 4.7%. */ -static double error = 0.05; - -enum state { - IDLE, START_BIT, BITS, STOP_BIT, ERROR +struct uart_tx_state { + double error = 0.05; + + enum state tx_state = IDLE; + unsigned long tx_countbits; + unsigned char tx_bits; + unsigned char tx_byte; + unsigned char tx_prev; + + enum state rx_state = IDLE; + unsigned char rx_char; + unsigned long rx_countbits; + unsigned char rx_bit; + unsigned char rx = 1; }; -static enum state tx_state = IDLE; -static unsigned long tx_countbits; -static unsigned char tx_bits; -static unsigned char tx_byte; -static unsigned char tx_prev; +static struct uart_tx_state uart; /* * Return an error if the transition is not close enough to the start or @@ -37,9 +47,9 @@ static unsigned char tx_prev; */ static bool is_error(unsigned long bits) { - double e = 1.0 * tx_countbits / BITWIDTH; + double e = 1.0 * uart.tx_countbits / BITWIDTH; - if ((e <= (1.0-error)) && (e >= error)) + if ((e <= (1.0-uart.error)) && (e >= uart.error)) return true; return false; @@ -47,88 +57,88 @@ static bool is_error(unsigned long bits) void uart_tx(unsigned char tx) { - switch (tx_state) { + switch (uart.tx_state) { case IDLE: if (tx == 0) { - tx_state = START_BIT; - tx_countbits = BITWIDTH; - tx_bits = 0; - tx_byte = 0; + uart.tx_state = START_BIT; + uart.tx_countbits = BITWIDTH; + uart.tx_bits = 0; + uart.tx_byte = 0; } break; case START_BIT: - tx_countbits--; + uart.tx_countbits--; if (tx == 1) { - if (is_error(tx_countbits)) { - printf("START_BIT error %ld %ld\n", BITWIDTH, tx_countbits); - tx_countbits = BITWIDTH*2; - tx_state = ERROR; + if (is_error(uart.tx_countbits)) { + printf("START_BIT error %ld %ld\n", BITWIDTH, uart.tx_countbits); + uart.tx_countbits = BITWIDTH*2; + uart.tx_state = ERROR; break; } } - if (tx_countbits == 0) { - tx_state = BITS; - tx_countbits = BITWIDTH; + if (uart.tx_countbits == 0) { + uart.tx_state = BITS; + uart.tx_countbits = BITWIDTH; } break; case BITS: - tx_countbits--; - if (tx_countbits == BITWIDTH/2) { - tx_byte = tx_byte | (tx << tx_bits); - tx_bits = tx_bits + 1; + uart.tx_countbits--; + if (uart.tx_countbits == BITWIDTH/2) { + uart.tx_byte = uart.tx_byte | (tx << uart.tx_bits); + uart.tx_bits = uart.tx_bits + 1; } - if (tx != tx_prev) { - if (is_error(tx_countbits)) { - printf("BITS error %ld %ld\n", BITWIDTH, tx_countbits); - tx_countbits = BITWIDTH*2; - tx_state = ERROR; + if (tx != uart.tx_prev) { + if (is_error(uart.tx_countbits)) { + printf("BITS error %ld %ld\n", BITWIDTH, uart.tx_countbits); + uart.tx_countbits = BITWIDTH*2; + uart.tx_state = ERROR; break; } } - if (tx_countbits == 0) { - if (tx_bits == 8) { - tx_state = STOP_BIT; + if (uart.tx_countbits == 0) { + if (uart.tx_bits == 8) { + uart.tx_state = STOP_BIT; } - tx_countbits = BITWIDTH; + uart.tx_countbits = BITWIDTH; } break; case STOP_BIT: - tx_countbits--; + uart.tx_countbits--; if (tx == 0) { - if (is_error(tx_countbits)) { - printf("STOP_BIT error %ld %ld\n", BITWIDTH, tx_countbits); - tx_countbits = BITWIDTH*2; - tx_state = ERROR; + if (is_error(uart.tx_countbits)) { + printf("STOP_BIT error %ld %ld\n", BITWIDTH, uart.tx_countbits); + uart.tx_countbits = BITWIDTH*2; + uart.tx_state = ERROR; break; } /* Go straight to idle */ - write(STDOUT_FILENO, &tx_byte, 1); - tx_state = IDLE; + write(STDOUT_FILENO, &uart.tx_byte, 1); + uart.tx_state = IDLE; } - if (tx_countbits == 0) { - write(STDOUT_FILENO, &tx_byte, 1); - tx_state = IDLE; + if (uart.tx_countbits == 0) { + write(STDOUT_FILENO, &uart.tx_byte, 1); + uart.tx_state = IDLE; } break; case ERROR: - tx_countbits--; - if (tx_countbits == 0) { - tx_state = IDLE; + uart.tx_countbits--; + if (uart.tx_countbits == 0) { + uart.tx_state = IDLE; } break; } - tx_prev = tx; + uart.tx_prev = tx; } static struct termios oldt; @@ -188,12 +198,6 @@ static int nonblocking_read(unsigned char *c) } } -static enum state rx_state = IDLE; -static unsigned char rx_char; -static unsigned long rx_countbits; -static unsigned char rx_bit; -static unsigned char rx = 1; - /* Avoid calling poll() too much */ #define RX_INTERVAL 10000 static unsigned long rx_sometimes; @@ -202,60 +206,60 @@ unsigned char uart_rx(void) { unsigned char c; - switch (rx_state) { + switch (uart.rx_state) { case IDLE: if (rx_sometimes++ >= RX_INTERVAL) { rx_sometimes = 0; if (nonblocking_read(&c)) { - rx_state = START_BIT; - rx_char = c; - rx_countbits = BITWIDTH; - rx_bit = 0; - rx = 0; + uart.rx_state = START_BIT; + uart.rx_char = c; + uart.rx_countbits = BITWIDTH; + uart.rx_bit = 0; + uart.rx = 0; } } break; case START_BIT: - rx_countbits--; - if (rx_countbits == 0) { - rx_state = BITS; - rx_countbits = BITWIDTH; - rx = rx_char & 1; + uart.rx_countbits--; + if (uart.rx_countbits == 0) { + uart.rx_state = BITS; + uart.rx_countbits = BITWIDTH; + uart.rx = uart.rx_char & 1; } break; case BITS: - rx_countbits--; - if (rx_countbits == 0) { - rx_bit = rx_bit + 1; - if (rx_bit == 8) { - rx = 1; - rx_state = STOP_BIT; + uart.rx_countbits--; + if (uart.rx_countbits == 0) { + uart.rx_bit = uart.rx_bit + 1; + if (uart.rx_bit == 8) { + uart.rx = 1; + uart.rx_state = STOP_BIT; } else { - rx = (rx_char >> rx_bit) & 1; + uart.rx = (uart.rx_char >> uart.rx_bit) & 1; } - rx_countbits = BITWIDTH; + uart.rx_countbits = BITWIDTH; } break; case STOP_BIT: - rx_countbits--; - if (rx_countbits == 0) { - rx_state = IDLE; + uart.rx_countbits--; + if (uart.rx_countbits == 0) { + uart.rx_state = IDLE; } break; } - return rx; + return uart.rx; } // cheating, here: to avoid having to save the uart state, check if it // is idle (both tx and rx) -bool uart_idle(void) +bool uart_state(void) { - return (tx_state == IDLE && rx_state == IDLE); + return (uart.tx_state == IDLE && uart.rx_state == IDLE); } -- 2.30.2