Add RTT logging
This commit is contained in:
21
Cargo.lock
generated
21
Cargo.lock
generated
@ -1126,6 +1126,16 @@ dependencies = [
|
|||||||
"crc-any",
|
"crc-any",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rtt-target"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3afa12c77ba1b9bf560e4039a9b9a08bb9cde0e9e6923955eeb917dd8d5cf303"
|
||||||
|
dependencies = [
|
||||||
|
"critical-section",
|
||||||
|
"ufmt-write",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
@ -1320,8 +1330,10 @@ dependencies = [
|
|||||||
name = "tangentbord1"
|
name = "tangentbord1"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"atomic-polyfill 1.0.2",
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
"cortex-m-rt",
|
"cortex-m-rt",
|
||||||
|
"critical-section",
|
||||||
"embassy-executor",
|
"embassy-executor",
|
||||||
"embassy-futures",
|
"embassy-futures",
|
||||||
"embassy-rp",
|
"embassy-rp",
|
||||||
@ -1335,11 +1347,14 @@ dependencies = [
|
|||||||
"embedded-io",
|
"embedded-io",
|
||||||
"fixed",
|
"fixed",
|
||||||
"futures",
|
"futures",
|
||||||
|
"heapless",
|
||||||
"log",
|
"log",
|
||||||
|
"once_cell",
|
||||||
"pio",
|
"pio",
|
||||||
"pio-proc",
|
"pio-proc",
|
||||||
"postcard",
|
"postcard",
|
||||||
"ron",
|
"ron",
|
||||||
|
"rtt-target",
|
||||||
"smart-leds",
|
"smart-leds",
|
||||||
"static_cell",
|
"static_cell",
|
||||||
"tgnt",
|
"tgnt",
|
||||||
@ -1410,6 +1425,12 @@ version = "1.16.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ufmt-write"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.8"
|
version = "1.0.8"
|
||||||
|
|||||||
@ -31,6 +31,11 @@ smart-leds = "0.3.0"
|
|||||||
embedded-alloc = "0.5.0"
|
embedded-alloc = "0.5.0"
|
||||||
postcard = { version = "1.0.4", features = ["alloc"] }
|
postcard = { version = "1.0.4", features = ["alloc"] }
|
||||||
fixed = "1.23.1"
|
fixed = "1.23.1"
|
||||||
|
rtt-target = "0.4.0"
|
||||||
|
heapless = "0.7.16"
|
||||||
|
once_cell = { version = "1.17.1", default-features = false }
|
||||||
|
atomic-polyfill = "1.0.2"
|
||||||
|
critical-section = "1.1.1"
|
||||||
|
|
||||||
#[patch."https://git.nubo.sh/hulthe/tgnt.git"]
|
#[patch."https://git.nubo.sh/hulthe/tgnt.git"]
|
||||||
#tgnt = { path = "../tgnt" }
|
#tgnt = { path = "../tgnt" }
|
||||||
|
|||||||
@ -4,11 +4,12 @@ use core::mem::MaybeUninit;
|
|||||||
|
|
||||||
use embedded_alloc::Heap;
|
use embedded_alloc::Heap;
|
||||||
|
|
||||||
|
pub const HEAP_SIZE: usize = 4096;
|
||||||
|
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static HEAP: Heap = Heap::empty();
|
static HEAP: Heap = Heap::empty();
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
const HEAP_SIZE: usize = 4096;
|
|
||||||
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
|
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
|
||||||
unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) }
|
unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,21 +14,33 @@ use embassy_time::{Duration, Timer};
|
|||||||
use log::error;
|
use log::error;
|
||||||
use tangentbord1::board::Board;
|
use tangentbord1::board::Board;
|
||||||
use tangentbord1::keyboard::{Half, KeyboardConfig};
|
use tangentbord1::keyboard::{Half, KeyboardConfig};
|
||||||
|
use tangentbord1::logger::Logger;
|
||||||
use tangentbord1::util::{stall, wheel};
|
use tangentbord1::util::{stall, wheel};
|
||||||
use tangentbord1::ws2812::{Rgb, Ws2812};
|
use tangentbord1::ws2812::{Rgb, Ws2812};
|
||||||
use tangentbord1::{allocator, uart, usb};
|
use tangentbord1::{allocator, rtt, uart, usb};
|
||||||
use tgnt::layer::Layer;
|
use tgnt::layer::Layer;
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let half = Half::Left;
|
let half = Half::Left;
|
||||||
|
|
||||||
|
let rtt_write = rtt::init_rtt_logger();
|
||||||
|
let logger = Logger {
|
||||||
|
outputs: [rtt_write],
|
||||||
|
};
|
||||||
|
logger.init();
|
||||||
|
|
||||||
|
log::error!("log_level: error");
|
||||||
|
log::warn!("log_level: warn");
|
||||||
|
log::info!("log_level: info");
|
||||||
|
log::debug!("log_level: debug");
|
||||||
|
log::trace!("log_level: trace");
|
||||||
|
|
||||||
allocator::init();
|
allocator::init();
|
||||||
|
|
||||||
let p = embassy_rp::init(Default::default());
|
let p = embassy_rp::init(Default::default());
|
||||||
let board = Board::from(p);
|
let board = Board::from(p);
|
||||||
|
|
||||||
let _led = Output::new(board.d13, Level::High);
|
|
||||||
let _neopixel_power = Output::new(board.neopixel_power, Level::High);
|
let _neopixel_power = Output::new(board.neopixel_power, Level::High);
|
||||||
|
|
||||||
let mut neopixel = Ws2812::new(board.PIO0, board.DMA_CH0, board.neopixel);
|
let mut neopixel = Ws2812::new(board.PIO0, board.DMA_CH0, board.neopixel);
|
||||||
|
|||||||
@ -14,21 +14,33 @@ use embassy_time::{Duration, Timer};
|
|||||||
use log::error;
|
use log::error;
|
||||||
use tangentbord1::board::Board;
|
use tangentbord1::board::Board;
|
||||||
use tangentbord1::keyboard::{Half, KeyboardConfig};
|
use tangentbord1::keyboard::{Half, KeyboardConfig};
|
||||||
|
use tangentbord1::logger::Logger;
|
||||||
use tangentbord1::util::{stall, wheel};
|
use tangentbord1::util::{stall, wheel};
|
||||||
use tangentbord1::ws2812::{Rgb, Ws2812};
|
use tangentbord1::ws2812::{Rgb, Ws2812};
|
||||||
use tangentbord1::{allocator, uart, usb};
|
use tangentbord1::{allocator, rtt, uart, usb};
|
||||||
use tgnt::layer::Layer;
|
use tgnt::layer::Layer;
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let half = Half::Right;
|
let half = Half::Right;
|
||||||
|
|
||||||
|
let rtt_write = rtt::init_rtt_logger();
|
||||||
|
let logger = Logger {
|
||||||
|
outputs: [rtt_write],
|
||||||
|
};
|
||||||
|
logger.init();
|
||||||
|
|
||||||
|
log::error!("log_level: error");
|
||||||
|
log::warn!("log_level: warn");
|
||||||
|
log::info!("log_level: info");
|
||||||
|
log::debug!("log_level: debug");
|
||||||
|
log::trace!("log_level: trace");
|
||||||
|
|
||||||
allocator::init();
|
allocator::init();
|
||||||
|
|
||||||
let p = embassy_rp::init(Default::default());
|
let p = embassy_rp::init(Default::default());
|
||||||
let board = Board::from(p);
|
let board = Board::from(p);
|
||||||
|
|
||||||
let _led = Output::new(board.d13, Level::High);
|
|
||||||
let _neopixel_power = Output::new(board.neopixel_power, Level::High);
|
let _neopixel_power = Output::new(board.neopixel_power, Level::High);
|
||||||
|
|
||||||
let mut neopixel = Ws2812::new(board.PIO0, board.DMA_CH0, board.neopixel);
|
let mut neopixel = Ws2812::new(board.PIO0, board.DMA_CH0, board.neopixel);
|
||||||
|
|||||||
0
src/defmt.rs
Normal file
0
src/defmt.rs
Normal file
@ -12,8 +12,10 @@ pub mod allocator;
|
|||||||
pub mod board;
|
pub mod board;
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
pub mod lights;
|
pub mod lights;
|
||||||
|
pub mod logger;
|
||||||
pub mod neopixel;
|
pub mod neopixel;
|
||||||
pub mod panic_handler;
|
pub mod panic_handler;
|
||||||
|
pub mod rtt;
|
||||||
pub mod uart;
|
pub mod uart;
|
||||||
pub mod usb;
|
pub mod usb;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|||||||
60
src/logger.rs
Normal file
60
src/logger.rs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
use core::{fmt::Write, sync::atomic::Ordering};
|
||||||
|
|
||||||
|
use atomic_polyfill::AtomicBool;
|
||||||
|
use embassy_time::Instant;
|
||||||
|
use log::{Metadata, Record};
|
||||||
|
use static_cell::StaticCell;
|
||||||
|
|
||||||
|
pub const LOGGER_OUTPUTS: usize = 1;
|
||||||
|
|
||||||
|
pub struct Logger {
|
||||||
|
pub outputs: [fn(&[u8]); LOGGER_OUTPUTS],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Logger {
|
||||||
|
/// Set this as the global logger.
|
||||||
|
///
|
||||||
|
/// Calling this function more than once does nothing.
|
||||||
|
pub fn init(self) {
|
||||||
|
// guard against calling this multiple times
|
||||||
|
static INITIALIZED: AtomicBool = AtomicBool::new(false);
|
||||||
|
if INITIALIZED.fetch_or(true, Ordering::SeqCst) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LOGGER: StaticCell<Logger> = StaticCell::new();
|
||||||
|
let logger = LOGGER.init(self);
|
||||||
|
unsafe { log::set_logger_racy(logger).unwrap() };
|
||||||
|
log::set_max_level(log::LevelFilter::Debug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl log::Log for Logger {
|
||||||
|
fn enabled(&self, _metadata: &Metadata) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn log(&self, record: &Record) {
|
||||||
|
if self.enabled(record.metadata()) {
|
||||||
|
let now = Instant::now();
|
||||||
|
let s = now.as_secs();
|
||||||
|
let ms = now.as_millis() % 1000;
|
||||||
|
let level = record.metadata().level();
|
||||||
|
let mut w = &mut Writer(self);
|
||||||
|
let _ = writeln!(&mut w, "[{s}.{ms:04}] ({level}) {}", record.args());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Writer<'a>(&'a Logger);
|
||||||
|
|
||||||
|
impl Write for Writer<'_> {
|
||||||
|
fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
|
||||||
|
for output in &self.0.outputs {
|
||||||
|
output(s.as_bytes());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,28 +1,29 @@
|
|||||||
use core::panic::PanicInfo;
|
use core::{fmt::Write, panic::PanicInfo};
|
||||||
|
|
||||||
use embassy_executor::Executor;
|
use cortex_m::asm;
|
||||||
use embassy_rp::gpio::{AnyPin, Level, Output, Pin};
|
use embassy_rp::gpio::{Level, Output};
|
||||||
use embassy_time::{Duration, Timer};
|
|
||||||
use static_cell::StaticCell;
|
use crate::rtt::rtt_write;
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic_blink(_info: &PanicInfo) -> ! {
|
fn panic_blink(info: &PanicInfo) -> ! {
|
||||||
static EXECUTOR: StaticCell<Executor> = StaticCell::new();
|
cortex_m::interrupt::disable();
|
||||||
|
|
||||||
|
let _ = write!(&mut Writer, "{info}");
|
||||||
|
|
||||||
// SAFETY: we panicked, so no other code will be running.
|
// SAFETY: we panicked, so no other code will be running.
|
||||||
let p = unsafe { embassy_rp::Peripherals::steal() };
|
let p = unsafe { embassy_rp::Peripherals::steal() };
|
||||||
|
let _led = Output::new(p.PIN_11, Level::High);
|
||||||
|
|
||||||
EXECUTOR.init(Executor::new()).run(|spawner| {
|
asm::udf()
|
||||||
spawner.spawn(blink(p.PIN_11.degrade())).ok();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[embassy_executor::task]
|
/// Write to RTT
|
||||||
async fn blink(led: AnyPin) {
|
struct Writer;
|
||||||
let mut led = Output::new(led, Level::High);
|
|
||||||
|
|
||||||
loop {
|
impl core::fmt::Write for Writer {
|
||||||
Timer::after(Duration::from_secs(1)).await;
|
fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
|
||||||
led.toggle();
|
rtt_write(s.as_bytes());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
42
src/rtt.rs
Normal file
42
src/rtt.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
use core::cell::RefCell;
|
||||||
|
|
||||||
|
use critical_section::Mutex;
|
||||||
|
use rtt_target::{rtt_init, UpChannel};
|
||||||
|
|
||||||
|
pub type RttWriteFn = fn(&[u8]);
|
||||||
|
|
||||||
|
static CHANNEL: Mutex<RefCell<Option<UpChannel>>> = Mutex::new(RefCell::new(None));
|
||||||
|
|
||||||
|
/// Write directly to the rtt output. Must call [init_rtt_logger] first.
|
||||||
|
pub fn rtt_write(bytes: &[u8]) {
|
||||||
|
critical_section::with(|cs| {
|
||||||
|
let mut slot = CHANNEL.borrow_ref_mut(cs);
|
||||||
|
if let Some(channel) = slot.as_mut() {
|
||||||
|
channel.write(bytes);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_rtt_logger() -> RttWriteFn {
|
||||||
|
let channels = rtt_init! {
|
||||||
|
up: {
|
||||||
|
0: {
|
||||||
|
size: 1024
|
||||||
|
mode: NoBlockSkip
|
||||||
|
name: "Terminal"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
critical_section::with(|cs| {
|
||||||
|
let mut slot = CHANNEL.borrow_ref_mut(cs);
|
||||||
|
|
||||||
|
if slot.is_some() {
|
||||||
|
return rtt_write;
|
||||||
|
}
|
||||||
|
|
||||||
|
*slot = Some(channels.up.0);
|
||||||
|
|
||||||
|
rtt_write
|
||||||
|
})
|
||||||
|
}
|
||||||
12
src/usb.rs
12
src/usb.rs
@ -21,16 +21,13 @@ static STATE: StaticCell<State> = StaticCell::new();
|
|||||||
|
|
||||||
pub async fn setup_logger_and_keyboard(usb: USB, events: KbEvents) {
|
pub async fn setup_logger_and_keyboard(usb: USB, events: KbEvents) {
|
||||||
let mut builder = builder(usb);
|
let mut builder = builder(usb);
|
||||||
logger::setup(&mut builder).await;
|
//logger::setup(&mut builder).await;
|
||||||
|
|
||||||
log::error!("log_level: error");
|
|
||||||
log::warn!("log_level: warn");
|
|
||||||
log::info!("log_level: info");
|
|
||||||
log::debug!("log_level: debug");
|
|
||||||
log::trace!("log_level: trace");
|
|
||||||
|
|
||||||
keyboard::setup(&mut builder, events).await;
|
keyboard::setup(&mut builder, events).await;
|
||||||
|
|
||||||
|
log::info!("building usb device");
|
||||||
let usb = builder.build();
|
let usb = builder.build();
|
||||||
|
log::info!("spawning usb task");
|
||||||
Spawner::for_current_executor().await.must_spawn(run(usb));
|
Spawner::for_current_executor().await.must_spawn(run(usb));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,5 +70,6 @@ pub fn builder(usb: USB) -> Builder<'static, Driver<'static, USB>> {
|
|||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
pub async fn run(mut device: UsbDevice<'static, Driver<'static, USB>>) {
|
pub async fn run(mut device: UsbDevice<'static, Driver<'static, USB>>) {
|
||||||
|
log::info!("running usb device");
|
||||||
device.run().await
|
device.run().await
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user