2026-02-08 22:06:36 +00:00
|
|
|
#include <stdint.h>
|
|
|
|
|
#include <stddef.h>
|
2026-02-09 02:31:24 +00:00
|
|
|
#include <stdarg.h>
|
2026-02-10 01:21:49 +00:00
|
|
|
#include <syscon/syscon.h>
|
2026-02-08 22:06:36 +00:00
|
|
|
#include <drivers/uart.h>
|
2026-02-09 21:44:08 +00:00
|
|
|
#include <lib/string.h>
|
2026-02-08 22:06:36 +00:00
|
|
|
|
2026-02-10 01:21:49 +00:00
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-09 18:55:51 +00:00
|
|
|
void uart_put(size_t base_addr, uint8_t data)
|
|
|
|
|
{
|
2026-02-08 22:06:36 +00:00
|
|
|
*(volatile uint8_t *)base_addr = data;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-10 01:21:49 +00:00
|
|
|
char uart_getc()
|
|
|
|
|
{
|
|
|
|
|
if (*UART_LSR & 0x01)
|
|
|
|
|
{
|
|
|
|
|
return (char)(*UART_RBR);
|
|
|
|
|
}
|
|
|
|
|
return '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void uart_handle_interrupt()
|
|
|
|
|
{
|
|
|
|
|
char c = uart_getc();
|
2026-02-10 03:21:44 +00:00
|
|
|
switch (c)
|
2026-02-10 01:21:49 +00:00
|
|
|
{
|
2026-02-10 03:21:44 +00:00
|
|
|
case '\r': // enter key
|
|
|
|
|
knewline();
|
|
|
|
|
break;
|
|
|
|
|
case '\0':
|
|
|
|
|
// do nowt
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2026-02-10 01:21:49 +00:00
|
|
|
kputchar(c);
|
2026-02-10 03:21:44 +00:00
|
|
|
break;
|
2026-02-10 01:21:49 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-09 18:55:51 +00:00
|
|
|
int kputchar(int ch)
|
|
|
|
|
{
|
2026-02-08 22:06:36 +00:00
|
|
|
uart_put(UART_ADDRESS, ch);
|
|
|
|
|
return ch;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-09 18:55:51 +00:00
|
|
|
void kprint(const char *str)
|
|
|
|
|
{
|
|
|
|
|
while (*str)
|
|
|
|
|
{
|
2026-02-08 22:06:36 +00:00
|
|
|
kputchar(*str++);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-09 18:55:51 +00:00
|
|
|
void kprint_int(int num)
|
|
|
|
|
{
|
2026-02-09 02:31:24 +00:00
|
|
|
char buffer[21];
|
2026-02-09 21:44:08 +00:00
|
|
|
memset(buffer, 0, sizeof(buffer));
|
2026-02-09 02:31:24 +00:00
|
|
|
int i = 0;
|
2026-02-09 18:55:51 +00:00
|
|
|
if (num == 0)
|
|
|
|
|
{
|
2026-02-09 02:31:24 +00:00
|
|
|
kputchar('0');
|
|
|
|
|
return;
|
|
|
|
|
}
|
2026-02-09 18:55:51 +00:00
|
|
|
if (num < 0)
|
|
|
|
|
{
|
2026-02-09 02:31:24 +00:00
|
|
|
kputchar('-');
|
|
|
|
|
num = -num;
|
|
|
|
|
}
|
2026-02-09 18:55:51 +00:00
|
|
|
while (num > 0)
|
|
|
|
|
{
|
2026-02-09 02:31:24 +00:00
|
|
|
buffer[i++] = '0' + (num % 10);
|
|
|
|
|
num /= 10;
|
|
|
|
|
}
|
2026-02-09 18:55:51 +00:00
|
|
|
while (i > 0)
|
|
|
|
|
{
|
2026-02-09 02:31:24 +00:00
|
|
|
kputchar(buffer[--i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-09 18:55:51 +00:00
|
|
|
void kprint_float(float num)
|
|
|
|
|
{
|
|
|
|
|
if (num < 0)
|
|
|
|
|
{
|
2026-02-09 02:55:15 +00:00
|
|
|
kputchar('-');
|
|
|
|
|
num = -num;
|
|
|
|
|
}
|
|
|
|
|
int int_part = (int)num;
|
|
|
|
|
float frac_part = num - int_part;
|
|
|
|
|
kprint_int(int_part);
|
|
|
|
|
kputchar('.');
|
2026-02-09 18:55:51 +00:00
|
|
|
for (int i = 0; i < 6; i++)
|
|
|
|
|
{
|
2026-02-09 02:55:15 +00:00
|
|
|
frac_part *= 10.0f;
|
|
|
|
|
}
|
2026-02-09 21:44:08 +00:00
|
|
|
int fraction = (int)(frac_part + 0.5f);
|
2026-02-09 02:55:15 +00:00
|
|
|
kprint_int(fraction);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-09 18:55:51 +00:00
|
|
|
void kprint_hex(uint64_t val)
|
|
|
|
|
{
|
|
|
|
|
char *digits = "0123456789ABCDEF";
|
2026-02-09 21:44:08 +00:00
|
|
|
char buffer[17]; //+1 for null terminator
|
|
|
|
|
memset(buffer, 0, sizeof(buffer));
|
|
|
|
|
buffer[16] = '\0';
|
2026-02-09 18:55:51 +00:00
|
|
|
|
|
|
|
|
for (int i = 15; i >= 0; i--)
|
|
|
|
|
{
|
|
|
|
|
buffer[i] = digits[val & 0xF];
|
|
|
|
|
val >>= 4;
|
|
|
|
|
}
|
2026-02-09 14:25:56 +00:00
|
|
|
kprint("0x");
|
2026-02-09 18:55:51 +00:00
|
|
|
kprint(buffer);
|
2026-02-09 02:31:24 +00:00
|
|
|
}
|
|
|
|
|
|
2026-02-09 18:55:51 +00:00
|
|
|
void knewline(void)
|
|
|
|
|
{
|
2026-02-08 22:06:36 +00:00
|
|
|
kputchar('\n');
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-09 18:55:51 +00:00
|
|
|
void kputs(const char *str)
|
|
|
|
|
{
|
2026-02-08 22:06:36 +00:00
|
|
|
kprint(str);
|
|
|
|
|
knewline();
|
2026-02-09 02:31:24 +00:00
|
|
|
}
|
|
|
|
|
|
2026-02-10 13:22:12 +00:00
|
|
|
void kprintf_internal(const char *format, va_list args)
|
|
|
|
|
{
|
|
|
|
|
for (const char *p = format; *p != '\0'; p++)
|
|
|
|
|
{
|
|
|
|
|
if (*p == '%')
|
|
|
|
|
{
|
|
|
|
|
p++;
|
|
|
|
|
switch (*p)
|
|
|
|
|
{
|
|
|
|
|
case 'c':
|
|
|
|
|
{
|
|
|
|
|
char c = (char)va_arg(args, int);
|
|
|
|
|
kputchar(c);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
knewline();
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-09 18:55:51 +00:00
|
|
|
void kprintf(const char *format, ...)
|
|
|
|
|
{
|
2026-02-10 13:22:12 +00:00
|
|
|
va_list args;
|
|
|
|
|
va_start(args, format);
|
|
|
|
|
kprintf_internal(format, args);
|
|
|
|
|
va_end(args);
|
2026-02-08 22:06:36 +00:00
|
|
|
}
|