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    pub rtt_memory: &'a mut SeggerRttMemory<'a>,
66}
67
68pub struct SeggerRttMemoryComponent {}
69
70impl SeggerRttMemoryComponent {
71    pub fn new() -> SeggerRttMemoryComponent {
72        SeggerRttMemoryComponent {}
73    }
74}
75
76impl Component for SeggerRttMemoryComponent {
77    type StaticInput = (
78        &'static mut MaybeUninit<SeggerRttMemory<'static>>,
79        &'static mut MaybeUninit<[VolatileCell<u8>; segger::rtt::DEFAULT_UP_BUFFER_LENGTH]>,
80        &'static mut MaybeUninit<[VolatileCell<u8>; segger::rtt::DEFAULT_DOWN_BUFFER_LENGTH]>,
81    );
82    type Output = SeggerRttMemoryRefs<'static>;
83
84    fn finalize(self, s: Self::StaticInput) -> Self::Output {
85        let name = b"Terminal\0";
86        let up_buffer_name = name;
87        let down_buffer_name = name;
88        let up_buffer =
89            s.1.write([const { VolatileCell::new(0) }; segger::rtt::DEFAULT_UP_BUFFER_LENGTH]);
90        let down_buffer =
91            s.2.write([const { VolatileCell::new(0) }; segger::rtt::DEFAULT_DOWN_BUFFER_LENGTH]);
92
93        let rtt_memory = s.0.write(SeggerRttMemory::new_raw(
94            up_buffer_name,
95            up_buffer,
96            down_buffer_name,
97            down_buffer,
98        ));
99        SeggerRttMemoryRefs { rtt_memory }
100    }
101}
102
103pub struct SeggerRttComponent<A: 'static + time::Alarm<'static>> {
104    mux_alarm: &'static MuxAlarm<'static, A>,
105    rtt_memory_refs: SeggerRttMemoryRefs<'static>,
106}
107
108impl<A: 'static + time::Alarm<'static>> SeggerRttComponent<A> {
109    pub fn new(
110        mux_alarm: &'static MuxAlarm<'static, A>,
111        rtt_memory_refs: SeggerRttMemoryRefs<'static>,
112    ) -> SeggerRttComponent<A> {
113        SeggerRttComponent {
114            mux_alarm,
115            rtt_memory_refs,
116        }
117    }
118}
119
120impl<A: 'static + time::Alarm<'static>> Component for SeggerRttComponent<A> {
121    type StaticInput = (
122        &'static mut MaybeUninit<VirtualMuxAlarm<'static, A>>,
123        &'static mut MaybeUninit<SeggerRtt<'static, VirtualMuxAlarm<'static, A>>>,
124    );
125    type Output = &'static SeggerRtt<'static, VirtualMuxAlarm<'static, A>>;
126
127    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
128        let virtual_alarm_rtt = static_buffer.0.write(VirtualMuxAlarm::new(self.mux_alarm));
129        virtual_alarm_rtt.setup();
130
131        // RTT communication channel
132        let rtt = static_buffer.1.write(SeggerRtt::new(
133            virtual_alarm_rtt,
134            self.rtt_memory_refs.rtt_memory,
135        ));
136
137        virtual_alarm_rtt.set_alarm_client(rtt);
138
139        rtt
140    }
141}