Closed NiklasC closed 1 year ago
Hey, welcome to embedded Rust! A couple of things:
By the looks of it, shouldn't you be using the stm32l0x1
feature instead of stm32l0x2
? Better yet, consider using ONLY the mcu-STM32L011K4Tx
feature - it will enable the other correct features for your MCU which is nice.
You also need to be careful around the combination of timer/channel/pin you use. If you can build the docs locally with cargo doc --open --features mcu-STM32L011K4Tx
and search for the pwm::Pin
trait, you'll see that it's only implemented for PA0, PA1, PA2 and PA3 for the STM32L011 chip you're using. There's a chain of trait bounds that are then not satisfied for PB3, leading to the compile errors you're seeing - those methods come from the PwmPin
trait.
Note that if you check the online docs here, you'll see the different combinations that can be used with different/bigger chips in the L0 series. This is because the mcu-STM32L071KBTx
feature turned on.
I appreciate this is confusing for someone just getting started, but if we did our work right in this crate, the pins enabled for your MCU should match the datasheet which is a good second reference. I haven't checked myself, so please confirm if your MCU really does/doesn't have PB3 available as a PWM output. If we got something wrong here, there's a bug to fix :)
Thank you for your quick reply! I've updated the feature as you suggested, however, I still get the same errors as before. To be honest I did not check the docs regarding the PWMpin itself, only the peripheral.
According to the datasheet on page 39, PB3 has the TIM2 Channel 2 alternate function listed, which is also why I selected the stm32l0x2 originally, since it does support PB3 as PWM output as specified in the pwm.rs file.
Can you paste your code here if it's not too long?
According to the datasheet on page 39, PB3 has the TIM2 Channel 2 alternate function listed, which is also why I selected the stm32l0x2 originally, since it does support PB3 as PWM output as specified in the pwm.rs file.
Ah ok, maybe there's a bug in this crate's feature selection then. I can try to take a look when I have a spare minute.
Hey! Sorry, it's been some time, and I've only recently come back to this project. My code is the same as in the example pwm.rs:
#![deny(warnings)]
#![deny(unsafe_code)]
#![no_main]
#![no_std]
extern crate panic_halt;
use cortex_m_rt::entry;
use stm32l0xx_hal::{pac, prelude::*, pwm, rcc::Config};
#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let cp = cortex_m::Peripherals::take().unwrap();
// Configure the clock.
let mut rcc = dp.RCC.freeze(Config::hsi16());
// Get the delay provider.
let mut delay = cp.SYST.delay(rcc.clocks);
// Acquire the GPIOA peripheral. This also enables the clock for GPIOA in
// the RCC register.
let gpioa = dp.GPIOA.split(&mut rcc);
// Initialize TIM2 for PWM
let pwm = pwm::Timer::new(dp.TIM2, 10_000.Hz(), &mut rcc);
#[cfg(feature = "stm32l0x1")]
let mut pwm = pwm.channel2.assign(gpioa.pa1);
// This is LD2 on ST's B-L072Z-LRWAN1 development board.
#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))]
let mut pwm = pwm.channel1.assign(gpioa.pa5);
let max = pwm.get_max_duty();
pwm.enable();
loop {
pwm.set_duty(max);
delay.delay_ms(500_u16);
pwm.set_duty(max / 2);
delay.delay_ms(500_u16);
pwm.set_duty(max / 4);
delay.delay_ms(500_u16);
pwm.set_duty(max / 8);
delay.delay_ms(500_u16);
}
}
I've tried to change the PWM output to PB3 as it is on my hardware as well, but that does not work either.
Hey, your comment spurred me to look into this a bit deeper and I think this crate has the pin config incorrect. Looking through the L011 datasheet and some other spot checks, it looks like TIM2 can output on a few pins for all L0 devices which we were only enabling for L0x2 and L0x3 devices. I've opened a PR in #224 which fixes this.
Would you mind giving it a test though? e.g. put this in your Cargo.toml
:
stm32l0xx-hal = { git = "https://github.com/stm32-rs/stm32l0xx-hal.git", branch = "correct-tim2-pins" }
Thank you very much :) I've tried your PR, but sadly I still get the same result as before. My Cargo.toml is looking like this:
[package]
name = "l011_blinky"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cortex-m = "0.7.6"
cortex-m-rt = "0.7.1"
embedded-hal = "0.2.7"
panic-halt = "^0.2.0"
stm32l0 = "0.15.1"
stm32l0xx-hal = {git = "https://github.com/stm32-rs/stm32l0xx-hal.git", branch = "correct-tim2-pins", features = ["mcu-STM32L011K4Tx", "rt"]}
I've also tried using TIM21 instead of TIM2 for PWM, but it seems like this is not implemented? I get the additional error message:
error[E0277]: the trait bound `stm32l0xx_hal::pac::TIM21: stm32l0xx_hal::pwm::Instance` is not satisfied
--> src/main.rs:27:31
|
27 | let pwm = pwm::Timer::new(dp.TIM21, 10_000.Hz(), &mut rcc);
| --------------- ^^^^^^^^ the trait `stm32l0xx_hal::pwm::Instance` is not implemented for `stm32l0xx_hal::pac::TIM21`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `stm32l0xx_hal::pwm::Instance`:
stm32l0xx_hal::pac::TIM2
stm32l0xx_hal::pac::TIM3
Is it not intended to use TIM21 for PWM? What about the Low Power Timers?
Ah, I only fixed TIM2 in the PR because that's what your code example uses. I'll check some datasheets but I think TIM21 has the same features across the L0 family so I can fix that in #224 as well.
Either way, according to the datasheet, Table 14 PA5
is only supported on TIM2
so you might want to use TIM2 instead.
Oh, you're right. I want to use TIM2 channel 2 on PB3, as that's the LED output on the Nucleo Board.
I've just pushed some changes to the PR branch - please try commit 871919380f8ea1e65d4e5b752cb20640ecb766a2
. The old commit might not work any more as I did a force push.
I'll check some datasheets but I think TIM21 has the same features across the L0 family so I can fix that in #224 as well.
Sigh, scratch that. I'm afraid I don't have the willpower to go through all the datasheets and fix the code for TIM21 😓 sorry about that.
It works! Thank you very much :)
I also had to remove the #[cfg(feature = "stm32l0x1")]
from the example, and only set the "mcu-STM32L011K4Tx"
in the Cargo.toml
Sigh, scratch that. I'm afraid I don't have the willpower to go through all the datasheets and fix the code for TIM21 😓 sorry about that.
Don't worry, thank you for your help! Once I get more familiar with embedded rust I'd love to help out by implementing stuff like that myself
Great to hear! Thanks for helping me test this. I'll merge #224 which will close this issue but please either reopen or make a new issue if you run into more problems.
Hey, just a quick question regarding the merge - I've changed the Cargo.toml back to
stm32l0xx-hal = {version = "0.10.0", features = ["mcu-STM32L011K4Tx", "rt"]}
as the branch is now closed, but I get error again. Do I need to specify a different version for that?
I haven't released a new version yet, so you'll have to use it from Github for now. Try this:
stm32l0xx-hal = {git = "https://github.com/stm32-rs/stm32l0xx-hal.git", rev = "e6031a3798dae9658f2cd2559891f4c19aaeabe0", features = ["mcu-STM32L011K4Tx", "rt"]}
That will point to the latest master commit at time of writing.
Thank you!
Hello! I'm a beginner with rust and am currently working with a STM32L011K4T6. I wanted to try out the PWM Example for my project, however, I'm running into some issues that I'm not sure how to fix.
I've copied the example into my project and changed the PWM pin to PB3 and use the feature stm32l0x2.
When compiling, I get the following error messages:
I've checked the documentation, and my understanding is that the required features are implemented at the PWM struct and not the Timer struct. However, due to my limited experience in Rust I'm not sure how to use instantiate the PWM peripheral correctly. Would it be possible to update the example?