diff options
author | Dario Nieuwenhuis <dirbaio@dirbaio.net> | 2020-12-03 00:46:23 +0100 |
---|---|---|
committer | Dario Nieuwenhuis <dirbaio@dirbaio.net> | 2020-12-03 00:46:23 +0100 |
commit | b84ee960edbcdd035ee8c95a0e2d64fdbce9f300 (patch) | |
tree | 27f343acd83ce819d6e5c9e8673b1820bd2b6ba6 /nrf-softdevice-defmt-rtt | |
parent | 7406f3d320dd138fd2eb763899701cdf7ff913b5 (diff) | |
download | nrf-softdevice-b84ee960edbcdd035ee8c95a0e2d64fdbce9f300.zip |
Remove useless file
Diffstat (limited to 'nrf-softdevice-defmt-rtt')
-rw-r--r-- | nrf-softdevice-defmt-rtt/src/lib2.rs | 216 |
1 files changed, 0 insertions, 216 deletions
diff --git a/nrf-softdevice-defmt-rtt/src/lib2.rs b/nrf-softdevice-defmt-rtt/src/lib2.rs deleted file mode 100644 index 2767fef..0000000 --- a/nrf-softdevice-defmt-rtt/src/lib2.rs +++ /dev/null @@ -1,216 +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 _; -//! ``` - -#![no_std] - -use core::{ - ptr, - sync::atomic::{AtomicBool, AtomicU8, AtomicUsize, Ordering}, -}; -use nrf_sofdevice::interrupt; - -// TODO make configurable -// NOTE use a power of 2 for best performance -const SIZE: usize = 1024; - -#[defmt::global_logger] -struct Logger; - -static TAKEN: AtomicBool = AtomicBool::new(false); -static INTERRUPTS_TOKEN: AtomicU8 = AtomicU8::new(0); - -unsafe impl defmt::Logger for Logger { - fn acquire() -> bool { - let token = unsafe { interrupt::disable_all() }; - if !TAKEN.load(Ordering::Relaxed) { - // no need for CAS because interrupts are disabled - TAKEN.store(true, Ordering::Relaxed); - - INTERRUPTS_TOKEN.store(token, Ordering::Relaxed); - - true - } else { - unsafe { interrupt::enable_all(token) }; - false - } - } - - unsafe fn release() { - TAKEN.store(false, Ordering::Relaxed); - unsafe { interrupt::enable_all(INTERRUPTS_TOKEN.load(Ordering::Relaxed)) }; - } - - unsafe fn write(bytes: &[u8]) { - handle().write_all(bytes) - } -} - -#[repr(C)] -struct Header { - id: [u8; 16], - max_up_channels: usize, - max_down_channels: usize, - up_channel: Channel, -} - -#[repr(C)] -struct Channel { - name: *const u8, - buffer: *mut u8, - size: usize, - write: AtomicUsize, - read: AtomicUsize, - flags: AtomicUsize, -} - -const BLOCK_IF_FULL: usize = 2; -const NOBLOCK_TRIM: usize = 1; - -impl Channel { - fn write_all(&self, mut bytes: &[u8]) { - // NOTE `flags` is modified by the host after RAM initialization while the device is halted - // it cannot otherwise be modified so we don't need to check its state more often than - // just here - if self.flags.load(Ordering::Relaxed) == BLOCK_IF_FULL { - while !bytes.is_empty() { - let consumed = self.blocking_write(bytes); - if consumed != 0 { - bytes = &bytes[consumed..]; - } - } - } else { - while !bytes.is_empty() { - let consumed = self.nonblocking_write(bytes); - if consumed != 0 { - bytes = &bytes[consumed..]; - } - } - } - } - - fn blocking_write(&self, bytes: &[u8]) -> usize { - if bytes.is_empty() { - return 0; - } - - let read = self.read.load(Ordering::Relaxed); - let write = self.write.load(Ordering::Acquire); - let available = if read > write { - read - write - 1 - } else if read == 0 { - SIZE - write - 1 - } else { - SIZE - write - }; - - if available == 0 { - return 0; - } - - let cursor = write; - let len = bytes.len().min(available); - - unsafe { - if cursor + len > SIZE { - // split memcpy - let pivot = SIZE - cursor; - ptr::copy_nonoverlapping( - bytes.as_ptr(), - self.buffer.add(cursor.into()), - pivot.into(), - ); - ptr::copy_nonoverlapping( - bytes.as_ptr().add(pivot.into()), - self.buffer, - (len - pivot).into(), - ); - } else { - // single memcpy - ptr::copy_nonoverlapping( - bytes.as_ptr(), - self.buffer.add(cursor.into()), - len.into(), - ); - } - } - self.write - .store(write.wrapping_add(len) % SIZE, Ordering::Release); - - len - } - - fn nonblocking_write(&self, bytes: &[u8]) -> usize { - let write = self.write.load(Ordering::Acquire); - let cursor = write; - // NOTE truncate at SIZE to avoid more than one "wrap-around" in a single `write` call - let len = bytes.len().min(SIZE); - - unsafe { - if cursor + len > SIZE { - // split memcpy - let pivot = SIZE - cursor; - ptr::copy_nonoverlapping( - bytes.as_ptr(), - self.buffer.add(cursor.into()), - pivot.into(), - ); - ptr::copy_nonoverlapping( - bytes.as_ptr().add(pivot.into()), - self.buffer, - (len - pivot).into(), - ); - } else { - // single memcpy - ptr::copy_nonoverlapping( - bytes.as_ptr(), - self.buffer.add(cursor.into()), - len.into(), - ); - } - } - self.write - .store(write.wrapping_add(len) % SIZE, Ordering::Release); - - len - } -} - -// 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(NOBLOCK_TRIM), - }, - }; - - #[link_section = ".uninit.defmt-rtt.BUFFER"] - static mut BUFFER: [u8; SIZE] = [0; SIZE]; - - static NAME: &[u8] = b"defmt\0"; - - &_SEGGER_RTT.up_channel -} |