diff --git a/Cargo.lock b/Cargo.lock index 4831ead..92d2cce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "blogos_armv8" +version = "0.1.0" +dependencies = [ + "lazy_static", + "spin 0.9.3", + "tock-registers", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -27,15 +36,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "rui_armv8_os" -version = "0.1.0" -dependencies = [ - "lazy_static", - "spin 0.9.2", - "tock-registers", -] - [[package]] name = "scopeguard" version = "1.1.0" @@ -50,9 +50,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" +checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" dependencies = [ "lock_api", ] diff --git a/Cargo.toml b/Cargo.toml index 4fbc36d..124be92 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,7 @@ [package] -name = "rui_armv8_os" +name = "blogos_armv8" version = "0.1.0" edition = "2021" -authors = ["Rui Li "] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/README.md b/README.md index 0778339..6a3065e 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,8 @@ https://os2022exps-doc.readthedocs.io/zh_CN/latest/index.html 4. [Lab5: 输入 - https://github.com/2X-ercha/blogOS-armV8/tree/lab5](https://github.com/2X-ercha/blogOS-armV8/tree/lab5) + 4. [Lab6: GPIO关机 - https://github.com/2X-ercha/blogOS-armV8/tree/lab6](https://github.com/2X-ercha/blogOS-armV8/tree/lab6) + -------- ## 实验环境 @@ -81,7 +83,7 @@ rm -rf gcc-arm-10* ```bash cargo build -qemu-system-aarch64 -machine virt -m 1024M -cpu cortex-a53 -nographic -kernel target/aarch64-unknown-none-softfloat/debug/rui_armv8_os +qemu-system-aarch64 -machine virt,gic-version=2 -cpu cortex-a57 -nographic -kernel target/aarch64-unknown-none-softfloat/debug/blogos_armv8 -semihosting ``` 如果你要进行`gdb`调试,可以在运行指令最后加上`-S -s`,默认端口为`1234` diff --git a/src/interrupts.rs b/src/interrupts.rs index ff23286..dde0d36 100644 --- a/src/interrupts.rs +++ b/src/interrupts.rs @@ -2,8 +2,6 @@ use core::ptr; use core::arch::asm; use core::arch::global_asm; -use tock_registers::interfaces::Readable; - /* GIC 部分的设备树描述: @@ -81,6 +79,10 @@ const ICFGR_LEVEL: u32 = 0; const TIMER_IRQ: u32 = 30; // 设备中断号33 const UART0_IRQ: u32 = 33; +// GPIO中断号39 +const GPIO_IRQ: u32 = 39; + +use tock_registers::interfaces::{Readable, Writeable}; static mut RUN_TIME: u32 = 0; @@ -161,6 +163,23 @@ pub fn init_gicv2() { // set_core(TIMER_IRQ, 0x1); // 单核实现无需设置中断目标核 clear(UART0_IRQ); //清除中断请求 enable(UART0_IRQ); //使能中断 + + // 初始化GPIO中断 + set_config(GPIO_IRQ, ICFGR_LEVEL); //电平触发 + set_priority(GPIO_IRQ, 0); //优先级设定 + clear(GPIO_IRQ); //清除中断请求 + enable(GPIO_IRQ); //使能中断 + + // 使能GPIO的poweroff key中断 + use crate::pl061::*; + unsafe{ + let pl061r: &PL061Regs = &*PL061REGS; + + // 启用pl061 gpio中的3号线中断 + // .write(): 写入一个或多个字段的值,将其他字段改写为零 + pl061r.ie.write(GPIOIE::IO3::Enabled); + + } } // 使能中断号为interrupt的中断 @@ -338,12 +357,13 @@ unsafe extern "C" fn el0_32_error(ctx: &mut ExceptionCtx) { } fn handle_irq_lines(ctx: &mut ExceptionCtx, _core_num: u32, irq_num: u32) { - if irq_num == TIMER_IRQ { handle_timer_irq(ctx); - }else if irq_num == UART0_IRQ { + } else if irq_num == UART0_IRQ { handle_uart0_rx_irq(ctx); - }else{ + } else if irq_num == GPIO_IRQ { + handle_gpio_irq(ctx); + } else{ catch(ctx, EL1_IRQ); } } @@ -389,3 +409,18 @@ fn handle_uart0_rx_irq(_ctx: &mut ExceptionCtx){ } } } + +fn handle_gpio_irq(_ctx: &mut ExceptionCtx){ + use crate::pl061::*; + crate::println!("power off!\n"); + unsafe { + let pl061r: &PL061Regs = &*PL061REGS; + + // 清除中断信号 此时get到的应该是0x8 + // .set(): 设置原始寄存器值; .get(): 获取原始寄存器值 + pl061r.ic.set(pl061r.ie.get()); + // 关机 + asm!("mov w0, #0x18"); + asm!("hlt #0xF000"); + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 608c0b3..308631a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ mod panic; mod uart_console; mod interrupts; +mod pl061; global_asm!(include_str!("start.s")); diff --git a/src/pl061.rs b/src/pl061.rs new file mode 100644 index 0000000..fbd89a3 --- /dev/null +++ b/src/pl061.rs @@ -0,0 +1,33 @@ +use tock_registers::{registers::{ReadWrite, WriteOnly}, register_bitfields, register_structs}; + +pub const PL061REGS: *mut PL061Regs = (0x0903_0000) as *mut PL061Regs; + +// https://developer.arm.com/documentation/ddi0190/b/programmer-s-model/summary-of-primecell-gpio-registers + +register_bitfields![ + u32, + + // PrimeCell GPIO interrupt mask + pub GPIOIE [ + IO3 OFFSET(3) NUMBITS(1) [ + Disabled = 0, + Enabled = 1 + ] + ], + + // PrimeCell GPIO raw interrupt status, when system_powerdown, this reg: 0x00 -> 0x08 + // pub GPIORIS [], + + // PrimeCell GPIO interrupt clear + // pub GPIOIC [] +]; + +register_structs! { + pub PL061Regs { + (0x000 => __reserved_0), + (0x410 => pub ie: ReadWrite), + (0x414 => __reserved_1), + (0x41c => pub ic: WriteOnly), + (0x420 => @END), + } +} \ No newline at end of file