#Self -referential struct (no_std)

7 messages · Page 1 of 1 (latest)

fiery monolith
#

Can someone help me to find a safe way to fix it?

#
    gpio::{DriveMode, interconnect::PeripheralOutput},
    ledc::{
        Ledc, LowSpeed,
        channel::{self, ChannelIFace},
        timer::{self, TimerIFace},
    },
    peripherals::LEDC,
    time::Rate,
};

pub struct Backlight;

impl<'a> Backlight {
    pub fn init(
        ledc_peripheral: LEDC<'a>,
        backlight_pin: impl PeripheralOutput<'a>,
    ) -> channel::Channel<'a, LowSpeed> {
        let mut ledc = Ledc::new(ledc_peripheral);
        ledc.set_global_slow_clock(esp_hal::ledc::LSGlobalClkSource::APBClk);

        let mut timer = ledc.timer(timer::Number::Timer0);

        timer
            .configure(timer::config::Config {
                duty: timer::config::Duty::Duty8Bit,
                clock_source: timer::LSClockSource::APBClk,
                frequency: Rate::from_khz(24),
            })
            .unwrap();

        let mut channel0 = ledc.channel(channel::Number::Channel0, backlight_pin);
        channel0
            .configure(channel::config::Config {
                timer: &timer,
                duty_pct: 100,
                drive_mode: DriveMode::PushPull,
            })
            .unwrap();

        channel0
    }
}
ocean grove
# fiery monolith ```use esp_hal::{ gpio::{DriveMode, interconnect::PeripheralOutput}, led...

channel0 holds &timer and timer is a local that gets dropped when init() returns. fix is to give the timer static lifetime via static_cell

use static_cell::StaticCell;
static LEDC_CELL: StaticCell<Ledc<'static>> = StaticCell::new();
static TIMER_CELL: StaticCell<Timer<'static, LowSpeed>> = StaticCell::new();
let ledc = LEDC_CELL.init({
    let mut l = Ledc::new(ledc_peripheral);
    l.set_global_slow_clock(LSGlobalClkSource::APBClk);
    l
});
let timer = TIMER_CELL.init({
    let mut t = ledc.timer(timer::Number::Timer0);
    t.configure(...).unwrap();
    t
});
let mut channel0 = ledc.channel(channel::Number::Channel0, backlight_pin);
channel0.configure(channel::config::Config {
    timer,
    ...
}).unwrap();

add static_cell = "2" to cargo.toml. staticcell panics on double init so you can't accidentally re initialise

ember zodiac
#

Maybe I overlooked something, but wouldn't it be better to just let Config own the timer instead of borrowing it? The timer doesn't seem to be used elsewhere.

flint reef
#

As is written, without leaking or placing the value in a static, there's not any real way to do this.

However, maybe you could store it in the Backlight type itself? (not far off from iamlockon's suggestion actually). After storing the relevant types in the Backlight type, making another function which returns this value which borrows from the struct should be easy. That'll change your usable scope on the borrow from function local to caller since now caller owns Backlight and its resources