#include "hv/config.h" #include "hv/mmio.h" #include "hv/uart.h" #define UART_DR 0x000u #define UART_FR 0x018u #define UART_IBRD 0x024u #define UART_FBRD 0x028u #define UART_LCRH 0x02cu #define UART_CR 0x030u #define UART_IMSC 0x038u #define UART_ICR 0x044u #define UART_FR_TXFF (1u << 5) #define UART_FR_RXFE (1u << 4) static uintptr_t uart_addr(uint32_t off) { return (uintptr_t)(CONFIG_UART_BASE + (uint64_t)off); } void uart_init(void) { mmio_write32(uart_addr(UART_CR), 0u); mmio_write32(uart_addr(UART_ICR), 0x7ffu); mmio_write32(uart_addr(UART_IBRD), 1u); mmio_write32(uart_addr(UART_FBRD), 40u); mmio_write32(uart_addr(UART_LCRH), (3u << 5)); mmio_write32(uart_addr(UART_IMSC), 0u); mmio_write32(uart_addr(UART_CR), (1u << 9) | (1u << 8) | 1u); } void uart_putc(char c) { if (c == '\n') { uart_putc('\r'); } while ((mmio_read32(uart_addr(UART_FR)) & UART_FR_TXFF) != 0u) { } mmio_write32(uart_addr(UART_DR), (uint32_t)(unsigned char)c); } void uart_puts(const char *s) { while (*s != '\0') { uart_putc(*s++); } } void uart_put_hex64(uint64_t value) { static const char hex[] = "0123456789abcdef"; uart_puts("0x"); for (int shift = 60; shift >= 0; shift -= 4) { uart_putc(hex[(value >> (unsigned)shift) & 0xfu]); } } void uart_put_dec64(uint64_t value) { char buf[21]; unsigned pos = 0; if (value == 0u) { uart_putc('0'); return; } while (value != 0u && pos < sizeof(buf)) { buf[pos++] = (char)('0' + (value % 10u)); value /= 10u; } while (pos != 0u) { uart_putc(buf[--pos]); } } void uart_put_label_hex64(const char *label, uint64_t value) { uart_puts(label); uart_puts("="); uart_put_hex64(value); uart_puts("\n"); } bool uart_getc_nonblocking(char *out) { if ((mmio_read32(uart_addr(UART_FR)) & UART_FR_RXFE) != 0u) { return false; } *out = (char)(mmio_read32(uart_addr(UART_DR)) & 0xffu); return true; }