#[macro_export]
#[doc(hidden)]
macro_rules! rtt_init_repeat {
({ $($code:tt)+ } { $($acc:tt)* }; $n:literal: { $($_:tt)* } $($tail:tt)*) => {
$crate::rtt_init_repeat!({ $($code)* } { $($code)* $($acc)* }; $($tail)*)
};
({ $($code:tt)+ } { $($acc:tt)* };) => {
($($acc)*)
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! rtt_init_channels {
(
$field:expr;
$number:literal: {
size: $size:expr
$(, mode: $mode:path )?
$(, name: $name:literal )?
$(,)?
}
$($tail:tt)*
) => {
let mut name: *const u8 = core::ptr::null();
$( name = concat!($name, "\0").as_bytes().as_ptr(); )?
let mut mode = $crate::ChannelMode::NoBlockSkip;
$( mode = $mode; )?
$field[$number].init(name, mode, {
static mut _RTT_CHANNEL_BUFFER: MaybeUninit<[u8; $size]> = MaybeUninit::uninit();
_RTT_CHANNEL_BUFFER.as_mut_ptr()
});
$crate::rtt_init_channels!($field; $($tail)*);
};
($field:expr;) => { };
}
#[macro_export]
#[doc(hidden)]
macro_rules! rtt_init_wrappers {
($field:expr; $cons:path; { $($acc:tt)* }; $n:literal: { $($_:tt)* } $($tail:tt)*) => {
$crate::rtt_init_wrappers!(
$field;
$cons;
{
$($acc)*
$cons(&mut $field[$n] as *mut _),
};
$($tail)*)
};
($field:expr; $cons:path; { $($acc:tt)* };) => {
($($acc)*)
};
}
#[macro_export]
macro_rules! rtt_init {
{
$(up: { $($up:tt)* } )?
$(down: { $($down:tt)* } )?
} => {{
use core::mem::MaybeUninit;
use core::ptr;
use core::cell::Cell;
use $crate::UpChannel;
use $crate::DownChannel;
use $crate::rtt::*;
#[repr(C)]
pub struct RttControlBlock {
header: RttHeader,
up_channels: [RttChannel; $crate::rtt_init_repeat!({ 1 + } { 0 }; $($($up)*)?)],
down_channels: [RttChannel; $crate::rtt_init_repeat!({ 1 + } { 0 }; $($($down)*)?)],
}
#[used]
#[no_mangle]
#[export_name = "_SEGGER_RTT"]
pub static mut CONTROL_BLOCK: MaybeUninit<RttControlBlock> = MaybeUninit::uninit();
#[allow(unused)]
#[export_name = "rtt_init_must_not_be_called_multiple_times"]
fn rtt_init_must_not_be_called_multiple_times() { }
use ::rtt_target::export::critical_section;
static INITIALIZED: critical_section::Mutex<Cell<bool>> = critical_section::Mutex::new(Cell::new(false));
critical_section::with(|cs| {
if INITIALIZED.borrow(cs).get() {
panic!("rtt_init! must not be called multiple times");
}
INITIALIZED.borrow(cs).set(true);
});
unsafe {
ptr::write_bytes(CONTROL_BLOCK.as_mut_ptr(), 0, 1);
let cb = &mut *CONTROL_BLOCK.as_mut_ptr();
$( $crate::rtt_init_channels!(cb.up_channels; $($up)*); )?
$( $crate::rtt_init_channels!(cb.down_channels; $($down)*); )?
cb.header.init(cb.up_channels.len(), cb.down_channels.len());
pub struct Channels {
$( pub up: $crate::rtt_init_repeat!({ UpChannel, } {}; $($up)*), )?
$( pub down: $crate::rtt_init_repeat!({ DownChannel, } {}; $($down)*), )?
}
Channels {
$( up: $crate::rtt_init_wrappers!(cb.up_channels; UpChannel::new; {}; $($up)*), )?
$( down: $crate::rtt_init_wrappers!(cb.down_channels; DownChannel::new; {}; $($down)*), )?
}
}
}};
}
#[macro_export]
macro_rules! rtt_init_default {
() => {
$crate::rtt_init! {
up: {
0: {
size: 1024,
name: "Terminal"
}
}
down: {
0: {
size: 16,
name: "Terminal"
}
}
};
};
}