rtt_print/
lib.rs

1#![no_std]
2
3use core::convert::Infallible;
4use local_static::LocalStatic;
5use rtt_target::UpChannel;
6use rtt_target::rtt::*;
7pub use ufmt;
8
9pub struct Printer;
10
11#[cfg(all(feature = "print-enable", not(feature = "ufmt")))]
12#[macro_export]
13macro_rules! println {
14    ($($arg:tt)*) => {{
15        {
16            use core::fmt::Write;
17            writeln!($crate::Printer, $($arg)*).ok();
18        }
19    }};
20}
21
22#[cfg(all(feature = "print-enable", not(feature = "ufmt")))]
23#[macro_export]
24macro_rules! print {
25    ($($arg:tt)*) => {{
26        {
27            use core::fmt::Write;
28            write!($crate::Printer, $($arg)*).ok();
29        }
30    }};
31}
32
33#[cfg(all(feature = "print-enable", feature = "ufmt"))]
34#[macro_export]
35macro_rules! println {
36    ($($arg:tt)*) => {{
37        {
38            use $crate::ufmt::{self, uWrite, uwriteln, UnstableDoAsFormatter};
39            uwriteln!($crate::Printer, $($arg)*).ok();
40        }
41    }};
42}
43
44#[cfg(all(feature = "print-enable", feature = "ufmt"))]
45#[macro_export]
46macro_rules! print {
47    ($($arg:tt)*) => {{
48        {
49            use $crate::ufmt::{self, uWrite, uwrite, UnstableDoAsFormatter};
50            uwrite!($crate::Printer, $($arg)*).ok();
51        }
52    }};
53}
54
55#[cfg(not(feature = "print-enable"))]
56#[macro_export]
57macro_rules! println {
58    ($($arg:tt)*) => {{}};
59}
60
61#[cfg(not(feature = "print-enable"))]
62#[macro_export]
63macro_rules! print {
64    ($($arg:tt)*) => {{}};
65}
66
67#[repr(C)]
68pub struct RttControlBlock {
69    header: RttHeader,
70    up_channels: [RttChannel; 1],
71}
72
73#[used]
74#[unsafe(export_name = "_SEGGER_RTT")]
75pub static CONTROL_BLOCK: LocalStatic<RttControlBlock> = LocalStatic::new();
76pub static UP_CHANNEL: LocalStatic<UpChannel> = LocalStatic::new();
77
78pub fn rtt_print_init() {
79    unsafe {
80        let cb: &mut RttControlBlock = CONTROL_BLOCK.get_mut();
81        let name = "Output [0]\u{0}".as_bytes().as_ptr();
82        let mode = rtt_target::ChannelMode::NoBlockTrim;
83
84        cb.up_channels[0].init(name, mode, {
85            static _RTT_CHANNEL_BUFFER: LocalStatic<[u8; UP_CH_BUFF_SIZE]> = LocalStatic::new();
86            _RTT_CHANNEL_BUFFER.get_mut() as *mut [u8]
87        });
88
89        cb.header.init(cb.up_channels.len(), 0);
90        UP_CHANNEL.set(UpChannel::new(&mut (cb.up_channels)[0] as *mut _));
91    }
92}
93
94impl ufmt::uWrite for Printer {
95    type Error = Infallible;
96
97    fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
98        let bytes = s.as_bytes();
99        UP_CHANNEL.get_mut().write(bytes);
100
101        Ok(())
102    }
103}
104
105impl core::fmt::Write for Printer {
106    fn write_str(&mut self, s: &str) -> core::fmt::Result {
107        let bytes = s.as_bytes();
108        UP_CHANNEL.get_mut().write(bytes);
109
110        Ok(())
111    }
112}
113
114#[cfg(feature = "up-ch-buff-size-64")]
115pub const UP_CH_BUFF_SIZE: usize = 64;
116#[cfg(feature = "up-ch-buff-size-128")]
117pub const UP_CH_BUFF_SIZE: usize = 128;
118#[cfg(feature = "up-ch-buff-size-256")]
119pub const UP_CH_BUFF_SIZE: usize = 256;
120#[cfg(feature = "up-ch-buff-size-512")]
121pub const UP_CH_BUFF_SIZE: usize = 512;
122#[cfg(feature = "up-ch-buff-size-1024")]
123pub const UP_CH_BUFF_SIZE: usize = 1024;
124#[cfg(feature = "up-ch-buff-size-2048")]
125pub const UP_CH_BUFF_SIZE: usize = 2048;
126#[cfg(feature = "up-ch-buff-size-4096")]
127pub const UP_CH_BUFF_SIZE: usize = 4096;
128
129#[cfg(not(any(
130    feature = "up-ch-buff-size-64",
131    feature = "up-ch-buff-size-128",
132    feature = "up-ch-buff-size-256",
133    feature = "up-ch-buff-size-512",
134    feature = "up-ch-buff-size-1024",
135    feature = "up-ch-buff-size-2048",
136    feature = "up-ch-buff-size-4096",
137)))]
138pub const UP_CH_BUFF_SIZE: usize = 256;