Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #628 #633

Merged
merged 8 commits into from
Nov 25, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions firmware/defmt-rtt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ version = "0.3.0"

[dependencies]
cortex-m = "0.7"
konst = "0.2"
defmt = { version = "0.3", path = "../../defmt" }
4 changes: 4 additions & 0 deletions firmware/defmt-rtt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ The fastest way to get started with `defmt` is to use our [app-template] to set

For more details about the framework check the book at https://defmt.ferrous-systems.com

## Customization

The RTT buffer size (default: 1024) can be configured with the `DEFMT_RTT_BUFFER_SIZE` environment variable in a tight memory situation. Use a power of 2 for best performance.

## Support

`defmt-rtt` is part of the [Knurling] project, [Ferrous Systems]' effort at
Expand Down
23 changes: 23 additions & 0 deletions firmware/defmt-rtt/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
fn main() {
println!("cargo:rerun-if-env-changed=DEFMT_RTT_BUFFER_SIZE");

let size = option_env!("DEFMT_RTT_BUFFER_SIZE")
.map(|s| s.parse().ok())
spookyvision marked this conversation as resolved.
Show resolved Hide resolved
.flatten()
.unwrap_or(1024_usize);

let non_power_of_two = (size & (size - 1)) != 0;

if non_power_of_two {
println!("cargo:warning=RTT buffer size of {} is not a power of two, performance will be degraded.", size)
}
spookyvision marked this conversation as resolved.
Show resolved Hide resolved

let out_dir_path = std::path::PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
let out_file_path = out_dir_path.join("consts.rs");

std::fs::write(
out_file_path,
format!("pub(crate) const BUF_SIZE: usize = {};", size),
)
.unwrap();
}
22 changes: 11 additions & 11 deletions firmware/defmt-rtt/src/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use core::{
sync::atomic::{AtomicUsize, Ordering},
};

use crate::{MODE_BLOCK_IF_FULL, MODE_MASK, SIZE};
use crate::{consts::BUF_SIZE, MODE_BLOCK_IF_FULL, MODE_MASK};

#[repr(C)]
pub(crate) struct Channel {
Expand Down Expand Up @@ -45,9 +45,9 @@ impl Channel {
let available = if read > write {
read - write - 1
} else if read == 0 {
SIZE - write - 1
BUF_SIZE - write - 1
} else {
SIZE - write
BUF_SIZE - write
};

if available == 0 {
Expand All @@ -58,9 +58,9 @@ impl Channel {
let len = bytes.len().min(available);

unsafe {
if cursor + len > SIZE {
if cursor + len > BUF_SIZE {
// split memcpy
let pivot = SIZE - cursor;
let pivot = BUF_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 {
Expand All @@ -69,21 +69,21 @@ impl Channel {
}
}
self.write
.store(write.wrapping_add(len) % SIZE, Ordering::Release);
.store(write.wrapping_add(len) % BUF_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);
// NOTE truncate atBUF_SIZE to avoid more than one "wrap-around" in a single `write` call
let len = bytes.len().min(BUF_SIZE);

unsafe {
if cursor + len > SIZE {
if cursor + len > BUF_SIZE {
// split memcpy
let pivot = SIZE - cursor;
let pivot = BUF_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 {
Expand All @@ -92,7 +92,7 @@ impl Channel {
}
}
self.write
.store(write.wrapping_add(len) % SIZE, Ordering::Release);
.store(write.wrapping_add(len) % BUF_SIZE, Ordering::Release);

len
}
Expand Down
2 changes: 2 additions & 0 deletions firmware/defmt-rtt/src/consts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// see `build.rs` for contents
include!(concat!(env!("OUT_DIR"), "/consts.rs"));
14 changes: 8 additions & 6 deletions firmware/defmt-rtt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ use cortex_m::{interrupt, register};

use crate::channel::Channel;

mod consts;

/// RTT buffer size. Default: 1024; can be customized by setting `DEFMT_RTT_BUFFER_SIZE`.
/// Use a power of 2 for best performance.
use crate::consts::BUF_SIZE;

#[defmt::global_logger]
struct Logger;

Expand Down Expand Up @@ -94,10 +100,6 @@ 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
Expand All @@ -115,7 +117,7 @@ unsafe fn handle() -> &'static Channel {
up_channel: Channel {
name: NAME as *const _ as *const u8,
buffer: unsafe { &mut BUFFER as *mut _ as *mut u8 },
size: SIZE,
size: BUF_SIZE,
write: AtomicUsize::new(0),
read: AtomicUsize::new(0),
flags: AtomicUsize::new(MODE_NON_BLOCKING_TRIM),
Expand All @@ -124,7 +126,7 @@ unsafe fn handle() -> &'static Channel {

#[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 mut BUFFER: [u8; BUF_SIZE] = [0; BUF_SIZE];

static NAME: &[u8] = b"defmt\0";

Expand Down