phil-opp / blog_os

Writing an OS in Rust

Home Page:http://os.phil-opp.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Edition 3 Post 3 Embedded Graphics part and logger not working

0xC0ba1t opened this issue · comments

Hey, i understand edition 3 is in development, everything works except the part after the embedded-graphics part, it the following errors (after adding embedded-graphics in dependency, as it wasn't recognizing the crate and some other things):

error: expected one of `::`, `;`, or `as`, found `-`
 --> dopamine\src\framebuffer.rs:2:13
  |
2 | use embedded-graphics;
  |             ^ expected one of `::`, `;`, or `as`

error[E0432]: unresolved import `framebuffer::Position`
 --> dopamine\src\main.rs:8:5
  |
8 | use framebuffer::Position;
  |     ^^^^^^^^^^^^^^^^^^^^^ no `Position` in `framebuffer`

error[E0423]: expected value, found module `framebuffer`
  --> dopamine\src\main.rs:40:29
   |
40 |     let frame_buffer_info = framebuffer.info().clone();
   |                             ^^^^^^^^^^^- help: use the path separator to refer to an item: `::`

error[E0277]: `OnceCell<LockedLogger>` cannot be shared between threads safely
  --> dopamine\src\main.rs:12:27
   |
12 | pub(crate) static LOGGER: OnceCell<LockedLogger> = OnceCell::uninit();
   |                           ^^^^^^^^^^^^^^^^^^^^^^ `OnceCell<LockedLogger>` cannot be shared between threads safely
   |
   = help: the trait `Sync` is not implemented for `OnceCell<LockedLogger>`
   = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::OnceLock` instead
   = note: shared static variables must have a type that implements `Sync`

error[E0599]: no function or associated item named `uninit` found for struct `OnceCell` in the current scope
  --> dopamine\src\main.rs:12:62
   |
12 | pub(crate) static LOGGER: OnceCell<LockedLogger> = OnceCell::uninit();
   |                                                              ^^^^^^ function or associated item not found in `OnceCell<_>`
   |
note: if you're trying to build a new `OnceCell<_>`, consider using `OnceCell::<T>::new` which returns `OnceCell<T>`
  --> C:\Users\REMOVED\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library/core/src/cell/once.rs:44:5
   |
44 |     pub const fn new() -> OnceCell<T> {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Some errors have detailed explanations: E0277, E0423, E0432, E0599.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `dopamine` (bin "dopamine") due to 5 previous errors

Thanks alot!, Hope to see edition 3 soon!

I read it, too. Here's my code, hope it helps you.

use embedded_graphics::mono_font::{ascii::FONT_9X18_BOLD, MonoTextStyle};
use embedded_graphics::pixelcolor::{Rgb888, RgbColor};
use embedded_graphics::prelude::{DrawTarget, Drawable, OriginDimensions, Pixel, Point, Size};
use embedded_graphics::text::Text;
use lazy_static::lazy_static;
use spin::Mutex;
use core::fmt;

const FONT_WIDTH: i32 = 9;
const FONT_HEIGHT: i32 = 18;

const XMAX: i32 = 1280;
const YMAX: i32 = 720;

pub struct Display {
    framebuffer: *mut u8,
}

impl Display {
    pub fn new() -> Self {
        let mut display = Self {
            framebuffer: 0x18000000000 as *mut u8,
        };
        display.clear();
        display
    }

    pub fn clear(&mut self) {
        for i in 0..720 {
            for j in 0..1280 {
                self.draw_pixel(j, i, Rgb888::BLACK)
            }
        }
    }

    pub fn draw_pixel(&mut self, x: i32, y: i32, color: Rgb888) {
        if x < 1280 && y < 720 && x >= 0 && y >= 0 {
            let index = ((1280 * y + x) * 3) as isize;
            unsafe {
                *self.framebuffer.offset(index) = color.b();
                *self.framebuffer.offset(index + 1) = color.g();
                *self.framebuffer.offset(index + 2) = color.r();
            }
        }
    }
}

impl DrawTarget for Display {
    type Color = Rgb888;
    type Error = core::convert::Infallible;

    fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
    where
        I: IntoIterator<Item = Pixel<Self::Color>>,
    {
        for Pixel(coord, color) in pixels.into_iter() {
            self.draw_pixel(coord.x, coord.y, color);
        }

        Ok(())
    }
}

impl OriginDimensions for Display {
    fn size(&self) -> Size {
        Size::new(1280, 720)
    }
}

pub struct Writer {
    display: Display,
    pos: Point,
}

impl Writer {
    pub fn new(display: Display) -> Self {
        Self {
            display: display,
            pos: Point { x: 1, y: 12 },
        }
    }

    fn scroll(&mut self) {
        for i in 0..898560 {
            let a = i * 3;
            let b = (i + 23040) * 3;
            unsafe {
                *self.display.framebuffer.offset(a) = *self.display.framebuffer.offset(b);
                *self.display.framebuffer.offset(a + 1) = *self.display.framebuffer.offset(b + 1);
                *self.display.framebuffer.offset(a + 2) = *self.display.framebuffer.offset(b + 2);
            }
        }
        for i in 898561..921600 {
            unsafe {
                *self.display.framebuffer.offset(i * 3) = 0;
                *self.display.framebuffer.offset(i * 3 + 1) = 0;
                *self.display.framebuffer.offset(i * 3 + 2) = 0;
            }
        }
    }

    fn new_line(&mut self) {
        self.pos.y += FONT_HEIGHT;
        self.pos.x = 1;

        if self.pos.y > YMAX {
            self.pos.y -= FONT_HEIGHT;
            self.scroll();
        }
    }

    pub fn write_char(&mut self, c: &str) {
        if c == "\n" || self.pos.x + FONT_WIDTH > XMAX {
            self.new_line();
            if c == "\n" {
                return;
            }
        }
        let style = MonoTextStyle::new(&FONT_9X18_BOLD, Rgb888::WHITE);
        Text::new(c, self.pos, style)
            .draw(&mut self.display)
            .unwrap();
        self.pos.x += FONT_WIDTH;
    }

    pub fn write_str(&mut self, s: &str) {
        self.pos.x -= FONT_WIDTH;
        for i in s.split("") {
            self.write_char(i);
        }
        self.pos.x -= FONT_WIDTH;
    }
}

unsafe impl Send for Writer {}
unsafe impl Sync for Writer {}

impl fmt::Write for Writer {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        self.write_str(s);
        Ok(())
    }
}

lazy_static! {
    pub static ref WRITER: Mutex<Writer> = Mutex::new(Writer::new(Display::new()));
}

#[macro_export]
macro_rules! print {
    ($($arg:tt)*) => ($crate::framebuffer::_print(format_args!($($arg)*)));
}

#[macro_export]
macro_rules! println {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
}

#[doc(hidden)]
pub fn _print(args: fmt::Arguments) {
    use core::fmt::Write;
    WRITER.lock().write_fmt(args).unwrap();
}

There may be some bugs, or cumbersome implementations, but I don't have a good way to do it for the time being, the level is limited. At least it works :)

屏幕截图(1)
屏幕截图(2)

oh, today I rewrite it. I think it is better than better.

// framebuffer.rs
use core::fmt;
use core::{convert::TryInto, fmt::Error};
use lazy_static::lazy_static;
use noto_sans_mono_bitmap::{
    get_raster, get_raster_width, FontWeight, RasterHeight, RasterizedChar,
};
use spin::mutex::Mutex;

#[derive(Debug)]
pub struct RGB {
    r: u8,
    g: u8,
    b: u8,
}

impl RGB {
    pub fn new(s: u8) -> Self {
        Self { r: s, g: s, b: s }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct Position {
    x: isize,
    y: isize,
}

impl TryInto<(isize, isize)> for Position {
    type Error = core::convert::Infallible;

    fn try_into(self) -> Result<(isize, isize), Self::Error> {
        Ok((self.x, self.y))
    }
}

#[derive(Debug)]
pub struct Pixel {
    color: RGB,
    pos: Position,
}

pub struct FrameWriter {
    framebuffer: *mut u8,
}

impl FrameWriter {
    pub fn new() -> Self {
        Self {
            framebuffer: 0x18000000000 as *mut u8,
        }
    }

    pub fn draw(&mut self, pixel: Pixel) {
        if let Ok((x @ 0..1280, y @ 0..720)) = pixel.pos.try_into() {
            let index = (x + y * 1280) * 3;
            unsafe {
                *self.framebuffer.offset(index) = pixel.color.b;
                *self.framebuffer.offset(index + 1) = pixel.color.g;
                *self.framebuffer.offset(index + 2) = pixel.color.r;
            }
        }
    }

    pub fn clear(&mut self) {
        for i in 0..720 {
            for j in 0..1280 {
                self.draw(Pixel {
                    color: RGB { r: 0, g: 0, b: 0 },
                    pos: Position { x: j, y: i },
                })
            }
        }
    }

    pub fn get(&mut self, pos: Position) -> Result<Pixel, Error> {
        if let Ok((x @ 0..1280, y @ 0..720)) = pos.try_into() {
            let index = (x + y * 1280) * 3;
            unsafe {
                let pixel = Pixel {
                    color: RGB {
                        b: *self.framebuffer.offset(index),
                        g: *self.framebuffer.offset(index + 1),
                        r: *self.framebuffer.offset(index + 2),
                    },
                    pos: Position { ..pos },
                };
                Ok(pixel)
            }
        } else {
            Err(Error)
        }
    }
}

pub struct Writer {
    framewriter: FrameWriter,
    pos: Position,
    width: isize,
}

impl Writer {
    pub fn new(framewriter: FrameWriter) -> Self {
        let mut writer = Self {
            framewriter: framewriter,
            pos: Position { x: 0, y: 0 },
            width: get_raster_width(FontWeight::Regular, RasterHeight::Size16) as isize,
        };
        writer.framewriter.clear();
        writer
    }

    fn get_raster(&mut self, c: char) -> RasterizedChar {
        get_raster(c, FontWeight::Regular, RasterHeight::Size16).expect("unsupported char")
    }

    fn write_char(&mut self, c: char) {
        match c {
            '\n' => {
                self.new_line();
            },
            '\r' => {
                self.carriage_return()
            },
            c => {
                if self.pos.x + self.width >= 1280 {
                    self.new_line();
                }
                for (row_i, row) in self.get_raster(c).raster().iter().enumerate() {
                    for (col_i, intensity) in row.iter().enumerate() {
                        self.framewriter.draw(Pixel {
                            color: RGB::new(*intensity),
                            pos: Position {
                                x: self.pos.x + col_i as isize,
                                y: self.pos.y + row_i as isize,
                            },
                        })
                    }
                }

                self.pos.x += self.width;
            }
        }
    }

    fn write_str(&mut self, s: &str) {
        for c in s.chars() {
            self.write_char(c);
        }
    }

    fn new_line(&mut self) {
        self.pos.y += RasterHeight::Size16 as isize;
        self.carriage_return();

        if self.pos.y >= 720 {
            self.scroll();
        }
    }

    fn carriage_return(&mut self) {
        self.pos.x = 0;
    }

    fn scroll(&mut self) {
        self.pos.y -= RasterHeight::Size16 as isize;
        for i in 0..720 {
            for j in 0..1280 {
                let pixel = self.framewriter.get(Position { x: j, y: i }).unwrap();
                self.framewriter.draw(Pixel {
                    color: pixel.color,
                    pos: Position {
                        x: pixel.pos.x,
                        y: pixel.pos.y - RasterHeight::Size16 as isize,
                    },
                })
            }
        }
        for i in 704..720 {
            for j in 0..1280 {
                self.framewriter.draw(Pixel {
                    color: RGB { r: 0, g: 0, b: 0 },
                    pos: Position { x: j, y: i },
                })
            }
        }
    }
}
# Cargo.toml
[[bin]]
name = "kernel"
test = false
bench = false

[dependencies]
bootloader_api = "0.11.5"
noto-sans-mono-bitmap = "0.2.0"
spin = "0.9.8"
uart_16550 = "0.3.0"

[dependencies.lazy_static]
version = "1.4.0"
features = ["spin_no_std"]

Thanks @xuanplus!! I haven't tried it but thanks alot!!

Also, @xuanplus wondering if you could help me in figuring out how to get a simple shell / programs working, thanks again