esp-rs / esp-hal

no_std Hardware Abstraction Layers for ESP32 microcontrollers
https://docs.esp-rs.org/esp-hal/
Apache License 2.0
625 stars 167 forks source link

can't declare type for esp_hal::lcd_cam::lcd::i8080::I8080 #1699

Open liebman opened 1 week ago

liebman commented 1 week ago

I'm attempting to declare specific type of a use esp_hal::lcd_cam::lcd::i8080::I8080;

#![no_std]
#![no_main]

use esp_backtrace as _;
use esp_hal::dma::gdma::Channel;
use esp_hal::dma::ChannelTx;
use esp_hal::dma::ChannelTxImpl;
use esp_hal::gpio::GpioPin;
use esp_hal::lcd_cam::lcd::i8080::TxSixteenBits;
use esp_hal::lcd_cam::lcd::i8080::I8080;
use esp_hal::prelude::*;

#[entry]
fn main() -> ! {
    let my_i8080: Option<
        I8080<
            ChannelTx<ChannelTxImpl<0>, Channel<0>>,
            TxSixteenBits<
                GpioPin<14>,
                GpioPin<46>,
                GpioPin<13>,
                GpioPin<9>,
                GpioPin<3>,
                GpioPin<10>,
                GpioPin<12>,
                GpioPin<11>,
                GpioPin<6>,
                GpioPin<7>,
                GpioPin<38>,
                GpioPin<42>,
                GpioPin<48>,
                GpioPin<47>,
                GpioPin<2>,
                GpioPin<21>,
            >,
        >,
    > = None;
    loop {}
}

but use esp_hal::dma::gdma::Channel is private (the gdma part is). And that Channel should be available as esp_hal::dma::Channel because its re-exported with a pub use gdma::* here but later another Channel is declared with a different type signature here and that seems to hide the one used. I'd submit a PR but I'm not sure how that should be fixed .... or maybe I'm just very confused.

bjoernQ commented 1 week ago

I think we had something similar regarding I2S on Matrix and this worked there:

i2s_tx: esp_hal::i2s::I2sTx<'a, esp_hal::peripherals::I2S0, esp_hal::dma::Channel0,esp_hal::Async >,

Dominaezzz commented 1 week ago

The generics on that type could really use some simplifying, like what was done for PARL_IO.

A little unrelated to this issue @liebman, can I ask what hardware your talking to with the I8080 driver? (I've been trying to find 16 bit screens to test the driver)

liebman commented 1 week ago

@Dominaezzz I'm (ab)using it to drive a 64x64 HUB75 LED matrix. This uses 14 pins and I waste 2 pins because they are not optional. See the example I have in this draft PR.

liebman commented 1 week ago

@bjoernQ that works! Thanks. Now what I really want is this to be static so I can start the next transaction from the send done interrupt:

static MY_I8080: Mutex<
    RefCell<
        Option<
            I8080<
                ChannelTx<ChannelTxImpl<0>, Channel0>,
                TxSixteenBits<
                    GpioPin<14>,
                    GpioPin<46>,
                    GpioPin<13>,
                    GpioPin<9>,
                    GpioPin<3>,
                    GpioPin<10>,
                    GpioPin<12>,
                    GpioPin<11>,
                    GpioPin<6>,
                    GpioPin<7>,
                    GpioPin<38>,
                    GpioPin<42>,
                    GpioPin<48>,
                    GpioPin<47>,
                    GpioPin<2>,
                    GpioPin<21>,
                >,
            >,
        >,
    >,
> = Mutex::new(RefCell::new(None));

But this yields:

error[E0277]: `*mut DmaDescriptor` cannot be sent between threads safely
    --> board-tests/src/bin/i8080-static.rs:44:18
     |
44   |   static MY_I8080: Mutex<
     |  __________________^
45   | |     RefCell<
46   | |         Option<
47   | |             I8080<
...    |
69   | |     >,
70   | | > = Mutex::new(RefCell::new(None));
     | |_^ `*mut DmaDescriptor` cannot be sent between threads safely

and

error[E0277]: `*const u8` cannot be sent between threads safely
    --> board-tests/src/bin/i8080-static.rs:44:18
     |
44   |   static MY_I8080: Mutex<
     |  __________________^
45   | |     RefCell<
46   | |         Option<
47   | |             I8080<
...    |
69   | |     >,
70   | | > = Mutex::new(RefCell::new(None));
     | |_^ `*const u8` cannot be sent between threads safely
Dominaezzz commented 1 week ago

Might need a PR to mark the channel type as Send.

Short term hack could be to wrap the I8080 type in a struct before putting it in the mutex, then you can mark this struct as Send. This will let you store it in the mutex I think.