From ae6912650971b427776e80f42903c206728362f9 Mon Sep 17 00:00:00 2001 From: Resaec Date: Fri, 27 Apr 2018 23:57:20 +0200 Subject: [PATCH 1/7] adding UartVendorStatus, UartLineStatus and UartLineControl refactor defines edited uart_wait_idle() second parameter type to UartVendorStatus --- exosphere/src/uart.c | 14 +++++------ exosphere/src/uart.h | 55 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/exosphere/src/uart.c b/exosphere/src/uart.c index 733e66984..1b6da6578 100644 --- a/exosphere/src/uart.c +++ b/exosphere/src/uart.c @@ -17,7 +17,7 @@ void uart_init(UartDevice dev, uint32_t baud) { /* Set baud rate. */ uint32_t rate = (8 * baud + 408000000) / (16 * baud); - uart->UART_LCR = 0x80; /* Enable DLAB. */ + uart->UART_LCR = UART_LCR_DLAB; /* Enable DLAB. */ uart->UART_THR_DLAB = (uint8_t)rate; /* Divisor latch LSB. */ uart->UART_IER_DLAB = (uint8_t)(rate >> 8); /* Divisor latch MSB. */ uart->UART_LCR = 0; /* Diable DLAB. */ @@ -27,17 +27,17 @@ void uart_init(UartDevice dev, uint32_t baud) { uart->UART_IIR_FCR = 7; /* Enable and clear TX and RX FIFOs. */ uart->UART_LSR; wait(3 * ((baud + 999999) / baud)); - uart->UART_LCR = 3; /* Set word length 8. */ + uart->UART_LCR = UART_LCR_WD_LENGTH_8; /* Set word length 8. */ uart->UART_MCR = 0; uart->UART_MSR = 0; uart->UART_IRDA_CSR = 0; - uart->UART_RX_FIFO_CFG = 1; + uart->UART_RX_FIFO_CFG = 1; /* Set RX_FIFO trigger level */ uart->UART_MIE = 0; uart->UART_ASR = 0; } -void uart_wait_idle(UartDevice dev, uint32_t which) { - while (!(get_uart_device(dev)->UART_VENDOR_STATUS & which)) { +void uart_wait_idle(UartDevice dev, UartVendorStatus status) { + while (!(get_uart_device(dev)->UART_VENDOR_STATUS & status)) { /* Wait */ } } @@ -47,7 +47,7 @@ void uart_send(UartDevice dev, const void *buf, size_t len) volatile uart_t *uart = get_uart_device(dev); for (size_t i = 0; i < len; i++) { - while (uart->UART_LSR & UART_TX_FIFO_FULL) { + while (uart->UART_LSR & UART_LSR_TX_FIFO_FULL) { /* Wait until the TX FIFO isn't full */ } uart->UART_THR_DLAB = *((const uint8_t *)buf + i); @@ -58,7 +58,7 @@ void uart_recv(UartDevice dev, void *buf, size_t len) { volatile uart_t *uart = get_uart_device(dev); for (size_t i = 0; i < len; i++) { - while (uart->UART_LSR & UART_RX_FIFO_EMPTY) { + while (uart->UART_LSR & UART_LSR_RX_FIFO_EMPTY) { /* Wait until the RX FIFO isn't empty */ } *((uint8_t *)buf + i) = uart->UART_THR_DLAB; diff --git a/exosphere/src/uart.h b/exosphere/src/uart.h index 247a79c64..54b42dac2 100644 --- a/exosphere/src/uart.h +++ b/exosphere/src/uart.h @@ -13,6 +13,8 @@ static inline uintptr_t get_uart_base(void) { #define UART_BASE (get_uart_base()) +#define BAUD_115200 115200 + /* Exosphère: add the clkreset values for UART C,D,E */ typedef enum { UART_A = 0, @@ -22,12 +24,53 @@ typedef enum { UART_E = 4, } UartDevice; -#define BAUD_115200 115200 +typedef enum { + UART_TX_IDLE = 1 << 0, + UART_RX_IDLE = 1 << 1, -#define UART_TX_IDLE 0x00000001 -#define UART_RX_IDLE 0x00000002 -#define UART_TX_FIFO_FULL 0x100 -#define UART_RX_FIFO_EMPTY 0x200 + /* This bit is set to 1 when a read is issued to an empty FIFO and gets cleared on register read (sticky bit until read) + 0 = NO_UNDERRUN + 1 = UNDERRUN */ + UART_UNDERRUN = 1 << 2, + + /* This bit is set to 1 when write data is issued to the TX FIFO when it is already full and gets cleared on register read (sticky bit until read) + 0 = NO_OVERRUN + 1 = OVERRUN */ + UART_OVERRUN = 1 << 3, + + RX_FIFO_COUNTER = 0b111111 << 16, /* reflects number of current entries in RX FIFO */ + TX_FIFO_COUNTER = 0b111111 << 24 /* reflects number of current entries in TX FIFO */ +} UartVendorStatus; + +typedef enum { + UART_LSR_RDR = 1 << 0, /* Receiver Data Ready */ + UART_LSR_OVRF = 1 << 1, /* Receiver Overrun Error */ + UART_LSR_PERR = 1 << 2, /* Parity Error */ + UART_LSR_FERR = 1 << 3, /* Framing Error */ + UART_LSR_BRK = 1 << 4, /* BREAK condition detected on line */ + UART_LSR_THRE = 1 << 5, /* Transmit Holding Register is Empty -- OK to write data */ + UART_LSR_TMTY = 1 << 6, /* Transmit Shift Register empty status */ + UART_LSR_FIFOE = 1 << 7, /* Receive FIFO Error */ + UART_LSR_TX_FIFO_FULL = 1 << 8, /* Transmitter FIFO full status */ + UART_LSR_RX_FIFO_EMPTY = 1 << 9, /* Receiver FIFO empty status */ +} UartLineStatus; + +typedef enum { + UART_LCR_WD_LENGTH_5 = 0, /* word length 5 */ + UART_LCR_WD_LENGTH_6 = 1, /* word length 6 */ + UART_LCR_WD_LENGTH_7 = 2, /* word length 7 */ + UART_LCR_WD_LENGTH_8 = 3, /* word length 8 */ + + /* STOP: + 0 = Transmit 1 stop bit + 1 = Transmit 2 stop bits (receiver always checks for 1 stop bit) */ + UART_LCR_STOP = 1 << 2, + UART_LCR_PAR = 1 << 3, /* Parity enabled */ + UART_LCR_EVEN = 1 << 4, /* Even parity format. There will always be an even number of 1s in the binary representation (PAR = 1) */ + UART_LCR_SET_P = 1 << 5, /* Set (force) parity to value in LCR[4] */ + UART_LCR_SET_B = 1 << 6, /* Set BREAK condition -- Transmitter sends all zeroes to indicate BREAK */ + UART_LCR_DLAB = 1 << 7, /* Divisor Latch Access Bit (set to allow programming of the DLH, DLM Divisors) */ +} UartLineControl; typedef struct { /* 0x00 */ uint32_t UART_THR_DLAB; @@ -48,7 +91,7 @@ typedef struct { void uart_select(UartDevice dev); void uart_init(UartDevice dev, uint32_t baud); -void uart_wait_idle(UartDevice dev, uint32_t which); +void uart_wait_idle(UartDevice dev, UartVendorStatus status); void uart_send(UartDevice dev, const void *buf, size_t len); void uart_recv(UartDevice dev, void *buf, size_t len); From e0f586d2d5608f25bdf32cc1608f3abc35b6996f Mon Sep 17 00:00:00 2001 From: Resaec Date: Sat, 28 Apr 2018 00:54:43 +0200 Subject: [PATCH 2/7] change multiline comments, they game (only?) me strange spacing errors in the VS info popup --- exosphere/src/uart.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/exosphere/src/uart.h b/exosphere/src/uart.h index 54b42dac2..7aab48b8d 100644 --- a/exosphere/src/uart.h +++ b/exosphere/src/uart.h @@ -30,12 +30,14 @@ typedef enum { /* This bit is set to 1 when a read is issued to an empty FIFO and gets cleared on register read (sticky bit until read) 0 = NO_UNDERRUN - 1 = UNDERRUN */ + 1 = UNDERRUN + */ UART_UNDERRUN = 1 << 2, /* This bit is set to 1 when write data is issued to the TX FIFO when it is already full and gets cleared on register read (sticky bit until read) 0 = NO_OVERRUN - 1 = OVERRUN */ + 1 = OVERRUN + */ UART_OVERRUN = 1 << 3, RX_FIFO_COUNTER = 0b111111 << 16, /* reflects number of current entries in RX FIFO */ @@ -63,7 +65,8 @@ typedef enum { /* STOP: 0 = Transmit 1 stop bit - 1 = Transmit 2 stop bits (receiver always checks for 1 stop bit) */ + 1 = Transmit 2 stop bits (receiver always checks for 1 stop bit) + */ UART_LCR_STOP = 1 << 2, UART_LCR_PAR = 1 << 3, /* Parity enabled */ UART_LCR_EVEN = 1 << 4, /* Even parity format. There will always be an even number of 1s in the binary representation (PAR = 1) */ From b6b0073178d7cb16972bd6c4965c62b36082583d Mon Sep 17 00:00:00 2001 From: Resaec Date: Sat, 28 Apr 2018 00:55:28 +0200 Subject: [PATCH 3/7] minor style fixes --- exosphere/src/uart.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/exosphere/src/uart.c b/exosphere/src/uart.c index 1b6da6578..7fe9bbc07 100644 --- a/exosphere/src/uart.c +++ b/exosphere/src/uart.c @@ -42,8 +42,7 @@ void uart_wait_idle(UartDevice dev, UartVendorStatus status) { } } -void uart_send(UartDevice dev, const void *buf, size_t len) -{ +void uart_send(UartDevice dev, const void *buf, size_t len) { volatile uart_t *uart = get_uart_device(dev); for (size_t i = 0; i < len; i++) { @@ -61,6 +60,6 @@ void uart_recv(UartDevice dev, void *buf, size_t len) { while (uart->UART_LSR & UART_LSR_RX_FIFO_EMPTY) { /* Wait until the RX FIFO isn't empty */ } - *((uint8_t *)buf + i) = uart->UART_THR_DLAB; + *((uint8_t *)buf + i) = uart->UART_THR_DLAB; } } From 5dcf2cb319e61a90f9ccb5cd10363a86ca68ae33 Mon Sep 17 00:00:00 2001 From: Resaec Date: Sat, 28 Apr 2018 00:58:42 +0200 Subject: [PATCH 4/7] adding UartFifoControl and UartInterruptIdentification for the UART_IIR_FCR_0 register adding reference manual intem numbers for register enums --- exosphere/src/uart.c | 2 +- exosphere/src/uart.h | 56 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/exosphere/src/uart.c b/exosphere/src/uart.c index 7fe9bbc07..9ca492f5b 100644 --- a/exosphere/src/uart.c +++ b/exosphere/src/uart.c @@ -24,7 +24,7 @@ void uart_init(UartDevice dev, uint32_t baud) { /* Setup UART in fifo mode. */ uart->UART_IER_DLAB = 0; - uart->UART_IIR_FCR = 7; /* Enable and clear TX and RX FIFOs. */ + uart->UART_IIR_FCR = UART_FCR_FCR_EN_FIFO | UART_FCR_RX_CLR | UART_FCR_TX_CLR; /* Enable and clear TX and RX FIFOs. */ uart->UART_LSR; wait(3 * ((baud + 999999) / baud)); uart->UART_LCR = UART_LCR_WD_LENGTH_8; /* Set word length 8. */ diff --git a/exosphere/src/uart.h b/exosphere/src/uart.h index 7aab48b8d..16a2c667c 100644 --- a/exosphere/src/uart.h +++ b/exosphere/src/uart.h @@ -24,6 +24,7 @@ typedef enum { UART_E = 4, } UartDevice; +/* 36.3.12 UART_VENDOR_STATUS_0_0 */ typedef enum { UART_TX_IDLE = 1 << 0, UART_RX_IDLE = 1 << 1, @@ -44,6 +45,7 @@ typedef enum { TX_FIFO_COUNTER = 0b111111 << 24 /* reflects number of current entries in TX FIFO */ } UartVendorStatus; +/* 36.3.6 UART_LSR_0 */ typedef enum { UART_LSR_RDR = 1 << 0, /* Receiver Data Ready */ UART_LSR_OVRF = 1 << 1, /* Receiver Overrun Error */ @@ -57,6 +59,7 @@ typedef enum { UART_LSR_RX_FIFO_EMPTY = 1 << 9, /* Receiver FIFO empty status */ } UartLineStatus; +/* 36.3.4 UART_LCR_0 */ typedef enum { UART_LCR_WD_LENGTH_5 = 0, /* word length 5 */ UART_LCR_WD_LENGTH_6 = 1, /* word length 6 */ @@ -75,6 +78,59 @@ typedef enum { UART_LCR_DLAB = 1 << 7, /* Divisor Latch Access Bit (set to allow programming of the DLH, DLM Divisors) */ } UartLineControl; +/* 36.3.3 UART_IIR_FCR_0 */ +typedef enum { + UART_FCR_FCR_EN_FIFO = 1 << 0, /* Enable the transmit and receive FIFOs. This bit should be enabled */ + UART_FCR_RX_CLR = 1 << 1, /* Clears the contents of the receive FIFO and resets its counter logic to 0 (the receive shift register is not cleared or altered). This bit returns to 0 after clearing the FIFOs */ + UART_FCR_TX_CLR = 1 << 2, /* Clears the contents of the transmit FIFO and resets its counter logic to 0 (the transmit shift register is not cleared or altered). This bit returns to 0 after clearing the FIFOs */ + + /* DMA: + 0 = DMA_MODE_0 + 1 = DMA_MODE_1 + */ + UART_FCR_DMA = 1 << 3, + + /* TX_TRIG + 0 = FIFO_COUNT_GREATER_16 + 1 = FIFO_COUNT_GREATER_8 + 2 = FIFO_COUNT_GREATER_4 + 3 = FIFO_COUNT_GREATER_1 + */ + UART_FCR_TX_TRIG = 3 << 4, + UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_16 = 0 << 4, + UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_8 = 1 << 4, + UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_4 = 2 << 4, + UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_1 = 3 << 4, + + /* RX_TRIG + 0 = FIFO_COUNT_GREATER_1 + 1 = FIFO_COUNT_GREATER_4 + 2 = FIFO_COUNT_GREATER_8 + 3 = FIFO_COUNT_GREATER_16 + */ + UART_FCR_RX_TRIG = 3 << 6, + UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_1 = 0 << 6, + UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_4 = 1 << 6, + UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_8 = 2 << 6, + UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_16 = 3 << 6, +} UartFifoControl; + +/* 36.3.3 UART_IIR_FCR_0 */ +typedef enum { + UART_IIR_IS_STA = 1 << 0, /* Interrupt Pending if ZERO */ + UART_IIR_IS_PRI0 = 1 << 1, /* Encoded Interrupt ID Refer to IIR[3:0] table [36.3.3] */ + UART_IIR_IS_PRI1 = 1 << 2, /* Encoded Interrupt ID Refer to IIR[3:0] table */ + UART_IIR_IS_PRI2 = 1 << 3, /* Encoded Interrupt ID Refer to IIR[3:0] table */ + + /* FIFO Mode Status + 0 = 16450 mode (no FIFO) + 1 = 16550 mode (FIFO) + */ + UART_IIR_EN_FIFO = 3 << 6, + UART_IIR_MODE_16450 = 0 << 6, + UART_IIR_MODE_16550 = 1 << 6, +} UartInterruptIdentification; + typedef struct { /* 0x00 */ uint32_t UART_THR_DLAB; /* 0x04 */ uint32_t UART_IER_DLAB; From dd319debe873397169d6f477953fece4db79da7d Mon Sep 17 00:00:00 2001 From: Resaec Date: Sat, 28 Apr 2018 01:13:16 +0200 Subject: [PATCH 5/7] adding comment for uart_wait_idle to warn about a possible dead lock --- exosphere/src/uart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/exosphere/src/uart.c b/exosphere/src/uart.c index 9ca492f5b..ee1379f92 100644 --- a/exosphere/src/uart.c +++ b/exosphere/src/uart.c @@ -36,6 +36,7 @@ void uart_init(UartDevice dev, uint32_t baud) { uart->UART_ASR = 0; } +/* This function blocks until the UART device (dev) is in the desired state (status). Make sure the desired state can be reached! */ void uart_wait_idle(UartDevice dev, UartVendorStatus status) { while (!(get_uart_device(dev)->UART_VENDOR_STATUS & status)) { /* Wait */ From 5430415578fc3aa2639700e41601084631e4f9d8 Mon Sep 17 00:00:00 2001 From: Resaec Date: Sat, 28 Apr 2018 01:27:16 +0200 Subject: [PATCH 6/7] somehow forgot to rename them --- exosphere/src/uart.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/exosphere/src/uart.h b/exosphere/src/uart.h index 16a2c667c..8d5c1ea0c 100644 --- a/exosphere/src/uart.h +++ b/exosphere/src/uart.h @@ -26,23 +26,23 @@ typedef enum { /* 36.3.12 UART_VENDOR_STATUS_0_0 */ typedef enum { - UART_TX_IDLE = 1 << 0, - UART_RX_IDLE = 1 << 1, + UART_VENDOR_STATE_TX_IDLE = 1 << 0, + UART_VENDOR_STATE_RX_IDLE = 1 << 1, /* This bit is set to 1 when a read is issued to an empty FIFO and gets cleared on register read (sticky bit until read) 0 = NO_UNDERRUN 1 = UNDERRUN */ - UART_UNDERRUN = 1 << 2, + UART_VENDOR_STATE_RX_UNDERRUN = 1 << 2, /* This bit is set to 1 when write data is issued to the TX FIFO when it is already full and gets cleared on register read (sticky bit until read) 0 = NO_OVERRUN 1 = OVERRUN */ - UART_OVERRUN = 1 << 3, + UART_VENDOR_STATE_TX_OVERRUN = 1 << 3, - RX_FIFO_COUNTER = 0b111111 << 16, /* reflects number of current entries in RX FIFO */ - TX_FIFO_COUNTER = 0b111111 << 24 /* reflects number of current entries in TX FIFO */ + UART_VENDOR_STATE_RX_FIFO_COUNTER = 0b111111 << 16, /* reflects number of current entries in RX FIFO */ + UART_VENDOR_STATE_TX_FIFO_COUNTER = 0b111111 << 24 /* reflects number of current entries in TX FIFO */ } UartVendorStatus; /* 36.3.6 UART_LSR_0 */ From 1c32f1ae34f641f20db5288691c70e531b2baeba Mon Sep 17 00:00:00 2001 From: Resaec Date: Tue, 1 May 2018 18:33:39 +0200 Subject: [PATCH 7/7] replacing tabs with spaces --- exosphere/src/uart.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/exosphere/src/uart.h b/exosphere/src/uart.h index 8d5c1ea0c..e39e56948 100644 --- a/exosphere/src/uart.h +++ b/exosphere/src/uart.h @@ -27,22 +27,22 @@ typedef enum { /* 36.3.12 UART_VENDOR_STATUS_0_0 */ typedef enum { UART_VENDOR_STATE_TX_IDLE = 1 << 0, - UART_VENDOR_STATE_RX_IDLE = 1 << 1, + UART_VENDOR_STATE_RX_IDLE = 1 << 1, /* This bit is set to 1 when a read is issued to an empty FIFO and gets cleared on register read (sticky bit until read) 0 = NO_UNDERRUN 1 = UNDERRUN */ - UART_VENDOR_STATE_RX_UNDERRUN = 1 << 2, + UART_VENDOR_STATE_RX_UNDERRUN = 1 << 2, /* This bit is set to 1 when write data is issued to the TX FIFO when it is already full and gets cleared on register read (sticky bit until read) 0 = NO_OVERRUN 1 = OVERRUN */ - UART_VENDOR_STATE_TX_OVERRUN = 1 << 3, + UART_VENDOR_STATE_TX_OVERRUN = 1 << 3, - UART_VENDOR_STATE_RX_FIFO_COUNTER = 0b111111 << 16, /* reflects number of current entries in RX FIFO */ - UART_VENDOR_STATE_TX_FIFO_COUNTER = 0b111111 << 24 /* reflects number of current entries in TX FIFO */ + UART_VENDOR_STATE_RX_FIFO_COUNTER = 0b111111 << 16, /* reflects number of current entries in RX FIFO */ + UART_VENDOR_STATE_TX_FIFO_COUNTER = 0b111111 << 24 /* reflects number of current entries in TX FIFO */ } UartVendorStatus; /* 36.3.6 UART_LSR_0 */