Skip to content

Support for the STM32L0x0 subfamily #146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 19 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ disable-linker-script = []

# STM32L0 subfamilies
# (Warning: Some peripherals, e.g. GPIO, don't follow this subfamily grouping.)
stm32l0x0 = ["stm32l0/stm32l0x0"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that enough, or do we need to add more features flags (thinking about the ones @dbrgn auto-generated from CubeMX).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably yes. I only have a l0x0RBT to test against, which is a class 5. I keep finding more things to fix; basically it's similar to the features of L020 class 5 with a lot of stuff cut out.

stm32l0x1 = ["stm32l0/stm32l0x1"]
stm32l0x2 = ["stm32l0/stm32l0x2"]
stm32l0x3 = ["stm32l0/stm32l0x3"]
Expand Down Expand Up @@ -337,7 +338,7 @@ required-features = ["stm32l0x2", "io-STM32L071"]

[[example]]
name = "serial"
required-features = ["stm32l0x2", "io-STM32L071"]
# required-features = ["stm32l0x2", "io-STM32L071"]

[[example]]
name = "serial_dma"
Expand Down
11 changes: 9 additions & 2 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ fn main() {

let mut feature_count = 0;

if cfg!(feature = "stm32l0x0") {
feature_count += 1;
}

if cfg!(feature = "stm32l0x1") {
feature_count += 1;
}
Expand All @@ -22,11 +26,13 @@ fn main() {
}

if feature_count != 1 {
panic!("\n\nMust select exactly one package for linker script generation!\nChoices: 'stm32l0x1' or 'stm32l0x2' or 'stm32l0x3'\nAlternatively, pick the mcu-feature that matches your MCU, for example 'mcu-STM32L071KBTx'\n\n");
panic!("\n\nMust select exactly one package for linker script generation!\nChoices: 'stm32l0x0' or 'stm32l0x1' or 'stm32l0x2' or 'stm32l0x3'\nAlternatively, pick the mcu-feature that matches your MCU, for example 'mcu-STM32L071KBTx'\n\n");
}

if !cfg!(feature = "disable-linker-script") {
let linker = if cfg!(feature = "stm32l0x1") {
let linker = if cfg!(feature = "stm32l0x0") {
include_bytes!("memory_l0x0.x").as_ref()
} else if cfg!(feature = "stm32l0x1") {
include_bytes!("memory_l0x1.x").as_ref()
} else if cfg!(feature = "stm32l0x2") {
include_bytes!("memory_l0x2.x").as_ref()
Expand All @@ -42,6 +48,7 @@ fn main() {
.unwrap();
println!("cargo:rustc-link-search={}", out.display());

println!("cargo:rerun-if-changed=memory_l0x0.x");
println!("cargo:rerun-if-changed=memory_l0x1.x");
println!("cargo:rerun-if-changed=memory_l0x2.x");
println!("cargo:rerun-if-changed=memory_l0x3.x");
Expand Down
4 changes: 2 additions & 2 deletions examples/blinky.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ fn main() -> ! {

// Acquire the GPIOA peripheral. This also enables the clock for GPIOA in
// the RCC register.
let gpioa = dp.GPIOA.split(&mut rcc);
let gpioc = dp.GPIOC.split(&mut rcc);

// Configure PA1 as output.
let mut led = gpioa.pa1.into_push_pull_output();
let mut led = gpioc.pc1.into_push_pull_output();

loop {
// Set the LED high one million times in a row.
Expand Down
6 changes: 3 additions & 3 deletions examples/blinky_delay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ fn main() -> ! {

// Acquire the GPIOA peripheral. This also enables the clock for GPIOA in
// the RCC register.
let gpioa = dp.GPIOA.split(&mut rcc);
let gpioa = dp.GPIOC.split(&mut rcc);

// Configure PA1 as output.
let mut led = gpioa.pa1.into_push_pull_output();
let mut led = gpioa.pc1.into_push_pull_output();

// Get the delay provider.
let mut delay = cp.SYST.delay(rcc.clocks);
Expand All @@ -29,6 +29,6 @@ fn main() -> ! {
delay.delay_ms(500_u16);

led.set_low().unwrap();
delay.delay_ms(500_u16);
delay.delay_ms(2000_u16);
}
}
10 changes: 5 additions & 5 deletions examples/lptim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use cortex_m_rt::entry;
use nb::block;
use stm32l0xx_hal::{
exti::{DirectLine, Exti},
gpio::{gpiob::PB, Output, PushPull},
gpio::{gpioc::PC, Output, PushPull},
lptim::{self, ClockSrc, LpTimer},
pac,
prelude::*,
Expand All @@ -27,11 +27,11 @@ fn main() -> ! {
let mut rcc = dp.RCC.freeze(rcc::Config::msi(rcc::MSIRange::Range0));
let mut exti = Exti::new(dp.EXTI);
let mut pwr = PWR::new(dp.PWR, &mut rcc);
let gpiob = dp.GPIOB.split(&mut rcc);
let gpioc = dp.GPIOC.split(&mut rcc);

let mut led = gpiob.pb2.into_push_pull_output().downgrade();
let mut led = gpioc.pc1.into_push_pull_output().downgrade();

let mut lptim = LpTimer::init_periodic(dp.LPTIM, &mut pwr, &mut rcc, ClockSrc::Lse);
let mut lptim = LpTimer::init_periodic(dp.LPTIM, &mut pwr, &mut rcc, ClockSrc::Lsi);

let exti_line = DirectLine::Lptim1;

Expand Down Expand Up @@ -105,7 +105,7 @@ fn main() -> ! {
}
}

fn blink(led: &mut PB<Output<PushPull>>) {
fn blink(led: &mut PC<Output<PushPull>>) {
led.set_high().unwrap();
delay();
led.set_low().unwrap();
Expand Down
2 changes: 1 addition & 1 deletion examples/pwm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ fn main() -> ! {
// Initialize TIM2 for PWM
let pwm = pwm::Timer::new(dp.TIM2, 10.khz(), &mut rcc);

#[cfg(feature = "stm32l0x1")]
#[cfg(any(feature = "stm32l0x0", feature = "stm32l0x1"))]
let mut pwm = pwm.channel2.assign(gpioa.pa1);

// This is LD2 on ST's B-L072Z-LRWAN1 development board.
Expand Down
6 changes: 3 additions & 3 deletions examples/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use stm32l0xx_hal::{
timer::Timer,
};

static LED: Mutex<RefCell<Option<gpioa::PA1<Output<PushPull>>>>> = Mutex::new(RefCell::new(None));
static LED: Mutex<RefCell<Option<gpioc::PC1<Output<PushPull>>>>> = Mutex::new(RefCell::new(None));
static TIMER: Mutex<RefCell<Option<Timer<pac::TIM2>>>> = Mutex::new(RefCell::new(None));

#[entry]
Expand All @@ -30,10 +30,10 @@ fn main() -> ! {

// Acquire the GPIOA peripheral. This also enables the clock for GPIOA in
// the RCC register.
let gpioa = dp.GPIOA.split(&mut rcc);
let gpioc = dp.GPIOC.split(&mut rcc);

// Configure PA1 as output.
let led = gpioa.pa1.into_push_pull_output();
let led = gpioc.pc1.into_push_pull_output();

// Configure the timer.
let mut timer = dp.TIM2.timer(1.hz(), &mut rcc);
Expand Down
8 changes: 4 additions & 4 deletions examples/timer_interrupt_rtic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use stm32l0xx_hal::{gpio::*, pac, prelude::*, rcc::Config, timer::Timer};
#[app(device = stm32l0xx_hal::pac, peripherals = true)]
const APP: () = {
struct Resources {
led: gpioa::PA<Output<PushPull>>,
led: gpioc::PC<Output<PushPull>>,
timer: Timer<pac::TIM2>,
}

Expand All @@ -24,13 +24,13 @@ const APP: () = {

// Acquire the GPIOA peripheral. This also enables the clock for GPIOA
// in the RCC register.
let gpioa = device.GPIOA.split(&mut rcc);
let gpioc = device.GPIOC.split(&mut rcc);

// Configure PA1 as output.
let led = gpioa.pa1.into_push_pull_output().downgrade();
let led = gpioc.pc1.into_push_pull_output().downgrade();

// Configure the timer.
let mut timer = device.TIM2.timer(1.hz(), &mut rcc);
let mut timer = device.TIM2.timer(8.hz(), &mut rcc);
timer.listen();

// Return the initialised resources.
Expand Down
5 changes: 5 additions & 0 deletions memory_l0x0.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
MEMORY
{
FLASH : ORIGIN = 0x08000000, LENGTH = 128K
RAM : ORIGIN = 0x20000000, LENGTH = 20K
}
17 changes: 12 additions & 5 deletions src/dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{
rcc::Rcc,
};

#[cfg(any(feature = "io-STM32L051", feature = "io-STM32L071"))]
#[cfg(all(not(feature = "stm32l0x0"), any(feature = "io-STM32L051", feature = "io-STM32L071")))]
use crate::pac::USART1;

#[cfg(any(
Expand All @@ -37,9 +37,16 @@ use crate::pac::USART1;
))]
use crate::{
i2c,
pac::{I2C1, I2C2, I2C3, USART2},
pac::{I2C1, USART2},
serial,
};
#[cfg(not(feature = "stm32l0x0"))]
use crate::{
pac::{
I2C2,
I2C3
},
};

use crate::{pac::SPI1, spi};

Expand Down Expand Up @@ -329,14 +336,14 @@ macro_rules! impl_channel {
handle: &mut Handle,
address: u32,
) {
handle.dma.$chfield.par.write(|w| w.pa().bits(address));
unsafe { handle.dma.$chfield.par.write(|w| w.pa().bits(address)); }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This confuses me. Wouldn't the bits method be unsafe for all targets? Why did it work in the first place?

}

fn set_memory_address(&self,
handle: &mut Handle,
address: u32,
) {
handle.dma.$chfield.mar.write(|w| w.ma().bits(address));
unsafe { handle.dma.$chfield.mar.write(|w| w.ma().bits(address)); }
}

fn set_transfer_len(&self, handle: &mut Handle, len: u16) {
Expand Down Expand Up @@ -509,7 +516,7 @@ impl_target!(
adc::DmaToken, Channel2, 0;
);

#[cfg(any(feature = "io-STM32L051", feature = "io-STM32L071"))]
#[cfg(all(not(feature = "stm32l0x0"), any(feature = "io-STM32L051", feature = "io-STM32L071")))]
impl_target!(
// USART1
serial::Tx<USART1>, Channel2, 3;
Expand Down
17 changes: 17 additions & 0 deletions src/exti.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,11 +308,14 @@ impl ExtiLine for GpioLine {
/// both.
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum ConfigurableLine {
#[cfg(not(feature = "stm32l0x0"))]
Pvd = 16,
RtcAlarm = 17,
RtcTamper_CssLse = 19,
RtcWakeup = 20,
#[cfg(not(feature = "stm32l0x0"))]
Comp1 = 21,
#[cfg(not(feature = "stm32l0x0"))]
Comp2 = 22,
}

Expand All @@ -321,12 +324,15 @@ impl ExtiLine for ConfigurableLine {
use ConfigurableLine::*;

Some(match line {
#[cfg(not(feature = "stm32l0x0"))]
16 => Pvd,
17 => RtcAlarm,
// 18 = USB (or reserved)
19 => RtcTamper_CssLse,
20 => RtcWakeup,
#[cfg(not(feature = "stm32l0x0"))]
21 => Comp1,
#[cfg(not(feature = "stm32l0x0"))]
22 => Comp2,
_ => return None,
})
Expand All @@ -341,8 +347,10 @@ impl ExtiLine for ConfigurableLine {
use ConfigurableLine::*;

match self {
#[cfg(not(feature = "stm32l0x0"))]
Pvd => Interrupt::PVD,
RtcAlarm | RtcTamper_CssLse | RtcWakeup => Interrupt::RTC,
#[cfg(not(feature = "stm32l0x0"))]
Comp1 | Comp2 => Interrupt::ADC_COMP,
}
}
Expand All @@ -354,7 +362,9 @@ pub enum DirectLine {
#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))]
Usb = 18,
I2C1 = 23,
#[cfg(not(feature = "stm32l0x0"))]
I2C3 = 24,
#[cfg(not(feature = "stm32l0x0"))]
Usart1 = 25,
Usart2 = 26,
// 27 = reserved
Expand All @@ -370,7 +380,9 @@ impl ExtiLine for DirectLine {
#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))]
18 => Usb,
23 => I2C1,
#[cfg(not(feature = "stm32l0x0"))]
24 => I2C3,
#[cfg(not(feature = "stm32l0x0"))]
25 => Usart1,
26 => Usart2,
// 27 = reserved
Expand All @@ -392,9 +404,14 @@ impl ExtiLine for DirectLine {
#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))]
Usb => Interrupt::USB,
I2C1 => Interrupt::I2C1,
#[cfg(not(feature = "stm32l0x0"))]
I2C3 => Interrupt::I2C3,
#[cfg(not(feature = "stm32l0x0"))]
Usart1 => Interrupt::USART1,
Usart2 => Interrupt::USART2,
#[cfg(feature = "stm32l0x0")]
Lpuart1 => Interrupt::LPUART1,
#[cfg(not(feature = "stm32l0x0"))]
Lpuart1 => Interrupt::AES_RNG_LPUART1,
Lptim1 => Interrupt::LPTIM1,
}
Expand Down
Loading