Git Product home page Git Product logo

stm32l4xx-hal's Introduction

stm32l4xx-hal

formerly MabezDev/stm32l4xx-hal

HAL for the STM32L4xx family of microcontrollers

  • Note: this HAL is a work in progress, contributions are appreciated :). If you have a L4 device that is currently unsupported see #29

About

- Minimum rustc version 1.51

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

stm32l4xx-hal's People

Contributors

akashihi avatar akloboucnik avatar burrbull avatar carrigan avatar ceigel avatar crzyrndm avatar datdenkikniet avatar david-oconnor avatar derfetzer avatar disasm avatar drtobe avatar engstad avatar forsakenharmony avatar frozendroid avatar hannobraun avatar hellow554 avatar janodw avatar karlp avatar korken89 avatar leo60228 avatar lucazulian avatar lucus16 avatar mabezdev avatar mathiaskoch avatar mathk avatar nickray avatar reitermarkus avatar robhany avatar signet-mob avatar wassasin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stm32l4xx-hal's Issues

Expose OSPEEDR register

Currently, there is no way to set the speed of a pin, because it is not exposed, as e.g. OTYPER or MODER are.
I think it's as simple as adding OSPEEDR to

pub struct Parts {
, adding the corresponding opaque definitions + impls.

DMA partial peek serial panic

It seems the logic for partial peeking causes a panic after 3 messages are sent, this will almost certainly be some faulty logic.

TX DMA for SPI

Would be nice to have buffered TX dma for SPI, this may not work as our writes will not be buffered, but we would know how many bytes we are going to send, maybe we can stream bytes in chunks.

Temperature values from HTS221 sensor using stm32l4xx-hal for stm32l475

Hi,
I try to get temperature values using HTMS221 sensor using this HAL, but I get a compile error.

It appears pb9 and pb10 are SCL and SDA for I2C2

Code:

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

extern crate cortex_m;
extern crate hts221;

#[macro_use]
extern crate cortex_m_rt as rt;
extern crate cortex_m_semihosting as sh;
extern crate panic_semihosting;
extern crate stm32l4xx_hal as hal;
// #[macro_use(block)]
// extern crate nb;

use crate::hal::prelude::*;
use crate::hal::delay::Delay;
use crate::rt::ExceptionFrame;
use crate::rt::entry;
use crate::sh::hio;

#[entry]
fn main() -> ! {

    let mut hstdout = hio::hstdout().unwrap();
    let cp = cortex_m::Peripherals::take().unwrap();
    let dp = hal::stm32::Peripherals::take().unwrap();
    let mut flash = dp.FLASH.constrain(); // .constrain();
    let mut rcc = dp.RCC.constrain();
    let clocks = rcc.cfgr.hclk(8.mhz()).freeze(&mut flash.acr);
    let mut gpiob = dp.GPIOB.split(&mut rcc.ahb2);
    let scl = gpiob.pb8.into_af4(&mut gpiob.moder, &mut gpiob.afrh);
    let sda = gpiob.pb9.into_af4(&mut gpiob.moder, &mut gpiob.afrh);
    let i2c = hal::i2c::I2c::i2c1(
        dp.I2C1,
        (scl, sda),
        1.mhz(),
        rcc.cfgr.freeze(&mut dp.FLASH.constrain().acr),
&mut rcc.apb1r1);

    let mut hts221 = hts221::Builder::new(i2c)
        .with_avg_t(hts221::AvgT::Avg256)
        .with_avg_h(hts221::AvgH::Avg512)
        .build()
        .unwrap();
    let relative_humidity = hts221.humidity_x2();
let temp_c = hts221.temperature_x8();

    
    let mut timer = Delay::new(cp.SYST, clocks);

    //writeln!(hstdout, "{}",temp_c.unwrap()).unwrap();


    loop {
       
    }
}

#[exception]
fn HardFault(ef: &ExceptionFrame) -> ! {
    panic!("{:#?}", ef);
}

Error:

tasosxak@tasosxak:~/Documents/RustProjects/stm32l4xx-hal$ cargo run --release --example temperature  --features="stm32l4x5,rt"
   Compiling stm32l4xx-hal v0.3.6 (/home/tasosxak/Documents/RustProjects/stm32l4xx-hal)
error[E0277]: the trait bound `hal::gpio::gpiob::PB8<hal::gpio::Alternate<hal::gpio::AF4, hal::gpio::Input<hal::gpio::Floating>>>: hal::i2c::SclPin<hal::stm32::I2C1>` is not satisfied
  --> examples/temperature.rs:35:15
   |
35 |     let i2c = hal::i2c::I2c::i2c1(
   |               ^^^^^^^^^^^^^^^^^^^ the trait `hal::i2c::SclPin<hal::stm32::I2C1>` is not implemented for `hal::gpio::gpiob::PB8<hal::gpio::Alternate<hal::gpio::AF4, hal::gpio::Input<hal::gpio::Floating>>>`
   |
   = note: required by `<hal::i2c::I2c<hal::stm32::I2C1, (SCL, SDA)>>::i2c1`

error[E0277]: the trait bound `hal::gpio::gpiob::PB9<hal::gpio::Alternate<hal::gpio::AF4, hal::gpio::Input<hal::gpio::Floating>>>: hal::i2c::SdaPin<hal::stm32::I2C1>` is not satisfied
  --> examples/temperature.rs:35:15
   |
35 |     let i2c = hal::i2c::I2c::i2c1(
   |               ^^^^^^^^^^^^^^^^^^^ the trait `hal::i2c::SdaPin<hal::stm32::I2C1>` is not implemented for `hal::gpio::gpiob::PB9<hal::gpio::Alternate<hal::gpio::AF4, hal::gpio::Input<hal::gpio::Floating>>>`
   |
   = note: required by `<hal::i2c::I2c<hal::stm32::I2C1, (SCL, SDA)>>::i2c1`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.
error: Could not compile `stm32l4xx-hal`.

To learn more, run the command again with --verbose.

Countdown timers longer than 1 sec

I think the current implementation of the Countdown trait for timers is decent at best, but I am having a hard time seeing how to use it for timers longer than 1 second (1 Hz)?

Maybe we should consider changing the Countdown implementation to use Microseconds as a time and then an impl From<Hertz> for Microseconds

as long as it includes the From<Hertz> it wouldn't even be a breaking change.

I think this can be used as a reference: https://github.com/jacobrosenthal/rppal/blob/46cfd55cc5d674d16901e697ef42fb1df9154dcd/src/hal.rs

Only thing i am unsure of is setting the prescalers correctly for all timers, but i can give it a shot, if people agree on changing the impl.

cannot find type `CRRCR` in module `rcc`

src/main.rs

use stm32l4::stm32l4x6;

fn main() {
}

Cargo.toml

[dependencies.stm32l4xx-hal]
git = "https://github.com/stm32-rs/stm32l4xx-hal.git"
#version = "0.3.5"
features = ["rt", "stm32l4x6"]
error[E0412]: cannot find type `CRRCR` in module `rcc`
   --> C:\Users\Marcel\.cargo\git\checkouts\stm32l4xx-hal-8d56012c7770dc85\a72e4c5\src\rcc.rs:123:45
    |
123 |     pub(crate) fn crrcr(&mut self) -> &rcc::CRRCR {
    |                                             ^^^^^ not found in `rcc`
help: possible candidate is found in another module, you can import it into scope
    |
3   | use crate::rcc::CRRCR;
    |

error[E0609]: no field `crrcr` on type `stm32l4::stm32l4x6::rcc::RegisterBlock`
   --> C:\Users\Marcel\.cargo\git\checkouts\stm32l4xx-hal-8d56012c7770dc85\a72e4c5\src\rcc.rs:125:33
    |
125 |         unsafe { &(*RCC::ptr()).crrcr }
    |                                 ^^^^^ unknown field
    |
    = note: available fields are: `cr`, `icscr`, `cfgr`, `pllcfgr`, `pllsai1cfgr` ... and 25 others

error[E0609]: no field `crrcr` on type `&stm32l4::stm32l4x6::rcc::RegisterBlock`
   --> C:\Users\Marcel\.cargo\git\checkouts\stm32l4xx-hal-8d56012c7770dc85\a72e4c5\src\rcc.rs:524:17
    |
524 |             rcc.crrcr.modify(|_, w| w.hsi48on().set_bit());
    |                 ^^^^^

error[E0609]: no field `crrcr` on type `&stm32l4::stm32l4x6::rcc::RegisterBlock`
   --> C:\Users\Marcel\.cargo\git\checkouts\stm32l4xx-hal-8d56012c7770dc85\a72e4c5\src\rcc.rs:526:23
    |
526 |             while rcc.crrcr.read().hsi48rdy().bit_is_clear() {}
    |                       ^^^^^

error: aborting due to 4 previous errors

Further PLL Configuration

We have a rudimentary PLL Configurator in master, but its not quite as robust as I would like, being able to calculate the sysclk from given pll configs would be far nicer.

Replace mem::uninitialized() with mem::MaybeUninit

I just compiled the crate for the first time, and I get a warning about a use of the deprecated mem::uninitialized() function on line 176 of src/pwm.rs. Since it is UB to call it, it would be a good idea to replace that asap with mem::MaybeUninit.

Sending a PWM pattern instead of a duty cycle

I'm trying to control an LED strip (WS2812B) and I would need to be able to send to send a PWM pattern representing 0s and 1s instead of a regular duty cycle. Does anyone know if this would be possible?

Here is a part of what I have:

let pwm = dp.TIM2.pwm(c1, 800.khz(), clocks, &mut rcc.apb1r1);
loop {
    pwma.set_duty(maxa * 0.72 as u32); // sending 1s repeatedly
    pwma.set_duty(maxa * 0.28 as u32); // sending 0s repeatedly
    // I want to send a sequence of 1s and 0s
}

What could probably work for me is if before setting a new duty cycle: one period is still executed. Between each periods there is 1.25 us so I cannot delay_ms in between each. I'm also new to this crate so I don't know how everything works.

I hope I've been clear in my issue and thanks if you can bring any help!

Feature gate devices

Devices that need to be feature gated (taken from stm):

L4x6

  • stm32l496
  • stm32l4A6
  • stm32l476
  • stm32l486

L4x5

  • stm32l475

L4x3

  • stm32l433
  • stm32l443

L4x2

  • stm32l452
  • stm32l462
  • stm32l432
  • stm32l442
  • stm32l412
  • stm32l422

L4x1

  • stm32l471
  • stm32l451
  • stm32l431

If you fancy feature gating a device, you will need to go through reference manual for the chip family and feature gate the relevant peripherals. These are normally found in footnote e.g *not present on the stm32l4blahblah etc.

no method named `read` found for type `stm32l4xx_hal::rng::Rng` in the current scope for STM32L475

cargo run --release --example rng --features="stm32l4x5,rt"

Error:


error[E0599]: no method named `read` found for type `stm32l4xx_hal::rng::Rng` in the current scope
  --> examples/rng.rs:71:13
   |
71 |         rng.read(&mut random_bytes).expect("missing random data for some reason");
   |             ^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
error: Could not compile `stm32l4xx-hal`.

To learn more, run the command again with --verbose.

Cargo.toml

[package]
name = "stm32l4xx-hal"
version = "0.3.6"
authors = ["Scott Mabin <[email protected]>"]
description = "Hardware abstraction layer for the stm32l4xx chips"
keywords = ["no-std", "stm32l4xx", "stm32l4", "embedded", "embedded-hal"]
categories = [
    "embedded",
    "hardware-support",
    "no-std",
]
repository = "https://github.com/MabezDev/stm32l4xx-hal"
readme = "README.md"
license = "MIT OR Apache-2.0"
exclude = [
	".travis.yml",
	".gitignore",
	"docs/",
	"docs/*"
]
edition = "2018"

[dependencies]
cortex-m = "0.5.8"
nb = "0.1.1"
stm32l4 = "0.6.0"
as-slice = "0.1"

[dependencies.cast]
version  = "0.2.2"
default-features = false

[dependencies.void]
version = "1.0.2"
default-features = false

[dependencies.stable_deref_trait]
default-features = false
version = "1.1"

[dependencies.embedded-hal]
version = "0.2.2"
features = ["unproven"]

[package.metadata.docs.rs]
features = ["rt", "stm32l4x2"]

[features]
rt = ["stm32l4/rt"]
stm32l4x1 = ["stm32l4/stm32l4x1"]
stm32l4x2 = ["stm32l4/stm32l4x2"]
stm32l4x3 = ["stm32l4/stm32l4x3"]
stm32l4x5 = ["stm32l4/stm32l4x5"]
stm32l4x6 = ["stm32l4/stm32l4x6"]
unproven = ["embedded-hal/unproven"]

[dev-dependencies]
panic-halt = "0.2.0"
panic-semihosting = "0.5.0"
cortex-m-semihosting = "0.3.1"
cortex-m-rt = "0.6.6"

[profile.dev]
incremental = false
codegen-units = 1

[profile.release]
codegen-units = 1
debug = true
lto = true

Simplify gpio.rs?

I happened on this while looking at https://github.com/stm32-rs/stm32f4xx-hal/blob/master/src/gpio.rs#L341-L345 (because I need AF10, and I felt there was too much copy-pasta): The f4 crew removed all the "opaque XXX registers" from the API, in particular the split() -> Parts only contain the pins themselves.

This makes everything nicer, you can e.g. call gpiob.pb3.into_push_pull_output() instead of passing in the gpiob.pb3.into_push_pull_output(&mut gpiob.moder, &mut gpiob.otyper), which really is an implementation detail a HAL should not expose.

@MabezDev @mathk @FrozenDroid: Do we want this too? It would break all the dependent code, but fixing it would be simple ("just remove function arguments until compiler is happy").

Implement Drop for DMA transfer types

Right now the DMA API is unsound, the problem happens if you use a smart pointer (Box, etc) that deallocates on drop. In that case, the DMA will continue the write/read to the invalid region if the user drops the transfer type.

The Drop implementation should stop the DMA. For more information and example see the embedonomicon.

CC @korken89

replace embedded_hal::v1 with embedded_hal::v2

warning: use of deprecated item 'embedded_hal::digital::v1::InputPin': Deprecated because the methods cannot return errors. Users should use the traits in digital::v2.

warning: use of deprecated item 'embedded_hal::digital::v1::OutputPin': Deprecated because the methods cannot return errors. Users should use the traits in digital::v2.

warning: use of deprecated item 'embedded_hal::digital::v1::OutputPin::set_high': Deprecated because the methods cannot return errors. Users should use the traits in digital::v2.

warning: use of deprecated item 'embedded_hal::digital::v1::OutputPin::set_low': Deprecated because the methods cannot return errors. Users should use the traits in digital::v2.

warning: use of deprecated item 'embedded_hal::digital::v1::InputPin::is_low': Deprecated because the methods cannot return errors. Users should use the traits in digital::v2.

It should be concidered to upgrade to v2. Should not be a big problem, but might break stuff. But I think its worth it.

I2C does not properly shift address

The embedded-hal specifies that I2C addresses are provided as a 7-bit value (without the R/W bit). However, this HAL writes the provided address directly into the I2C_CR2 SADD field, where BIT0 is set as the R/W bit. No shifting is completed to properly align the address with the requirements of the embedded-hal.

stm32l4xx-hal/src/i2c.rs

Lines 186 to 196 in 3d157d5

w.sadd()
.bits(addr as u16) // upto 9 bits for address
.rd_wrn()
.clear_bit()
.nbytes()
.bits(bytes.len() as u8)
.start()
.set_bit()
.autoend()
.set_bit()
});

(Note the above is for Write, but the bug is present for all I2C functions)

image

Use of four PWM

From the example https://github.com/stm32-rs/stm32l4xx-hal/blob/master/examples/pwm.rs I'm trying to use the four pwn, but with this code only the pwm.3 works. Is it possible to use all the pwm exits? What is wrong with my implementation?

//! Testing PWM output

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

extern crate panic_halt;

// use cortex_m::asm;
use stm32l4xx_hal::{
    prelude::*,
    stm32,
    delay,
};
use cortex_m_rt::entry;

#[entry]
fn main() -> ! {
    let c = cortex_m::Peripherals::take().unwrap();
    let p = stm32::Peripherals::take().unwrap();

    let mut flash = p.FLASH.constrain();
    let mut rcc = p.RCC.constrain();

    let clocks = rcc.cfgr.freeze(&mut flash.acr);

    let mut gpioa = p.GPIOA.split(&mut rcc.ahb2);

    // TIM2
    let c1 = gpioa.pa0
        .into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper)
        .into_af1(&mut gpioa.moder, &mut gpioa.afrl);
    let c2 = gpioa.pa1
        .into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper)
        .into_af1(&mut gpioa.moder, &mut gpioa.afrl);
    let c3 = gpioa.pa2
        .into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper)
        .into_af1(&mut gpioa.moder, &mut gpioa.afrl);
    let c4 = gpioa.pa3
        .into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper)
        .into_af1(&mut gpioa.moder, &mut gpioa.afrl);

    let mut pwm = p
        .TIM2
        .pwm(
            (c1, c2, c3, c4),
            1.khz(),
            clocks,
            &mut rcc.apb1r1,
        );

    let mut pwma = pwm.0;
    let mut pwmb = pwm.1;
    let mut pwmc = pwm.2;
    let mut pwmd = pwm.3;
   
    let maxa = pwma.get_max_duty();
    let maxb = pwmb.get_max_duty();
    let maxc = pwmc.get_max_duty();
    let maxd = pwmd.get_max_duty();

    pwma.enable();
    pwmb.enable();
    pwmc.enable();
    pwmd.enable();

    let mut timer = delay::Delay::new(c.SYST, clocks);
    let second: u32 = 100;

    // NB: if the pins are LEDs, brightness is not
    //     linear in duty value.
    loop {
        pwma.set_duty(maxa);
        pwmb.set_duty(maxb);
        pwmc.set_duty(maxc);
        pwmd.set_duty(maxd);
        timer.delay_ms(second);
        // asm::bkpt();

        pwma.set_duty(maxa/11*10);
        pwmb.set_duty(maxb/11*10);
        pwmc.set_duty(maxc/11*10);
        pwmd.set_duty(maxd/11*10);
        timer.delay_ms(second);
    }
}

Delay not working correctly?

In an example of mine, Delay's delay_ms duration depends on the rcc.cfg.hclk setting, is this a known issue? If so I'll look into it.

Let's use rustfmt

Just adding an issue to check if you agree.
If so, it should be tested and enforced in #34

Flash programming

While I'm still iterating on the Flash traits, the implementation is ready for consumption.

My question is how we'd want to handle "more than unproven" traits, as there seems to be no consensus and no progress in the case of Flash (and others...) currently. I certainly would like to retain the freedom to iterate the trait API while I start using it in earnest.

One tricky issue is the fact that in a general Flash trait, the size/alignment rules for reads, writes and erases are chip dependent. I'm currently using the generic-array approach, an alternative would be the "config crate" approach demo'd in https://github.com/jamesmunns/mcf-config-demo

Options are:

  1. treat as unproven
  2. treat as extra-traits
  3. include traits in HAL implementation
  4. use separate flash-traits crate
  5. not merge at all into this repository

Currently I'm doing 2+3+5.

Question: Remaining serial interfaces

Hi.

I am in a situation, where i need USART3 & 4 on my stm32l475. I have implemented these, and they are tested and working fully. Now i would like to add a PR on these, but was thinking i would add the full suite of uart and usart peripherals for the entire family.

So the question is, if i want to contribute this, would you be interested in me doing it in the same fashion as https://github.com/stm32-rs/stm32f4xx-hal/blob/master/src/serial.rs, with regards to the feature gating? Or is there another way you want to go about it?

Blinky.rs for stm32l475 LED PA5

I modified the blinky.rs example to run for stm32l475:

//! Blinks an LED

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

extern crate cortex_m;
#[macro_use]
extern crate cortex_m_rt as rt;
extern crate cortex_m_semihosting as sh;
extern crate panic_semihosting;
extern crate stm32l4xx_hal as hal;
// #[macro_use(block)]
// extern crate nb;

use crate::hal::prelude::*;
use crate::hal::delay::Delay;
use crate::rt::ExceptionFrame;
use crate::rt::entry;

use core::fmt::Write;
use crate::sh::hio;

#[entry]
fn main() -> ! {

    let mut hstdout = hio::hstdout().unwrap();

    writeln!(hstdout, "Hello, world!").unwrap();

    let cp = cortex_m::Peripherals::take().unwrap();
    let dp = hal::stm32::Peripherals::take().unwrap();

    let mut flash = dp.FLASH.constrain(); // .constrain();
    let mut rcc = dp.RCC.constrain();

    // Try a different clock configuration
    let clocks = rcc.cfgr.hclk(8.mhz()).freeze(&mut flash.acr);
    // let clocks = rcc.cfgr
    //     .sysclk(64.mhz())
    //     .pclk1(32.mhz())
    //     .freeze(&mut flash.acr);

    // let mut gpioc = dp.GPIOC.split(&mut rcc.ahb2);
    // let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.afrh);

    let mut gpioa = dp.GPIOA.split(&mut rcc.ahb2);
    let mut led = gpioa.pa5.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper);

    let mut timer = Delay::new(cp.SYST, clocks);
    loop {
        // block!(timer.wait()).unwrap();
        //timer.delay_ms(1000 as u32);
        led.set_high();
        // block!(timer.wait()).unwrap();
        //timer.delay_ms(1000 as u32);
        led.set_low();
    }
}

#[exception]
fn HardFault(ef: &ExceptionFrame) -> ! {
    panic!("{:#?}", ef);
}
cargo run  --release --example blinky --features="stm32l4x5,rt"
Compiling stm32l4xx-hal v0.3.6 (/home/tasosxak/Documents/RustProjects/stm32l4xx-hal)
Finished release [optimized + debuginfo] target(s) in 1.43s
     Running `gdb-multiarch -q -x openocd.gdb target/thumbv7em-none-eabi/release/examples/blinky`
Reading symbols from target/thumbv7em-none-eabi/release/examples/blinky...done.
0x00000000 in ?? ()
Breakpoint 1 at 0x8000a1a: file /home/tasosxak/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.7/src/lib.rs, line 550.
Breakpoint 2 at 0x8002982: file examples/blinky.rs, line 63.
Breakpoint 3 at 0x800064c: file /home/tasosxak/.cargo/registry/src/github.com-1ecc6299db9ec823/panic-semihosting-0.5.1/src/lib.rs, line 78.
semihosting is enabled
Loading section .vector_table, size 0x188 lma 0x8000000
Loading section .text, size 0x283c lma 0x8000188
Loading section .rodata, size 0x1950 lma 0x80029e0
Start address 0x80007ca, load size 17172
Transfer rate: 24 KB/sec, 5724 bytes/write.
(gdb) continue
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.

The program gets stuck at this point.

Openocd :

openocd -f interface/stlink-v2-1.cfg -f target/stm32l4x.cfg
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 500 kHz
adapter_nsrst_delay: 100
none separate
Info : Unable to match requested speed 500 kHz, using 480 kHz
Info : Unable to match requested speed 500 kHz, using 480 kHz
Info : clock speed 480 kHz
Info : STLINK v2 JTAG v28 API v2 SWIM v18 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 3.240714
Info : stm32l4x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : accepting 'gdb' connection on tcp/3333
Info : device id = 0x10076415
Info : flash size = 1024kbytes
undefined debug reason 7 - target needs reset
semihosting is enabled
Info : Unable to match requested speed 500 kHz, using 480 kHz
Info : Unable to match requested speed 500 kHz, using 480 kHz
adapter speed: 480 kHz
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x080007ca msp: 0x20018000, semihosting
adapter speed: 4000 kHz
Info : Padding image section 0 with 28 bytes
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x20000050 msp: 0x20018000, semihosting
Warn : block write succeeded
Info : Unable to match requested speed 500 kHz, using 480 kHz
Info : Unable to match requested speed 500 kHz, using 480 kHz
adapter speed: 480 kHz
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x080007ca msp: 0x20018000, semihosting
Hello, world!

Tests and continuous builds

Tests would be ideal of course :)

It would be great if at minimum we ensure the crate builds for all the features (checked for pull requests). If someone applies for GitHub Actions for the stm32-rs organization, that would be one route, otherwise there is CircleCI or Travis or possibly some Rust / Rust Embedded infra we might use.

MonoTimer always 0 value

I'm using a loop with MonoTimer but it seems not working. The part of the code I'm using:

#[entry]
fn main() -> ! {
        let pa = cortex_m::Peripherals::take().unwrap();
        let dwt = pa.DWT;

        let time = MonoTimer::new(dwt, clocks);

    loop {
    	// writes on serial interface
        writeln!(tx, "Hello time {}\r\n", time.now().elapsed()).unwrap();   
    }
}

But it can see always:

Hello time 0
Hello time 0
...

What am i doing wrong?

Replace extension traits with constructors?

Somewhat orthogonal to #56, there is a fundamental rethink of the HAL API going on in nRF land. Instead of extension traits with associated constrain/split methods, "constructors" (new methods) can be used.

Examples:

This is mostly being driven by @hannobraun. Some obvious advantages:

  • less methods to remember
  • less magic introduced by "prelude" imports - easier to lookup what code does

@MabezDev @mathk @FrozenDroid: Do we want this too? :)

error[E0412]: cannot find type `CRRCR` in module `rcc`

cargo build --release --examples --features="stm32l4x5,rt"


Compiling stm32l4xx-hal v0.3.6 (/home/tasosxak/Documents/RustProjects/stm32l4xx-hal)
error[E0412]: cannot find type `CRRCR` in module `rcc`
   --> src/rcc.rs:118:45
    |
118 |     pub(crate) fn crrcr(&mut self) -> &rcc::CRRCR {
    |                                             ^^^^^ not found in `rcc`
help: possible candidate is found in another module, you can import it into scope
    |
3   | use crate::rcc::CRRCR;
    |

error[E0609]: no field `crrcr` on type `stm32l4::stm32l4x5::rcc::RegisterBlock`
   --> src/rcc.rs:120:33
    |
120 |         unsafe { &(*RCC::ptr()).crrcr }
    |                                 ^^^^^ unknown field
    |
    = note: available fields are: `cr`, `icscr`, `cfgr`, `pllcfgr`, `pllsai1cfgr` ... and 25 others

error[E0609]: no field `crrcr` on type `&stm32l4::stm32l4x5::rcc::RegisterBlock`
   --> src/rcc.rs:507:21
    |
507 |                 rcc.crrcr.modify(|_, w| w.hsi48on().set_bit());
    |                     ^^^^^

error[E0609]: no field `crrcr` on type `&stm32l4::stm32l4x5::rcc::RegisterBlock`
   --> src/rcc.rs:509:27
    |
509 |                 while rcc.crrcr.read().hsi48rdy().bit_is_clear() {}
    |                           ^^^^^

error: aborting due to 4 previous errors

Some errors occurred: E0412, E0609.
For more information about an error, try `rustc --explain E0412`.
error: Could not compile `stm32l4xx-hal`.

To learn more, run the command again with --verbose.

Missing I2C3 Peripheral on STM32L476

I'm working on a STM32L476 which has 3 I2C peripherals, but I2C3 is not implemented by the HAL.

For now I cloned the repo and added it myself, but I would like to create a pull request.
How should I go about feature locking so only devices supporting I2C3 can use it?

I2C and SSD1306

So great that you're working on the I2C, thanks! I'm trying to get this to work together with @jamwaffles's ssd1306 crate, but... no luck so far. Seeing as you have your own OLED driver (is I2C working with your ssd1351?), I was wondering if you see an obvious issue in https://github.com/nickray/ssd1306/blob/2be6dda92c9521a5babd6154f0012d8679898704/examples/stm32l4_graphics_i2c_128x32.rs? All I know is I'm getting a NACKF upon disp.init. The display (I have two) is attached as GND/VDD/SCL/SDA --> GND/3V3/D1/D0.

RTC alarm

  • configurable Alarms using the RTC.

RTC

  • LSI RC for clock source (internal)

How to set the stm32l4x2 for stm32l432?

$ cargo build --release --example blinky
Compiling typenum v1.10.0
Compiling semver-parser v0.7.0
Compiling proc-macro2 v0.4.30
Compiling unicode-xid v0.1.0
Compiling stable_deref_trait v1.1.1
Compiling rand_core v0.4.2
Compiling cortex-m v0.6.0
Compiling vcell v0.1.0
Compiling syn v0.15.42
Compiling stm32l4 v0.7.1
Compiling cortex-m v0.5.10
Compiling cortex-m-semihosting v0.3.3
Compiling void v1.0.2
Compiling aligned v0.2.0
Compiling cortex-m-rt v0.6.10
Compiling nb v0.1.2
Compiling r0 v0.2.2
Compiling cast v0.2.2
Compiling panic-halt v0.2.0
Compiling rand_core v0.3.1
Compiling volatile-register v0.2.0
Compiling semver v0.9.0
Compiling embedded-hal v0.2.3
Compiling rand v0.5.6
Compiling rustc_version v0.2.3
Compiling generic-array v0.12.3
Compiling bare-metal v0.2.4
Compiling as-slice v0.1.0
Compiling aligned v0.3.1
Compiling quote v0.6.13
Compiling panic-semihosting v0.5.2
Compiling stm32l4xx-hal v0.4.0 (C:\Users\daniel\Desktop\github_\stm32l4xx-hal)
error: This crate requires one of the following features enabled: stm32l4x1, stm32l4x2, stm32l4x3, stm32l4x4, stm32l4x5 or stm32l4x6
--> src\lib.rs:23:1
|
23 | compile_error!("This crate requires one of the following features enabled: stm32l4x1, stm32l4x2, stm32l4x3, stm32l4x4, stm32l4x5 or stm32l4x6");

Ok, next try
$ RUSTFLAGS='--cfg=feature="stm32l4x2"' cargo build --release --example blinky
Compiling semver-parser v0.7.0
Compiling typenum v1.10.0
Compiling proc-macro2 v0.4.30
Compiling stable_deref_trait v1.1.1
Compiling unicode-xid v0.1.0
Compiling vcell v0.1.0
Compiling cortex-m v0.6.0
Compiling rand_core v0.4.2
Compiling syn v0.15.42
Compiling cortex-m-semihosting v0.3.3
Compiling cortex-m v0.5.10
Compiling stm32l4 v0.7.1
Compiling cortex-m-rt v0.6.10
Compiling aligned v0.2.0
Compiling void v1.0.2
Compiling nb v0.1.2
Compiling cast v0.2.2
Compiling r0 v0.2.2
Compiling panic-halt v0.2.0
Compiling volatile-register v0.2.0
Compiling rand_core v0.3.1
Compiling semver v0.9.0
Compiling embedded-hal v0.2.3
Compiling rand v0.5.6
Compiling rustc_version v0.2.3
Compiling generic-array v0.12.3
Compiling as-slice v0.1.0
Compiling bare-metal v0.2.4
Compiling aligned v0.3.1
Compiling quote v0.6.13
Compiling panic-semihosting v0.5.2
Building [===============================> ] 46/52
Compiling stm32l4xx-hal v0.4.0 (C:\Users\daniel\Desktop\github_\stm32l4xx-hal)
error[E0432]: unresolved import crate::stm32::gpiod
--> src\gpio.rs:141:32
|
141 | use crate::stm32::{$gpioy, $GPIOX};
| ^^^^^^ no gpiod in stm32l4x2

$ rustc --version
rustc 1.38.0-nightly (04b88a9eb 2019-07-29)

$ rustup show
Default host: x86_64-pc-windows-msvc

installed toolchains

stable-x86_64-pc-windows-gnu
nightly-x86_64-pc-windows-gnu (default)

installed targets for active toolchain

thumbv6m-none-eabi
thumbv7em-none-eabi
thumbv7em-none-eabihf
thumbv7m-none-eabi
x86_64-pc-windows-gnu

active toolchain

nightly-x86_64-pc-windows-gnu (default)
rustc 1.38.0-nightly (04b88a9eb 2019-07-29)

Host OS: windows7, cygwin

What should be fixed?

Serial Framing error with USART1

I'm trying to use USART1 with that code with STM32L432KC:

#![no_std]
#![no_main]

extern crate cortex_m;

#[macro_use(block)]
extern crate nb;

#[macro_use]
extern crate log;

use panic_halt as _;

use cortex_m::asm;
use cortex_m::asm::wfi;
use rtfm::app;

//use cortex_m_semihosting as sh; // semihosting
//use cortex_m_semihosting::hprintln; // semihosting

use embedded_hal::digital::v2::OutputPin;
use stm32l4xx_hal::{
    gpio::{gpiob::PB3, Output, PushPull},
    pac,
    prelude::*,
    timer::{Event, Timer},
    delay::Delay,
    i2c::I2c,
    serial::{Config, Serial, Event as SerialEvent, Error},
    time::{MonoTimer, Instant},
    stm32,
    dma::{dma1, CircBuffer},
};

extern crate cortex_m_rt as rt;
extern crate panic_halt;

use rt::{exception, pre_init, ExceptionFrame};

#[app(device = stm32l4xx_hal::pac)]
const APP: () = {

    static mut LED_STATE: bool = ();
    static mut LED: PB3<Output<PushPull>> = ();
    static mut TIMER_HANDLER: Timer<pac::TIM7> = ();
    static mut USART1_RX: stm32l4xx_hal::serial::Rx<stm32l4xx_hal::stm32l4::stm32l4x2::USART1> = ();
    static mut USART1_TX: stm32l4xx_hal::serial::Tx<stm32l4xx_hal::stm32l4::stm32l4x2::USART1> = ();
    
    #[init(resources = [])]
    fn init() -> init::LateResources {
        core.DCB.enable_trace(); // required for DWT cycle clounter to work when not connected to the debugger
        core.DWT.enable_cycle_counter();

        let mut flash = device.FLASH.constrain();
        let mut rcc = device.RCC.constrain();
        let mut gpioa = device.GPIOA.split(&mut rcc.ahb2);
        let mut gpiob = device.GPIOB.split(&mut rcc.ahb2);

        let clocks = rcc
            .cfgr
            .sysclk(80.mhz())
            .pclk1(80.mhz())
            .pclk2(80.mhz())
            .freeze(&mut flash.acr);

        let mut delay = Delay::new(core.SYST, clocks);

        // user led
        let led = gpiob
            .pb3
            .into_push_pull_output(&mut gpiob.moder, &mut gpiob.otyper);

        // serial peripheral
        let tx = gpiob.pb6.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
        let rx = gpiob.pb7.into_af7(&mut gpiob.moder, &mut gpiob.afrl);

        let mut serial = Serial::usart1(
            device.USART1,
            (tx, rx),
            Config::default().baudrate(115_200.bps()),
            clocks,
            &mut rcc.apb2,
        );

        serial.listen(SerialEvent::Idle); // listen to Idle Line detection, it is NOT enable until after init is complete
        let (tx, rx) = serial.split();

        delay.delay_ms(100_u8); // allow module to boot

        


        init::LateResources {
            USART1_RX: rx,
            USART1_TX: tx,
            LED_STATE: true,
            LASER_SENSORS: laser_sensors,
            LASER_VALUES: laser_sensors_val,
            LED: led,
            TIMER_HANDLER: timer,
        }
    }

    #[idle]
    fn idle() -> ! {
        loop {
            wfi();
        }
    }

    #[interrupt(binds = TIM7, priority = 1, resources = [LED_STATE, LED, TIMER_HANDLER, USART1_RX, USART1_TX])]
    fn systick() {

        if *resources.LED_STATE == false{
            resources.LED.set_high().unwrap();
            *resources.LED_STATE = true;
        } else {
            resources.LED.set_low().unwrap();
            *resources.LED_STATE = false;
        }

        match block!(resources.USART1_RX.read()){
            Ok(received) => block!(resources.USART1_TX.write(b'D')).ok(),
            Err(e) => match e {
                Error::Framing => block!(resources.USART1_TX.write(b'F')).ok(),
                Error::Noise => block!(resources.USART1_TX.write(b'N')).ok(),
                Error::Overrun => block!(resources.USART1_TX.write(b'O')).ok(),
                Error::Parity => block!(resources.USART1_TX.write(b'P')).ok(),
                _ => block!(resources.USART1_TX.write(b'U')).ok()
            }
        };

        block!(resources.USART1_TX.write(b'=')).ok();

        //block!(resources.USART1_TX.write(received)).ok();

        resources.TIMER_HANDLER.clear_update_interrupt_flag();
    }
};

#[exception]
fn HardFault(ef: &ExceptionFrame) -> ! {
    panic!("{:#?}", ef);
}

but it in the serial I only read F output mapped as Error::Framing. Even with serial examples I have the same error, what am I missing?

Serial error with USART1

I'm using the example in examples/serial.rs but I'm not able to receive data, even if I can see data sent from the stm. What is wrong with that implementation with USART1?

Serial Hardware flowcontrol

I am currently working on a project where i need hardware flow control of the U(S)ART peripherals (CTS/RTS).
As far as i can see it would only be a matter of setting the two bits in CR3, and it should work fully, assuming the two gpio pins for CTS and RTS are already configured for the correct alternate function.

While implementing this, i see two paths and wanted to hear your take on which would be the correct way for this HAL.

1. option

pub enum FlowControl {
    FlowControlNone,
    FlowControlRts,
    FlowControlCts,
    FlowControlCtsRts,
}

pub struct Config {
    pub baudrate: Bps,
    pub parity: Parity,
    pub stopbits: StopBits,
    pub flow_control: FlowControl,
}

**SNIPPET [pub fn $usartX(...) -> Self]**
// Enable DMA transfers
usart.cr3.write(|w| w.dmat().set_bit().dmar().set_bit());

// Configure hardware flow control
match config.flow_control {
    FlowControl::FlowControlNone => usart.cr3.write(|w| w.rtse().clear_bit().ctse().clear_bit()),
    FlowControl::FlowControlRts => usart.cr3.write(|w| w.rtse().set_bit()),
    FlowControl::FlowControlCts => usart.cr3.write(|w| w.ctse().set_bit()),
    FlowControl::FlowControlCtsRts => usart.cr3.write(|w| w.rtse().set_bit().ctse().set_bit()),
};

// Enable One bit sampling method
usart.cr3.write(|w| w.onebit().set_bit());

// Configure baud rate
let brr = clocks.$pclkX().0 / config.baudrate.0;
assert!(brr >= 16, "impossible baud rate");
usart.brr.write(|w| unsafe { w.bits(brr) });
**SNIPPET END**

to be used as:

let tx = gpioa.pa0.into_af8(&mut gpioa.moder, &mut gpioa.afrl);
let rx = gpioa.pa1.into_af8(&mut gpioa.moder, &mut gpioa.afrl);
let _rts = gpioa.pa15.into_af8(&mut gpioa.moder, &mut gpioa.afrh);
let _cts = gpiob.pb7.into_af8(&mut gpiob.moder, &mut gpiob.afrl);

Serial::uart4(
    dp.UART4,
    (tx, rx),
    Config::default()
        .baudrate(115_200_u32.bps())
        .flow_control(FlowControl::FlowControlCtsRts),
    clocks,
    &mut rcc.apb1r1,
)

2. option

impl Pins<UART4> for ($TX, $RX, $CTS, $RTS) {
    const REMAP: u8 = 0;
    const FLOWCTL: u8 = 1;
}

impl Pins<UART4> for (PA0<Alternate<AF8, Input<Floating>>>, PA1<Alternate<AF8, Input<Floating>>>, PA15<Alternate<AF8, Input<Floating>>>, PB7<Alternate<AF8, Input<Floating>>>) {
    const REMAP: u8 = 0;
    const FLOWCTL: u8 = 1;
}

While keeping the already implemented Pins<> as

impl Pins<UART4> for (PA0<Alternate<AF8, Input<Floating>>>, PA1<Alternate<AF8, Input<Floating>>>) {
    const REMAP: u8 = 0;
    const FLOWCTL: u8 = 0;
}

to be used as:

let tx = gpioa.pa0.into_af8(&mut gpioa.moder, &mut gpioa.afrl);
let rx = gpioa.pa1.into_af8(&mut gpioa.moder, &mut gpioa.afrl);
let rts = gpioa.pa15.into_af8(&mut gpioa.moder, &mut gpioa.afrh);
let cts = gpiob.pb7.into_af8(&mut gpiob.moder, &mut gpiob.afrl);

Serial::uart4(
    dp.UART4,
    (tx, rx, rts, cts),
    Config::default()
        .baudrate(115_200_u32.bps()),
    clocks,
    &mut rcc.apb1r1,
)

The first option is definitely the faster one to write, but also opens up for configuring flowcontrol on the serial peripheral without putting the CTS/RTS pins into the correct AF mode.

I'd be happy to implement either or fully (all feature gates etc), i just don't wanna implement one of them, only to open a PR where the other one or maybe a third way is proposed.

ADC implementation

Hi,

For a project I'm working on, I need to use the ADC. Is work being done on it?
For now, I made a quick and crude implementation to use the ADC.
If no work is being done on it, I might take it upon me to handle this issue.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.