stm32-rs / stm32f1xx-hal

A Rust embedded-hal HAL impl for the STM32F1 family based on japarics stm32f103xx-hal
Apache License 2.0
575 stars 179 forks source link

HardFault when setting the system clock settings #338

Open chmanie opened 3 years ago

chmanie commented 3 years ago

I am using a blue pill with the default settings from this repository. When testing I noticed that whenever I set the system clock to anything else than the default settings, the code panics.

Here's the simple example I came up with

#![no_main]
#![no_std]

#[macro_use(entry, exception)]
extern crate cortex_m_rt as rt;
extern crate cortex_m_semihosting as sh;
extern crate panic_semihosting;

extern crate stm32f1xx_hal as hal;

use hal::prelude::*;
use rt::ExceptionFrame;

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

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

    rcc
        .cfgr
        .sysclk(8.mhz()) // Removing this line will make it work!
        .freeze(&mut flash.acr);

    loop {}
}

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

My Cargo.toml:

[package]
# ...

[package.metadata]
chip = "STM32F103C8"

[dependencies]
cortex-m = "0.7.2"
cortex-m-rt = "0.6.13"
cortex-m-semihosting = "0.3.7"
panic-semihosting = "0.5.6"
embedded-hal = "0.2.5"

[dependencies.stm32f1xx-hal]
version = "0.7.0"
features = ["rt", "stm32f103", "medium"]

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

When debugging I am presented the following error:

Info : halted: PC: 0x08006408
panicked at 'ExceptionFrame {
    r0: 0xfffffffe,
    r1: 0x00000002,
    r2: 0x003d0900,
    r3: 0x20004ee4,
    r12: 0x00000000,
    lr: 0x08001e05,
    pc: 0x080026ee,
    xpsr: 0x41000000,
}', src/main.rs:169:5

Is there anything more I can try? Might this be related to #311?

Another simple way to break things in a reproducible way is to use the following lines in the blinky example instead of the clock configuration there:

    rcc
        .cfgr
        .sysclk(8.mhz()) // Removing this line will make it work!
        .freeze(&mut flash.acr);
TeXitoi commented 3 years ago

Can you try with

        let clocks = rcc
                    .cfgr
                    .use_hse(8.mhz())
                    .sysclk(72.mhz())
                    .pclk1(36.mhz())
                    .freeze(&mut flash.acr);

This crate is picky when the different clocks are not coherent.

TeXitoi commented 3 years ago

Also, if it panics, you should have the message from semihosting.

TeXitoi commented 3 years ago

Mmm, it doesn't panic, it HardFault, you should clarify it in your text, I missed that.

chmanie commented 3 years ago

Ah, thanks, yeah I adjusted the title.

So I got the blinky example running with the following setting:

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

Using your code above I get

panicked at 'assertion failed: rvr < (1 << 24)', /Users/chris/dev/rust/stm32f1xx-hal/src/timer
.rs:248:9

This is a bit more informative. I'll look into it more and keep you updated! Thanks a lot so far!

fishrockz commented 3 years ago

Setting HSE is really important, on the blue pill it's a 8mhz crystal so always set it to 8 MHz in your case. But after that there are a lot of things that can effect how fast you can push it. If you have a bluepill clone with a cheap voltage reg then you may never get it quite as fast but be careful about the combination of sysclk and pclk1 looking at the excellent stm32 data sheets to see which the chip actually supports and be aware of clone chips which might not conform exactly to the real thing

chmanie commented 3 years ago

Thank you for the detailed explanation, @fishrockz! I think I regret going for the blue pill already. I was used to having access to proper chips that I put on simple breadboard adapters and they just worked. Now they're just so expensive :(

TeXitoi commented 3 years ago

A blue pill is a great cheap board. As it is popular, quality depends a lot of the supplier.

another solution in this class is the WeAct Mini-F4. https://m.aliexpress.com/item/1005001456186625.html

chmanie commented 3 years ago

Thank you both! I think this can be closed, it seems I was just using it wrong.

fishrockz commented 3 years ago

I was just trying to point out some things to watch for. I have actually had really good luck with the bluepill! I have got a number of peripherals working and comms over USB.

It's a really great offering at the price point. No matter what chip you go for you are Gona want to make friends with the data sheets weather it's for details about the bus' or some dma registers, I am loving using rust for embedded but the community it really young so you may end up submitting the odd patch here or there!

TheZoq2 commented 3 years ago

Thank you both! I think this can be closed, it seems I was just using it wrong.

I'll go ahead and re-open this since this crate is designed to have safe abstractions to avoid hard faults and panics, at least until we can figure out what the underlying issue is and rule out non-hardware problems.

I've also not had any issues with the blue pills I've tried, but of course, your mileage may vary

andreyk0 commented 3 years ago

Here's another possibly similar issue. Experimenting with stm32f107vct6 board that I took from an old 3D printer. It has a 25Mhz crystal but when I try to use that value freeze panics. When STM32CubeMX sets up clock tree for 25Mhz it ends up switching prediv1 source (via prediv1 source mux) from using HSE directly to a pll2clk, perhaps that's the missing part.

(gdb) frame
#0  stm32f1xx_hal::rcc::CFGR::freeze (self=..., acr=<optimized out>)
    at /home/andrey/.cargo/registry/src/github.com-1ecc6299db9ec823/stm32f1xx-hal-0.7.0/src/rcc.rs:244
244         assert!(sysclk <= 72_000_000);
(gdb) list
239             let pllmul = cmp::min(cmp::max(pllmul, 4), 9);
240 
241             (Some(pllmul as u8 - 2), pllsrcclk * pllmul)
242         };
243 
244         assert!(sysclk <= 72_000_000);
245 
246         let hpre_bits = self
247             .hclk
248             .map(|hclk| match sysclk / hclk {
(gdb) print sysclk 
$1 = 100000000
(gdb) next
halted: PC: 0x080022b0
halted: PC: 0x080025ec
halted: PC: 0x080025f0
halted: PC: 0x080025f4
halted: PC: 0x080025f8
halted: PC: 0x080025fc
halted: PC: 0x080025fe
halted: PC: 0x080025ac
halted: PC: 0x08002856

Breakpoint 3, panic_halt::panic (_info=0x2000fec0)
    at /home/andrey/.cargo/registry/src/github.com-1ecc6299db9ec823/panic-halt-0.2.0/src/lib.rs:32
32      loop {
(gdb) bt
#0  panic_halt::panic (_info=0x2000fec0)
    at /home/andrey/.cargo/registry/src/github.com-1ecc6299db9ec823/panic-halt-0.2.0/src/lib.rs:32
#1  0x080028ec in core::panicking::panic_fmt () at library/core/src/panicking.rs:92
#2  0x08002884 in core::panicking::panic () at library/core/src/panicking.rs:50
#3  0x080025b0 in stm32f1xx_hal::rcc::CFGR::freeze (self=..., acr=<optimized out>)
    at /home/andrey/.cargo/registry/src/github.com-1ecc6299db9ec823/stm32f1xx-hal-0.7.0/src/rcc.rs:329
#4  0x08000ab8 in blink::init (cx=...) at src/bin/blink.rs:43
#5  0x08001cda in blink::APP::main () at src/bin/blink.rs:26
(gdb)