diff --git a/hello_world/Makefile b/hello_world/Makefile index 89f3e00..0cbc69f 100644 --- a/hello_world/Makefile +++ b/hello_world/Makefile @@ -15,8 +15,8 @@ LDFLAGS = -T powerpc.lds all: hello_world.hex -hello_world.elf: hello_world.o head.o - $(LD) $(LDFLAGS) -o hello_world.elf hello_world.o head.o +hello_world.elf: hello_world.o head.o console.o + $(LD) $(LDFLAGS) -o hello_world.elf hello_world.o head.o console.o hello_world.bin: hello_world.elf $(OBJCOPY) -O binary hello_world.elf hello_world.bin diff --git a/hello_world/console.c b/hello_world/console.c new file mode 100644 index 0000000..640eb48 --- /dev/null +++ b/hello_world/console.c @@ -0,0 +1,132 @@ +#include +#include +#include +#include + +/* + * Core UART functions to implement for a port + */ + +static uint64_t potato_uart_base; + +#define PROC_FREQ 50000000 +#define UART_FREQ 115200 +#define UART_BASE 0xc0002000 + +#define POTATO_CONSOLE_TX 0x00 +#define POTATO_CONSOLE_RX 0x08 +#define POTATO_CONSOLE_STATUS 0x10 +#define POTATO_CONSOLE_STATUS_RX_EMPTY 0x01 +#define POTATO_CONSOLE_STATUS_TX_EMPTY 0x02 +#define POTATO_CONSOLE_STATUS_RX_FULL 0x04 +#define POTATO_CONSOLE_STATUS_TX_FULL 0x08 +#define POTATO_CONSOLE_CLOCK_DIV 0x18 +#define POTATO_CONSOLE_IRQ_EN 0x20 + +static uint64_t potato_uart_reg_read(int offset) +{ + uint64_t addr; + uint64_t val; + + addr = potato_uart_base + offset; + + val = *(volatile uint64_t *)addr; + + return val; +} + +static void potato_uart_reg_write(int offset, uint64_t val) +{ + uint64_t addr; + + addr = potato_uart_base + offset; + + *(volatile uint64_t *)addr = val; +} + +static int potato_uart_rx_empty(void) +{ + uint64_t val; + + val = potato_uart_reg_read(POTATO_CONSOLE_STATUS); + + if (val & POTATO_CONSOLE_STATUS_RX_EMPTY) + return 1; + + return 0; +} + +static int potato_uart_tx_full(void) +{ + uint64_t val; + + val = potato_uart_reg_read(POTATO_CONSOLE_STATUS); + + if (val & POTATO_CONSOLE_STATUS_TX_FULL) + return 1; + + return 0; +} + +static char potato_uart_read(void) +{ + uint64_t val; + + val = potato_uart_reg_read(POTATO_CONSOLE_RX); + + return (char)(val & 0x000000ff); +} + +static void potato_uart_write(char c) +{ + uint64_t val; + + val = c; + + potato_uart_reg_write(POTATO_CONSOLE_TX, val); +} + +static unsigned long potato_uart_divisor(unsigned long proc_freq, unsigned long uart_freq) +{ + return proc_freq / (uart_freq * 16) - 1; +} + +void potato_uart_init(void) +{ + potato_uart_base = UART_BASE; + + potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, potato_uart_divisor(PROC_FREQ, UART_FREQ)); +} + +int getchar(void) +{ + while (potato_uart_rx_empty()) + /* Do nothing */ ; + + return potato_uart_read(); +} + +void putchar(unsigned char c) +{ + while (potato_uart_tx_full()) + /* Do Nothing */; + + potato_uart_write(c); +} + +void putstr(const char *str, unsigned long len) +{ + for (unsigned long i = 0; i < len; i++) { + putchar(str[i]); + } +} + +size_t strlen(const char *s) +{ + size_t len = 0; + + while (*s++) + len++; + + return len; +} diff --git a/hello_world/console.h b/hello_world/console.h new file mode 100644 index 0000000..85e7b36 --- /dev/null +++ b/hello_world/console.h @@ -0,0 +1,5 @@ +void potato_uart_init(void); +int getchar(void); +void putchar(unsigned char c); +void putstr(const char *str, unsigned long len); +size_t strlen(const char *s); diff --git a/hello_world/hello_world.c b/hello_world/hello_world.c index e4e9835..f1d1367 100644 --- a/hello_world/hello_world.c +++ b/hello_world/hello_world.c @@ -3,133 +3,7 @@ #include #include -/* - * Core UART functions to implement for a port - */ - -static uint64_t potato_uart_base; - -#define PROC_FREQ 50000000 -#define UART_FREQ 115200 -#define UART_BASE 0xc0002000 - -#define POTATO_CONSOLE_TX 0x00 -#define POTATO_CONSOLE_RX 0x08 -#define POTATO_CONSOLE_STATUS 0x10 -#define POTATO_CONSOLE_STATUS_RX_EMPTY 0x01 -#define POTATO_CONSOLE_STATUS_TX_EMPTY 0x02 -#define POTATO_CONSOLE_STATUS_RX_FULL 0x04 -#define POTATO_CONSOLE_STATUS_TX_FULL 0x08 -#define POTATO_CONSOLE_CLOCK_DIV 0x18 -#define POTATO_CONSOLE_IRQ_EN 0x20 - -static uint64_t potato_uart_reg_read(int offset) -{ - uint64_t addr; - uint64_t val; - - addr = potato_uart_base + offset; - - val = *(volatile uint64_t *)addr; - - return val; -} - -static void potato_uart_reg_write(int offset, uint64_t val) -{ - uint64_t addr; - - addr = potato_uart_base + offset; - - *(volatile uint64_t *)addr = val; -} - -static int potato_uart_rx_empty(void) -{ - uint64_t val; - - val = potato_uart_reg_read(POTATO_CONSOLE_STATUS); - - if (val & POTATO_CONSOLE_STATUS_RX_EMPTY) - return 1; - - return 0; -} - -static int potato_uart_tx_full(void) -{ - uint64_t val; - - val = potato_uart_reg_read(POTATO_CONSOLE_STATUS); - - if (val & POTATO_CONSOLE_STATUS_TX_FULL) - return 1; - - return 0; -} - -static char potato_uart_read(void) -{ - uint64_t val; - - val = potato_uart_reg_read(POTATO_CONSOLE_RX); - - return (char)(val & 0x000000ff); -} - -static void potato_uart_write(char c) -{ - uint64_t val; - - val = c; - - potato_uart_reg_write(POTATO_CONSOLE_TX, val); -} - -static unsigned long potato_uart_divisor(unsigned long proc_freq, unsigned long uart_freq) -{ - return proc_freq / (uart_freq * 16) - 1; -} - -void potato_uart_init(void) -{ - potato_uart_base = UART_BASE; - - potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, potato_uart_divisor(PROC_FREQ, UART_FREQ)); -} - -int getchar(void) -{ - while (potato_uart_rx_empty()) - /* Do nothing */ ; - - return potato_uart_read(); -} - -void putchar(unsigned char c) -{ - while (potato_uart_tx_full()) - /* Do Nothing */; - - potato_uart_write(c); -} - -void putstr(const char *str, unsigned long len) -{ - for (unsigned long i = 0; i < len; i++) { - putchar(str[i]); - } -} - -size_t strlen(const char *s) -{ - size_t len = 0; - - while (*s++) - len++; - - return len; -} +#include "console.h" #define HELLO_WORLD "Hello World\r\n"