This repository has been archived on 2026-08-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
donglora/vendor/xtensa-lx/src/interrupt.rs
T
swaitsandClaude Opus 4.6 3102fc747a feat: add display UI with splash screen, dashboard, and RSSI sparkline
Implement full SSD1306 OLED display support:
- Splash screen on boot (1.5s) with project name, version, board
- Dashboard showing radio state, config, counters, RSSI/SNR
- RSSI history sparkline (64-sample ring buffer, 2px-wide bars)
- DisplayOn/DisplayOff host commands routed via dedicated channel
- Pure render functions against generic DrawTarget (no hardware coupling)
- Display on/off control bypasses radio task entirely

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 20:42:54 -06:00

171 lines
3.8 KiB
Rust

//! Interrupts
use core::arch::asm;
pub use bare_metal::CriticalSection;
/// Trait for enums of external interrupt numbers.
///
/// This trait should be implemented by a peripheral access crate (PAC)
/// on its enum of available external interrupts for a specific device.
/// Each variant must convert to a u16 of its interrupt number,
/// which is its exception number - 16.
///
/// # Safety
///
/// This trait must only be implemented on enums of device interrupts. Each
/// enum variant must represent a distinct value (no duplicates are permitted),
/// and must always return the same value (do not change at runtime).
///
/// These requirements ensure safe nesting of critical sections.
pub unsafe trait InterruptNumber: Copy {
/// Return the interrupt number associated with this variant.
///
/// See trait documentation for safety requirements.
fn number(self) -> u16;
}
/// Disables all interrupts and return the previous settings
#[inline]
pub fn disable() -> u32 {
unsafe { set_mask(0) }
}
/// Enables all the interrupts
///
/// # Safety
///
/// - Do not call this function inside an `interrupt::free` critical section
#[inline]
pub unsafe fn enable() -> u32 {
set_mask(!0)
}
/// Enables specific interrupts and returns the previous setting
///
/// # Safety
///
/// - Do not call this function inside an `interrupt::free` critical section
#[inline]
pub unsafe fn set_mask(mut mask: u32) -> u32 {
asm!("
xsr {0}, intenable
rsync
",
inout(reg) mask, options(nostack)
);
mask
}
/// Disables specific interrupts and returns the previous settings
#[inline]
pub fn disable_mask(mask: u32) -> u32 {
let mut prev: u32 = 0;
let _dummy: u32;
unsafe {
asm!("
xsr.intenable {0} // get mask and temporarily disable interrupts
and {1}, {1}, {0}
rsync
wsr.intenable {1}
rsync
", inout(reg) prev, inout(reg) !mask => _dummy, options(nostack)
);
}
prev
}
/// Enables specific interrupts and returns the previous setting
///
/// # Safety
///
/// - Do not call this function inside an `interrupt::free` critical section
#[inline]
pub unsafe fn enable_mask(mask: u32) -> u32 {
let mut prev: u32 = 0;
let _dummy: u32;
asm!("
xsr.intenable {0} // get mask and temporarily disable interrupts
or {1}, {1}, {0}
rsync
wsr.intenable {1}
rsync
", inout(reg) prev, inout(reg) mask => _dummy, options(nostack));
prev
}
/// Get current interrupt mask
#[inline]
pub fn get_mask() -> u32 {
let mask: u32;
unsafe { asm!("rsr.intenable {0}", out(reg) mask) };
mask
}
/// Get currently active interrupts
#[inline]
pub fn get() -> u32 {
let mask: u32;
unsafe {
asm!("rsr.interrupt {0}", out(reg) mask, options(nostack));
}
mask
}
/// Set interrupt
///
/// Only valid for software interrupts
#[inline]
pub unsafe fn set(mask: u32) {
asm!("
wsr.intset {0}
rsync
",
in(reg) mask, options(nostack)
);
}
/// Clear interrupt
///
/// Only valid for software and edge-triggered interrupts
#[inline]
pub unsafe fn clear(mask: u32) {
asm!("
wsr.intclear {0}
rsync
",
in(reg) mask, options(nostack)
);
}
/// Get current interrupt level
#[inline]
pub fn get_level() -> u32 {
let ps: u32;
unsafe {
asm!("rsr.ps {0}", out(reg) ps, options(nostack));
};
ps & 0xf
}
/// Execute closure `f` in an interrupt-free context.
///
/// This as also known as a "critical section".
#[inline]
pub fn free<F, R>(f: F) -> R
where
F: FnOnce(&CriticalSection) -> R,
{
// disable interrupts and store old mask
let old_mask = disable();
let r = f(unsafe { &CriticalSection::new() });
// enable previously disable interrupts
unsafe {
enable_mask(old_mask);
}
r
}