1use core::marker::PhantomData;
32use core::mem::MaybeUninit;
33
34use capsules_core::spi_controller::{Spi, DEFAULT_READ_BUF_LENGTH, DEFAULT_WRITE_BUF_LENGTH};
35use capsules_core::spi_peripheral::SpiPeripheral;
36use capsules_core::virtualizers::virtual_spi;
37use capsules_core::virtualizers::virtual_spi::{MuxSpiMaster, VirtualSpiMasterDevice};
38use kernel::capabilities;
39use kernel::component::Component;
40use kernel::create_capability;
41use kernel::hil::spi;
42use kernel::hil::spi::{SpiMasterDevice, SpiSlaveDevice};
43
44#[macro_export]
46macro_rules! spi_mux_component_static {
47 ($S:ty $(,)?) => {{
48 kernel::static_buf!(capsules_core::virtualizers::virtual_spi::MuxSpiMaster<'static, $S>)
49 };};
50}
51
52#[macro_export]
53macro_rules! spi_syscall_component_static {
54 ($S:ty $(,)?) => {{
55 let virtual_spi = kernel::static_buf!(
56 capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<'static, $S>
57 );
58 let spi = kernel::static_buf!(
59 capsules_core::spi_controller::Spi<
60 'static,
61 capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<'static, $S>,
62 >
63 );
64
65 let spi_read_buf =
66 kernel::static_buf!([u8; capsules_core::spi_controller::DEFAULT_READ_BUF_LENGTH]);
67 let spi_write_buf =
68 kernel::static_buf!([u8; capsules_core::spi_controller::DEFAULT_WRITE_BUF_LENGTH]);
69
70 (virtual_spi, spi, spi_read_buf, spi_write_buf)
71 };};
72}
73
74#[macro_export]
75macro_rules! spi_syscallp_component_static {
76 ($S:ty $(,)?) => {{
77 let spi_slave = kernel::static_buf!(
78 capsules_core::virtualizers::virtual_spi::SpiSlaveDevice<'static, $S>
79 );
80 let spi_peripheral = kernel::static_buf!(
81 capsules_core::spi_peripheral::SpiPeripheral<
82 'static,
83 capsules_core::virtualizers::virtual_spi::SpiSlaveDevice<'static, $S>,
84 >
85 );
86
87 let spi_read_buf =
88 kernel::static_buf!([u8; capsules_core::spi_controller::DEFAULT_READ_BUF_LENGTH]);
89 let spi_write_buf =
90 kernel::static_buf!([u8; capsules_core::spi_controller::DEFAULT_WRITE_BUF_LENGTH]);
91
92 (spi_slave, spi_peripheral, spi_read_buf, spi_write_buf)
93 };};
94}
95
96#[macro_export]
97macro_rules! spi_component_static {
98 ($S:ty $(,)?) => {{
99 kernel::static_buf!(
100 capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<'static, $S>
101 )
102 };};
103}
104
105#[macro_export]
106macro_rules! spi_peripheral_component_static {
107 ($S:ty $(,)?) => {{
108 kernel::static_buf!(capsules_core::spi_peripheral::SpiPeripheral<'static, $S>)
109 };};
110}
111
112pub struct SpiMuxComponent<S: 'static + spi::SpiMaster<'static>> {
113 spi: &'static S,
114}
115
116pub struct SpiSyscallComponent<S: 'static + spi::SpiMaster<'static>> {
117 board_kernel: &'static kernel::Kernel,
118 spi_mux: &'static MuxSpiMaster<'static, S>,
119 chip_select: S::ChipSelect,
120 driver_num: usize,
121}
122
123pub struct SpiSyscallPComponent<S: 'static + spi::SpiSlave<'static>> {
124 board_kernel: &'static kernel::Kernel,
125 spi_slave: &'static S,
126 driver_num: usize,
127}
128
129pub struct SpiComponent<
130 S: 'static + spi::SpiMaster<'static>,
131 CS: spi::cs::IntoChipSelect<S::ChipSelect, AP>,
132 AP: spi::cs::ChipSelectActivePolarity,
133> {
134 spi_mux: &'static MuxSpiMaster<'static, S>,
135 chip_select: CS,
136 _phantom: PhantomData<AP>,
137}
138
139impl<S: 'static + spi::SpiMaster<'static>> SpiMuxComponent<S> {
140 pub fn new(spi: &'static S) -> Self {
141 Self { spi }
142 }
143}
144
145impl<S: 'static + spi::SpiMaster<'static>> Component for SpiMuxComponent<S> {
146 type StaticInput = &'static mut MaybeUninit<MuxSpiMaster<'static, S>>;
147 type Output = &'static MuxSpiMaster<'static, S>;
148
149 fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
150 let mux_spi = static_buffer.write(MuxSpiMaster::new(self.spi));
151 kernel::deferred_call::DeferredCallClient::register(mux_spi);
152
153 self.spi.set_client(mux_spi);
154
155 if let Err(error) = self.spi.init() {
156 panic!("SPI init failed ({:?})", error);
157 }
158
159 mux_spi
160 }
161}
162
163impl<S: 'static + spi::SpiMaster<'static>> SpiSyscallComponent<S> {
164 pub fn new(
165 board_kernel: &'static kernel::Kernel,
166 mux: &'static MuxSpiMaster<'static, S>,
167 chip_select: S::ChipSelect,
168 driver_num: usize,
169 ) -> Self {
170 SpiSyscallComponent {
171 board_kernel,
172 spi_mux: mux,
173 chip_select,
174 driver_num,
175 }
176 }
177}
178
179impl<S: 'static + spi::SpiMaster<'static>> Component for SpiSyscallComponent<S> {
180 type StaticInput = (
181 &'static mut MaybeUninit<VirtualSpiMasterDevice<'static, S>>,
182 &'static mut MaybeUninit<Spi<'static, VirtualSpiMasterDevice<'static, S>>>,
183 &'static mut MaybeUninit<[u8; DEFAULT_READ_BUF_LENGTH]>,
184 &'static mut MaybeUninit<[u8; DEFAULT_WRITE_BUF_LENGTH]>,
185 );
186 type Output = &'static Spi<'static, VirtualSpiMasterDevice<'static, S>>;
187
188 fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
189 let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
190
191 let syscall_spi_device = static_buffer
192 .0
193 .write(VirtualSpiMasterDevice::new(self.spi_mux, self.chip_select));
194
195 let spi_syscalls = static_buffer.1.write(Spi::new(
196 syscall_spi_device,
197 self.board_kernel.create_grant(self.driver_num, &grant_cap),
198 ));
199
200 let spi_read_buf = static_buffer.2.write([0; DEFAULT_READ_BUF_LENGTH]);
201 let spi_write_buf = static_buffer.3.write([0; DEFAULT_WRITE_BUF_LENGTH]);
202
203 spi_syscalls.config_buffers(spi_read_buf, spi_write_buf);
204 syscall_spi_device.setup();
205 syscall_spi_device.set_client(spi_syscalls);
206 spi_syscalls
207 }
208}
209
210impl<S: 'static + spi::SpiSlave<'static>> SpiSyscallPComponent<S> {
211 pub fn new(
212 board_kernel: &'static kernel::Kernel,
213 slave: &'static S,
214 driver_num: usize,
215 ) -> Self {
216 SpiSyscallPComponent {
217 board_kernel,
218 spi_slave: slave,
219 driver_num,
220 }
221 }
222}
223
224impl<S: 'static + spi::SpiSlave<'static>> Component for SpiSyscallPComponent<S> {
225 type StaticInput = (
226 &'static mut MaybeUninit<virtual_spi::SpiSlaveDevice<'static, S>>,
227 &'static mut MaybeUninit<SpiPeripheral<'static, virtual_spi::SpiSlaveDevice<'static, S>>>,
228 &'static mut MaybeUninit<[u8; DEFAULT_READ_BUF_LENGTH]>,
229 &'static mut MaybeUninit<[u8; DEFAULT_WRITE_BUF_LENGTH]>,
230 );
231 type Output = &'static SpiPeripheral<'static, virtual_spi::SpiSlaveDevice<'static, S>>;
232
233 fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
234 let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
235
236 let syscallp_spi_device = static_buffer
237 .0
238 .write(virtual_spi::SpiSlaveDevice::new(self.spi_slave));
239
240 let spi_syscallsp = static_buffer.1.write(SpiPeripheral::new(
241 syscallp_spi_device,
242 self.board_kernel.create_grant(self.driver_num, &grant_cap),
243 ));
244
245 let spi_read_buf = static_buffer.2.write([0; DEFAULT_READ_BUF_LENGTH]);
246 let spi_write_buf = static_buffer.3.write([0; DEFAULT_WRITE_BUF_LENGTH]);
247
248 spi_syscallsp.config_buffers(spi_read_buf, spi_write_buf);
249 syscallp_spi_device.set_client(spi_syscallsp);
250
251 spi_syscallsp
252 }
253}
254
255impl<
256 S: 'static + spi::SpiMaster<'static>,
257 CS: spi::cs::IntoChipSelect<S::ChipSelect, AP>,
258 AP: spi::cs::ChipSelectActivePolarity,
259 > SpiComponent<S, CS, AP>
260{
261 pub fn new(mux: &'static MuxSpiMaster<'static, S>, chip_select: CS) -> Self {
262 SpiComponent {
263 spi_mux: mux,
264 _phantom: PhantomData,
265 chip_select,
266 }
267 }
268}
269
270impl<
271 S: 'static + spi::SpiMaster<'static>,
272 CS: spi::cs::IntoChipSelect<S::ChipSelect, AP>,
273 AP: spi::cs::ChipSelectActivePolarity,
274 > Component for SpiComponent<S, CS, AP>
275{
276 type StaticInput = &'static mut MaybeUninit<VirtualSpiMasterDevice<'static, S>>;
277 type Output = &'static VirtualSpiMasterDevice<'static, S>;
278
279 fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
280 let spi_device = static_buffer.write(VirtualSpiMasterDevice::new(
281 self.spi_mux,
282 self.chip_select.into_cs(),
283 ));
284 spi_device.setup();
285 spi_device
286 }
287}
288
289pub struct SpiPeripheralComponent<S: 'static + spi::SpiSlave<'static>> {
290 board_kernel: &'static kernel::Kernel,
291 device: &'static S,
292 driver_num: usize,
293}
294
295impl<S: 'static + spi::SpiSlave<'static>> SpiPeripheralComponent<S> {
296 pub fn new(
297 board_kernel: &'static kernel::Kernel,
298 device: &'static S,
299 driver_num: usize,
300 ) -> Self {
301 SpiPeripheralComponent {
302 board_kernel,
303 device,
304 driver_num,
305 }
306 }
307}
308
309impl<S: 'static + spi::SpiSlave<'static> + kernel::hil::spi::SpiSlaveDevice<'static>> Component
310 for SpiPeripheralComponent<S>
311{
312 type StaticInput = &'static mut MaybeUninit<SpiPeripheral<'static, S>>;
313 type Output = &'static SpiPeripheral<'static, S>;
314
315 fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
316 let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
317
318 let spi_device = static_buffer.write(SpiPeripheral::new(
319 self.device,
320 self.board_kernel.create_grant(self.driver_num, &grant_cap),
321 ));
322
323 spi_device
324 }
325}