2023-06-08 13:14:16 +02:00

171 lines
6.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef _PLATFORM_UART_H
#define _PLATFORM_UART_H
#include <stdint.h>
#include <macro.h>
// <Description> <[Doc Page]>
// UART Base Addesses [141]
#define UART_0_ADDR 0x10010000L
#define UART_1_ADDR 0x10010000L
// UART Control Register Offsets [142]
#define UART_TXDATA_OFF 0x00 // Transmit data register
#define UART_RXDATA_OFF 0x04 // Receive data register
#define UART_TXCTRL_OFF 0x08 // Transmit control register
#define UART_RXCTRL_OFF 0x0C // Receive control register
#define UART_IE_OFF 0x10 // UART interrupt enable
#define UART_IP_OFF 0x14 // UART interrupt pending
#define UART_DIV_OFF 0x18 // Baud rate divisor
#define UART_NUMBER 2
#define DEFAULT_BAUD 115200
// UART ids
typedef enum {
UART0 = 0,
UART1 = 1,
} uart_id;
/* Transmit Data Register (txdata) [142]
* Writing to the txdata register enqueues the character contained in the data
* field to the transmit FIFO if the FIFO is able to accept new entries. Reading
* from txdata returns the current value of the full flag and zero in the data
* field. The full flag indicates whether the transmit FIFO is able to accept
* new entries; when set, writes to data are ignored. A RISCV amoor.w
* instruction can be used to both read the full status and attempt to enqueue
* data, with a non-zero return value indicating the character was not accepted.
*/
struct S_PACKED uart_txdata_reg {
uint32_t data:8;
uint32_t reserved:23;
uint32_t full:1;
};
static_assert((sizeof(struct uart_txdata_reg) == sizeof(uint32_t)),
"uart_txdata_reg is not the right size");
/* Receive Data Register (rxdata) [143]
* Reading the rxdata register dequeues a character from the receive FIFO and
* returns the value in the data field. The empty flag indicates if the receive
* FIFO was empty; when set, the data field does not contain a valid character.
* Writes to rxdata are ignored.
*/
struct S_PACKED uart_rxdata_reg {
uint32_t data:8;
uint32_t reserved:23;
uint32_t empty:1;
};
static_assert((sizeof(struct uart_rxdata_reg) == sizeof(uint32_t)),
"uart_rxdata_reg is not the right size");
/* Transmit Control Register (txctrl) [143]
* The read-write txctrl register controls the operation of the transmit channel.
* The txen bit con- trols whether the Tx channel is active. When cleared,
* transmission of Tx FIFO contents is suppressed, and the txd pin is driven
* high. The nstop field specifies the number of stop bits: 0 for one stop bit
* and 1 for two stop bits. The txcnt field specifies the threshold at which the
* Tx FIFO watermark interrupt triggers. The txctrl register is reset to 0.
*/
struct S_PACKED uart_txctrl_reg {
uint32_t txen:1;
uint32_t nstop:1;
uint32_t reserved0:14;
uint32_t txcnt:3;
uint32_t reserved1:13;
};
static_assert((sizeof(struct uart_txctrl_reg) == sizeof(uint32_t)),
"uart_txctrl_reg is not the right size");
/* Receive Control Register (rxctrl) [144]
* The read-write rxctrl register controls the operation of the receive channel.
* The rxen bit controls whether the Rx channel is active. When cleared, the
* state of the rxd pin is ignored, and no characters will be enqueued into the
* Rx FIFO. The rxcnt field specifies the threshold at which the Rx FIFO
* watermark interrupt triggers. The rxctrl register is reset to 0. Characters
* are enqueued when a zero (low) start bit is seen.
*/
struct S_PACKED uart_rxctrl_reg {
uint32_t rxen:1;
uint32_t reserved0:15;
uint32_t rxcnt:3;
uint32_t reserved1:13;
};
static_assert((sizeof(struct uart_rxctrl_reg) == sizeof(uint32_t)),
"uart_rxctrl_reg is not the right size");
/* Interrupt Registers (ip and ie) [144]
* The ip register is a read-only register indicating the pending interrupt
* conditions, and the read- write ie register controls which UART interrupts
* are enabled. ie is reset to 0. The txwm condition becomes raised when the
* number of entries in the transmit FIFO is strictly less than the count
* specified by the txcnt field of the txctrl register. The pending bit is
* cleared when sufficient entries have been enqueued to exceed the watermark.
* The rxwm condition becomes raised when the number of entries in the receive
* FIFO is strictly greater than the count specified by the rxcnt field of the
* rxctrl register. The pending bit is cleared when sufficient entries have been
* dequeued to fall below the watermark.
*/
struct S_PACKED uart_ie_reg {
uint32_t txwm:1;
uint32_t rxwm:1;
uint32_t reserved:30;
};
static_assert((sizeof(struct uart_ie_reg) == sizeof(uint32_t)),
"uart_ie_reg is not the right size");
struct S_PACKED uart_ip_reg {
uint32_t txwm:1;
uint32_t rxwm:1;
uint32_t reserved:30;
};
static_assert((sizeof(struct uart_ip_reg) == sizeof(uint32_t)),
"uart_ip_reg is not the right size");
/* Baud Rate Divisor Register (div) [145]
* The read-write, div_width-bit div register specifies the divisor used by baud
* rate generation for both Tx and Rx channels. The relationship between the
* input clock and baud rate is given by the following formula: The input clock
* is the bus clock pclk. The reset value of the register is set to div_init,
* which is tuned to provide a 115200 baud output out of reset given the
* expected frequency of pclk. Table 85 shows divisors for some common core
* clock rates and commonly used baud rates. Note that the table shows the
* divide ratios, which are one greater than the value stored in the div
* register. The receive channel is sampled at 16× the baud rate, and a majority
* vote over 3 neighboring bits is used to determine the received value. For
* this reason, the divisor must be ≥16 for a receive channel.
*/
struct S_PACKED uart_div_reg {
uint32_t div:16;
uint32_t reserved:16;
};
static_assert((sizeof(struct uart_div_reg) == sizeof(uint32_t)),
"uart_div_reg is not the right size");
struct S_PACKED uart_memory_map {
struct uart_txdata_reg txdata;
struct uart_rxdata_reg rxdata;
struct uart_txctrl_reg txctrl;
struct uart_rxctrl_reg rxctrl;
struct uart_ie_reg ie;
struct uart_ip_reg ip;
struct uart_div_reg div;
};
static_assert((sizeof(struct uart_memory_map) == sizeof(uint32_t[7])),
"uart_memory_map is not the right size");
int uart_set_baudrate(uart_id id, int baud);
int uart_init(uart_id id, uint32_t baud, int stop_bits);
void uart_tx_byte(uart_id id, unsigned char b);
void uart_tx_full(uart_id id);
void uart_tx_buf(uart_id id, unsigned char *buf, unsigned int size);
#endif