diff options
Diffstat (limited to 'nrf-softdevice-defmt-rtt/src/channel.rs')
-rw-r--r-- | nrf-softdevice-defmt-rtt/src/channel.rs | 112 |
1 files changed, 0 insertions, 112 deletions
diff --git a/nrf-softdevice-defmt-rtt/src/channel.rs b/nrf-softdevice-defmt-rtt/src/channel.rs deleted file mode 100644 index d0d899f..0000000 --- a/nrf-softdevice-defmt-rtt/src/channel.rs +++ /dev/null @@ -1,112 +0,0 @@ -use core::ptr; -use core::sync::atomic::{AtomicUsize, Ordering}; - -use crate::{MODE_BLOCK_IF_FULL, MODE_MASK, SIZE}; - -#[repr(C)] -pub(crate) struct Channel { - pub name: *const u8, - pub buffer: *mut u8, - pub size: usize, - pub write: AtomicUsize, - pub read: AtomicUsize, - /// Channel properties. - /// - /// Currently, only the lowest 2 bits are used to set the channel mode (see constants below). - pub flags: AtomicUsize, -} - -impl Channel { - pub fn write_all(&self, mut bytes: &[u8]) { - // the host-connection-status is only modified after RAM initialization while the device is - // halted, so we only need to check it once before the write-loop - let write = match self.host_is_connected() { - true => Channel::blocking_write, - false => Channel::nonblocking_write, - }; - - while !bytes.is_empty() { - let consumed = write(self, 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), pivot); - ptr::copy_nonoverlapping(bytes.as_ptr().add(pivot), self.buffer, len - pivot); - } else { - // single memcpy - ptr::copy_nonoverlapping(bytes.as_ptr(), self.buffer.add(cursor), len); - } - } - 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), pivot); - ptr::copy_nonoverlapping(bytes.as_ptr().add(pivot), self.buffer, len - pivot); - } else { - // single memcpy - ptr::copy_nonoverlapping(bytes.as_ptr(), self.buffer.add(cursor), len); - } - } - self.write.store(write.wrapping_add(len) % SIZE, Ordering::Release); - - len - } - - pub fn flush(&self) { - // return early, if host is disconnected - if !self.host_is_connected() { - return; - } - - // busy wait, until the read- catches up with the write-pointer - let read = || self.read.load(Ordering::Relaxed); - let write = || self.write.load(Ordering::Relaxed); - while read() != write() {} - } - - fn host_is_connected(&self) -> bool { - // we assume that a host is connected if we are in blocking-mode. this is what probe-run does. - self.flags.load(Ordering::Relaxed) & MODE_MASK == MODE_BLOCK_IF_FULL - } -} |