stm32-rs / stm32h7xx-hal

Peripheral access API for STM32H7 series microcontrollers
BSD Zero Clause License
210 stars 99 forks source link

`stm32h747cm7` compatible with stm32h745i-DISCO? #432

Closed sgasse closed 1 year ago

sgasse commented 1 year ago

Hi!

I am pretty new to embedded development but have been doing Rust for some time. A colleague borrowed me a STM32H745I-DISCO which has both a Cortex M4 and Cortex M7. Another colleague looked into getting started with me and suggested that I look for a HAL crate. The reference sheet (link currently dead for me) has the title "STM32H745/755 and STM32H747/757 advanced Arm ® -based 32-bit MCUs" so I would hope that the STM32H747 is compatible with the STM32H745. Both have the combination of M4+M7 and I am happy only using the M7.

However, when I try to run an example in the debugger, it always hangs on let pwrcfg = pwr.freeze();. I also tried pwr.ldo().freeze() and pwr.smps().freeze() (without knowing in detail what it is about, some power domains right?). Below is the blinky example adapted:

//! Blinky example adapted (no macro use, semihosting and PI13 as output)

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

use cortex_m_rt::entry;
use cortex_m_semihosting::hprintln;
use panic_semihosting as _;
use stm32h7xx_hal::{pac, prelude::*};

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

    // Constrain and Freeze power
    hprintln!("Setup PWR...                  ").unwrap();
    let pwr = dp.PWR.constrain();
    let pwrcfg = pwr.freeze();

    // Constrain and Freeze clock
    hprintln!("Setup RCC...                  ").unwrap();
    let rcc = dp.RCC.constrain();
    let ccdr = rcc.sys_ck(100.MHz()).freeze(pwrcfg, &dp.SYSCFG);

    hprintln!("").unwrap();
    hprintln!("stm32h7xx-hal example - Blinky").unwrap();
    hprintln!("").unwrap();

    let gpioi = dp.GPIOI.split(ccdr.peripheral.GPIOI);

    // Configure PE1 as output.
    let mut led = gpioi.pi13.into_push_pull_output();

    // Get the delay provider.
    let mut delay = cp.SYST.delay(ccdr.clocks);

    loop {
        loop {
            led.set_high();
            delay.delay_ms(500_u16);

            led.set_low();
            delay.delay_ms(500_u16);
        }
    }
}

[dependencies]
cortex-m = "0.6.0"
cortex-m-rt = "0.6.10"
cortex-m-semihosting = "0.3.3"
panic-halt = "0.2.0"
panic-semihosting = "0.6.0"
stm32h7xx-hal = { version = "0.14.0", features = ["stm32h747cm7", "rt"] }

# this lets you use `cargo fix`!
[[bin]]
name = "stm-hello-world"
test = false
bench = false

[profile.release]
codegen-units = 1 # better optimizations
debug = true      # symbols are nice and they don't increase the size on Flash
lto = true        # better optimizations

I am running the example like this:

cargo build && gdb-multiarch -x openocd.gdb target/thumbv7em-none-eabi/debug/stm-hello-world
# A second terminal runs `openocd` in version `0.12`.

Output of openocd:

Open On-Chip Debugger 0.12.0+dev-00150-g91bd43134 (2023-04-17-15:03)
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
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 1800 kHz
Info : STLINK V3J3M2 (API v3) VID:PID 0483:374E
Info : Target voltage: 3.300400
Info : [stm32h7x.cpu0] Cortex-M7 r1p1 processor detected
Info : [stm32h7x.cpu0] target has 8 breakpoints, 4 watchpoints
Info : starting gdb server for stm32h7x.cpu0 on 3333
Info : Listening on port 3333 for gdb connections
Info : accepting 'gdb' connection on tcp/3333
[stm32h7x.cpu0] halted due to debug-request, current mode: Thread 
xPSR: 0x61000000 pc: 0x0800cd3c msp: 0x2407f890
Info : Device: STM32H74x/75x
Info : flash size probed value 2048k
Info : STM32H7 flash has dual banks
Info : Bank (0) size is 1024 kb, base address is 0x08000000
[stm32h7x.cpu0] halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08000298 msp: 0x24080000, semihosting
Info : Unable to match requested speed 4000 kHz, using 3300 kHz
Info : Unable to match requested speed 4000 kHz, using 3300 kHz
Info : Padding image section 0 at 0x080100d0 with 16 bytes (bank write end alignment)
[stm32h7x.cpu0] halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08000298 msp: 0x24080000, semihosting
Info : halted: PC: 0x0800029a
Info : halted: PC: 0x0800047e
Setup PWR...  

Output of gdb:

Reading symbols from target/thumbv7em-none-eabi/debug/stm-hello-world...
core::ptr::read_volatile (src=0x7aa88221)
    at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/ptr/mod.rs:1492
1492    /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/ptr/mod.rs: No such file or directory.
Breakpoint 1 at 0x800cd88: file src/lib.rs, line 570.
Breakpoint 2 at 0x800e600: file src/lib.rs, line 560.
Breakpoint 3 at 0x800c0b4: file src/lib.rs, line 71.
Breakpoint 4 at 0x8000478: file src/main.rs, line 12.
semihosting is enabled
Loading section .vector_table, size 0x298 lma 0x8000000
Loading section .text, size 0xe37c lma 0x8000298
Loading section .rodata, size 0x1abc lma 0x800e614
Start address 0x08000298, load size 65744
Transfer rate: 42 KB/sec, 10957 bytes/write.
Note: automatically using hardware breakpoints for read-only addresses.
halted: PC: 0x0800029a
0x0800029a in cortex_m_rt::Reset () at src/lib.rs:497
497     pub unsafe extern "C" fn Reset() -> ! {
(gdb) continue
Continuing.

Breakpoint 4, main () at src/main.rs:12
12      #[entry]
(gdb) continue
Continuing.
halted: PC: 0x0800047e

Almost every example needs a handle to pwrcfg, so I don't really get around it. Of course, maybe something else is completely messed up as I don't understand much about embedded programming ^^ However if I just put a log with a counter into the loop and remove all HAL-related stuff, I see the prints coming through semihosting, so I think the memory setup and flashing/booting in general works.

Thus I wonder: Do I just need to fiddle a little more with it, or does it just not work because the chip I have is not compatible with the one I use? Any help would be greatly appreciated!

richardeoin commented 1 year ago

Hi! You can use the examples and instructions for the STM32H747 with a STM32H745 development board. However you need to configure the power supply correctly to use these examples. In the User Manual for your development board there is a section "SMPS/LDO power supply" and this will help you learn about SMPS and LDO modes.

I suspect you should try:

  1. Set the power supply configuration to SMPS with pwr.smps().freeze()
  2. Turn your board off and on again
sgasse commented 1 year ago

Hey @richardeoin , thank you for pointing me to the power supply docs. I re-read them but the issue turned out to be something else: When I researched the board, I found the info somewhere that it did not have hard float support, so I used the target thumbv7em-none-eabi, but apparently the right target for the board is thumbv7em-none-eabihf (including FPUs).

# .cargo/config.toml
[build]
target = "thumbv7em-none-eabihf"

Now it works. Thanks for you swift reply! :slightly_smiling_face: