From 41ad4c6268b0292464802d88ac6835d21e69cabb Mon Sep 17 00:00:00 2001 From: vetch Date: Thu, 3 Oct 2019 17:57:43 +0200 Subject: changes in Makefile, modularize kernel --- uart.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 uart.c (limited to 'uart.c') diff --git a/uart.c b/uart.c new file mode 100644 index 0000000..139cfe0 --- /dev/null +++ b/uart.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include + +// Memory-Mapped I/O output +static inline void mmio_write(uint32_t reg, uint32_t data) +{ + *(volatile uint32_t*)reg = data; +} + +// Memory-Mapped I/O input +static inline uint32_t mmio_read(uint32_t reg) +{ + return *(volatile uint32_t*)reg; +} + +// Loop times in a way that the compiler won't optimize away +static inline void delay(int32_t count) +{ + asm volatile("__delay_%=: subs %[count], %[count], #1; bne __delay_%=\n" + : "=r"(count): [count]"0"(count) : "cc"); +} + +void uart_init() +{ + // Disable UART0. + mmio_write(UART0_CR, 0x00000000); + // Setup the GPIO pin 14 && 15. + + // Disable pull up/down for all GPIO pins & delay for 150 cycles. + mmio_write(GPPUD, 0x00000000); + delay(150); + + // Disable pull up/down for pin 14,15 & delay for 150 cycles. + mmio_write(GPPUDCLK0, (1 << 14) | (1 << 15)); + delay(150); + + // Write 0 to GPPUDCLK0 to make it take effect. + mmio_write(GPPUDCLK0, 0x00000000); + + // Clear pending interrupts. + mmio_write(UART0_ICR, 0x7FF); + + // Set integer & fractional part of baud rate. + // Divider = UART_CLOCK/(16 * Baud) + // Fraction part register = (Fractional part * 64) + 0.5 + // UART_CLOCK = 3000000; Baud = 115200. + + // Divider = 3000000 / (16 * 115200) = 1.627 = ~1. + mmio_write(UART0_IBRD, 1); + // Fractional part register = (.627 * 64) + 0.5 = 40.6 = ~40. + mmio_write(UART0_FBRD, 40); + + // Enable FIFO & 8 bit data transmission (1 stop bit, no parity). + mmio_write(UART0_LCRH, (1 << 4) | (1 << 5) | (1 << 6)); + + // Mask all interrupts. + mmio_write(UART0_IMSC, (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) | + (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10)); + + // Enable UART0, receive & transfer part of UART. + mmio_write(UART0_CR, (1 << 0) | (1 << 8) | (1 << 9)); +} + +void uart_putc(unsigned char c) +{ + // Wait for UART to become ready to transmit. + while ( mmio_read(UART0_FR) & (1 << 5) ) { } + mmio_write(UART0_DR, c); +} + +unsigned char uart_getc() +{ + // Wait for UART to have received something. + while ( mmio_read(UART0_FR) & (1 << 4) ) { } + return mmio_read(UART0_DR); +} + +void uart_puts(const char* str) +{ + for (size_t i = 0; str[i] != '\0'; i ++) + uart_putc((unsigned char)str[i]); +} -- cgit v1.2.3