diff --git a/Cargo.toml b/Cargo.toml index 7ac26a4..9f5b81f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,13 +8,12 @@ documentation = "https://docs.rs/qingke" homepage = "https://github.com/ch32-rs/qingke" categories = ["embedded", "no-std", "hardware-support"] license = "MIT/Apache-2.0" -version = "0.2.1" # for rt and macros +version = "0.3.0" # for rt and macros edition = "2021" [package] name = "qingke" -# version.workspace = true -version = "0.2.0" +version.workspace = true edition.workspace = true authors.workspace = true repository.workspace = true @@ -30,7 +29,7 @@ readme = "README.md" bit_field = "0.10.2" riscv = "0.11.1" critical-section = { version = "1.1.3", features = [ - "restore-state-u8", + "restore-state-bool", ], optional = true } defmt = { version = "0.3.8", optional = true } diff --git a/qingke-rt/Cargo.toml b/qingke-rt/Cargo.toml index 46854f2..e71972c 100644 --- a/qingke-rt/Cargo.toml +++ b/qingke-rt/Cargo.toml @@ -23,8 +23,8 @@ v4 = [] highcode = [] [dependencies] -qingke-rt-macros = { path = "./macros", version = "=0.2.1" } -qingke = { path = "../", version = "=0.2.0" } +qingke-rt-macros = { path = "./macros", version = "0.3" } +qingke = { path = "../", version = "0.3" } [package.metadata.docs.rs] targets = ["riscv32imac-unknown-none-elf"] diff --git a/qingke-rt/src/lib.rs b/qingke-rt/src/lib.rs index 0210c74..614d12a 100644 --- a/qingke-rt/src/lib.rs +++ b/qingke-rt/src/lib.rs @@ -176,6 +176,8 @@ unsafe extern "C" fn qingke_setup_interrupts() { #[cfg(not(feature = "highcode"))] mtvec::write(0x00000000, TrapMode::VectoredAddress); + + qingke::pfic::wfi_to_wfe(true); } #[doc(hidden)] diff --git a/src/critical_section_impl.rs b/src/critical_section_impl.rs index 7931dbb..189ca3b 100644 --- a/src/critical_section_impl.rs +++ b/src/critical_section_impl.rs @@ -6,16 +6,13 @@ set_impl!(SingleHartCriticalSection); unsafe impl Impl for SingleHartCriticalSection { unsafe fn acquire() -> RawRestoreState { - let irq_state = gintenr::read(); - if irq_state & 0x08 != 0 { - gintenr::write(irq_state & (!0x08)); - } - irq_state as u8 // as the high bits are reserved 0x0. + (gintenr::set_disable() & 0x8) != 0 } unsafe fn release(irq_state: RawRestoreState) { // Only re-enable interrupts if they were enabled before the critical section. - let irq_state = irq_state as usize; - gintenr::write(gintenr::read() | (irq_state & 0x08)); + if irq_state { + gintenr::set_enable(); + } } } diff --git a/src/pfic.rs b/src/pfic.rs index f94164b..b0dff45 100644 --- a/src/pfic.rs +++ b/src/pfic.rs @@ -167,3 +167,16 @@ pub unsafe fn disable_vtf(channel: u8) { let val = ptr::read_volatile(PFIC_VTFADDRR0.offset(channel as isize)); ptr::write_volatile(PFIC_VTFADDRR0.offset(channel as isize), val & 0xFFFF_FFFE); } + +pub unsafe fn wfi_to_wfe(v: bool) { + critical_section::with(|_| { + let mut val = ptr::read_volatile(PFIC_SCTLR); + // 0x8 is WFITOWFE bit + if v { + val |= 0x8; + } else { + val &= !0x8; + } + ptr::write_volatile(PFIC_SCTLR, val); + }); +} diff --git a/src/register/gintenr.rs b/src/register/gintenr.rs index b512671..714c7a1 100644 --- a/src/register/gintenr.rs +++ b/src/register/gintenr.rs @@ -17,15 +17,20 @@ pub fn read() -> usize { #[inline] pub unsafe fn write(bits: usize) { - asm!("csrs 0x800, {}", in(reg) bits); + asm!("csrw 0x800, {}", in(reg) bits); } #[inline] pub unsafe fn set_enable() { - write(0x08) + let mask = 0x8; + asm!("csrs 0x800, {}", in(reg) mask); } #[inline] -pub unsafe fn set_disable() { - write(0x00) +/// Disable interrupt and return the old `GINTENR` value +pub fn set_disable() -> usize { + let prev: usize; + let mask = 0x8usize; + unsafe { asm!("csrrc {}, 0x800, {}", out(reg) prev, in(reg) mask) }; + prev }