#include #include #include #include #include #include void uart_init() { kprint("UART Drive Init..."); volatile uint8_t *UART_IER = (uint8_t *)(UART_ADDRESS + 1); *UART_IER = 0x01; // Enable "Received Data Available" interrupt kputs("OK"); } void uart_put(size_t base_addr, uint8_t data) { *(volatile uint8_t *)base_addr = data; } char uart_getc() { if (*UART_LSR & 0x01) { return (char)(*UART_RBR); } return '\0'; } void uart_handle_interrupt() { char c = uart_getc(); if (c != '\0') { // Later, this will go into a "Circular Buffer" kputchar(c); } } int kputchar(int ch) { uart_put(UART_ADDRESS, ch); return ch; } void kprint(const char *str) { while (*str) { kputchar(*str++); } } void kprint_int(int num) { char buffer[21]; memset(buffer, 0, sizeof(buffer)); int i = 0; if (num == 0) { kputchar('0'); return; } if (num < 0) { kputchar('-'); num = -num; } while (num > 0) { buffer[i++] = '0' + (num % 10); num /= 10; } while (i > 0) { kputchar(buffer[--i]); } } void kprint_float(float num) { if (num < 0) { kputchar('-'); num = -num; } int int_part = (int)num; float frac_part = num - int_part; kprint_int(int_part); kputchar('.'); for (int i = 0; i < 6; i++) { frac_part *= 10.0f; } int fraction = (int)(frac_part + 0.5f); kprint_int(fraction); } void kprint_hex(uint64_t val) { char *digits = "0123456789ABCDEF"; char buffer[17]; //+1 for null terminator memset(buffer, 0, sizeof(buffer)); buffer[16] = '\0'; for (int i = 15; i >= 0; i--) { buffer[i] = digits[val & 0xF]; val >>= 4; } kprint("0x"); kprint(buffer); } void knewline(void) { kputchar('\n'); } void kputs(const char *str) { kprint(str); knewline(); } void kprintf(const char *format, ...) { va_list args; va_start(args, format); for (const char *p = format; *p != '\0'; p++) { if (*p == '%') { p++; switch (*p) { case 'c': { char c = (char)va_arg(args, int); kputchar(c); } case 's': { char *s = va_arg(args, char *); kprint(s); break; } case 'd': { int d = va_arg(args, int); kprint_int(d); break; } case 'f': { double f = va_arg(args, double); kprint_float((float)f); break; } case 'x': // Hex case 'p': // Pointer { uint64_t x = va_arg(args, uint64_t); kprint_hex(x); break; } case '%': kputchar('%'); break; default: kputchar('%'); kputchar(*p); } } else { kputchar(*p); } } va_end(args); knewline(); }