Basic UART communications

This commit is contained in:
FyloZ 2026-02-21 22:00:38 -05:00
parent 6e2611ab74
commit 1f25cc23da
9 changed files with 162 additions and 43 deletions

2
.idea/editor.xml generated
View File

@ -139,7 +139,7 @@
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNotAllPathsReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppObjectMemberMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppOutParameterMustBeWritten/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConst/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConstPtrOrRef/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNamesMismatch/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="CppParameterMayBeConst" enabled="false" level="HINT" enabled_by_default="false" />
</profile>
</component>

11
src/kernel/common.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef COMMON_H
#define COMMON_H
/**
* Sends a kernel panic message through the UART and hang the core.
* @param format The format of the message
* @param ... The parameters of the message
*/
void panic(const char *format, ...);
#endif

View File

@ -1,46 +1,12 @@
/*
* =====================================================================================
*
* Filename: kernel.c
*
* Description: Kernel entry point
*
* Version: 1.0
* Created: 2026-02-16 10:13:30 PM
* Revision: none
* Compiler: gcc
*
* Author: William Nolin,
*
* =====================================================================================
*/
#include <stdint.h>
#include <stddef.h>
#include "syscon.h"
#include "uart.h"
unsigned char *uart = (unsigned char *)0x10000000;
void putchar(char c) {
*uart = c;
return;
}
void print(const char * str) {
while(*str != '\0') {
putchar(*str);
str++;
}
return;
}
#define ARCH "RISC-V 64"
void kmain(void) {
power_off();
uart_init();
uart_printf("Hello world, %s!\n", ARCH);
// print("Hello world!\r\n");
// while(1) {
// // Read input from the UART
// putchar(*uart);
// }
// return;
power_off();
}

View File

@ -0,0 +1,21 @@
#include "../common.h"
#include <stdarg.h>
#include "../uart.h"
void panic(const char *format, ...) {
uart_puts("Kernel panic!");
uart_puts("Reason:");
va_list args = nullptr;
va_start(args, format);
// Print the reason
uart_vprintf(format, args);
va_end(args);
// Hang
asm volatile("wfi");
}

View File

@ -1,13 +1,16 @@
#include <stdint.h>
#include "../../syscon.h"
#include "../../uart.h"
// QEMU exposes a syscon-compatible device at address 0x1000000
#define SYSCON_ADDR 0x100000
void power_off() {
uart_puts("Power off requested");
*(uint32_t *) SYSCON_ADDR = 0x5555;
}
void reboot() {
uart_puts("Reboot requested");
*(uint32_t *) SYSCON_ADDR = 0x7777;
}

View File

@ -0,0 +1,81 @@
#include <stdint.h>
#include "../../uart.h"
// QEMU emulates the NS16550A UART
// The UART is memory mapped at 0x1000000
#define UART_ADDR 0x10000000
void uart_init() {
volatile uint8_t *ptr = (uint8_t *) UART_ADDR;
// Set the word length to 8 bits
ptr[3] = 0b11;
// Enable FIFO
ptr[2] = 0b1;
// Enable receiver buffer interrupts
ptr[1] = 0b1;
// For real hardware, we would need to set a baud rate
}
void uart_putchar(const char c) {
*(uint8_t *) UART_ADDR = c;
}
static void uart_print(const char *str) {
while (*str) {
uart_putchar(*str);
str++;
}
}
void uart_puts(const char *line) {
uart_print(line);
uart_putchar('\n');
}
// Basic implementation of printf supporting the following formats:
// - c: Character
// - s: String of characters
// - %: Literal '%'
void uart_vprintf(const char *restrict format, va_list args) {
while (*format) {
if (*format == '%') {
// Ignore this character as it indicates the format of a parameter
format++;
if (!*format) {
// There is nothing after '%'
return;
}
switch (*format) {
case 'c': // Character
uart_putchar(va_arg(args, int));
break;
case 's': // String
uart_print(va_arg(args, char*));
break;
case '%': // Literal '%'
uart_putchar('%');
break;
default: // Unsupported format
uart_putchar('%');
uart_putchar(*format);
break;
}
} else {
uart_putchar(*format);
}
format++;
}
}
void uart_printf(const char *restrict format, ...) {
va_list args = nullptr;
va_start(args, format);
uart_vprintf(format, args);
va_end(args);
}

View File

@ -1,3 +0,0 @@
//
// Created by william on 2026-02-21.
//

34
src/kernel/uart.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef UART_H
#define UART_H
#include <stdarg.h>
/** Initializes a UART device. */
void uart_init();
/**
* Sends a character to the UART.
* @param c The character to put
*/
void uart_putchar(char c);
/**
* Sends a line to the UART.
* @param line The line to put
*/
void uart_puts(const char *line);
/**
* Sends a string to the UART following a format.
* @param format The format of the string
* @param args The parameters of the string
*/
void uart_vprintf(const char *restrict format, va_list args);
/**
* Sends a string to the UART following a format.
* @param format The format of the string
* @param ... The parameters of the string
*/
void uart_printf(const char *restrict format, ...);
#endif