#ifndef _TB_UART_IO_H #define _TB_UART_IO_H #include #include // Testbench UART-over-TCP MMIO (see tb_common/include/tb_constants.h). // // Each UART is exposed as a raw TCP byte stream (one client at a time). // Software should poll STATUS.RX_AVAIL before reading DATA. #ifndef TB_IO_BASE #define TB_IO_BASE 0xC0000000u #endif #define TB_UART_BASE 0x200u #define TB_UART_STRIDE 0x20u #define TB_UART_DATA 0x00u #define TB_UART_STATUS 0x04u #define TB_UART_CTRL 0x08u #define TB_UART_STATUS_RX_AVAIL (1u << 0) #define TB_UART_STATUS_TX_READY (1u << 1) #define TB_UART_STATUS_CONNECTED (1u << 2) #define TB_UART_STATUS_OVERRUN (1u << 3) #define TB_UART_CTRL_CLR_OVERRUN (1u << 0) static inline volatile uint32_t *tb_uart_reg(unsigned uart_idx, unsigned reg_off) { return (volatile uint32_t *)(TB_IO_BASE + TB_UART_BASE + (uart_idx * TB_UART_STRIDE) + reg_off); } static inline uint32_t tb_uart_status(unsigned uart_idx) { return *tb_uart_reg(uart_idx, TB_UART_STATUS); } static inline bool tb_uart_connected(unsigned uart_idx) { return (tb_uart_status(uart_idx) & TB_UART_STATUS_CONNECTED) != 0; } static inline bool tb_uart_can_read(unsigned uart_idx) { return (tb_uart_status(uart_idx) & TB_UART_STATUS_RX_AVAIL) != 0; } static inline int tb_uart_try_read(unsigned uart_idx) { if (!tb_uart_can_read(uart_idx)) return -1; return (int)(*tb_uart_reg(uart_idx, TB_UART_DATA) & 0xffu); } static inline void tb_uart_write(unsigned uart_idx, uint8_t byte) { *tb_uart_reg(uart_idx, TB_UART_DATA) = (uint32_t)byte; } static inline void tb_uart_clear_overrun(unsigned uart_idx) { *tb_uart_reg(uart_idx, TB_UART_CTRL) = TB_UART_CTRL_CLR_OVERRUN; } #endif