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:
swaitsandClaude Opus 4.6 committed 2026-03-29 20:42:54 -06:00
1 parent 7064110293
commit 3102fc747a
17624 files changed
+4564928 -38

No files matched your search

+7
View File
@@ -0,0 +1,7 @@
# How to run
To run the compile tests, use the following command on the root of the project:
```
cargo test --package cortex-m-rt --test compiletest --features device
```
@@ -0,0 +1,16 @@
#![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, undef: u32) {}
//~^ ERROR `DefaultHandler` must have signature `unsafe fn(i16) [-> !]`
@@ -0,0 +1,18 @@
#![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) -> u32 {
//~^ ERROR `DefaultHandler` must have signature `unsafe fn(i16) [-> !]`
0
}
@@ -0,0 +1,22 @@
// ignore-test :sadface: it's not possible to prevent this user error at compile time
// see rust-lang/rust#53975 for details
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, exception};
#[entry]
fn foo() -> ! {
loop {}
}
mod hidden {
use cortex_m_rt::exception;
#[exception]
unsafe fn DefaultHandler(_irqn: i16) {}
}
@@ -0,0 +1,22 @@
#![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) {}
pub mod reachable {
use cortex_m_rt::exception;
#[exception] //~ ERROR symbol `DefaultHandler` is already defined
unsafe fn DefaultHandler(_irqn: i16) {}
}
@@ -0,0 +1,32 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, exception, interrupt};
#[allow(non_camel_case_types)]
enum interrupt {
UART0,
}
#[entry]
fn foo() -> ! {
static mut X: u32 = 0;
static mut X: i32 = 0; //~ ERROR the name `X` is defined multiple times
loop {}
}
#[exception]
fn SVCall() {
static mut X: u32 = 0;
static mut X: i32 = 0; //~ ERROR the name `X` is defined multiple times
}
#[interrupt]
fn UART0() {
static mut X: u32 = 0;
static mut X: i32 = 0; //~ ERROR the name `X` is defined multiple times
}
+12
View File
@@ -0,0 +1,12 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::entry;
#[entry(foo)] //~ ERROR This attribute accepts no arguments
fn foo() -> ! {
loop {}
}
@@ -0,0 +1,11 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::entry;
#[entry]
fn foo() {}
//~^ ERROR `#[entry]` function must have signature `[unsafe] fn() -> !`
@@ -0,0 +1,11 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::entry;
#[entry]
fn foo(undef: i32) -> ! {}
//~^ ERROR `#[entry]` function must have signature `[unsafe] fn() -> !`
@@ -0,0 +1,13 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::entry;
#[entry]
extern "C" fn foo() -> ! {
//~^ ERROR `#[entry]` function must have signature `[unsafe] fn() -> !`
loop {}
}
+19
View File
@@ -0,0 +1,19 @@
// ignore-test :sadface: it's not possible to prevent this user error at compile time
// see rust-lang/rust#53975 for details
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
mod hidden {
use cortex_m_rt::entry;
// this function needs to be "reachable" (all modules between it and the crate root must be
// `pub`) or linking will fail
#[entry]
fn foo() -> ! { //~ ERROR function is never used
loop {}
}
}
@@ -0,0 +1,26 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, exception};
#[entry]
fn foo() -> ! {
static mut COUNT: u64 = 0;
loop {
if *COUNT % 2 == 0 {
*COUNT += 1;
} else {
*COUNT *= 2;
}
}
}
#[exception]
fn SysTick() {
// If this was allowed it would lead to a data race as `SysTick` can preempt `foo`
foo(); //~ ERROR cannot find function `foo` in this scope
}
+17
View File
@@ -0,0 +1,17 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::entry;
#[entry]
fn foo() -> ! {
loop {}
}
#[entry] //~ ERROR symbol `main` is already defined
fn bar() -> ! {
loop {}
}
+15
View File
@@ -0,0 +1,15 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, exception};
#[entry]
fn foo() -> ! {
loop {}
}
#[exception(SysTick)] //~ ERROR This attribute accepts no arguments
fn SysTick() {}
@@ -0,0 +1,16 @@
#![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(undef: u32) {}
//~^ ERROR `#[exception]` handlers other than `DefaultHandler` and `HardFault` must have signature `[unsafe] fn() [-> !]`
@@ -0,0 +1,18 @@
#![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() -> u32 {
//~^ ERROR `#[exception]` handlers other than `DefaultHandler` and `HardFault` must have signature `[unsafe] fn() [-> !]`
0
}
@@ -0,0 +1,22 @@
// ignore-test :sadface: it's not possible to prevent this user error at compile time
// see rust-lang/rust#53975 for details
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, exception};
#[entry]
fn foo() -> ! {
loop {}
}
mod hidden {
use cortex_m_rt::exception;
#[exception]
fn SysTick() {}
}
@@ -0,0 +1,24 @@
#![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 DefaultHandler(_irq: i16) {}
//~^ ERROR defining a `DefaultHandler` is unsafe and requires an `unsafe fn`
#[exception]
fn HardFault() {}
//~^ ERROR defining a `HardFault` handler is unsafe and requires an `unsafe fn`
#[exception]
fn NonMaskableInt() {}
//~^ ERROR defining a `NonMaskableInt` handler is unsafe and requires an `unsafe fn`
@@ -0,0 +1,29 @@
#![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() {
static mut COUNT: u64 = 0;
if *COUNT % 2 == 0 {
*COUNT += 1;
} else {
*COUNT *= 2;
}
}
#[exception]
fn SVCall() {
// If this was allowed it would lead to a data race as `SVCall` could preempt `SysTick`
SysTick(); //~ ERROR cannot find function, tuple struct or tuple variant `SysTick` in this scope [E0425]
}
@@ -0,0 +1,22 @@
#![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() {}
pub mod reachable {
use cortex_m_rt::exception;
#[exception] //~ ERROR symbol `SysTick` is already defined
fn SysTick() {}
}
@@ -0,0 +1,16 @@
#![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 SecureFault() {}
//~^ ERROR no variant or associated item named `SecureFault`
@@ -0,0 +1,18 @@
#![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, undef: u32) -> ! {
//~^ ERROR `HardFault` handler must have signature `unsafe fn(&ExceptionFrame) -> !`
loop {}
}
@@ -0,0 +1,18 @@
#![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(trampoline = true)]
unsafe fn HardFault() -> ! {
//~^ ERROR `HardFault` handler must have signature `unsafe fn(&ExceptionFrame) -> !`
loop {}
}
@@ -0,0 +1,18 @@
#![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(trampoline = false)]
unsafe fn HardFault(_ef: &ExceptionFrame) -> ! {
//~^ ERROR `HardFault` handler must have signature `unsafe fn() -> !`
loop {}
}
@@ -0,0 +1,24 @@
// ignore-test :sadface: it's not possible to prevent this user error at compile time
// see rust-lang/rust#53975 for details
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, exception, ExceptionFrame};
#[entry]
fn foo() -> ! {
loop {}
}
mod hidden {
use cortex_m_rt::{exception, ExceptionFrame};
#[exception]
fn HardFault(_ef: &ExceptionFrame) -> ! {
loop {}
}
}
@@ -0,0 +1,26 @@
#![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(trampoline = false)]
unsafe fn HardFault() -> ! {
loop {}
}
pub mod reachable {
use cortex_m_rt::{exception, ExceptionFrame};
#[exception] //~ ERROR symbol `_HardFault` is already defined
unsafe fn HardFault(_ef: &ExceptionFrame) -> ! {
loop {}
}
}
@@ -0,0 +1,26 @@
#![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 {}
}
pub mod reachable {
use cortex_m_rt::{exception, ExceptionFrame};
#[exception] //~ ERROR symbol `_HardFault` is already defined
unsafe fn HardFault(_ef: &ExceptionFrame) -> ! {
loop {}
}
}
+20
View File
@@ -0,0 +1,20 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, interrupt};
#[entry]
fn foo() -> ! {
loop {}
}
#[allow(non_camel_case_types)]
enum interrupt {
USART1,
}
#[interrupt(true)] //~ ERROR This attribute accepts no arguments
fn USART1() {}
@@ -0,0 +1,21 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, interrupt};
#[entry]
fn foo() -> ! {
loop {}
}
#[allow(non_camel_case_types)]
enum interrupt {
USART1,
}
#[interrupt]
fn USART1(undef: i32) {}
//~^ ERROR `#[interrupt]` handlers must have signature `[unsafe] fn() [-> !]`
@@ -0,0 +1,23 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, interrupt};
#[entry]
fn foo() -> ! {
loop {}
}
#[allow(non_camel_case_types)]
enum interrupt {
USART1,
}
#[interrupt]
fn USART1() -> i32 {
//~^ ERROR `#[interrupt]` handlers must have signature `[unsafe] fn() [-> !]`
0
}
@@ -0,0 +1,22 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, interrupt};
#[entry]
fn entry() -> ! {
loop {}
}
#[allow(non_camel_case_types)]
enum interrupt {
USART1,
}
// NOTE this looks a bit better when using a device crate:
// "no variant named `foo` found for type `stm32f30x::Interrupt` in the current scope"
#[interrupt]
fn foo() {} //~ ERROR no variant or associated item named `foo` found for enum `interrupt` in the current scope [E0599]
@@ -0,0 +1,15 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, interrupt};
#[entry]
fn foo() -> ! {
loop {}
}
#[interrupt] //~ ERROR failed to resolve: use of undeclared crate or module `interrupt`
fn USART1() {}
@@ -0,0 +1,34 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, interrupt};
#[entry]
fn foo() -> ! {
loop {}
}
#[allow(non_camel_case_types)]
enum interrupt {
USART1,
USART2,
}
#[interrupt]
fn USART1() {
static mut COUNT: u64 = 0;
if *COUNT % 2 == 0 {
*COUNT += 1;
} else {
*COUNT *= 2;
}
}
#[interrupt]
fn USART2() {
USART1(); //~ ERROR cannot find function, tuple struct or tuple variant `USART1` in this scope [E0425]
}
@@ -0,0 +1,31 @@
#![allow(non_camel_case_types)]
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, interrupt};
#[entry]
fn foo() -> ! {
loop {}
}
enum interrupt {
USART1,
}
#[interrupt]
fn USART1() {}
pub mod reachable {
use cortex_m_rt::interrupt;
enum interrupt {
USART1,
}
#[interrupt] //~ ERROR symbol `USART1` is already defined
fn USART1() {}
}
@@ -0,0 +1,44 @@
//! Tests that no `&'static mut` to static mutable resources can be obtained, which would be
//! unsound.
//!
//! Regression test for https://github.com/rust-embedded/cortex-m-rt/issues/212
#![no_std]
#![no_main]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, exception, interrupt, ExceptionFrame};
#[allow(non_camel_case_types)]
enum interrupt {
UART0,
}
#[exception]
fn SVCall() {
static mut STAT: u8 = 0;
let _stat: &'static mut u8 = STAT;
//~^ ERROR lifetime may not live long enough
}
#[interrupt]
fn UART0() {
static mut STAT: u8 = 0;
let _stat: &'static mut u8 = STAT;
//~^ ERROR lifetime may not live long enough
}
#[entry]
fn you_died_of_dis_entry() -> ! {
static mut STAT: u8 = 0;
// Allowed. This is sound for the entry point since it is only ever called once, and it makes
// resources far more useful.
let _stat: &'static mut u8 = STAT;
loop {}
}
+15
View File
@@ -0,0 +1,15 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, pre_init};
#[pre_init(foo)] //~ ERROR This attribute accepts no arguments
unsafe fn foo() {}
#[entry]
fn baz() -> ! {
loop {}
}
@@ -0,0 +1,16 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, pre_init};
#[pre_init]
fn foo() {}
//~^ ERROR `#[pre_init]` function must have signature `unsafe fn()`
#[entry]
fn bar() -> ! {
loop {}
}
@@ -0,0 +1,16 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, pre_init};
#[pre_init]
unsafe fn foo(undef: i32) {}
//~^ ERROR `#[pre_init]` function must have signature `unsafe fn()`
#[entry]
fn bar() -> ! {
loop {}
}
@@ -0,0 +1,23 @@
// ignore-test :sadface: it's not possible to prevent this user error at compile time
// see rust-lang/rust#53975 for details
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
mod hidden {
use cortex_m_rt::pre_init;
// this function needs to be "reachable" (all modules between it and the crate root must be
// `pub`) or the function will be ignored
#[entry]
unsafe fn pre_init() {} //~ ERROR function is never used
}
#[entry]
fn foo() -> ! {
//~ ERROR function is never used
loop {}
}
+18
View File
@@ -0,0 +1,18 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, pre_init};
#[pre_init]
unsafe fn foo() {}
#[pre_init] //~ ERROR symbol `__pre_init` is already defined
unsafe fn bar() {}
#[entry]
fn baz() -> ! {
loop {}
}
@@ -0,0 +1,45 @@
//! Makes sure that the expansion of the attributes doesn't put the resource initializer in an
//! implicit `unsafe` block.
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, exception, interrupt};
#[allow(non_camel_case_types)]
enum interrupt {
UART0,
}
const unsafe fn init() -> u32 { 0 }
#[entry]
fn foo() -> ! {
static mut X: u32 = init(); //~ ERROR requires unsafe
loop {}
}
#[exception]
fn SVCall() {
static mut X: u32 = init(); //~ ERROR requires unsafe
}
#[exception]
unsafe fn DefaultHandler(_irq: i16) {
static mut X: u32 = init(); //~ ERROR requires unsafe
}
#[exception]
unsafe fn HardFault(_frame: &cortex_m_rt::ExceptionFrame) -> ! {
static mut X: u32 = init(); //~ ERROR requires unsafe
loop {}
}
#[interrupt]
fn UART0() {
static mut X: u32 = init(); //~ ERROR requires unsafe
}
+32
View File
@@ -0,0 +1,32 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, exception, interrupt};
#[inline] //~ ERROR this attribute is not allowed on a cortex-m-rt entry point
#[entry]
fn foo() -> ! {
loop {}
}
#[inline] //~ ERROR this attribute is not allowed on an exception handler controlled by cortex-m-rt
#[exception]
fn SysTick() {}
#[allow(non_camel_case_types)]
enum interrupt {
USART1,
USART2,
}
#[inline] //~ ERROR this attribute is not allowed on an interrupt handler controlled by cortex-m-rt
#[interrupt]
fn USART1() {}
#[cfg(feature = "device")]
#[cfg_attr(feature = "device", inline)] //~ ERROR this attribute is not allowed on an interrupt handler controlled by cortex-m-rt
#[interrupt]
fn USART2() {}
+32
View File
@@ -0,0 +1,32 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, exception, interrupt};
#[export_name = "not_allowed"] //~ ERROR this attribute is not allowed on a cortex-m-rt entry point
#[entry]
fn foo() -> ! {
loop {}
}
#[export_name = "not_allowed"] //~ ERROR this attribute is not allowed on an exception handler controlled by cortex-m-rt
#[exception]
fn SysTick() {}
#[allow(non_camel_case_types)]
enum interrupt {
USART1,
USART2,
}
#[export_name = "not_allowed"] //~ ERROR this attribute is not allowed on an interrupt handler controlled by cortex-m-rt
#[interrupt]
fn USART1() {}
#[cfg(feature = "device")]
#[cfg_attr(feature = "device", export_name = "not_allowed")] //~ ERROR this attribute is not allowed on an interrupt handler controlled by cortex-m-rt
#[interrupt]
fn USART2() {}
+32
View File
@@ -0,0 +1,32 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, exception, interrupt};
#[no_mangle] //~ ERROR this attribute is not allowed on a cortex-m-rt entry point
#[entry]
fn foo() -> ! {
loop {}
}
#[no_mangle] //~ ERROR this attribute is not allowed on an exception handler controlled by cortex-m-rt
#[exception]
fn SysTick() {}
#[allow(non_camel_case_types)]
enum interrupt {
USART1,
USART2,
}
#[no_mangle] //~ ERROR this attribute is not allowed on an interrupt handler controlled by cortex-m-rt
#[interrupt]
fn USART1() {}
#[cfg(feature = "device")]
#[cfg_attr(feature = "device", no_mangle)] //~ ERROR this attribute is not allowed on an interrupt handler controlled by cortex-m-rt
#[interrupt]
fn USART2() {}
+32
View File
@@ -0,0 +1,32 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, exception, interrupt};
#[must_use] //~ ERROR this attribute is not allowed on a cortex-m-rt entry point
#[entry]
fn foo() -> ! {
loop {}
}
#[must_use] //~ ERROR this attribute is not allowed on an exception handler controlled by cortex-m-rt
#[exception]
fn SysTick() {}
#[allow(non_camel_case_types)]
enum interrupt {
USART1,
USART2,
}
#[must_use] //~ ERROR this attribute is not allowed on an interrupt handler controlled by cortex-m-rt
#[interrupt]
fn USART1() {}
#[cfg(feature = "device")]
#[cfg_attr(feature = "device", must_use)] //~ ERROR this attribute is not allowed on an interrupt handler controlled by cortex-m-rt
#[interrupt]
fn USART2() {}
@@ -0,0 +1,13 @@
#![no_main]
#![no_std]
extern crate cortex_m_rt;
extern crate panic_halt;
use cortex_m_rt::{entry, exception};
#[exception]
#[entry] //~ ERROR this attribute is not allowed on an exception handler
fn SVCall() -> ! {
loop {}
}
+22
View File
@@ -0,0 +1,22 @@
extern crate compiletest_rs as compiletest;
use std::path::PathBuf;
fn run_mode(mode: &'static str) {
let mut config = compiletest::Config::default();
config.mode = mode.parse().expect("Invalid mode");
config.src_base = PathBuf::from(format!("tests/{}", mode));
config.target_rustcflags = Some(
"-L ../target/debug -L ../target/debug/deps -C panic=abort --cfg feature=\"device\""
.to_owned(),
);
config.clean_rmeta(); // If your tests import the parent crate, this helps with E0464
compiletest::run_tests(&config);
}
#[test]
fn compile_test() {
run_mode("compile-fail");
}