How to make a library agnostic

Hey all,

I'm trying to develop my first embedded Rust project with RP Pico and it's been a fun ride so far. But I'm stuck at one point and pretty sure I could not get something about Traits.

This is the code I'm using to create a new Sx130x instance:

impl Sx130x {
    pub fn init_new(mut spi: hal::spi::Spi<hal::spi::Enabled, hal::spi::SpiDevice, 8>,
                    mut cs_pin: hal::gpio::Pin<hal::gpio::pin::bank0::Gpio9, hal::gpio::PushPullOutput>,
                    mut rst_pin: hal::gpio::Pin<hal::gpio::pin::bank0::Gpio20, hal::gpio::PushPullOutput>) -> Self {

This is a half working function definition. cs_pin and rst_pin params are OK but the spi param definition is giving error: "trait objects must include the 'dyn' keyword.".

It's obvious that I need either pass an implemented trait or keep it generic via passing it like Box<dyn SpiDevice> But that means I'll be using the heap, which I don't want to use right now. (It won't be freed anytime, so it's safe to use it on the heap, but I'd like to find out the idiomatic and correct way of doing that)

What I want to achieve is basically keep this library agnostic and make the parent take care of the device details like which GPIO or SPI.

Even that the cs_pin definition is correct from compiler perspective, it makes it hardwired to the GPIO9 and conflicts with the primary idea.

How can I do what I want?

P.S: SPI0 and SPI1 are implemented and can be used like mut spi: hal::spi::Spi<hal::spi::Enabled, hal::pac::SPI1, 8>, but that would make it hardwired again.


I think you can use generics with trait bounds.

impl<SPI, CS, RST> Sx130x<SPI, CS, RST>
    SPI: embedded_hal::blocking::spi::Write<u8>,
    CS: embedded_hal::digital::v2::OutputPin,
    RST: embedded_hal::digital::v2::OutputPin,
    pub fn init_new(spi: SPI, cs_pin: CS, rst_pin: RST) -> Self {
        Self {

Thanks @lonesometraveler, that did the trick. After ironing couple of other things around, it is compiling as expected.