#ifndef UART_H #define UART_H #include #include "global.h" #include "interrupts.h" #define DEFAULT_UART_CLOCK_RATE 3000000 #define UART_WLEN_8_BITS (0b11 << 5) #define UART_WLEN_7_BITS (0b10 << 5) #define UART_WLEN_6_BITS (0b01 << 5) #define UART_WLEN_5_BITS 0b00 #define UART_2_STOP (1 << 3) #define UART_1_STOP 0 #define UART_ODD_PAR (1 << 1) #define UART_EVEN_PAR ((1 << 1) | (1 << 2)) #define UART_NO_PAR 0 // The offsets for reach register. // GPIO Pin Pull-up/down Enable #define GPPUD (GPIO_BASE + 0x94) // GPIO Pin Pull-up/down Enable Clock 0 #define GPPUDCLK0 (GPIO_BASE + 0x98) // The base address for UART. #define PL011_UART_BASE (GPIO_BASE + 0x1000) // The offsets for reach register for the UART. #define PL011_UART_DR (PL011_UART_BASE + 0x00) #define PL011_UART_RSRECR (PL011_UART_BASE + 0x04) #define PL011_UART_FR (PL011_UART_BASE + 0x18) #define PL011_UART_ILPR (PL011_UART_BASE + 0x20) #define PL011_UART_IBRD (PL011_UART_BASE + 0x24) #define PL011_UART_FBRD (PL011_UART_BASE + 0x28) #define PL011_UART_LCRH (PL011_UART_BASE + 0x2C) #define PL011_UART_CR (PL011_UART_BASE + 0x30) #define PL011_UART_IFLS (PL011_UART_BASE + 0x34) #define PL011_UART_IMSC (PL011_UART_BASE + 0x38) #define PL011_UART_RIS (PL011_UART_BASE + 0x3C) #define PL011_UART_MIS (PL011_UART_BASE + 0x40) #define PL011_UART_ICR (PL011_UART_BASE + 0x44) #define PL011_UART_DMACR (PL011_UART_BASE + 0x48) #define PL011_UART_ITCR (PL011_UART_BASE + 0x80) #define PL011_UART_ITIP (PL011_UART_BASE + 0x84) #define PL011_UART_ITOP (PL011_UART_BASE + 0x88) #define PL011_UART_TDR (PL011_UART_BASE + 0x8C) void uart_init(); void putchar(char c); char getchar(void); _Bool putchar_non_blocking(char c); int getchar_non_blocking(void); // TODO experiment to see if this gives us raw uart irq or the uart // irq bit or'd with it's enable bit (not crucial for now, sice in our // code this function only gets called when this irq is enabled) static inline _Bool uart_irq_pending(void) { return ((uint32_t) 1 << 25) & rd32(ARM_IRQ_PENDING_2); } static inline void uart_irq_disable(void) { // Mask uart in arm peripheral interrupts wr32(ARM_DISABLE_IRQS_2, ((uint32_t) 1) << 25); } static inline void uart_irq_enable(void) { // Unmask uart in arm peripheral interrupts wr32(ARM_ENABLE_IRQS_2, ((uint32_t) 1) << 25); } static inline _Bool uart_recv_irq_pending(void) { return (1 << 4) & rd32(PL011_UART_MIS); } static inline void uart_recv_irq_disable(void) { wr32(PL011_UART_IMSC, rd32(PL011_UART_IMSC) & ~(1 << 4)); } static inline void uart_recv_irq_enable(void) { wr32(PL011_UART_IMSC, rd32(PL011_UART_IMSC) | (1 << 4)); } static inline void uart_clear_recv_irq(void) { wr32(PL011_UART_ICR, (1 << 4)); } static inline _Bool uart_send_irq_pending(void) { return (1 << 5) & rd32(PL011_UART_MIS); } static inline void uart_send_irq_disable(void) { wr32(PL011_UART_IMSC, rd32(PL011_UART_IMSC) & ~(1 << 5)); } static inline void uart_send_irq_enable(void) { wr32(PL011_UART_IMSC, rd32(PL011_UART_IMSC) | (1 << 5)); } static inline void uart_clear_send_irq(void) { wr32(PL011_UART_ICR, (1 << 5)); } #endif // UART_H