components/
segger_rtt.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Component for SeggerRttMemory.
6//!
7//! This provides two `Component`s:
8//! - `SeggerRttMemoryComponent`, which creates suitable memory for the Segger
9//!   RTT capsule.
10//! - `SeggerRttComponent`, which instantiates the Segger RTT capsule.
11//!
12//! Usage
13//! -----
14//! ```rust
15//! let rtt_memory = components::segger_rtt::SeggerRttMemoryComponent::new()
16//!     .finalize(components::segger_rtt_memory_component_static!());
17//! let rtt = components::segger_rtt::SeggerRttComponent::new(mux_alarm, rtt_memory)
18//!     .finalize(components::segger_rtt_component_static!(nrf52832::rtc::Rtc));
19//! ```
20
21// Author: Guillaume Endignoux <guillaumee@google.com>
22// Last modified: 07/02/2020
23
24use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
25use core::mem::MaybeUninit;
26use kernel::component::Component;
27use kernel::hil::time::{self, Alarm};
28use kernel::utilities::cells::VolatileCell;
29use segger::rtt::{SeggerRtt, SeggerRttMemory};
30
31// Setup static space for the objects.
32#[macro_export]
33macro_rules! segger_rtt_memory_component_static {
34    () => {{
35        let rtt_memory = kernel::static_named_buf!(segger::rtt::SeggerRttMemory, "_SEGGER_RTT");
36        let up_buffer = kernel::static_buf!(
37            [kernel::utilities::cells::VolatileCell<u8>; segger::rtt::DEFAULT_UP_BUFFER_LENGTH]
38        );
39        let down_buffer = kernel::static_buf!(
40            [kernel::utilities::cells::VolatileCell<u8>; segger::rtt::DEFAULT_DOWN_BUFFER_LENGTH]
41        );
42
43        (rtt_memory, up_buffer, down_buffer)
44    };};
45}
46
47#[macro_export]
48macro_rules! segger_rtt_component_static {
49    ($A:ty $(,)?) => {{
50        let alarm = kernel::static_buf!(
51            capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>
52        );
53        let rtt = kernel::static_buf!(
54            segger::rtt::SeggerRtt<
55                'static,
56                capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>,
57            >
58        );
59
60        (alarm, rtt)
61    };};
62}
63
64pub struct SeggerRttMemoryRefs<'a> {
65    rtt_memory: &'a mut SeggerRttMemory<'a>,
66}
67
68impl<'a> SeggerRttMemoryRefs<'a> {
69    pub unsafe fn get_rtt_memory_ptr(&mut self) -> *mut SeggerRttMemory<'a> {
70        core::ptr::from_mut(self.rtt_memory)
71    }
72}
73
74pub struct SeggerRttMemoryComponent {}
75
76impl SeggerRttMemoryComponent {
77    pub fn new() -> SeggerRttMemoryComponent {
78        SeggerRttMemoryComponent {}
79    }
80}
81
82impl Component for SeggerRttMemoryComponent {
83    type StaticInput = (
84        &'static mut MaybeUninit<SeggerRttMemory<'static>>,
85        &'static mut MaybeUninit<[VolatileCell<u8>; segger::rtt::DEFAULT_UP_BUFFER_LENGTH]>,
86        &'static mut MaybeUninit<[VolatileCell<u8>; segger::rtt::DEFAULT_DOWN_BUFFER_LENGTH]>,
87    );
88    type Output = SeggerRttMemoryRefs<'static>;
89
90    fn finalize(self, s: Self::StaticInput) -> Self::Output {
91        let name = b"Terminal\0";
92        let up_buffer_name = name;
93        let down_buffer_name = name;
94        let up_buffer =
95            s.1.write([const { VolatileCell::new(0) }; segger::rtt::DEFAULT_UP_BUFFER_LENGTH]);
96        let down_buffer =
97            s.2.write([const { VolatileCell::new(0) }; segger::rtt::DEFAULT_DOWN_BUFFER_LENGTH]);
98
99        let rtt_memory = s.0.write(SeggerRttMemory::new_raw(
100            up_buffer_name,
101            up_buffer,
102            down_buffer_name,
103            down_buffer,
104        ));
105        SeggerRttMemoryRefs { rtt_memory }
106    }
107}
108
109pub struct SeggerRttComponent<A: 'static + time::Alarm<'static>> {
110    mux_alarm: &'static MuxAlarm<'static, A>,
111    rtt_memory_refs: SeggerRttMemoryRefs<'static>,
112}
113
114impl<A: 'static + time::Alarm<'static>> SeggerRttComponent<A> {
115    pub fn new(
116        mux_alarm: &'static MuxAlarm<'static, A>,
117        rtt_memory_refs: SeggerRttMemoryRefs<'static>,
118    ) -> SeggerRttComponent<A> {
119        SeggerRttComponent {
120            mux_alarm,
121            rtt_memory_refs,
122        }
123    }
124}
125
126impl<A: 'static + time::Alarm<'static>> Component for SeggerRttComponent<A> {
127    type StaticInput = (
128        &'static mut MaybeUninit<VirtualMuxAlarm<'static, A>>,
129        &'static mut MaybeUninit<SeggerRtt<'static, VirtualMuxAlarm<'static, A>>>,
130    );
131    type Output = &'static SeggerRtt<'static, VirtualMuxAlarm<'static, A>>;
132
133    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
134        let virtual_alarm_rtt = static_buffer.0.write(VirtualMuxAlarm::new(self.mux_alarm));
135        virtual_alarm_rtt.setup();
136
137        // RTT communication channel
138        let rtt = static_buffer.1.write(SeggerRtt::new(
139            virtual_alarm_rtt,
140            self.rtt_memory_refs.rtt_memory,
141        ));
142
143        virtual_alarm_rtt.set_alarm_client(rtt);
144
145        rtt
146    }
147}