1use capsules_core::console;
39use capsules_core::console_ordered::ConsoleOrdered;
40
41use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
42use capsules_core::virtualizers::virtual_uart::{MuxUart, UartDevice};
43use core::mem::MaybeUninit;
44use kernel::capabilities;
45use kernel::component::Component;
46use kernel::create_capability;
47use kernel::hil;
48use kernel::hil::time::{self, Alarm};
49use kernel::hil::uart;
50
51use capsules_core::console::DEFAULT_BUF_SIZE;
52
53#[macro_export]
54macro_rules! uart_mux_component_static {
55 ($rx_buffer_len: expr) => {{
57 use capsules_core::virtualizers::virtual_uart::MuxUart;
58 use kernel::static_buf;
59 let uart_mux = static_buf!(MuxUart<'static>);
60 let rx_buf = static_buf!([u8; $rx_buffer_len]);
61 (uart_mux, rx_buf)
62 }};
63 () => {
64 $crate::uart_mux_component_static!(capsules_core::virtualizers::virtual_uart::RX_BUF_LEN);
65 };
66 ($rx_buffer_len: literal) => {
67 $crate::uart_mux_component_static!($rx_buffer_len);
68 };
69}
70
71pub struct UartMuxComponent<const RX_BUF_LEN: usize> {
72 uart: &'static dyn uart::Uart<'static>,
73 baud_rate: u32,
74}
75
76impl<const RX_BUF_LEN: usize> UartMuxComponent<RX_BUF_LEN> {
77 pub fn new(
78 uart: &'static dyn uart::Uart<'static>,
79 baud_rate: u32,
80 ) -> UartMuxComponent<RX_BUF_LEN> {
81 UartMuxComponent { uart, baud_rate }
82 }
83}
84
85impl<const RX_BUF_LEN: usize> Component for UartMuxComponent<RX_BUF_LEN> {
86 type StaticInput = (
87 &'static mut MaybeUninit<MuxUart<'static>>,
88 &'static mut MaybeUninit<[u8; RX_BUF_LEN]>,
89 );
90 type Output = &'static MuxUart<'static>;
91
92 fn finalize(self, s: Self::StaticInput) -> Self::Output {
93 let rx_buf = s.1.write([0; RX_BUF_LEN]);
94 let uart_mux = s.0.write(MuxUart::new(self.uart, rx_buf, self.baud_rate));
95 kernel::deferred_call::DeferredCallClient::register(uart_mux);
96
97 uart_mux.initialize();
98 hil::uart::Transmit::set_transmit_client(self.uart, uart_mux);
99 hil::uart::Receive::set_receive_client(self.uart, uart_mux);
100
101 uart_mux
102 }
103}
104
105#[macro_export]
106macro_rules! console_component_static {
107 ($rx_buffer_len: expr, $tx_buffer_len: expr) => {{
109 use capsules_core::console::{Console, DEFAULT_BUF_SIZE};
110 use capsules_core::virtualizers::virtual_uart::UartDevice;
111 use kernel::static_buf;
112 let read_buf = static_buf!([u8; $rx_buffer_len]);
113 let write_buf = static_buf!([u8; $tx_buffer_len]);
114 let console_uart = static_buf!(UartDevice);
116 let console = static_buf!(Console<'static>);
117 (write_buf, read_buf, console_uart, console)
118 }};
119 () => {
120 $crate::console_component_static!(DEFAULT_BUF_SIZE, DEFAULT_BUF_SIZE);
121 };
122 ($rx_buffer_len: literal, $tx_buffer_len: literal) => {
123 $crate::console_component_static!($rx_buffer_len, $tx_buffer_len);
124 };
125}
126
127pub struct ConsoleComponent<const RX_BUF_LEN: usize, const TX_BUF_LEN: usize> {
128 board_kernel: &'static kernel::Kernel,
129 driver_num: usize,
130 uart_mux: &'static MuxUart<'static>,
131}
132
133impl<const RX_BUF_LEN: usize, const TX_BUF_LEN: usize> ConsoleComponent<RX_BUF_LEN, TX_BUF_LEN> {
134 pub fn new(
135 board_kernel: &'static kernel::Kernel,
136 driver_num: usize,
137 uart_mux: &'static MuxUart,
138 ) -> ConsoleComponent<RX_BUF_LEN, TX_BUF_LEN> {
139 ConsoleComponent {
140 board_kernel,
141 driver_num,
142 uart_mux,
143 }
144 }
145}
146
147impl<const RX_BUF_LEN: usize, const TX_BUF_LEN: usize> Component
148 for ConsoleComponent<RX_BUF_LEN, TX_BUF_LEN>
149{
150 type StaticInput = (
151 &'static mut MaybeUninit<[u8; TX_BUF_LEN]>,
152 &'static mut MaybeUninit<[u8; RX_BUF_LEN]>,
153 &'static mut MaybeUninit<UartDevice<'static>>,
154 &'static mut MaybeUninit<console::Console<'static>>,
155 );
156 type Output = &'static console::Console<'static>;
157
158 fn finalize(self, s: Self::StaticInput) -> Self::Output {
159 let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
160
161 let write_buffer = s.0.write([0; TX_BUF_LEN]);
162
163 let read_buffer = s.1.write([0; RX_BUF_LEN]);
164
165 let console_uart = s.2.write(UartDevice::new(self.uart_mux, true));
166 console_uart.setup();
167
168 let console = s.3.write(console::Console::new(
169 console_uart,
170 write_buffer,
171 read_buffer,
172 self.board_kernel.create_grant(self.driver_num, &grant_cap),
173 ));
174 hil::uart::Transmit::set_transmit_client(console_uart, console);
175 hil::uart::Receive::set_receive_client(console_uart, console);
176
177 console
178 }
179}
180#[macro_export]
181macro_rules! console_ordered_component_static {
182 ($A:ty $(,)?) => {{
183 let mux_alarm = kernel::static_buf!(VirtualMuxAlarm<'static, $A>);
184 let read_buf = static_buf!([u8; capsules_core::console::DEFAULT_BUF_SIZE]);
185 let console_uart =
186 kernel::static_buf!(capsules_core::virtualizers::virtual_uart::UartDevice);
187 let console = kernel::static_buf!(ConsoleOrdered<'static, VirtualMuxAlarm<'static, $A>>);
188 (mux_alarm, read_buf, console_uart, console)
189 };};
190}
191
192pub struct ConsoleOrderedComponent<A: 'static + time::Alarm<'static>> {
193 board_kernel: &'static kernel::Kernel,
194 driver_num: usize,
195 uart_mux: &'static MuxUart<'static>,
196 alarm_mux: &'static MuxAlarm<'static, A>,
197 atomic_size: usize,
198 retry_timer: u32,
199 write_timer: u32,
200}
201
202impl<A: 'static + time::Alarm<'static>> ConsoleOrderedComponent<A> {
203 pub fn new(
204 board_kernel: &'static kernel::Kernel,
205 driver_num: usize,
206 uart_mux: &'static MuxUart<'static>,
207 alarm_mux: &'static MuxAlarm<'static, A>,
208 atomic_size: usize,
209 retry_timer: u32,
210 write_timer: u32,
211 ) -> ConsoleOrderedComponent<A> {
212 ConsoleOrderedComponent {
213 board_kernel,
214 driver_num,
215 uart_mux,
216 alarm_mux,
217 atomic_size,
218 retry_timer,
219 write_timer,
220 }
221 }
222}
223
224impl<A: 'static + time::Alarm<'static>> Component for ConsoleOrderedComponent<A> {
225 type StaticInput = (
226 &'static mut MaybeUninit<VirtualMuxAlarm<'static, A>>,
227 &'static mut MaybeUninit<[u8; DEFAULT_BUF_SIZE]>,
228 &'static mut MaybeUninit<UartDevice<'static>>,
229 &'static mut MaybeUninit<ConsoleOrdered<'static, VirtualMuxAlarm<'static, A>>>,
230 );
231 type Output = &'static ConsoleOrdered<'static, VirtualMuxAlarm<'static, A>>;
232
233 fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
234 let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
235
236 let virtual_alarm1 = static_buffer.0.write(VirtualMuxAlarm::new(self.alarm_mux));
237 virtual_alarm1.setup();
238
239 let read_buffer = static_buffer.1.write([0; DEFAULT_BUF_SIZE]);
240
241 let console_uart = static_buffer.2.write(UartDevice::new(self.uart_mux, true));
242 console_uart.setup();
243
244 let console = static_buffer.3.write(ConsoleOrdered::new(
245 console_uart,
246 virtual_alarm1,
247 read_buffer,
248 self.board_kernel.create_grant(self.driver_num, &grant_cap),
249 self.atomic_size,
250 self.retry_timer,
251 self.write_timer,
252 ));
253
254 virtual_alarm1.set_alarm_client(console);
255 hil::uart::Receive::set_receive_client(console_uart, console);
256 console
257 }
258}