Basic UART communications
This commit is contained in:
parent
6e2611ab74
commit
1f25cc23da
2
.idea/editor.xml
generated
2
.idea/editor.xml
generated
@ -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" />
|
||||
|
||||
6
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
6
.idea/inspectionProfiles/Project_Default.xml
generated
Normal 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
11
src/kernel/common.h
Normal 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
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
21
src/kernel/riscv64/common.c
Normal file
21
src/kernel/riscv64/common.c
Normal 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");
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
81
src/kernel/riscv64/qemu/uart.c
Normal file
81
src/kernel/riscv64/qemu/uart.c
Normal 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);
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
//
|
||||
// Created by william on 2026-02-21.
|
||||
//
|
||||
34
src/kernel/uart.h
Normal file
34
src/kernel/uart.h
Normal 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
|
||||
Loading…
Reference in New Issue
Block a user