stm32f4xx-hal icon indicating copy to clipboard operation
stm32f4xx-hal copied to clipboard

Releasing drivers / pins

Open schteve opened this issue 3 years ago • 2 comments

HAL drivers naturally need to own some peripherals while they are in use. However, it should be possible to safely release the peripheral ownership (destroying the driver in the process) so the peripherals can be used for something else. This is necessary if you want to use the same pin for several purposes at different times.

Some drivers already seem to implement this, at least in part. For example there is a Serial::release(), however this only works if you have the serial struct still (calling split() on it separates the Tx and Rx and prevents being able to release them afterwards). In this example it seems like the most natural thing to do would be to 'unsplit' Tx and Rx back into a Serial and then release Serial. But, I don't see anything to that effect.

Is there already an existing way to handle this? If not, does it make sense to add one?

To illustrate another example, you can run PWM on a timer channel, but you might want to reclaim that timer and pin to use for other purposes. I'm imagining it would look something like below. Note there is already a PwmHz::release(), but at the point I would like to release it I only have a PwmChannel.

if let (Some(dp), Some(cp)) = (
    stm32f4xx_hal::pac::Peripherals::take(),
    cortex_m::peripheral::Peripherals::take(),
) {
    let rcc = dp.RCC.constrain();
    let clocks = rcc.cfgr.freeze();

    let gpioa = dp.GPIOA.split();

    let mut pwm_ch1 = dp.TIM2
        .pwm_hz(gpioa.pa5.into_alternate(), 20.kHz(), &clocks)
        .split();
    pwm_ch1.set_duty(50);
    pwm_ch1.enable();

    // Do other things. Later...
    // Release PA5 and TIM2
    // let (pa5, tim2) = pwm_ch1.release();
    
    // Use PA5 and TIM2 for other purposes
    // ...
}

schteve avatar Jul 20 '22 01:07 schteve

Note there is already a PwmHz::release(), but at the point I would like to release it I only have a PwmChannel.

PwmChannel erases information about Pin, so it is impossible to restore it (same as Rx and Tx in serial). The only way is to keep Pin inside PwmChannel but not everyone agrees with this as it makes type more complicate.

burrbull avatar Jul 20 '22 03:07 burrbull

That makes sense, I have a hard time understanding all of the usage of generics in this code so I can see how adding more could really complicate things. It's too bad there's not a safe way to handle this situation, though. Even though it's not super common, I think re-using pins isn't unheard of and it would be great to leverage Rust 's guarantees to help manage that. I guess as a workaround the app could create a new pin out of thin air as long as it's sure the old one is no longer in use (but I think that veers into unsafe territory).

schteve avatar Jul 20 '22 23:07 schteve