Interrupts are working again, new fontplate
This commit is contained in:
BIN
assets/cozette.otb
Normal file
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
42
assets/fontplate.py
Executable 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")
|
||||||
@@ -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),*]
|
||||||
|
|||||||
@@ -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"};
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
12
src/main.rs
12
src/main.rs
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user