imix/test/
spi_loopback.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//! A SPI test which read/writes and expects MOSI to
6//! be loopbacked to MISO. It checks that what it writes
7//! is what it reads. The values put in the buffer are
8//! a circular ring of 8-bit values, starting with an
9//! initial value and incrementing by 1 on each write.
10//! So if the first write is [33, 34, ... , 32],
11//! the next write will be [34, 35, ..., 34]. You can set
12//! the speed of the operation to check that configurations
13//! are being set correctly: running two tests in parallel
14//! with different bit rates should see different clock
15//! frequencies.
16
17use capsules_core::virtualizers::virtual_spi::MuxSpiMaster;
18use components::spi::SpiComponent;
19use core::cell::Cell;
20use core::ptr::addr_of_mut;
21use kernel::component::Component;
22use kernel::debug;
23use kernel::hil::spi::{self, SpiMasterDevice};
24use kernel::utilities::leasable_buffer::SubSliceMut;
25use kernel::ErrorCode;
26
27#[allow(unused_variables, dead_code)]
28pub struct SpiLoopback {
29    cs: Cell<u8>,
30    val: Cell<u8>,
31    spi: &'static dyn SpiMasterDevice<'static>,
32}
33
34impl SpiLoopback {
35    pub fn new(spi: &'static dyn SpiMasterDevice<'static>, cs: u8, counter: u8) -> Self {
36        Self {
37            val: Cell::new(counter),
38            cs: Cell::new(cs),
39            spi,
40        }
41    }
42}
43
44pub static mut WBUF: [u8; 256] = [0; 256];
45pub static mut RBUF: [u8; 256] = [0; 256];
46pub static mut WBUF2: [u8; 256] = [0; 256];
47pub static mut RBUF2: [u8; 256] = [0; 256];
48
49impl spi::SpiMasterClient for SpiLoopback {
50    #[allow(unused_variables, dead_code)]
51    fn read_write_done(
52        &self,
53        mut write: SubSliceMut<'static, u8>,
54        read: Option<SubSliceMut<'static, u8>>,
55        status: Result<usize, ErrorCode>,
56    ) {
57        let mut good = true;
58        let read = read.unwrap();
59        for (c, v) in write[..].iter().enumerate() {
60            if read[c] != *v {
61                debug!(
62                    "SPI test error at index {}: wrote {} but read {}",
63                    c, v, read[c]
64                );
65                good = false;
66            }
67        }
68        if good {
69            debug!("SPI CS={} test passed.", self.cs.get());
70        }
71        self.val.set(self.val.get() + 1);
72        let counter = self.val.get();
73
74        for i in 0..write.len() {
75            write[i] = counter.wrapping_add(i as u8);
76        }
77
78        if let Err((e, _, _)) = self.spi.read_write_bytes(write, Some(read)) {
79            panic!(
80                "Could not continue SPI test, error on read_write_bytes is {:?}",
81                e
82            );
83        }
84    }
85}
86
87#[inline(never)]
88#[allow(unused_variables, dead_code)]
89pub unsafe fn spi_loopback_test(
90    spi: &'static dyn SpiMasterDevice<'static>,
91    counter: u8,
92    speed: u32,
93) {
94    let spicb = kernel::static_init!(SpiLoopback, SpiLoopback::new(spi, 0, counter));
95    spi.set_client(spicb);
96    spi.set_rate(speed)
97        .expect("Failed to set SPI speed in SPI loopback test.");
98
99    let wbuf = &mut *addr_of_mut!(WBUF);
100    let len = wbuf.len();
101    if let Err((e, _, _)) = spi.read_write_bytes(
102        (wbuf as &mut [u8]).into(),
103        Some((&mut *addr_of_mut!(RBUF) as &mut [u8]).into()),
104    ) {
105        panic!(
106            "Could not start SPI test, error on read_write_bytes is {:?}",
107            e
108        );
109    }
110}
111
112#[inline(never)]
113#[allow(unused_variables, dead_code)]
114pub unsafe fn spi_two_loopback_test(mux: &'static MuxSpiMaster<'static, sam4l::spi::SpiHw>) {
115    let spi_fast = SpiComponent::new(mux, sam4l::spi::Peripheral::Peripheral0)
116        .finalize(components::spi_component_static!(sam4l::spi::SpiHw));
117    let spi_slow = SpiComponent::new(mux, sam4l::spi::Peripheral::Peripheral1)
118        .finalize(components::spi_component_static!(sam4l::spi::SpiHw));
119
120    let spicb_fast = kernel::static_init!(SpiLoopback, SpiLoopback::new(spi_fast, 0, 0x80));
121    let spicb_slow = kernel::static_init!(SpiLoopback, SpiLoopback::new(spi_slow, 1, 0x00));
122    spi_fast
123        .set_rate(1000000)
124        .expect("Failed to set SPI speed in SPI loopback test.");
125    spi_slow
126        .set_rate(250000)
127        .expect("Failed to set SPI speed in SPI loopback test.");
128    spi_fast.set_client(spicb_fast);
129    spi_slow.set_client(spicb_slow);
130
131    let wbuf = &mut *addr_of_mut!(WBUF);
132    let len = wbuf.len();
133    if let Err((e, _, _)) = spi_fast.read_write_bytes(
134        (wbuf as &mut [u8]).into(),
135        Some((&mut *addr_of_mut!(RBUF) as &mut [u8]).into()),
136    ) {
137        panic!(
138            "Could not start SPI test, error on read_write_bytes is {:?}",
139            e
140        );
141    }
142
143    let wbuf = &mut *addr_of_mut!(WBUF);
144    let len = wbuf.len();
145    if let Err((e, _, _)) = spi_slow.read_write_bytes(
146        (wbuf as &mut [u8]).into(),
147        Some((&mut *addr_of_mut!(RBUF2) as &mut [u8]).into()),
148    ) {
149        panic!(
150            "Could not start SPI test, error on read_write_bytes is {:?}",
151            e
152        );
153    }
154}