imix/test/
spi_dummy.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! A dummy SPI client to test the SPI implementation

use core::ptr::addr_of_mut;

use kernel::hil::gpio::Configure;
use kernel::hil::spi::{self, SpiMaster};
use kernel::utilities::leasable_buffer::SubSliceMut;
use kernel::ErrorCode;

#[allow(unused_variables, dead_code)]
pub struct DummyCB {
    val: u8,
    spi: &'static sam4l::spi::SpiHw<'static>,
}

impl DummyCB {
    pub fn new(spi: &'static sam4l::spi::SpiHw<'static>) -> Self {
        Self { val: 0x55_u8, spi }
    }
}

pub static mut FLOP: bool = false;
pub static mut BUF1: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0];
pub static mut BUF2: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
pub static mut A5: [u8; 16] = [0xA5; 16];

impl spi::SpiMasterClient for DummyCB {
    #[allow(unused_variables, dead_code)]
    fn read_write_done(
        &self,
        write: SubSliceMut<'static, u8>,
        read: Option<SubSliceMut<'static, u8>>,
        status: Result<usize, ErrorCode>,
    ) {
        unsafe {
            // do actual stuff
            // TODO verify SPI return value
            let _ = self
                .spi
                .read_write_bytes((&mut *addr_of_mut!(A5) as &mut [u8]).into(), None);

            // FLOP = !FLOP;
            // let len: usize = BUF1.len();
            // if FLOP {
            //     sam4l::spi::SPI.read_write_bytes(&mut BUF1, Some(&mut BUF2), len);
            // } else {
            //     sam4l::spi::SPI.read_write_bytes(&mut BUF2, Some(&mut BUF1), len);
            // }
        }
    }
}

// This test first turns on the Imix's User led, asserts pin D2 and then
// initiates a continuous SPI transfer of 8 bytes.
//
// If the SPI transfer of multiple bytes fail, then the test will loop writing
// 0xA5.
//
// The first SPI transfer outputs [8, 7, 6, 5, 4, 3, 2, 1] then echoes whatever
// input it recieves from the slave on peripheral 1 continuously.
//
// To test with a logic analyzer, connect probes to pin D2 on the Imix, and
// the SPI MOSI and CLK pins (exposed on the Imix's 20-pin header). Setup
// the logic analyzer to trigger sampling on assertion of pin 2, then restart
// the board.
#[inline(never)]
#[allow(unused_variables, dead_code)]
pub unsafe fn spi_dummy_test(spi: &'static sam4l::spi::SpiHw<'static>) {
    // set the LED to mark that we've programmed.
    let pin = sam4l::gpio::GPIOPin::new(sam4l::gpio::Pin::PC10);
    pin.make_output();
    pin.set();

    let pin2 = sam4l::gpio::GPIOPin::new(sam4l::gpio::Pin::PC31); // It's on D2 of the IMIX
    pin2.make_output();
    pin2.set();

    let spicb = kernel::static_init!(DummyCB, DummyCB::new(spi));
    spi.specify_chip_select(sam4l::spi::Peripheral::Peripheral0)
        .unwrap();
    spi.set_client(spicb);

    spi.init().unwrap();
    spi.set_baud_rate(200000);

    let buf2 = &mut *addr_of_mut!(BUF2);
    let len = buf2.len();
    if spi.read_write_bytes(
        (buf2 as &mut [u8]).into(),
        Some((&mut *addr_of_mut!(BUF1) as &mut [u8]).into()),
    ) != Ok(())
    {
        loop {
            spi.write_byte(0xA5).unwrap();
        }
    }

    pin2.clear();
}