ssd1306 icon indicating copy to clipboard operation
ssd1306 copied to clipboard

ssd1306 with rtic 1.0.0

Open pdgilbert opened this issue 3 years ago • 7 comments

(some relationship with #162.)

  • Version of ssd1306 in use: recent git
  • MCU/other hardware in use: blackpill 411 using a recent git version of stm32f4xx_hal (no-std)
  • Display resolution and interface:128x64 I2C shared-bus

Description of the problem/feature request/other

I am trying to use ssd1306 with rtic v1.0.0 and am stuck on two errors. One is a trait problem with the draw method trying to write on the display

Click to expand
 Compiling test-example v0.1.0 (/home/paul/githubClones/rust-integration-testing/dev-testing)
error[E0599]: the method `draw` exists for struct `Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>>`, but its trait bounds were not satisfied
   --> examples/zzdisplay_stuff_rtic.rs:123:15
    |
123 |             ).draw(&mut cx.local.display).unwrap();
    |               ^^^^ method cannot be called on `Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>>` due to unsatisfied trait bounds
    |
   ::: /home/paul/.cargo/registry/src/github.com-1ecc6299db9ec823/embedded-graphics-0.7.1/src/text/text.rs:23:1
    |
23  | pub struct Text<'a, S> {
    | ----------------------
    | |
    | doesn't satisfy `<_ as Iterator>::Item = Pixel<_>`
    | doesn't satisfy `_: Iterator`
    | doesn't satisfy `_: embedded_graphics::Drawable`
    | doesn't satisfy `_: embedded_graphics::iterator::PixelIteratorExt<_>`
    |
    = note: the following trait bounds were not satisfied:
            `<Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>> as Iterator>::Item = Pixel<_>`
            which is required by `Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>>: embedded_graphics::iterator::PixelIteratorExt<_>`
            `Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>>: Iterator`
            which is required by `Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>>: embedded_graphics::iterator::PixelIteratorExt<_>`
            `<&Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>> as Iterator>::Item = Pixel<_>`
            which is required by `&Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>>: embedded_graphics::iterator::PixelIteratorExt<_>`
            `&Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>>: Iterator`
            which is required by `&Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>>: embedded_graphics::iterator::PixelIteratorExt<_>`
            `&mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>: TextRenderer`
            which is required by `Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>>: embedded_graphics::Drawable`
            `<&mut Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>> as Iterator>::Item = Pixel<_>`
            which is required by `&mut Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>>: embedded_graphics::iterator::PixelIteratorExt<_>`
            `&mut Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>>: Iterator`
            which is required by `&mut Text<'_, &mut embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>>: embedded_graphics::iterator::PixelIteratorExt<_>`

The other is a problem with something not being thread safe.

Click to expand
error[E0277]: `(dyn GlyphMapping + 'static)` cannot be shared between threads safely
   --> examples/zzdisplay_stuff_rtic.rs:15:35
    |
15  | #[cfg_attr(feature = "stm32f4xx", app(device = stm32f4xx_hal::pac,   dispatchers = [TIM2, TIM3]))]
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn GlyphMapping + 'static)` cannot be shared between threads safely
    |
    = help: within `MonoFont<'static>`, the trait `Sync` is not implemented for `(dyn GlyphMapping + 'static)`
    = note: required because it appears within the type `&'static (dyn GlyphMapping + 'static)`
    = note: required because it appears within the type `MonoFont<'static>`
    = note: required because of the requirements on the impl of `Send` for `&'static MonoFont<'static>`
    = note: required because it appears within the type `embedded_graphics::mono_font::MonoTextStyle<'static, embedded_graphics::pixelcolor::BinaryColor>`
note: required by a bound in `assert_send`
   --> /home/paul/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rtic-1.0.0/src/export.rs:107:8
    |
107 |     T: Send,
    |        ^^^^ required by this bound in `assert_send`
    = note: this error originates in the attribute macro `app` (in Nightly builds, run with -Z macro-backtrace for more info)

I do have a similar non-rtic example working with stm32f4xx_hal , so this is an rtic specific problem.

Test case

Click to expand code
//! Display the word "stuff" on OLED with i2c.   Using stm32f4xx_hal

#![deny(unsafe_code)]
#![no_std]
#![no_main]

#[cfg(debug_assertions)]
use panic_semihosting as _;

#[cfg(not(debug_assertions))]
use panic_halt as _;

use rtic::app;

#[cfg_attr(feature = "stm32f4xx", app(device = stm32f4xx_hal::pac,   dispatchers = [TIM2, TIM3]))]

mod app {
    //use cortex_m_semihosting::{debug, hprintln};
    use cortex_m_semihosting::{hprintln};

    use core::fmt::Write;

    use embedded_graphics::{
        mono_font::{iso_8859_1::FONT_10X20, MonoTextStyleBuilder, MonoTextStyle},  //FONT_6X10  FONT_8X13
        pixelcolor::BinaryColor,
        prelude::*,
        text::{Baseline, Text},
    };

    use ssd1306::{mode::BufferedGraphicsMode, prelude::*, I2CDisplayInterface, Ssd1306};

    use systick_monotonic::*;    

    const MONOTICK: u32 = 100;
    const READ_INTERVAL: u64 = 10;  // used as seconds

    use shared_bus::{I2cProxy};
    use core::cell::RefCell;
    use cortex_m::interrupt::Mutex;


    use stm32f4xx_hal::{
        gpio::{Alternate, OpenDrain, 
        gpiob::{PB8, PB9, },
        },
        i2c::I2c,
        pac::{Peripherals, I2C1},
        prelude::*,
    };

    pub type I2c1Type = I2c<I2C1, (PB8<Alternate<OpenDrain, 4u8>>, PB9<Alternate<OpenDrain, 4u8>>)>;

    const MONOCLOCK: u32 = 16_000_000; //should be set for board not for HAL

    fn setup(dp: Peripherals) -> I2c1Type {
       let rcc = dp.RCC.constrain();
       let clocks = rcc.cfgr.freeze();

       let gpiob = dp.GPIOB.split();

       let scl = gpiob.pb8.into_alternate_open_drain(); 
       let sda = gpiob.pb9.into_alternate_open_drain(); 

       let i2c = I2c::new(dp.I2C1, (scl, sda), 400.khz(), &clocks);

       i2c
    }

    #[monotonic(binds = SysTick, default = true)]
    type MyMono = Systick<MONOTICK>;

    #[init]
    fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
       let mono = Systick::new(cx.core.SYST, MONOCLOCK);

       let i2c = setup(cx.device);

       let manager: &'static _ = shared_bus::new_cortexm!(I2c1Type = i2c).unwrap();
       let interface = I2CDisplayInterface::new(manager.acquire_i2c());

       let text_style = MonoTextStyleBuilder::new().font(&FONT_10X20).text_color(BinaryColor::On).build();

       let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
          .into_buffered_graphics_mode();

       display.init().unwrap();
       hprintln!("display.init",).unwrap();

       Text::with_baseline("Display initialized ...", Point::zero(), text_style, Baseline::Top, )
          .draw(&mut display).unwrap();

       display_stuff::spawn().unwrap();

       (Shared {}, Local { display, text_style }, init::Monotonics(mono))
    }

    #[shared]
    struct Shared {}

    #[local]
    struct Local {
        display:  Ssd1306<I2CInterface<I2cProxy<'static, Mutex<RefCell<I2c1Type>>>>, 
                     ssd1306::prelude::DisplaySize128x64, 
                     BufferedGraphicsMode<DisplaySize128x64>>,
        text_style: MonoTextStyle<'static, BinaryColor>,
    }

    #[task(shared = [], local = [display, text_style,], capacity=2)]
    fn display_stuff(cx: display_stuff::Context) {

        let mut lines: [heapless::String<32>; 1] = [ heapless::String::new(), ];
       
        write!(lines[0], "stuff").unwrap();
     
        cx.local.display.clear();
        for i in 0..lines.len() {
            // start from 0 requires that the top is used for font baseline
            Text::with_baseline(
                &lines[i],
                Point::new(0, i as i32 * 12), //with font 6x10, 12 = 10 high + 2 space
                cx.local.text_style,
                Baseline::Top,
            ).draw(&mut cx.local.display).unwrap();
        }
        cx.local.display.flush().unwrap();
          
        display_stuff::spawn_after(READ_INTERVAL.secs()).unwrap();
    }
}
Click to expand Cargo.toml
[package]
authors = ["Paul"]
categories = ["embedded", "no-std"]
description = "test example"
keywords = ["driver", "i2c", "spi", "example"]
license = "MIT OR Apache-2.0"
name = "test-example"
version = "0.1.0"
edition = "2021"

[dependencies]

stm32f4xx-hal = { git = "https://github.com/stm32-rs/stm32f4xx-hal", optional = true } 

ssd1306         = { git = "https://github.com/jamwaffles/ssd1306"  }  

cortex-m-rtic = ">=1.0" 
#cortex-m-rtic = { git = "https://github.com/rtic-rs/cortex-m-rtic" }
systick-monotonic = {version = "1.0.0", optional = true }
#systick-monotonic = { git = "https://github.com/rtic-rs/systick-monotonic.git", optional = true }

#dwt-systick-monotonic = "1.0"   # this seems to be needed for adc_dma_rtic fiddling


embedded-hal = {version = "^0.2.4" }
#embedded-hal = { version = "1.0.0-alpha.6,<1.0.0-alpha.7", package = "embedded-hal" }  

embedded-graphics = ">=0.7"
#shared-bus = { version = "0.2.2", features = ["cortex-m"] } 
shared-bus = {  git = "https://github.com/Rahix/shared-bus", features = ["cortex-m"] } 
heapless = "0.7"
nb = ">=0.1.2"
libm = "0.2"
cortex-m = ">=0.7"
cortex-m-rt = ">=0.7.0"

cortex-m-semihosting = { version = "0.3.7" }
panic-semihosting    = { version = ">=0.5.2" }
panic-reset          = { version = ">=0.1.0" }
panic-halt           = { version = ">=0.2.0" }

[features]
stm32f4xx = ["stm32f4xx-hal/rt", "systick-monotonic"]
stm32f411     = ["stm32f4xx-hal/stm32f411"  ] 

pdgilbert avatar Feb 07 '22 01:02 pdgilbert

Thanks for the detailed issue! I don't have much spare time at the moment but I'll look at reproducing your issue when I can :)

jamwaffles avatar Feb 10 '22 09:02 jamwaffles

I'm trying to do something similar to the above code. The problem seems to come from passing the embedded_graphics MonoFontStyle value as a resource, which isn't an issue with this crate.

A workaround is to build the text style in the task itself.

afternoon avatar Oct 17 '22 16:10 afternoon

Thanks @afternoon for pointing out this workaround. I have now re-enabled ssd1306 code in several examples and all are compiling. I'll get around to testing on hardware sometime soon.

pdgilbert avatar Nov 07 '22 22:11 pdgilbert

@pdgilbert I am also using the Blackpill board which is based on that STM32F411CEU6 and RTIC v2.0. Have you managed to make it work? Can you share a sample code?

snorkman88 avatar Dec 07 '23 16:12 snorkman88

I have made this work with RTIC v1 (cortex-m-rtic = ">=1.0"). I have several examples at https://github.com/pdgilbert/rust-integration-testing. See directory examples/. I have just started playing with RTIC v2 but am running into problems compiling rtic with embedded-hal 1.0.0-rc.2. See https://github.com/rtic-rs/rtic/issues/862.

pdgilbert avatar Dec 08 '23 02:12 pdgilbert

I have now compiled examples using RTIC v2 and stm32f4xx_hal with both embedded-hal 1.0.0-rc2 and a fork using rc3. These are in the eh-1-rc2 and eh-1-rc3 branches at https://github.com/pdgilbert/rust-integration-testing. (See the CI testing in Actions.) I have also run tested one example on hardware. This all uses the stm32f4xx_hal dual support for embedded-hal 1.0.0 as well as an older version. That means user code and rtic can use embedded-hal 1.0.0 while ssd1306 uses embedded-hal 0.2.7. The tree for this is pretty ugly. I think it must be considered a transition solution and I look forward to an ssd1306 crate based on embedded-hal 1.0.0 .

pdgilbert avatar Dec 17 '23 03:12 pdgilbert

It seems likely that rtic v1.x.x will be abandoned with the release of embedded-hal 1.0.0. Users really should convert to rtic v2. (This needs to be emphasized given this old issue title "ssd1306 with rtic 1.0.0".)

pdgilbert avatar Dec 17 '23 03:12 pdgilbert