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>
144 lines
4.2 KiB
Rust
144 lines
4.2 KiB
Rust
//! FFI shim around the inline assembly in `inline.rs`.
|
|
//!
|
|
//! We use this file to precompile some assembly stubs into the static libraries you can find in
|
|
//! `bin`. Apps using the `cortex-m` crate then link against those static libraries and don't need
|
|
//! to build this file themselves.
|
|
//!
|
|
//! Nowadays the assembly stubs are no longer actual assembly files, but actually just this small
|
|
//! Rust crate that uses unstable inline assembly, coupled with the `xtask` tool to invoke rustc
|
|
//! and build the files.
|
|
//!
|
|
//! Precompiling this to a static lib allows users to call assembly routines from stable Rust, but
|
|
//! also perform [linker plugin LTO] with the precompiled artifacts to completely inline the
|
|
//! assembly routines into their code, which brings the "outline assembly" on par with "real" inline
|
|
//! assembly.
|
|
//!
|
|
//! For developers and contributors to `cortex-m`, this setup means that they don't have to install
|
|
//! any binutils, assembler, or C compiler to hack on the crate. All they need is to run `cargo
|
|
//! xtask assemble` to rebuild the archives from this file.
|
|
//!
|
|
//! Cool, right?
|
|
//!
|
|
//! # Rust version management
|
|
//!
|
|
//! Since inline assembly is still unstable, and we want to ensure that the created blobs are
|
|
//! up-to-date in CI, we have to pin the nightly version we use for this. The nightly toolchain is
|
|
//! stored in `asm-toolchain`.
|
|
//!
|
|
//! The `cargo xtask` automation will automatically install the `asm-toolchain` as well as all
|
|
//! Cortex-M targets needed to generate the blobs.
|
|
//!
|
|
//! [linker plugin LTO]: https://doc.rust-lang.org/stable/rustc/linker-plugin-lto.html
|
|
|
|
#![feature(asm)]
|
|
#![no_std]
|
|
#![crate_type = "staticlib"]
|
|
#![deny(warnings)]
|
|
// Don't warn about feature(asm) being stable on Rust >= 1.59.0
|
|
#![allow(stable_features)]
|
|
|
|
mod inline;
|
|
|
|
macro_rules! shims {
|
|
(
|
|
$( fn $name:ident( $($arg:ident: $argty:ty),* ) $(-> $ret:ty)?; )+
|
|
) => {
|
|
$(
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn $name(
|
|
$($arg: $argty),*
|
|
) $(-> $ret)? {
|
|
crate::inline::$name($($arg),*)
|
|
}
|
|
)+
|
|
};
|
|
}
|
|
|
|
shims! {
|
|
fn __bkpt();
|
|
fn __control_r() -> u32;
|
|
fn __control_w(w: u32);
|
|
fn __cpsid();
|
|
fn __cpsie();
|
|
fn __delay(cyc: u32);
|
|
fn __dmb();
|
|
fn __dsb();
|
|
fn __isb();
|
|
fn __msp_r() -> u32;
|
|
fn __msp_w(val: u32);
|
|
fn __nop();
|
|
fn __primask_r() -> u32;
|
|
fn __psp_r() -> u32;
|
|
fn __psp_w(val: u32);
|
|
fn __sev();
|
|
fn __udf() -> !;
|
|
fn __wfe();
|
|
fn __wfi();
|
|
fn __sh_syscall(nr: u32, arg: u32) -> u32;
|
|
fn __bootstrap(msp: u32, rv: u32) -> !;
|
|
}
|
|
|
|
// v7m *AND* v8m.main, but *NOT* v8m.base
|
|
#[cfg(any(armv7m, armv8m_main))]
|
|
shims! {
|
|
fn __basepri_max(val: u8);
|
|
fn __basepri_r() -> u8;
|
|
fn __basepri_w(val: u8);
|
|
fn __faultmask_r() -> u32;
|
|
fn __enable_icache();
|
|
fn __enable_dcache();
|
|
}
|
|
|
|
#[cfg(armv7em)]
|
|
shims! {
|
|
fn __basepri_max_cm7_r0p1(val: u8);
|
|
fn __basepri_w_cm7_r0p1(val: u8);
|
|
}
|
|
|
|
// Baseline and Mainline.
|
|
#[cfg(armv8m)]
|
|
shims! {
|
|
fn __tt(target: u32) -> u32;
|
|
fn __ttt(target: u32) -> u32;
|
|
fn __tta(target: u32) -> u32;
|
|
fn __ttat(target: u32) -> u32;
|
|
fn __msp_ns_r() -> u32;
|
|
fn __msp_ns_w(val: u32);
|
|
fn __bxns(val: u32);
|
|
}
|
|
|
|
// Mainline only.
|
|
#[cfg(armv8m_main)]
|
|
shims! {
|
|
fn __msplim_r() -> u32;
|
|
fn __msplim_w(val: u32);
|
|
fn __psplim_r() -> u32;
|
|
fn __psplim_w(val: u32);
|
|
}
|
|
|
|
// All targets with FPU.
|
|
#[cfg(has_fpu)]
|
|
shims! {
|
|
fn __fpscr_r() -> u32;
|
|
fn __fpscr_w(val: u32);
|
|
}
|
|
|
|
/// We *must* define a panic handler here, even though nothing here should ever be able to panic.
|
|
///
|
|
/// We prove that nothing will ever panic by calling a function that doesn't exist. If the panic
|
|
/// handler gets linked in, this causes a linker error. We always build this file with optimizations
|
|
/// enabled, but even without them the panic handler should never be linked in.
|
|
#[panic_handler]
|
|
#[link_section = ".text.asm_panic_handler"]
|
|
fn panic(_: &core::panic::PanicInfo) -> ! {
|
|
extern "C" {
|
|
#[link_name = "cortex-m internal error: panic handler not optimized out, please file an \
|
|
issue at https://github.com/rust-embedded/cortex-m"]
|
|
fn __cortex_m_should_not_panic() -> !;
|
|
}
|
|
|
|
unsafe {
|
|
__cortex_m_should_not_panic();
|
|
}
|
|
}
|