mirror of
https://github.com/rcore-os/rCore-Tutorial-v3.git
synced 2024-11-22 09:26:26 +04:00
Merge branch 'ch9-dev' into ch9
This commit is contained in:
commit
23bd5df121
@ -2,7 +2,7 @@
|
||||
name = "os"
|
||||
version = "0.1.0"
|
||||
authors = ["Yifan Wu <shinbokuow@163.com>"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@ -18,6 +18,9 @@ k210-pac = { git = "https://github.com/wyfcyx/k210-pac" }
|
||||
k210-hal = { git = "https://github.com/wyfcyx/k210-hal" }
|
||||
k210-soc = { git = "https://github.com/wyfcyx/k210-soc" }
|
||||
easy-fs = { path = "../easy-fs" }
|
||||
virtio-input-decoder = "0.1.4"
|
||||
embedded-graphics = "0.7.1"
|
||||
tinybmp = "0.3.1"
|
||||
|
||||
[features]
|
||||
board_qemu = []
|
||||
|
26
os/Makefile
26
os/Makefile
@ -89,15 +89,35 @@ disasm-vim: kernel
|
||||
|
||||
run: run-inner
|
||||
|
||||
run-inner: build
|
||||
gui: build
|
||||
ifeq ($(BOARD),qemu)
|
||||
@qemu-system-riscv64 \
|
||||
-M 128m \
|
||||
-machine virt \
|
||||
-nographic \
|
||||
-bios $(BOOTLOADER) \
|
||||
-device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) \
|
||||
-drive file=$(FS_IMG),if=none,format=raw,id=x0 \
|
||||
-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
|
||||
-device virtio-blk-device,drive=x0 \
|
||||
-device virtio-gpu-device \
|
||||
-device virtio-keyboard-device \
|
||||
-device virtio-mouse-device \
|
||||
-serial stdio
|
||||
endif
|
||||
|
||||
run-inner: build
|
||||
ifeq ($(BOARD),qemu)
|
||||
@qemu-system-riscv64 \
|
||||
-M 128m \
|
||||
-machine virt \
|
||||
-bios $(BOOTLOADER) \
|
||||
-display none \
|
||||
-device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) \
|
||||
-drive file=$(FS_IMG),if=none,format=raw,id=x0 \
|
||||
-device virtio-blk-device,drive=x0 \
|
||||
-device virtio-gpu-device \
|
||||
-device virtio-keyboard-device \
|
||||
-device virtio-mouse-device \
|
||||
-serial stdio
|
||||
else
|
||||
(which $(K210-BURNER)) || (cd .. && git clone https://github.com/sipeed/kflash.py.git && mv kflash.py tools)
|
||||
@cp $(BOOTLOADER) $(BOOTLOADER).copy
|
||||
|
11
os/run-fdt.sh
Executable file
11
os/run-fdt.sh
Executable file
@ -0,0 +1,11 @@
|
||||
qemu-system-riscv64 -M 128m -machine virt,dumpdtb=virt.out \
|
||||
-bios ../bootloader/rustsbi-qemu.bin \
|
||||
-device loader,file=target/riscv64gc-unknown-none-elf/release/os.bin,addr=0x80200000 \
|
||||
-drive file=../user/target/riscv64gc-unknown-none-elf/release/fs.img,if=none,format=raw,id=x0 \
|
||||
-device virtio-blk-device,drive=x0 \
|
||||
-device virtio-gpu-device \
|
||||
-device virtio-keyboard-device \
|
||||
-device virtio-mouse-device \
|
||||
-serial stdio
|
||||
|
||||
fdtdump virt.out
|
10
os/run-nodisp.sh
Executable file
10
os/run-nodisp.sh
Executable file
@ -0,0 +1,10 @@
|
||||
qemu-system-riscv64 -M 128m -machine virt \
|
||||
-bios ../bootloader/rustsbi-qemu.bin \
|
||||
-display none \
|
||||
-device loader,file=target/riscv64gc-unknown-none-elf/release/os.bin,addr=0x80200000 \
|
||||
-drive file=../user/target/riscv64gc-unknown-none-elf/release/fs.img,if=none,format=raw,id=x0 \
|
||||
-device virtio-blk-device,drive=x0 \
|
||||
-device virtio-gpu-device \
|
||||
-device virtio-keyboard-device \
|
||||
-device virtio-mouse-device \
|
||||
-serial stdio
|
9
os/run.sh
Executable file
9
os/run.sh
Executable file
@ -0,0 +1,9 @@
|
||||
qemu-system-riscv64 -M 128m -machine virt \
|
||||
-bios ../bootloader/rustsbi-qemu.bin \
|
||||
-device loader,file=target/riscv64gc-unknown-none-elf/release/os.bin,addr=0x80200000 \
|
||||
-drive file=../user/target/riscv64gc-unknown-none-elf/release/fs.img,if=none,format=raw,id=x0 \
|
||||
-device virtio-blk-device,drive=x0 \
|
||||
-device virtio-gpu-device \
|
||||
-device virtio-keyboard-device \
|
||||
-device virtio-mouse-device \
|
||||
-serial stdio
|
BIN
os/src/assert/desktop.bmp
Normal file
BIN
os/src/assert/desktop.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 MiB |
BIN
os/src/assert/file.bmp
Normal file
BIN
os/src/assert/file.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
os/src/assert/folder.bmp
Normal file
BIN
os/src/assert/folder.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
os/src/assert/mouse.bmp
Normal file
BIN
os/src/assert/mouse.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
@ -1,10 +1,10 @@
|
||||
pub const CLOCK_FREQ: usize = 12500000;
|
||||
|
||||
pub const MMIO: &[(usize, usize)] = &[
|
||||
(0x1000_0000, 0x1000), // VIRT_UART0 in virt machine
|
||||
(0x1000_1000, 0x1000), // VIRT_VIRTIO in virt machine
|
||||
(0x0C00_0000, 0x40_0000), // VIRT_PLIC in virt machine
|
||||
(0x0010_0000, 0x00_2000), // VIRT_TEST/RTC in virt machine
|
||||
(0x2000000, 0x10000),
|
||||
(0xc000000, 0x210000), // VIRT_PLIC in virt machine
|
||||
(0x10000000, 0x9000), // VIRT_UART0 with GPU in virt machine
|
||||
];
|
||||
|
||||
pub type BlockDeviceImpl = crate::drivers::block::VirtIOBlock;
|
||||
@ -13,9 +13,13 @@ pub type CharDeviceImpl = crate::drivers::chardev::NS16550a<VIRT_UART>;
|
||||
pub const VIRT_PLIC: usize = 0xC00_0000;
|
||||
pub const VIRT_UART: usize = 0x1000_0000;
|
||||
|
||||
pub const VIRTGPU_XRES: u32 = 1280;
|
||||
pub const VIRTGPU_YRES: u32 = 800;
|
||||
|
||||
use crate::drivers::block::BLOCK_DEVICE;
|
||||
use crate::drivers::chardev::{CharDevice, UART};
|
||||
use crate::drivers::plic::{IntrTargetPriority, PLIC};
|
||||
use crate::drivers::{KEYBOARD_DEVICE, MOUSE_DEVICE};
|
||||
|
||||
pub fn device_init() {
|
||||
use riscv::register::sie;
|
||||
@ -25,7 +29,8 @@ pub fn device_init() {
|
||||
let machine = IntrTargetPriority::Machine;
|
||||
plic.set_threshold(hart_id, supervisor, 0);
|
||||
plic.set_threshold(hart_id, machine, 1);
|
||||
for intr_src_id in [1usize, 10] {
|
||||
//irq nums: 5 keyboard, 6 mouse, 8 block, 10 uart
|
||||
for intr_src_id in [5usize, 6, 8 , 10] {
|
||||
plic.enable(hart_id, supervisor, intr_src_id);
|
||||
plic.set_priority(intr_src_id, 1);
|
||||
}
|
||||
@ -38,7 +43,9 @@ pub fn irq_handler() {
|
||||
let mut plic = unsafe { PLIC::new(VIRT_PLIC) };
|
||||
let intr_src_id = plic.claim(0, IntrTargetPriority::Supervisor);
|
||||
match intr_src_id {
|
||||
1 => BLOCK_DEVICE.handle_irq(),
|
||||
5 => KEYBOARD_DEVICE.handle_irq(),
|
||||
6 => MOUSE_DEVICE.handle_irq(),
|
||||
8 => BLOCK_DEVICE.handle_irq(),
|
||||
10 => UART.handle_irq(),
|
||||
_ => panic!("unsupported IRQ {}", intr_src_id),
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
pub const USER_STACK_SIZE: usize = 4096 * 2;
|
||||
pub const KERNEL_STACK_SIZE: usize = 4096 * 2;
|
||||
pub const KERNEL_HEAP_SIZE: usize = 0x20_0000;
|
||||
pub const MEMORY_END: usize = 0x80800000;
|
||||
pub const KERNEL_HEAP_SIZE: usize = 0x100_0000;
|
||||
pub const MEMORY_END: usize = 0x88000000;
|
||||
pub const PAGE_SIZE: usize = 0x1000;
|
||||
pub const PAGE_SIZE_BITS: usize = 0xc;
|
||||
|
||||
|
@ -12,7 +12,7 @@ use lazy_static::*;
|
||||
use virtio_drivers::{BlkResp, RespStatus, VirtIOBlk, VirtIOHeader};
|
||||
|
||||
#[allow(unused)]
|
||||
const VIRTIO0: usize = 0x10001000;
|
||||
const VIRTIO0: usize = 0x10008000;
|
||||
|
||||
pub struct VirtIOBlock {
|
||||
virtio_blk: UPIntrFreeCell<VirtIOBlk<'static>>,
|
||||
|
66
os/src/drivers/gpu/mod.rs
Normal file
66
os/src/drivers/gpu/mod.rs
Normal file
@ -0,0 +1,66 @@
|
||||
use crate::sync::UPIntrFreeCell;
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use core::any::Any;
|
||||
use embedded_graphics::pixelcolor::Rgb888;
|
||||
use tinybmp::Bmp;
|
||||
use virtio_drivers::{VirtIOGpu, VirtIOHeader};
|
||||
const VIRTIO7: usize = 0x10007000;
|
||||
pub trait GPUDevice: Send + Sync + Any {
|
||||
fn update_cursor(&self);
|
||||
fn getfreambuffer(&self) -> &mut [u8];
|
||||
fn flush(&self);
|
||||
}
|
||||
|
||||
lazy_static::lazy_static!(
|
||||
pub static ref GPU_DEVICE: Arc<dyn GPUDevice> = Arc::new(VirtIOGPU::new());
|
||||
);
|
||||
|
||||
pub struct VirtIOGPU {
|
||||
gpu: UPIntrFreeCell<VirtIOGpu<'static>>,
|
||||
fb: &'static [u8],
|
||||
}
|
||||
static BMP_DATA: &[u8] = include_bytes!("../../assert/mouse.bmp");
|
||||
impl VirtIOGPU {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let mut virtio = VirtIOGpu::new(&mut *(VIRTIO7 as *mut VirtIOHeader)).unwrap();
|
||||
|
||||
let fbuffer = virtio.setup_framebuffer().unwrap();
|
||||
let len = fbuffer.len();
|
||||
let ptr = fbuffer.as_mut_ptr();
|
||||
let fb = core::slice::from_raw_parts_mut(ptr, len);
|
||||
|
||||
let bmp = Bmp::<Rgb888>::from_slice(BMP_DATA).unwrap();
|
||||
let raw = bmp.as_raw();
|
||||
let mut b = Vec::new();
|
||||
for i in raw.image_data().chunks(3) {
|
||||
let mut v = i.to_vec();
|
||||
b.append(&mut v);
|
||||
if i == [255, 255, 255] {
|
||||
b.push(0x0)
|
||||
} else {
|
||||
b.push(0xff)
|
||||
}
|
||||
}
|
||||
virtio.setup_cursor(b.as_slice(), 50, 50, 50, 50).unwrap();
|
||||
|
||||
Self {
|
||||
gpu: UPIntrFreeCell::new(virtio),
|
||||
fb,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GPUDevice for VirtIOGPU {
|
||||
fn flush(&self) {
|
||||
self.gpu.exclusive_access().flush().unwrap();
|
||||
}
|
||||
fn getfreambuffer(&self) -> &mut [u8] {
|
||||
unsafe {
|
||||
let ptr = self.fb.as_ptr() as *const _ as *mut u8;
|
||||
core::slice::from_raw_parts_mut(ptr, self.fb.len())
|
||||
}
|
||||
}
|
||||
fn update_cursor(&self) {}
|
||||
}
|
74
os/src/drivers/input/mod.rs
Normal file
74
os/src/drivers/input/mod.rs
Normal file
@ -0,0 +1,74 @@
|
||||
use crate::{
|
||||
gui::{Button, Component},
|
||||
sync::UPIntrFreeCell,
|
||||
syscall::PAD,
|
||||
};
|
||||
use alloc::{string::ToString, sync::Arc};
|
||||
use core::any::Any;
|
||||
use embedded_graphics::{
|
||||
prelude::{Point, Size},
|
||||
text::Text,
|
||||
};
|
||||
use k210_hal::cache::Uncache;
|
||||
use virtio_drivers::{VirtIOHeader, VirtIOInput};
|
||||
use virtio_input_decoder::{Decoder, Key, KeyType};
|
||||
|
||||
use super::GPU_DEVICE;
|
||||
|
||||
const VIRTIO5: usize = 0x10005000;
|
||||
const VIRTIO6: usize = 0x10006000;
|
||||
|
||||
struct VirtIOINPUT(UPIntrFreeCell<VirtIOInput<'static>>);
|
||||
|
||||
pub trait INPUTDevice: Send + Sync + Any {
|
||||
fn handle_irq(&self);
|
||||
}
|
||||
|
||||
lazy_static::lazy_static!(
|
||||
pub static ref KEYBOARD_DEVICE: Arc<dyn INPUTDevice> = Arc::new(VirtIOINPUT::new(VIRTIO5));
|
||||
pub static ref MOUSE_DEVICE: Arc<dyn INPUTDevice> = Arc::new(VirtIOINPUT::new(VIRTIO6));
|
||||
);
|
||||
|
||||
impl VirtIOINPUT {
|
||||
pub fn new(addr: usize) -> Self {
|
||||
Self(unsafe {
|
||||
UPIntrFreeCell::new(VirtIOInput::new(&mut *(addr as *mut VirtIOHeader)).unwrap())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl INPUTDevice for VirtIOINPUT {
|
||||
fn handle_irq(&self) {
|
||||
let mut input = self.0.exclusive_access();
|
||||
input.ack_interrupt();
|
||||
let event = input.pop_pending_event().unwrap();
|
||||
let dtype = match Decoder::decode(
|
||||
event.event_type as usize,
|
||||
event.code as usize,
|
||||
event.value as usize,
|
||||
) {
|
||||
Ok(dtype) => dtype,
|
||||
Err(_) => return,
|
||||
};
|
||||
match dtype {
|
||||
virtio_input_decoder::DecodeType::Key(key, r#type) => {
|
||||
println!("{:?} {:?}", key, r#type);
|
||||
if r#type == KeyType::Press {
|
||||
let mut inner = PAD.exclusive_access();
|
||||
let a = inner.as_ref().unwrap();
|
||||
match key.to_char() {
|
||||
Ok(mut k) => {
|
||||
if k == '\r' {
|
||||
a.repaint(k.to_string() + "\n")
|
||||
} else {
|
||||
a.repaint(k.to_string())
|
||||
}
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
virtio_input_decoder::DecodeType::Mouse(mouse) => println!("{:?}", mouse),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
pub mod block;
|
||||
pub mod chardev;
|
||||
pub mod gpu;
|
||||
pub mod input;
|
||||
pub mod plic;
|
||||
|
||||
pub use block::BLOCK_DEVICE;
|
||||
pub use chardev::UART;
|
||||
pub use gpu::*;
|
||||
pub use input::*;
|
||||
|
@ -11,6 +11,6 @@ pub trait File: Send + Sync {
|
||||
fn write(&self, buf: UserBuffer) -> usize;
|
||||
}
|
||||
|
||||
pub use inode::{list_apps, open_file, OSInode, OpenFlags};
|
||||
pub use inode::{list_apps, open_file, OSInode, OpenFlags, ROOT_INODE};
|
||||
pub use pipe::{make_pipe, Pipe};
|
||||
pub use stdio::{Stdin, Stdout};
|
||||
|
79
os/src/gui/button.rs
Normal file
79
os/src/gui/button.rs
Normal file
@ -0,0 +1,79 @@
|
||||
use alloc::{string::String, sync::Arc};
|
||||
use embedded_graphics::{
|
||||
mono_font::{
|
||||
ascii::{FONT_10X20, FONT_6X10},
|
||||
MonoTextStyle,
|
||||
},
|
||||
pixelcolor::Rgb888,
|
||||
prelude::{Dimensions, Point, Primitive, RgbColor, Size},
|
||||
primitives::{PrimitiveStyle, Rectangle},
|
||||
text::{Alignment, Text},
|
||||
Drawable,
|
||||
};
|
||||
|
||||
use crate::{drivers::GPU_DEVICE, sync::UPIntrFreeCell};
|
||||
|
||||
use super::{Component, Graphics};
|
||||
|
||||
pub struct Button {
|
||||
inner: UPIntrFreeCell<ButtonInner>,
|
||||
}
|
||||
|
||||
pub struct ButtonInner {
|
||||
graphic: Graphics,
|
||||
text: String,
|
||||
parent: Option<Arc<dyn Component>>,
|
||||
}
|
||||
|
||||
impl Button {
|
||||
pub fn new(size: Size, point: Point, parent: Option<Arc<dyn Component>>, text: String) -> Self {
|
||||
let point = match &parent {
|
||||
Some(p) => {
|
||||
let (_, p) = p.bound();
|
||||
Point::new(p.x + point.x, p.y + point.y)
|
||||
}
|
||||
None => point,
|
||||
};
|
||||
Self {
|
||||
inner: unsafe {
|
||||
UPIntrFreeCell::new(ButtonInner {
|
||||
graphic: Graphics {
|
||||
size,
|
||||
point,
|
||||
drv: GPU_DEVICE.clone(),
|
||||
},
|
||||
text,
|
||||
parent,
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Button {
|
||||
fn paint(&self) {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let text = inner.text.clone();
|
||||
Text::with_alignment(
|
||||
text.as_str(),
|
||||
inner.graphic.bounding_box().center(),
|
||||
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
|
||||
Alignment::Center,
|
||||
)
|
||||
.draw(&mut inner.graphic);
|
||||
}
|
||||
|
||||
fn add(&self, comp: alloc::sync::Arc<dyn Component>) {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn bound(
|
||||
&self,
|
||||
) -> (
|
||||
embedded_graphics::prelude::Size,
|
||||
embedded_graphics::prelude::Point,
|
||||
) {
|
||||
let inner = self.inner.exclusive_access();
|
||||
(inner.graphic.size, inner.graphic.point)
|
||||
}
|
||||
}
|
57
os/src/gui/graphic.rs
Normal file
57
os/src/gui/graphic.rs
Normal file
@ -0,0 +1,57 @@
|
||||
use alloc::sync::Arc;
|
||||
use embedded_graphics::{
|
||||
draw_target::DrawTarget,
|
||||
pixelcolor::Rgb888,
|
||||
prelude::{OriginDimensions, Point, RgbColor, Size},
|
||||
};
|
||||
|
||||
use crate::drivers::{GPUDevice, GPU_DEVICE,};
|
||||
use crate::board::{VIRTGPU_XRES, VIRTGPU_YRES};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Graphics {
|
||||
pub size: Size,
|
||||
pub point: Point,
|
||||
pub drv: Arc<dyn GPUDevice>,
|
||||
}
|
||||
|
||||
impl Graphics {
|
||||
pub fn new(size: Size, point: Point) -> Self {
|
||||
Self {
|
||||
size,
|
||||
point,
|
||||
drv: GPU_DEVICE.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OriginDimensions for Graphics {
|
||||
fn size(&self) -> Size {
|
||||
self.size
|
||||
}
|
||||
}
|
||||
|
||||
impl DrawTarget for Graphics {
|
||||
type Color = Rgb888;
|
||||
|
||||
type Error = core::convert::Infallible;
|
||||
|
||||
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
|
||||
where
|
||||
I: IntoIterator<Item = embedded_graphics::Pixel<Self::Color>>,
|
||||
{
|
||||
let fb = self.drv.getfreambuffer();
|
||||
|
||||
pixels.into_iter().for_each(|px| {
|
||||
let idx = ((self.point.y + px.0.y) * VIRTGPU_XRES as i32 + self.point.x + px.0.x) as usize * 4;
|
||||
if idx + 2 >= fb.len() {
|
||||
return;
|
||||
}
|
||||
fb[idx] = px.1.b();
|
||||
fb[idx + 1] = px.1.g();
|
||||
fb[idx + 2] = px.1.r();
|
||||
});
|
||||
self.drv.flush();
|
||||
Ok(())
|
||||
}
|
||||
}
|
79
os/src/gui/icon.rs
Normal file
79
os/src/gui/icon.rs
Normal file
@ -0,0 +1,79 @@
|
||||
use alloc::{string::String, sync::Arc, vec::Vec};
|
||||
use embedded_graphics::{
|
||||
image::Image,
|
||||
mono_font::{ascii::FONT_10X20, iso_8859_13::FONT_6X12, MonoTextStyle},
|
||||
pixelcolor::Rgb888,
|
||||
prelude::{Point, RgbColor, Size},
|
||||
text::Text,
|
||||
Drawable,
|
||||
};
|
||||
use tinybmp::Bmp;
|
||||
|
||||
use crate::{drivers::GPU_DEVICE, sync::UPIntrFreeCell};
|
||||
use crate::board::{VIRTGPU_XRES, VIRTGPU_YRES};
|
||||
use super::{Component, Graphics, ImageComp};
|
||||
|
||||
static FILEICON: &[u8] = include_bytes!("../assert/file.bmp");
|
||||
|
||||
pub struct IconController {
|
||||
inner: UPIntrFreeCell<IconControllerInner>,
|
||||
}
|
||||
|
||||
pub struct IconControllerInner {
|
||||
files: Vec<String>,
|
||||
graphic: Graphics,
|
||||
parent: Option<Arc<dyn Component>>,
|
||||
}
|
||||
|
||||
impl IconController {
|
||||
pub fn new(files: Vec<String>, parent: Option<Arc<dyn Component>>) -> Self {
|
||||
IconController {
|
||||
inner: unsafe {
|
||||
UPIntrFreeCell::new(IconControllerInner {
|
||||
files,
|
||||
graphic: Graphics {
|
||||
size: Size::new(VIRTGPU_XRES, VIRTGPU_YRES),
|
||||
point: Point::new(0, 0),
|
||||
drv: GPU_DEVICE.clone(),
|
||||
},
|
||||
parent,
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for IconController {
|
||||
fn paint(&self) {
|
||||
println!("demo");
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let mut x = 10;
|
||||
let mut y = 10;
|
||||
let v = inner.files.clone();
|
||||
for file in v {
|
||||
println!("file");
|
||||
let bmp = Bmp::<Rgb888>::from_slice(FILEICON).unwrap();
|
||||
Image::new(&bmp, Point::new(x, y)).draw(&mut inner.graphic);
|
||||
let text = Text::new(
|
||||
file.as_str(),
|
||||
Point::new(x + 20, y + 80),
|
||||
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
|
||||
);
|
||||
text.draw(&mut inner.graphic);
|
||||
if y >= 600 {
|
||||
x = x + 70;
|
||||
y = 10;
|
||||
} else {
|
||||
y = y + 90;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add(&self, comp: Arc<dyn Component>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bound(&self) -> (Size, Point) {
|
||||
todo!()
|
||||
}
|
||||
}
|
80
os/src/gui/image.rs
Normal file
80
os/src/gui/image.rs
Normal file
@ -0,0 +1,80 @@
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use embedded_graphics::{
|
||||
image::Image,
|
||||
pixelcolor::Rgb888,
|
||||
prelude::{Point, Size},
|
||||
Drawable,
|
||||
};
|
||||
use tinybmp::Bmp;
|
||||
|
||||
use crate::{
|
||||
drivers::{BLOCK_DEVICE, GPU_DEVICE},
|
||||
sync::UPIntrFreeCell,
|
||||
};
|
||||
|
||||
use super::{Component, Graphics};
|
||||
|
||||
pub struct ImageComp {
|
||||
inner: UPIntrFreeCell<ImageInner>,
|
||||
}
|
||||
|
||||
pub struct ImageInner {
|
||||
image: &'static [u8],
|
||||
graphic: Graphics,
|
||||
parent: Option<Arc<dyn Component>>,
|
||||
}
|
||||
|
||||
impl ImageComp {
|
||||
pub fn new(
|
||||
size: Size,
|
||||
point: Point,
|
||||
v: &'static [u8],
|
||||
parent: Option<Arc<dyn Component>>,
|
||||
) -> Self {
|
||||
unsafe {
|
||||
ImageComp {
|
||||
inner: UPIntrFreeCell::new(ImageInner {
|
||||
parent,
|
||||
image: v,
|
||||
graphic: Graphics {
|
||||
size,
|
||||
point,
|
||||
drv: GPU_DEVICE.clone(),
|
||||
},
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for ImageComp {
|
||||
fn paint(&self) {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let b = unsafe {
|
||||
let len = inner.image.len();
|
||||
let ptr = inner.image.as_ptr() as *const u8;
|
||||
core::slice::from_raw_parts(ptr, len)
|
||||
};
|
||||
let bmp = Bmp::<Rgb888>::from_slice(b).unwrap();
|
||||
let point = match &inner.parent {
|
||||
Some(parent) => {
|
||||
let (_, point) = parent.bound();
|
||||
Point::new(
|
||||
point.x + inner.graphic.point.x,
|
||||
point.y + inner.graphic.point.y,
|
||||
)
|
||||
}
|
||||
None => inner.graphic.point,
|
||||
};
|
||||
Image::new(&bmp, point).draw(&mut inner.graphic);
|
||||
}
|
||||
|
||||
fn add(&self, comp: alloc::sync::Arc<dyn Component>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bound(&self) -> (Size, Point) {
|
||||
let inner = self.inner.exclusive_access();
|
||||
(inner.graphic.size, inner.graphic.point)
|
||||
}
|
||||
}
|
21
os/src/gui/mod.rs
Normal file
21
os/src/gui/mod.rs
Normal file
@ -0,0 +1,21 @@
|
||||
mod button;
|
||||
mod graphic;
|
||||
mod icon;
|
||||
mod image;
|
||||
mod panel;
|
||||
mod terminal;
|
||||
use alloc::sync::Arc;
|
||||
pub use button::*;
|
||||
use core::any::Any;
|
||||
use embedded_graphics::prelude::{Point, Size};
|
||||
pub use graphic::*;
|
||||
pub use icon::*;
|
||||
pub use image::*;
|
||||
pub use panel::*;
|
||||
pub use terminal::*;
|
||||
|
||||
pub trait Component: Send + Sync + Any {
|
||||
fn paint(&self);
|
||||
fn add(&self, comp: Arc<dyn Component>);
|
||||
fn bound(&self) -> (Size, Point);
|
||||
}
|
66
os/src/gui/panel.rs
Normal file
66
os/src/gui/panel.rs
Normal file
@ -0,0 +1,66 @@
|
||||
use alloc::{collections::VecDeque, rc::Weak, sync::Arc};
|
||||
use embedded_graphics::{
|
||||
pixelcolor::Rgb888,
|
||||
prelude::{Point, Primitive, RgbColor, Size},
|
||||
primitives::{PrimitiveStyle, Rectangle},
|
||||
Drawable,
|
||||
};
|
||||
|
||||
use crate::{drivers::GPU_DEVICE, sync::UPIntrFreeCell};
|
||||
|
||||
use super::{Component, Graphics};
|
||||
|
||||
pub struct Panel {
|
||||
inner: UPIntrFreeCell<PanelInner>,
|
||||
}
|
||||
struct PanelInner {
|
||||
graphic: Graphics,
|
||||
comps: VecDeque<Arc<dyn Component>>,
|
||||
}
|
||||
|
||||
impl Panel {
|
||||
pub fn new(size: Size, point: Point) -> Self {
|
||||
Self {
|
||||
inner: unsafe {
|
||||
UPIntrFreeCell::new(PanelInner {
|
||||
graphic: Graphics {
|
||||
size,
|
||||
point,
|
||||
drv: GPU_DEVICE.clone(),
|
||||
},
|
||||
comps: VecDeque::new(),
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Panel {
|
||||
fn paint(&self) {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
|
||||
Rectangle::new(Point::new(0, 0), inner.graphic.size)
|
||||
.into_styled(PrimitiveStyle::with_fill(Rgb888::WHITE))
|
||||
.draw(&mut inner.graphic)
|
||||
.unwrap();
|
||||
|
||||
let len = inner.comps.len();
|
||||
drop(inner);
|
||||
for i in 0..len {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let comp = Arc::downgrade(&inner.comps[i]);
|
||||
drop(inner);
|
||||
comp.upgrade().unwrap().paint();
|
||||
}
|
||||
}
|
||||
|
||||
fn add(&self, comp: alloc::sync::Arc<dyn Component>) {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
inner.comps.push_back(comp);
|
||||
}
|
||||
|
||||
fn bound(&self) -> (Size, Point) {
|
||||
let inner = self.inner.exclusive_access();
|
||||
(inner.graphic.size, inner.graphic.point)
|
||||
}
|
||||
}
|
105
os/src/gui/terminal.rs
Normal file
105
os/src/gui/terminal.rs
Normal file
@ -0,0 +1,105 @@
|
||||
use alloc::{
|
||||
collections::VecDeque,
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
};
|
||||
use embedded_graphics::{
|
||||
mono_font::{ascii::FONT_10X20, MonoTextStyle},
|
||||
pixelcolor::Rgb888,
|
||||
prelude::{Dimensions, Point, Primitive, RgbColor, Size},
|
||||
primitives::{PrimitiveStyle, Rectangle},
|
||||
text::{Alignment, Text},
|
||||
Drawable,
|
||||
};
|
||||
|
||||
use crate::{drivers::GPU_DEVICE, sync::UPIntrFreeCell};
|
||||
|
||||
use super::{button::Button, Component, Graphics, Panel};
|
||||
|
||||
pub struct Terminal {
|
||||
inner: UPIntrFreeCell<TerminalInner>,
|
||||
}
|
||||
|
||||
pub struct TerminalInner {
|
||||
pub text: String,
|
||||
titel: Option<String>,
|
||||
graphic: Graphics,
|
||||
comps: VecDeque<Arc<dyn Component>>,
|
||||
}
|
||||
|
||||
impl Terminal {
|
||||
pub fn new(
|
||||
size: Size,
|
||||
point: Point,
|
||||
parent: Option<Arc<dyn Component>>,
|
||||
titel: Option<String>,
|
||||
text: String,
|
||||
) -> Self {
|
||||
Self {
|
||||
inner: unsafe {
|
||||
UPIntrFreeCell::new(TerminalInner {
|
||||
text,
|
||||
titel,
|
||||
graphic: Graphics {
|
||||
size,
|
||||
point,
|
||||
drv: GPU_DEVICE.clone(),
|
||||
},
|
||||
comps: VecDeque::new(),
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn repaint(&self, text: String) {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
inner.text += text.as_str();
|
||||
Text::with_alignment(
|
||||
inner.text.clone().as_str(),
|
||||
Point::new(20, 50),
|
||||
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
|
||||
Alignment::Left,
|
||||
)
|
||||
.draw(&mut inner.graphic);
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Terminal {
|
||||
fn paint(&self) {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let len = inner.comps.len();
|
||||
drop(inner);
|
||||
for i in 0..len {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let comp = Arc::downgrade(&inner.comps[i]);
|
||||
drop(inner);
|
||||
comp.upgrade().unwrap().paint();
|
||||
}
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
let titel = inner.titel.get_or_insert("No Titel".to_string()).clone();
|
||||
let text = Text::new(
|
||||
titel.as_str(),
|
||||
Point::new(20, 20),
|
||||
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
|
||||
);
|
||||
text.draw(&mut inner.graphic);
|
||||
|
||||
Text::with_alignment(
|
||||
inner.text.clone().as_str(),
|
||||
Point::new(20, 50),
|
||||
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
|
||||
Alignment::Left,
|
||||
)
|
||||
.draw(&mut inner.graphic);
|
||||
}
|
||||
|
||||
fn add(&self, comp: Arc<dyn Component>) {
|
||||
let mut inner = self.inner.exclusive_access();
|
||||
inner.comps.push_back(comp);
|
||||
}
|
||||
|
||||
fn bound(&self) -> (Size, Point) {
|
||||
let inner = self.inner.exclusive_access();
|
||||
(inner.graphic.size, inner.graphic.point)
|
||||
}
|
||||
}
|
@ -3,6 +3,8 @@
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(alloc_error_handler)]
|
||||
|
||||
use crate::drivers::{GPU_DEVICE, KEYBOARD_DEVICE, MOUSE_DEVICE};
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
#[macro_use]
|
||||
@ -20,6 +22,7 @@ mod console;
|
||||
mod config;
|
||||
mod drivers;
|
||||
mod fs;
|
||||
mod gui;
|
||||
mod lang_items;
|
||||
mod mm;
|
||||
mod sbi;
|
||||
@ -29,6 +32,8 @@ mod task;
|
||||
mod timer;
|
||||
mod trap;
|
||||
|
||||
// use syscall::create_desktop; //for test
|
||||
|
||||
core::arch::global_asm!(include_str!("entry.asm"));
|
||||
|
||||
fn clear_bss() {
|
||||
@ -54,11 +59,19 @@ lazy_static! {
|
||||
pub fn rust_main() -> ! {
|
||||
clear_bss();
|
||||
mm::init();
|
||||
println!("KERN: init gpu");
|
||||
GPU_DEVICE.clone();
|
||||
println!("KERN: init keyboard");
|
||||
KEYBOARD_DEVICE.clone();
|
||||
println!("KERN: init mouse");
|
||||
MOUSE_DEVICE.clone();
|
||||
println!("KERN: init trap");
|
||||
trap::init();
|
||||
trap::enable_timer_interrupt();
|
||||
timer::set_next_trigger();
|
||||
board::device_init();
|
||||
fs::list_apps();
|
||||
//syscall::create_desktop(); //for test
|
||||
task::add_initproc();
|
||||
*DEV_NON_BLOCKING_ACCESS.exclusive_access() = true;
|
||||
task::run_tasks();
|
||||
|
63
os/src/syscall/gui.rs
Normal file
63
os/src/syscall/gui.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use alloc::{string::ToString, sync::Arc, vec::Vec};
|
||||
use embedded_graphics::{
|
||||
prelude::{Point, Size},
|
||||
primitives::arc,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
fs::ROOT_INODE,
|
||||
gui::{Button, Component, IconController, ImageComp, Panel, Terminal},
|
||||
sync::UPIntrFreeCell,
|
||||
};
|
||||
|
||||
use crate::board::{VIRTGPU_XRES, VIRTGPU_YRES};
|
||||
|
||||
static DT: &[u8] = include_bytes!("../assert/desktop.bmp");
|
||||
|
||||
lazy_static::lazy_static!(
|
||||
pub static ref DESKTOP:UPIntrFreeCell<Arc<dyn Component>> = unsafe {
|
||||
UPIntrFreeCell::new(Arc::new(Panel::new(Size::new(VIRTGPU_XRES, VIRTGPU_YRES), Point::new(0, 0))))
|
||||
};
|
||||
pub static ref PAD:UPIntrFreeCell<Option<Arc<Terminal>>> = unsafe {
|
||||
UPIntrFreeCell::new(None)
|
||||
};
|
||||
);
|
||||
|
||||
pub fn create_desktop() -> isize {
|
||||
let mut p: Arc<dyn Component + 'static> =
|
||||
Arc::new(Panel::new(Size::new(VIRTGPU_XRES, VIRTGPU_YRES), Point::new(0, 0)));
|
||||
let image = ImageComp::new(Size::new(VIRTGPU_XRES, VIRTGPU_YRES), Point::new(0, 0), DT, Some(p.clone()));
|
||||
let icon = IconController::new(ROOT_INODE.ls(), Some(p.clone()));
|
||||
p.add(Arc::new(image));
|
||||
p.add(Arc::new(icon));
|
||||
let mut desktop = DESKTOP.exclusive_access();
|
||||
*desktop = p;
|
||||
desktop.paint();
|
||||
drop(desktop);
|
||||
create_terminal();
|
||||
1
|
||||
}
|
||||
|
||||
pub fn create_terminal() {
|
||||
let desktop = DESKTOP.exclusive_access();
|
||||
let arc_t = Arc::new(Terminal::new(
|
||||
Size::new(400, 400),
|
||||
Point::new(200, 100),
|
||||
Some(desktop.clone()),
|
||||
Some("demo.txt".to_string()),
|
||||
"".to_string(),
|
||||
));
|
||||
let text = Panel::new(Size::new(400, 400), Point::new(200, 100));
|
||||
let button = Button::new(
|
||||
Size::new(20, 20),
|
||||
Point::new(370, 10),
|
||||
Some(arc_t.clone()),
|
||||
"X".to_string(),
|
||||
);
|
||||
arc_t.add(Arc::new(text));
|
||||
arc_t.add(Arc::new(button));
|
||||
arc_t.paint();
|
||||
desktop.add(arc_t.clone());
|
||||
let mut pad = PAD.exclusive_access();
|
||||
*pad = Some(arc_t);
|
||||
}
|
@ -25,13 +25,16 @@ const SYSCALL_SEMAPHORE_DOWN: usize = 1022;
|
||||
const SYSCALL_CONDVAR_CREATE: usize = 1030;
|
||||
const SYSCALL_CONDVAR_SIGNAL: usize = 1031;
|
||||
const SYSCALL_CONDVAR_WAIT: usize = 1032;
|
||||
|
||||
const SYSCALL_CREATE_DESKTOP: usize = 2000;
|
||||
mod fs;
|
||||
mod gui;
|
||||
mod process;
|
||||
mod sync;
|
||||
mod thread;
|
||||
|
||||
pub use self::gui::create_desktop;
|
||||
use fs::*;
|
||||
pub use gui::PAD;
|
||||
use process::*;
|
||||
use sync::*;
|
||||
use thread::*;
|
||||
@ -65,6 +68,7 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
||||
SYSCALL_CONDVAR_CREATE => sys_condvar_create(args[0]),
|
||||
SYSCALL_CONDVAR_SIGNAL => sys_condvar_signal(args[0]),
|
||||
SYSCALL_CONDVAR_WAIT => sys_condvar_wait(args[0], args[1]),
|
||||
SYSCALL_CREATE_DESKTOP => create_desktop(),
|
||||
_ => panic!("Unsupported syscall_id: {}", syscall_id),
|
||||
}
|
||||
}
|
||||
|
19
user/src/bin/gui.rs
Normal file
19
user/src/bin/gui.rs
Normal file
@ -0,0 +1,19 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use user_lib::create_desktop;
|
||||
|
||||
#[macro_use]
|
||||
extern crate user_lib;
|
||||
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main() -> i32 {
|
||||
println!("gui");
|
||||
create_desktop();
|
||||
println!("exit pass.");
|
||||
loop{}
|
||||
0
|
||||
}
|
||||
|
@ -198,7 +198,9 @@ pub fn condvar_signal(condvar_id: usize) {
|
||||
pub fn condvar_wait(condvar_id: usize, mutex_id: usize) {
|
||||
sys_condvar_wait(condvar_id, mutex_id);
|
||||
}
|
||||
|
||||
pub fn create_desktop() {
|
||||
sys_create_desktop();
|
||||
}
|
||||
#[macro_export]
|
||||
macro_rules! vstore {
|
||||
($var_ref: expr, $value: expr) => {
|
||||
|
@ -154,3 +154,6 @@ pub fn sys_condvar_signal(condvar_id: usize) -> isize {
|
||||
pub fn sys_condvar_wait(condvar_id: usize, mutex_id: usize) -> isize {
|
||||
syscall(SYSCALL_CONDVAR_WAIT, [condvar_id, mutex_id, 0])
|
||||
}
|
||||
pub fn sys_create_desktop() -> isize {
|
||||
syscall(2000, [0, 0, 0])
|
||||
}
|
Loading…
Reference in New Issue
Block a user