Skip to content

Traits for GPIO pin / SPI device / etc #13

@laanwj

Description

@laanwj

The macros for the various peripherals create a new type for each instance of the same hardware. These types share the general embedded_hal traits, but I need something that provides the hardware-specific methods. I'd like to write some code that is general and doesn't care, say, what SPI device (for example) is passed in.

I have code like this, for example:

use hifive1::hal::spi::{Spi, Mode, Polarity, Phase};
...

// SPI backend trait for display interface
pub trait SPI {
    fn send(&mut self, data: u8);
    fn complete(&mut self);
    fn mode_data(&mut self);
    fn mode_cmd(&mut self);
}

pub struct Hifive1SPI<X, Y, DC> where
    DC: OutputPin {
    hwspi:  Spi<X, Y>,
    dc:    DC,
}

impl <Y, DC> Hifive1SPI<QSPI1, Y, DC> where
    Y: hifive1::hal::spi::Pins<QSPI1>,
    DC: OutputPin {
    pub fn new(hwspi: Spi<QSPI1, Y>, dc: DC) -> Hifive1SPI<QSPI1, Y, DC> {
        Hifive1SPI {
            hwspi,
            dc,
        }
    }
}

impl <Y, DC> SPI for Hifive1SPI<QSPI1, Y, DC> where
    Y: hifive1::hal::spi::Pins<QSPI1>,
    DC: OutputPin {
    fn complete(&mut self)
    {
        // Wait for send FIFO to drain
        while !self.hwspi.tx_wm_is_pending() {
            // IDLE
        }
    }

    fn send(&mut self, data: u8)
    {
        while let Err(_) = self.hwspi.send(data) {
            // IDLE
        }
    }

    fn mode_data(&mut self)
    {
        self.complete();
        self.dc.set_high();
    }

    fn mode_cmd(&mut self)
    {
        self.complete();
        self.dc.set_low();
    }
}

Currently this specializes on QSPI1 because I don't see a way to generalize it over all SPI devices, as tx_wm_is_pending is not on a trait.

(I had a similar situation with GPIO pins in the board setup, where I wanted to make it possible to pass in arbitrary pins to configure, but there is no trait that provides into_output into_inverted_output. There's OutputPin of course, but that's only useful when the pin is already set up)

I'm fairly new to Rust, entirely new to using Rust for embedded programming, so I may be missing something.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions