Interrupts are working again, new fontplate

This commit is contained in:
2026-03-15 17:26:11 +01:00
parent b1aac20b57
commit baeea20aa7
10 changed files with 62 additions and 62 deletions

BIN
assets/cozette.otb Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

42
assets/fontplate.py Executable file
View File

@@ -0,0 +1,42 @@
#!/bin/python
from fontTools.ttLib import TTFont
from PIL import Image, ImageDraw, ImageFont
COLUMNS, ROWS = 32, 42
CHAR_WIDTH, CHAR_HEIGHT = 6, 13
font_path = "assets/cozette.otb"
canvas = Image.new("1", (COLUMNS * CHAR_WIDTH, ROWS * CHAR_HEIGHT), color=0)
try:
font = ImageFont.truetype(font_path, 13)
ttfont = TTFont(font_path)
cmap = ttfont.getBestCmap()
if cmap is None:
raise Exception()
except Exception:
print("The font can't be loaded")
exit()
ranges = [
range(ROWS * COLUMNS),
]
for range in ranges:
for i in range:
pos = i
x = (pos % COLUMNS) * CHAR_WIDTH
y = (pos // COLUMNS) * CHAR_HEIGHT
char_to_draw = chr(i)
if i < 32 or i not in cmap:
char_to_draw = chr(0xFFFD)
cell = Image.new("1", (CHAR_WIDTH, CHAR_HEIGHT), color=0)
cell_draw = ImageDraw.Draw(cell)
cell_draw.text((0, 0), char_to_draw, font=font, fill=1)
canvas.paste(cell, (x, y))
canvas.save("assets/fontplate.png")

View File

@@ -34,7 +34,7 @@ fn to_format(img: ImageBuffer<Luma<u8>, Vec<u8>>, width: usize, height: usize) -
output output
} }
fn path_to_image(path: &str) -> (Vec<u8>, String, usize, usize) { fn path_to_image(path: &str) -> (Vec<u8>, usize, usize) {
let img = match image::open(path) { let img = match image::open(path) {
Ok(img) => img.to_luma8(), Ok(img) => img.to_luma8(),
Err(e) => panic!("failed to open image {}: {}", path, e), Err(e) => panic!("failed to open image {}: {}", path, e),
@@ -45,14 +45,7 @@ fn path_to_image(path: &str) -> (Vec<u8>, String, usize, usize) {
let bytes = to_format(img, width, height); let bytes = to_format(img, width, height);
let path = path (bytes, width, height)
.split('/')
.next_back()
.expect("failed to get last part of path");
let split: Vec<_> = path.split('.').collect();
let name = remove_non_alphanumeric(&split[0..split.len() - 1].join(".")).to_uppercase();
(bytes, name, width, height)
} }
struct ParsedArgs { struct ParsedArgs {
@@ -69,20 +62,11 @@ impl Parse for ParsedArgs {
pub fn parse_image( pub fn parse_image(
input: TokenStream, input: TokenStream,
) -> Result< ) -> Result<(u8, u8, usize, Vec<proc_macro2::TokenStream>), syn::Error> {
(
u8,
u8,
proc_macro2::Ident,
usize,
Vec<proc_macro2::TokenStream>,
),
syn::Error,
> {
// parse the input into a comma separated list of arguments // parse the input into a comma separated list of arguments
let parsed_args = syn::parse::<ParsedArgs>(input)?; let parsed_args = syn::parse::<ParsedArgs>(input)?;
// let parsed_args = parse_macro_input!(input as ParsedArgs); // let parsed_args = parse_macro_input!(input as ParsedArgs);
let (bytes, name, width, height) = path_to_image(&parsed_args.path); let (bytes, width, height) = path_to_image(&parsed_args.path);
let width = width as u8; let width = width as u8;
let height = height as u8; let height = height as u8;
@@ -90,14 +74,12 @@ pub fn parse_image(
let byte_array = bytes.as_slice(); let byte_array = bytes.as_slice();
let byte_count = byte_array.len(); let byte_count = byte_array.len();
let name_ident = syn::Ident::new(&name, Span::call_site().into());
let byte_tokens = bytes.iter().map(|b| quote! { #b }).collect::<Vec<_>>(); let byte_tokens = bytes.iter().map(|b| quote! { #b }).collect::<Vec<_>>();
Ok((width, height, name_ident, byte_count, byte_tokens)) Ok((width, height, byte_count, byte_tokens))
} }
pub fn include_bitmap_image_impl(input: TokenStream) -> TokenStream { pub fn include_bitmap_image_impl(input: TokenStream) -> TokenStream {
let (_, _, _, _, byte_tokens) = parse_image(input).unwrap(); let (_, _, _, byte_tokens) = parse_image(input).unwrap();
let output = quote! { let output = quote! {
[#(#byte_tokens),*] [#(#byte_tokens),*]

View File

@@ -39,12 +39,6 @@ pub trait Draw {
/// ///
/// Uses the embedded font plate to render glyphs into the framebuffer. /// Uses the embedded font plate to render glyphs into the framebuffer.
unsafe fn draw_char_bg(&mut self, x: u16, y: u16, c: char, color: Color, bg_color: Color) { unsafe fn draw_char_bg(&mut self, x: u16, y: u16, c: char, color: Color, bg_color: Color) {
let c = if (c as u8 > b'~') || ((c as u8) < b' ') {
b'/' - b' '
} else {
c as u8 - b' '
};
// Get char position within font plate // Get char position within font plate
let char_x = (c as usize % 32) * FONT_WIDTH; let char_x = (c as usize % 32) * FONT_WIDTH;
let char_y = (c as usize / 32) * FONT_HEIGHT; let char_y = (c as usize / 32) * FONT_HEIGHT;
@@ -119,6 +113,6 @@ pub trait Draw {
pub const FONT_WIDTH: usize = 6; pub const FONT_WIDTH: usize = 6;
pub const FONT_HEIGHT: usize = 13; pub const FONT_HEIGHT: usize = 13;
pub const FONTPLATE_WIDTH: usize = 32 * FONT_WIDTH; pub const FONTPLATE_WIDTH: usize = 32 * FONT_WIDTH;
pub const FONTPLATE_HEIGHT: usize = 3 * FONT_HEIGHT; pub const FONTPLATE_HEIGHT: usize = 42 * FONT_HEIGHT;
pub const FONTPLATE_SIZE: usize = FONTPLATE_WIDTH * FONTPLATE_HEIGHT / 8; pub const FONTPLATE_SIZE: usize = FONTPLATE_WIDTH * FONTPLATE_HEIGHT / 8;
pub static FONTPLATE: [u8; FONTPLATE_SIZE] = include_bitmap_image! {"assets/fontplate.png"}; pub static FONTPLATE: [u8; FONTPLATE_SIZE] = include_bitmap_image! {"assets/fontplate.png"};

View File

@@ -385,17 +385,6 @@ unsafe extern "C" fn _supervisor_mode_trap() {
csrr t0, sepc csrr t0, sepc
sd t0, 248(sp) sd t0, 248(sp)
csrr t0, sstatus csrr t0, sstatus
// Move SIE bit to SPIE. Restore_context, in the sret instruction, will do the inverse operation
// Isolate SIE bit (1)
andi t1, t0, 0x2
// li t1, 0x2
// Shift to bit 5 (SPIE)
slli t1, t1, 4
// Clear bit 1 and 5
li t2, ~0x22
and t0, t0, t2
// Add the SPIE bit
or t0, t0, t1
sd t0, 256(sp) sd t0, 256(sp)
mv a0, sp mv a0, sp

View File

@@ -115,7 +115,7 @@ pub static mut KBD_DRIVER: VirtioPciDriver = unsafe {
} }
_ => {} _ => {}
} }
// println!("event: {:#?}", event); println!("event: {:#?}", event);
} }
} else { } else {
// println!("key pressed, {:#?}", event); // println!("key pressed, {:#?}", event);
@@ -171,12 +171,12 @@ pub extern "C" fn supervisor_mode_entry() {
info!("Hello World !"); info!("Hello World !");
// unsafe { Vga.draw_string(10, 10, "Hello World !", Color::WHITE, Color::BLACK) }; // unsafe { Vga.draw_string(10, 10, "Hello World !", Color::WHITE, Color::BLACK) };
// SCHEDULER.lock().create_process(Box::new(test), "proc1"); SCHEDULER.lock().create_process(Box::new(test), "proc1");
// SCHEDULER.lock().create_process(Box::new(proc2), "proc2"); SCHEDULER.lock().create_process(Box::new(proc2), "proc2");
// SCHEDULER SCHEDULER
// .lock() .lock()
// .create_process_from_file("/usr/bin/test_pic"); .create_process_from_file("/usr/bin/test_pic");
enable_supervisor_interrupt(); enable_supervisor_interrupt();

View File

@@ -16,6 +16,7 @@ use shared::syscall::exit;
use crate::{ use crate::{
println, println,
riscv::SStatus,
scheduler::{ACTIVE_PID, SCHEDULER, Scheduler}, scheduler::{ACTIVE_PID, SCHEDULER, Scheduler},
time::elapsed_time_since_startup, time::elapsed_time_since_startup,
tty::TTY0, tty::TTY0,
@@ -25,15 +26,6 @@ use crate::{
/// Size of the stack allocated to each process (in 64-bit words). /// Size of the stack allocated to each process (in 64-bit words).
const STACK_SIZE: usize = 4096; const STACK_SIZE: usize = 4096;
/// MSTATUS bit to enable supervisor mode interrupts.
const MSTATUS_SIE: u64 = 1 << 1;
/// MSTATUS bit to enable supervisor mode interrupts.
const MSTATUS_SPIE: u64 = 1 << 5;
/// MSTATUS bit to set previous privilege mode to supervisor.
const MSTATUS_SPP: u64 = 1 << 1;
/// Represents the state of a process in the system. /// Represents the state of a process in the system.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum ProcessState { pub enum ProcessState {
@@ -317,7 +309,7 @@ impl Scheduler {
process.ctx.mepc = process_launcher as *const _; process.ctx.mepc = process_launcher as *const _;
// Configure mstatus for supervisor mode with interrupts enabled // Configure mstatus for supervisor mode with interrupts enabled
process.ctx.mstatus = MSTATUS_SPP | MSTATUS_SPIE; process.ctx.mstatus = SStatus::SPIE;
// Initialize stack pointer at the top of the stack // Initialize stack pointer at the top of the stack
process.ctx.sp = &raw const process.stack[STACK_SIZE - 1]; process.ctx.sp = &raw const process.stack[STACK_SIZE - 1];

View File

@@ -22,8 +22,9 @@ impl MStatus {
pub const MPIE: usize = 1 << 7; pub const MPIE: usize = 1 << 7;
} }
impl SStatus { impl SStatus {
pub const SIE: usize = 1 << 1; pub const SPP: u64 = 1 << 8;
pub const SPIE: usize = 1 << 5; pub const SIE: u64 = 1 << 1;
pub const SPIE: u64 = 1 << 5;
} }
/// Return the current machine interrupt enable state. /// Return the current machine interrupt enable state.
@@ -32,7 +33,7 @@ pub fn get_interrupt_state() -> bool {
} }
/// Return whether supervisor interrupts are currently enabled. /// Return whether supervisor interrupts are currently enabled.
pub fn get_supervisor_interrupt_state() -> bool { pub fn get_supervisor_interrupt_state() -> bool {
(read_csr!(sstatus) & SStatus::SIE as u64) != 0 (read_csr!(sstatus) & SStatus::SIE) != 0
} }
/// Enable machine-level interrupts. /// Enable machine-level interrupts.
pub fn enable_interrupt() { pub fn enable_interrupt() {

View File

@@ -26,7 +26,7 @@ const CLINT_TIMER: *const u64 = 0x0200_bff8 as *const u64;
/// The hardware timer frequency (Hz). /// The hardware timer frequency (Hz).
const TIMER_FREQUENCY: u64 = 10_000_000; // 10 MHz const TIMER_FREQUENCY: u64 = 10_000_000; // 10 MHz
/// The frequency at which timer interrupts should occur (Hz). /// The frequency at which timer interrupts should occur (Hz).
const INTERRUPT_FREQUENCY: u64 = 200; // 20 Hz const INTERRUPT_FREQUENCY: u64 = 100; // 100 Hz
/// Stores the instant when the kernel started. /// Stores the instant when the kernel started.
static START_TIME: AtomicU64 = AtomicU64::new(0); static START_TIME: AtomicU64 = AtomicU64::new(0);