summaryrefslogtreecommitdiff
path: root/nrf-softdevice-defmt-rtt/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'nrf-softdevice-defmt-rtt/src/lib.rs')
-rw-r--r--nrf-softdevice-defmt-rtt/src/lib.rs125
1 files changed, 0 insertions, 125 deletions
diff --git a/nrf-softdevice-defmt-rtt/src/lib.rs b/nrf-softdevice-defmt-rtt/src/lib.rs
deleted file mode 100644
index 90d4d6f..0000000
--- a/nrf-softdevice-defmt-rtt/src/lib.rs
+++ /dev/null
@@ -1,125 +0,0 @@
-//! [`defmt`](https://github.com/knurling-rs/defmt) global logger over RTT.
-//!
-//! NOTE when using this crate it's not possible to use (link to) the `rtt-target` crate
-//!
-//! To use this crate, link to it by importing it somewhere in your project.
-//!
-//! ```
-//! // src/main.rs or src/bin/my-app.rs
-//! use defmt_rtt as _;
-//! ```
-//!
-//! # Blocking/Non-blocking
-//!
-//! `probe-run` puts RTT into blocking-mode, to avoid losing data.
-//!
-//! As an effect this implementation may block forever if `probe-run` disconnects on runtime. This
-//! is because the RTT buffer will fill up and writing will eventually halt the program execution.
-//!
-//! `defmt::flush` would also block forever in that case.
-
-#![no_std]
-
-mod channel;
-
-use core::sync::atomic::{AtomicBool, AtomicU8, AtomicUsize, Ordering};
-
-use crate::channel::Channel;
-
-#[defmt::global_logger]
-struct Logger;
-
-/// Global logger lock.
-static TAKEN: AtomicBool = AtomicBool::new(false);
-static INTERRUPTS_TOKEN: AtomicU8 = AtomicU8::new(0);
-static mut ENCODER: defmt::Encoder = defmt::Encoder::new();
-
-unsafe impl defmt::Logger for Logger {
- fn acquire() {
- let token = unsafe { critical_section::acquire() };
-
- if !TAKEN.load(Ordering::Relaxed) {
- // no need for CAS because interrupts are disabled
- TAKEN.store(true, Ordering::Relaxed);
-
- INTERRUPTS_TOKEN.store(token, Ordering::Relaxed);
-
- // safety: accessing the `static mut` is OK because we have disabled interrupts.
- unsafe { ENCODER.start_frame(do_write) }
- } else {
- unsafe { critical_section::release(token) };
- }
- }
-
- unsafe fn flush() {
- // SAFETY: if we get here, the global logger mutex is currently acquired
- handle().flush();
- }
-
- unsafe fn release() {
- // safety: accessing the `static mut` is OK because we have disabled interrupts.
- ENCODER.end_frame(do_write);
- TAKEN.store(false, Ordering::Relaxed);
- critical_section::release(INTERRUPTS_TOKEN.load(Ordering::Relaxed));
- }
-
- unsafe fn write(bytes: &[u8]) {
- // safety: accessing the `static mut` is OK because we have disabled interrupts.
- ENCODER.write(bytes, do_write);
- }
-}
-
-fn do_write(bytes: &[u8]) {
- unsafe { handle().write_all(bytes) }
-}
-
-#[repr(C)]
-struct Header {
- id: [u8; 16],
- max_up_channels: usize,
- max_down_channels: usize,
- up_channel: Channel,
-}
-
-const MODE_MASK: usize = 0b11;
-/// Block the application if the RTT buffer is full, wait for the host to read data.
-const MODE_BLOCK_IF_FULL: usize = 2;
-/// Don't block if the RTT buffer is full. Truncate data to output as much as fits.
-const MODE_NON_BLOCKING_TRIM: usize = 1;
-
-// TODO make configurable
-// NOTE use a power of 2 for best performance
-const SIZE: usize = 1024;
-
-// make sure we only get shared references to the header/channel (avoid UB)
-/// # Safety
-/// `Channel` API is not re-entrant; this handle should not be held from different execution
-/// contexts (e.g. thread-mode, interrupt context)
-unsafe fn handle() -> &'static Channel {
- // NOTE the `rtt-target` API is too permissive. It allows writing arbitrary data to any
- // channel (`set_print_channel` + `rprint*`) and that can corrupt defmt log frames.
- // So we declare the RTT control block here and make it impossible to use `rtt-target` together
- // with this crate.
- #[no_mangle]
- static mut _SEGGER_RTT: Header = Header {
- id: *b"SEGGER RTT\0\0\0\0\0\0",
- max_up_channels: 1,
- max_down_channels: 0,
- up_channel: Channel {
- name: NAME as *const _ as *const u8,
- buffer: unsafe { &mut BUFFER as *mut _ as *mut u8 },
- size: SIZE,
- write: AtomicUsize::new(0),
- read: AtomicUsize::new(0),
- flags: AtomicUsize::new(MODE_NON_BLOCKING_TRIM),
- },
- };
-
- #[cfg_attr(target_os = "macos", link_section = ".uninit,defmt-rtt.BUFFER")]
- #[cfg_attr(not(target_os = "macos"), link_section = ".uninit.defmt-rtt.BUFFER")]
- static mut BUFFER: [u8; SIZE] = [0; SIZE];
-
- static NAME: &[u8] = b"defmt\0";
-
- &_SEGGER_RTT.up_channel
-}