components/
debug_writer.rs1use capsules_core::virtualizers::virtual_uart::{MuxUart, UartDevice};
31use capsules_system::debug_writer::uart_debug_writer::UartDebugWriter;
32use core::mem::MaybeUninit;
33use kernel::capabilities;
34use kernel::capabilities::SetDebugWriterCapability;
35use kernel::collections::ring_buffer::RingBuffer;
36use kernel::component::Component;
37use kernel::hil;
38use kernel::hil::uart;
39
40pub const DEFAULT_DEBUG_BUFFER_KBYTE: usize = 2;
46
47const DEBUG_BUFFER_SPLIT: usize = 64;
50
51#[macro_export]
57macro_rules! debug_writer_component_static {
58    ($BUF_SIZE_KB:expr) => {{
59        let uart = kernel::static_buf!(capsules_core::virtualizers::virtual_uart::UartDevice);
60        let ring = kernel::static_buf!(kernel::collections::ring_buffer::RingBuffer<'static, u8>);
61        let buffer = kernel::static_buf!([u8; 1024 * $BUF_SIZE_KB]);
62        let debug =
63            kernel::static_buf!(capsules_system::debug_writer::uart_debug_writer::UartDebugWriter);
64
65        (uart, ring, buffer, debug)
66    };};
67    () => {{
68        $crate::debug_writer_component_static!($crate::debug_writer::DEFAULT_DEBUG_BUFFER_KBYTE)
69    };};
70}
71
72#[macro_export]
78macro_rules! debug_writer_no_mux_component_static {
79    ($BUF_SIZE_KB:expr) => {{
80        let ring = kernel::static_buf!(kernel::collections::ring_buffer::RingBuffer<'static, u8>);
81        let buffer = kernel::static_buf!([u8; 1024 * $BUF_SIZE_KB]);
82        let debug =
83            kernel::static_buf!(capsules_system::debug_writer::uart_debug_writer::UartDebugWriter);
84
85        (ring, buffer, debug)
86    };};
87    () => {{
88        use $crate::debug_writer::DEFAULT_DEBUG_BUFFER_KBYTE;
89        $crate::debug_writer_no_mux_component_static!(DEFAULT_DEBUG_BUFFER_KBYTE)
90    };};
91}
92
93#[allow(dead_code)]
95pub struct DebugWriterComponent<const BUF_SIZE_BYTES: usize, C: SetDebugWriterCapability> {
96    uart_mux: &'static MuxUart<'static>,
97    marker: core::marker::PhantomData<[u8; BUF_SIZE_BYTES]>,
98    capability: C,
99}
100
101impl<const BUF_SIZE_BYTES: usize, C: SetDebugWriterCapability>
102    DebugWriterComponent<BUF_SIZE_BYTES, C>
103{
104    #[cfg(target_has_atomic = "ptr")]
107    pub fn new<P: kernel::platform::chip::ThreadIdProvider>(
108        uart_mux: &'static MuxUart,
109        capability: C,
110    ) -> Self {
111        kernel::debug::initialize_debug_writer_wrapper::<P>();
112
113        Self {
114            uart_mux,
115            marker: core::marker::PhantomData,
116            capability,
117        }
118    }
119
120    pub fn new_unsafe<F>(uart_mux: &'static MuxUart, capability: C, bind_debug_global: F) -> Self
141    where
142        F: FnOnce(),
143    {
144        bind_debug_global();
145
146        Self {
147            uart_mux,
148            marker: core::marker::PhantomData,
149            capability,
150        }
151    }
152}
153
154pub struct Capability;
155unsafe impl capabilities::ProcessManagementCapability for Capability {}
156
157impl<const BUF_SIZE_BYTES: usize, C: SetDebugWriterCapability> Component
158    for DebugWriterComponent<BUF_SIZE_BYTES, C>
159{
160    type StaticInput = (
161        &'static mut MaybeUninit<UartDevice<'static>>,
162        &'static mut MaybeUninit<RingBuffer<'static, u8>>,
163        &'static mut MaybeUninit<[u8; BUF_SIZE_BYTES]>,
164        &'static mut MaybeUninit<UartDebugWriter>,
165    );
166    type Output = ();
167
168    fn finalize(self, s: Self::StaticInput) -> Self::Output {
169        let buf = s.2.write([0; BUF_SIZE_BYTES]);
170
171        let (output_buf, internal_buf) = buf.split_at_mut(DEBUG_BUFFER_SPLIT);
172
173        let debugger_uart = s.0.write(UartDevice::new(self.uart_mux, false));
175        debugger_uart.setup();
176        let ring_buffer = s.1.write(RingBuffer::new(internal_buf));
177        let debugger =
178            s.3.write(UartDebugWriter::new(debugger_uart, output_buf, ring_buffer));
179        hil::uart::Transmit::set_transmit_client(debugger_uart, debugger);
180
181        kernel::debug::set_debug_writer_wrapper(debugger, self.capability);
182    }
183}
184
185#[allow(dead_code)]
187pub struct DebugWriterNoMuxComponent<
188    U: uart::Uart<'static> + uart::Transmit<'static> + 'static,
189    const BUF_SIZE_BYTES: usize,
190    C: SetDebugWriterCapability,
191> {
192    uart: &'static U,
193    marker: core::marker::PhantomData<[u8; BUF_SIZE_BYTES]>,
194    capability: C,
195}
196
197impl<
198        U: uart::Uart<'static> + uart::Transmit<'static> + 'static,
199        const BUF_SIZE_BYTES: usize,
200        C: SetDebugWriterCapability,
201    > DebugWriterNoMuxComponent<U, BUF_SIZE_BYTES, C>
202{
203    pub fn new(uart: &'static U, capability: C) -> Self {
204        Self {
205            uart,
206            marker: core::marker::PhantomData,
207            capability,
208        }
209    }
210}
211
212impl<
213        U: uart::Uart<'static> + uart::Transmit<'static> + 'static,
214        const BUF_SIZE_BYTES: usize,
215        C: SetDebugWriterCapability,
216    > Component for DebugWriterNoMuxComponent<U, BUF_SIZE_BYTES, C>
217{
218    type StaticInput = (
219        &'static mut MaybeUninit<RingBuffer<'static, u8>>,
220        &'static mut MaybeUninit<[u8; BUF_SIZE_BYTES]>,
221        &'static mut MaybeUninit<UartDebugWriter>,
222    );
223    type Output = ();
224
225    fn finalize(self, s: Self::StaticInput) -> Self::Output {
226        let buf = s.1.write([0; BUF_SIZE_BYTES]);
227        let (output_buf, internal_buf) = buf.split_at_mut(DEBUG_BUFFER_SPLIT);
228
229        let ring_buffer = s.0.write(RingBuffer::new(internal_buf));
231        let debugger =
232            s.2.write(UartDebugWriter::new(self.uart, output_buf, ring_buffer));
233        hil::uart::Transmit::set_transmit_client(self.uart, debugger);
234
235        kernel::debug::set_debug_writer_wrapper(debugger, self.capability);
236
237        let _ = self.uart.configure(uart::Parameters {
238            baud_rate: 115200,
239            width: uart::Width::Eight,
240            stop_bits: uart::StopBits::One,
241            parity: uart::Parity::None,
242            hw_flow_control: false,
243        });
244    }
245}