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>
This commit is contained in:
17624 files changed
+4564928
-38
No files matched your search
+33
@@ -0,0 +1,33 @@
|
||||
//! This is not an example; this is a link-pass test
|
||||
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt as rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use core::ptr;
|
||||
|
||||
use rt::entry;
|
||||
|
||||
static mut BSS1: u16 = 0;
|
||||
static mut BSS2: u8 = 0;
|
||||
static mut DATA1: u8 = 1;
|
||||
static mut DATA2: u16 = 1;
|
||||
static RODATA1: &[u8; 3] = b"012";
|
||||
static RODATA2: &[u8; 2] = b"34";
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
unsafe {
|
||||
let _bss1 = ptr::read_volatile(ptr::addr_of!(BSS1));
|
||||
let _bss2 = ptr::read_volatile(ptr::addr_of!(BSS2));
|
||||
let _data1 = ptr::read_volatile(ptr::addr_of!(DATA1));
|
||||
let _data2 = ptr::read_volatile(ptr::addr_of!(DATA2));
|
||||
let _rodata1 = ptr::read_volatile(ptr::addr_of!(RODATA1));
|
||||
let _rodata2 = ptr::read_volatile(ptr::addr_of!(RODATA2));
|
||||
}
|
||||
|
||||
loop {}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
//! using `#[cfg]` on `static` shouldn't cause compile errors
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
// This example uses an undefined cfg, `cfg(never)`
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
||||
extern crate cortex_m_rt as rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use rt::{entry, exception};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
#[cfg(never)]
|
||||
static mut COUNT: u32 = 0;
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[exception]
|
||||
fn SysTick() {
|
||||
#[cfg(never)]
|
||||
static mut FOO: u32 = 0;
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
//! This is not an example; this is a linker overflow detection test
|
||||
//! which should fail to link due to .data overflowing FLASH.
|
||||
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt as rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use core::ptr;
|
||||
use rt::entry;
|
||||
|
||||
// This large static array uses most of .rodata
|
||||
const RODATA_SIZE: usize = 250 * 1024;
|
||||
static RODATA: [u8; RODATA_SIZE] = [1u8; RODATA_SIZE];
|
||||
|
||||
// This large mutable array causes .data to use the rest of FLASH
|
||||
// without also overflowing RAM.
|
||||
const DATA_SIZE: usize = 8 * 1024;
|
||||
static mut DATA: [u8; DATA_SIZE] = [1u8; DATA_SIZE];
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
unsafe {
|
||||
let _bigdata: u8 = ptr::read_volatile(ptr::addr_of!(RODATA) as *const u8);
|
||||
let _bigdata: u8 = ptr::read_volatile(ptr::addr_of!(DATA) as *const u8);
|
||||
}
|
||||
|
||||
loop {}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
//! Manually create the interrupts portion of the vector table
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt as rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use rt::entry;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
// interrupts portion of the vector table
|
||||
#[repr(C)]
|
||||
pub union Vector {
|
||||
handler: unsafe extern "C" fn(),
|
||||
reserved: usize,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn WWDG();
|
||||
fn PVD();
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
#[link_section = ".vector_table.interrupts"]
|
||||
#[no_mangle]
|
||||
pub static __INTERRUPTS: [Vector; 3] = [
|
||||
Vector { handler: WWDG },
|
||||
Vector { reserved: 0 },
|
||||
Vector { handler: PVD },
|
||||
];
|
||||
@@ -0,0 +1,18 @@
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use cortex_m_rt::{entry, exception};
|
||||
|
||||
#[entry]
|
||||
fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[exception]
|
||||
unsafe fn DefaultHandler(_irqn: i16) -> ! {
|
||||
loop {}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use cortex_m_rt::{entry, exception};
|
||||
|
||||
#[entry]
|
||||
fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[exception]
|
||||
fn SysTick() -> ! {
|
||||
loop {}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
//! `static mut` variables local to the entry point are safe to use
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt as rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use rt::entry;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
static mut COUNT: u32 = 0;
|
||||
|
||||
loop {
|
||||
*COUNT += 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
//! This is not an example; this is a linker test that ensures
|
||||
//! that the jump from HardFault to _HardFault doesn't exceed
|
||||
//! the 2kB limit of the branch instruction.
|
||||
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use core::arch::asm;
|
||||
use cortex_m_rt::{entry, exception, ExceptionFrame};
|
||||
|
||||
// This defines both `HardFault` and `_HardFault`. Both should have
|
||||
// link_section attributes placing them at the end of the .text section,
|
||||
// close to each other. If one of them is missing that attribute, they
|
||||
// will end up separated by `foo`, which will make the linker fail.
|
||||
#[exception(trampoline = true)]
|
||||
unsafe fn HardFault(_ef: &ExceptionFrame) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[entry]
|
||||
fn foo() -> ! {
|
||||
unsafe {
|
||||
// 2kB of NOP instructions to make the function artificially larger
|
||||
asm!(".fill 1024,2,0xbf00",);
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
//! Directly plug a `main` symbol instead of using `#[entry]`
|
||||
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt as rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn main() -> ! {
|
||||
loop {}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
//! Minimal `cortex-m-rt` based program
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt as rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use rt::entry;
|
||||
|
||||
// the program entry point
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
loop {}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
//! How to override the hard fault exception handler and the default exception handler
|
||||
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m;
|
||||
extern crate cortex_m_rt as rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use cortex_m::asm;
|
||||
use rt::{entry, exception, ExceptionFrame};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[exception]
|
||||
unsafe fn DefaultHandler(_irqn: i16) {
|
||||
asm::bkpt();
|
||||
}
|
||||
|
||||
#[exception]
|
||||
unsafe fn HardFault(_ef: &ExceptionFrame) -> ! {
|
||||
asm::bkpt();
|
||||
|
||||
loop {}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
//! `cortex-m-rt` based program with a function run before RAM is initialized.
|
||||
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt as rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use rt::{entry, pre_init};
|
||||
|
||||
#[pre_init]
|
||||
unsafe fn disable_watchdog() {
|
||||
// Do what you need to disable the watchdog.
|
||||
}
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
loop {}
|
||||
}
|
||||
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use core::{
|
||||
fmt::Write,
|
||||
sync::atomic::{AtomicU32, Ordering},
|
||||
};
|
||||
|
||||
static DATA_VAL: AtomicU32 = AtomicU32::new(1234);
|
||||
|
||||
static BSS_VAL: AtomicU32 = AtomicU32::new(0);
|
||||
|
||||
#[cortex_m_rt::entry]
|
||||
fn main() -> ! {
|
||||
let x = 42;
|
||||
|
||||
loop {
|
||||
let mut hstdout = cortex_m_semihosting::hio::hstdout().unwrap();
|
||||
// check that .data and .bss were initialised OK
|
||||
if DATA_VAL.load(Ordering::Relaxed) == 1234 && BSS_VAL.load(Ordering::Relaxed) == 0 {
|
||||
_ = writeln!(hstdout, "x = {}", x);
|
||||
}
|
||||
cortex_m_semihosting::debug::exit(cortex_m_semihosting::debug::EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
// Define a panic handler that uses semihosting to exit immediately,
|
||||
// so that any panics cause qemu to quit instead of hang.
|
||||
#[panic_handler]
|
||||
fn panic(_: &core::panic::PanicInfo) -> ! {
|
||||
loop {
|
||||
cortex_m_semihosting::debug::exit(cortex_m_semihosting::debug::EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
//! Preserving state across executions of an exception handler
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt as rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use rt::{entry, exception};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
// exception handler with state
|
||||
#[exception]
|
||||
fn SysTick() {
|
||||
static mut STATE: u32 = 0;
|
||||
|
||||
*STATE += 1;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use cortex_m_rt::{entry, exception};
|
||||
|
||||
#[entry]
|
||||
fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[exception]
|
||||
unsafe fn DefaultHandler(_irqn: i16) {}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
|
||||
#[entry]
|
||||
unsafe fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use cortex_m_rt::{entry, exception};
|
||||
|
||||
#[entry]
|
||||
fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[exception]
|
||||
unsafe fn SysTick() {}
|
||||
@@ -0,0 +1,18 @@
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use cortex_m_rt::{entry, exception, ExceptionFrame};
|
||||
|
||||
#[entry]
|
||||
fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[exception]
|
||||
unsafe fn HardFault(_ef: &ExceptionFrame) -> ! {
|
||||
loop {}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
//! Checks that the declared unsafety is respected by the attributes
|
||||
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate cortex_m_rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use cortex_m_rt::{entry, exception, ExceptionFrame};
|
||||
|
||||
#[entry]
|
||||
unsafe fn main() -> ! {
|
||||
foo();
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[exception]
|
||||
unsafe fn DefaultHandler(_irqn: i16) {
|
||||
foo();
|
||||
}
|
||||
|
||||
#[exception]
|
||||
unsafe fn HardFault(_ef: &ExceptionFrame) -> ! {
|
||||
foo();
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[exception]
|
||||
unsafe fn SysTick() {
|
||||
foo();
|
||||
}
|
||||
|
||||
unsafe fn foo() {}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
//! Tests that a crate can still build with all warnings enabled.
|
||||
//!
|
||||
//! The code generated by the `cortex-m-rt` macros might need to manually
|
||||
//! `#[allow]` some of them (even though Rust does that by default for a few
|
||||
//! warnings too).
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![deny(warnings, missing_docs, rust_2018_idioms)]
|
||||
|
||||
extern crate cortex_m_rt;
|
||||
extern crate panic_halt;
|
||||
|
||||
use cortex_m_rt::{entry, exception, interrupt, pre_init, ExceptionFrame};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
enum interrupt {
|
||||
INT,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn INT();
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
union Vector {
|
||||
#[allow(dead_code)]
|
||||
handler: unsafe extern "C" fn(),
|
||||
}
|
||||
|
||||
#[link_section = ".vector_table.interrupts"]
|
||||
#[no_mangle]
|
||||
#[used]
|
||||
static __INTERRUPTS: [Vector; 1] = [Vector { handler: INT }];
|
||||
|
||||
/// Dummy interrupt.
|
||||
#[interrupt]
|
||||
fn INT() {}
|
||||
|
||||
#[exception]
|
||||
fn HardFault(_eh: &ExceptionFrame) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[pre_init]
|
||||
unsafe fn pre_init() {}
|
||||
Reference in new issue
Block a user