driver_pal/hal/
linux.rs

1
2
3use linux_embedded_hal::SpidevBus;
4pub use linux_embedded_hal::{
5    spidev, spidev::SpiModeFlags, Delay, SpidevDevice, SysfsPin as Pindev,
6    sysfs_gpio::{Direction, Error as PinError},
7};
8use embedded_hal_bus::spi::{ExclusiveDevice, NoDelay};
9
10use super::*;
11
12pub struct LinuxDriver;
13
14pub type LinuxSpiDevice = ExclusiveDevice<SpidevBus, Pindev, NoDelay>;
15
16impl LinuxDriver {
17    /// Load an SPI device using the provided configuration
18    pub fn new(path: &str, spi: &SpiConfig, pins: &PinConfig) -> Result<HalInst, HalError> {
19        let mut flags = match spi.mode {
20            0 => SpiModeFlags::SPI_MODE_0,
21            1 => SpiModeFlags::SPI_MODE_1,
22            2 => SpiModeFlags::SPI_MODE_2,
23            3 => SpiModeFlags::SPI_MODE_3,
24            _ => return Err(HalError::InvalidSpiMode),
25        };
26
27        flags |= SpiModeFlags::SPI_NO_CS;
28
29        debug!(
30            "Conecting to spi: {} at {} baud with mode: {:?}",
31            path, spi.baud, flags
32        );
33
34        let spi_bus = load_spi(path, spi.baud, flags)?;
35        let spi_cs = load_pin(pins.chip_select, Direction::Out)?;
36        let spi = ExclusiveDevice::new_no_delay(spi_bus, spi_cs);
37
38        let pins = Self::load_pins(pins)?;
39
40        Ok(HalInst {
41            base: HalBase::None,
42            spi: HalSpi::Linux(spi),
43            pins,
44        })
45    }
46
47    /// Load pins using the provided config
48    fn load_pins(pins: &PinConfig) -> Result<HalPins, HalError> {
49        let reset = load_pin(pins.reset, Direction::Out)?;
50
51        let busy = match pins.busy {
52            Some(p) => HalInputPin::Linux(load_pin(p, Direction::In)?),
53            None => HalInputPin::None,
54        };
55
56        let ready = match pins.ready {
57            Some(p) => HalInputPin::Linux(load_pin(p, Direction::In)?),
58            None => HalInputPin::None,
59        };
60
61        let led0 = match pins.led0 {
62            Some(p) => HalOutputPin::Linux(load_pin(p, Direction::Out)?),
63            None => HalOutputPin::None,
64        };
65
66        let led1 = match pins.led1 {
67            Some(p) => HalOutputPin::Linux(load_pin(p, Direction::Out)?),
68            None => HalOutputPin::None,
69        };
70
71        let pins = HalPins {
72            reset: HalOutputPin::Linux(reset),
73            busy,
74            ready,
75            led0,
76            led1,
77        };
78
79        Ok(pins)
80    }
81}
82
83/// Load an SPI device using the provided configuration
84fn load_spi(path: &str, baud: u32, mode: spidev::SpiModeFlags) -> Result<SpidevBus, HalError> {
85    debug!(
86        "Conecting to spi: {} at {} baud with mode: {:?}",
87        path, baud, mode
88    );
89
90    let mut spi = SpidevBus::open(path)?;
91
92    let mut config = spidev::SpidevOptions::new();
93    config.mode(SpiModeFlags::SPI_MODE_0 | SpiModeFlags::SPI_NO_CS);
94    config.max_speed_hz(baud);
95    spi.configure(&config)?;
96
97    Ok(spi)
98}
99
100/// Load a Pin using the provided configuration
101fn load_pin(index: u64, direction: Direction) -> Result<Pindev, HalError> {
102    debug!(
103        "Connecting to pin: {} with direction: {:?}",
104        index, direction
105    );
106
107    let p = Pindev::new(index);
108    p.export()?;
109    p.set_direction(direction)?;
110
111    Ok(p)
112}