diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..c6ab50fe7026da205491acc8f4f52b51d7da40c0 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,6 @@ +# Changelog + +## 2021-02-15 + +- Initial release for the e7020e course 2021 + \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 736149cdad35f5482777c9b851eecd1b2d8daddc..d9339e9f1654b00327b9dce5b5c92760db54934f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,14 +16,14 @@ usb-device = "0.2.7" # Panic handlers, comment all but one to generate doc! panic-halt = "0.2.0" -# Uncomment for the panic example. -#panic-itm = "0.4.2" +# Uncomment for the itm panic examples. +panic-itm = "0.4.2" -# Uncomment for the rtt-timing example. +# Uncomment for the rtt-timing examples. panic-rtt-target = { version = "0.1.1", features = ["cortex-m"] } -# Uncomment for the panic example. -#panic-semihosting = "0.5.6" +# Uncomment for the semihosting examples. +panic-semihosting = "0.5.6" # Tracing rtt-target = { version = "0.3.0", features = ["cortex-m"] } @@ -42,7 +42,7 @@ features = ["rt", "stm32f411", "usb_fs"] # Enable to use the latest git version # gitgit = "https://github.com/stm32-rs/stm32f4xx-hal" # Enable to use your forked/cloned local repo -path = "../stm32f4xx-hal" +# path = "../stm32f4xx-hal" # this lets you use `cargo fix`! diff --git a/README.md b/README.md index a6655f0780d165f43dde4c5b8ebf55744222841a..e300365de26479f9fcf700daebacc12f4c028bd1 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,52 @@ -# App +# RTIC on the STM32F4xx Nucleo board -## Resources +All tooling have been developed and tested under Linux. Any modern Linux distro should work, we usually recommend Arch linux as it provides a great package manager with rolling releases. If you want to run Arch, but don't want to install everything from scratch, you may opt for [Manjaro](https://manjaro.org/) or [Endeavour](https://endeavouros.com/). You will get the best user experience by a native install, but you may run Linux under a VM like virtualbox, or vmware (the player is free). You should install the guest extensions, to get better graphics performance (and perhaps better USB forwarding). Since you will connect your Nucleo using USB, you must make sure that USB port forwarding works (the Nucleo stlink programmer is a USB2 device running in full speed 12MBit). + +This repo will be updated with more information throughout the course so please check the `CHANGELOG.md` and recent commits to see what has changed. (You should `pull` the upstream to keep your repository updated.) If you have suggestions to further improvements, please raise an issue and/or create a merge/pull request. + +## Rust + +We assume Rust to be installed using [rustup](https://www.rust-lang.org/tools/install). + +Additionally you need to install the `thumbv7em-none-eabi` target. + +```shell +> rustup target add thumbv7em-none-eabi +``` + +You also need [cargo-binutils](https://github.com/rust-embedded/cargo-binutils), for inspecting the generated binaries. You install Rust applications through `cargo` + +```shell +> cargo install cargo-binutils +``` + +There are a number of other useful [cargo subcommands](https://github.com/rust-lang/cargo/wiki/Third-party-cargo-subcommands), notably `cargo-bloat` (that gives you info on the size of different sections of the generated binary), `cargo-tree` (that list your dependency tree), etc. + +## For RTT tracing + +We assume the following tools are in place: + +- [probe-run](https://crates.io/crates/probe-run) + +## For programming and low level `gdb` based debugging + +Linux tooling: + +- `stlink`, this package will install programming utilities like `st-flash` (useful if you need to recover a bricked target by erasing the flash), and setup `udev` rules, allowing you to access the USB device without `sudo`. Install may require you to login/logout to have new `udev` rules applied. +- `openocd`, this tool allows the host to connect to the (stlink) programmer. +- `arm-none-eabi-gdb`, or `gdb-multiarch` (dependent on Linux distro). This tool allows you to program (flash) and debug your target. + +## Editor + +You may use any editor of choice. `vscode` supports Rust using the `rust-analyzer` plugin. You may also want to install the `Cortex Debug` plugin. In the `.vscode` folder, there are a number of configuration files (`launch.json` for target debugging, `tasks.json` for building, etc.). + +## Useful Resources - Nucleo 64 - [UM1724 - stm32 Nucleo-64](https://www.st.com/resource/en/user_manual/dm00105823-stm32-nucleo64-boards-mb1136-stmicroelectronics.pdf). - [Nucleo 64 Schematics](https://www.st.com/resource/en/schematic_pack/nucleo_64pins_sch.zip) (The file MB1136.pdf is the schematics in pdf.) - [stm32f4xx_hal](https://docs.rs/stm32f4xx-hal/0.8.3/stm32f4xx_hal/) documentation of the HAL API, and [git repository](https://github.com/stm32-rs/stm32f4xx-hal). - - STM32F01/FO11 - [RM0383 - F411 Reference Manual](https://www.st.com/resource/zh/reference_manual/dm00119316-stm32f411xce-advanced-armbased-32bit-mcus-stmicroelectronics.pdf) - [RM0368 - F401 Reference Manual](https://www.st.com/resource/en/reference_manual/dm00096844-stm32f401xbc-and-stm32f401xde-advanced-armbased-32bit-mcus-stmicroelectronics.pdf) @@ -22,85 +61,113 @@ --- -## Connections +## Examples -- [USB Cable] +### VSCODE based debug and trace -| Signal | Color | Pin | -| ------ | ----- | ---- | -| V+ | Red | ---- | -| D- | White | PA11 | -| D+ | Green | PA12 | -| Gnd | Black | ---- | +Some simple bare metal examples for you to try out before starting to run your own code: +Using `vscode` just press F5 to launch and debug the program in the currently active vscode window. -D+ used for re-enumeration +- `rtic_hello.rs`, this example uses semihosting to print the output terminal. Open the `OUTPUT` pane, and select `Adapter Output` (which is the openocd console). +- `itm_rtic_hello.rs`, this examples uses the ITM trace to print to an output trace channel. Open the `OUTPUT` pane, and select `SWO:ITM[port:0, type:console]`. +- `rtic_panic.rs`, this example shows how to trace panic messages (in this case over semihosting). Open the `OUTPUT` pane, and select `Adapter Output` (which is the openocd console). +- `rtic_crash.rs`, this example shows how to trace a HardFault (an error raised by the ARM processor). ---- +### Console based debug and trace -## Debug interface +- `rtt_rtic_hello.rs`, this example uses the RTT framework for tracing. -- Serial Wire debugging uses pins PA13 and PA14. So refrain from using those unless absolutely necessary. + ```shell + > cargo run --example rtt_rtic_hello + ``` --- -## Examples +## Nucleo Connections +Some of the examples need external connection to the Nucleo to work. ---- +### USB example -## Troubleshooting +| Signal | Color | Pin | Nucleo | +| ------ | ----- | ---- | --------- | +| V+ | Red | | | +| D- | White | PA11 | CN10 - 14 | +| D+ | Green | PA12 | CN10 - 12 | +| Gnd | Black | | CN10 - 9 | -### Fail to connect with openocd +D+ used for re-enumeration. You don't need to connect the V+ from the USB cable, as the NUCLEO is self powered. -First check that your stlink nucleo programmer is found by the host. +### PWM example -```shell -> lsusb -... -Bus 003 Device 013: ID 0483:374b STMicroelectronics ST-LINK/V2.1 -... -``` +| Signal | Pin | Nucleo | +| ------ | --- | ------- | +| PWM1 | PA8 | CN9 - 8 | +| PWM2 | PA9 | CN5 - 1 | -If not check your USB cable. Notice, you need a USB data cable (not a USB charging cable). -If the problem is still there, there might be a USB issue with the host (or VM if you run Linux under a VM that is). +## Debug interface -If you get a connection error similar to the below: +- Serial Wire debugging uses pins PA13 and PA14. So refrain from using those unless absolutely necessary. -```shell -> openocd -f openocd.cfg -Open On-Chip Debugger 0.10.0+dev-01157-gd6541a811-dirty (2020-03-28-18:34) -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 2000 kHz -Info : STLINK V2J37M26 (API v2) VID:PID 0483:374B -Info : Target voltage: 3.243627 -Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints -Info : Listening on port 3333 for gdb connections -Error: jtag status contains invalid mode value - communication failure -Polling target stm32f4x.cpu failed, trying to reexamine -Examination failed, GDB will be halted. Polling again in 100ms -Info : Previous state query failed, trying to reconnect -Error: jtag status contains invalid mode value - communication failure -Polling target stm32f4x.cpu failed, trying to reexamine -``` +--- -First thing to try is holding the reset button while connecting. -If this does not work you can try to erase the flash memory (the program running on the STM32F401/F11). +## Troubleshooting -``` shell -> st-util erase -st-flash 1.6.1 -2021-01-11T16:02:14 INFO common.c: F4xx (Dynamic Efficency): 96 KiB SRAM, 512 KiB flash in at least 16 KiB pages. -Mass erasing....... -``` +--- -If this still does not work you can connect `Boot0` to `VDD` (found on CN7 pins 7, and 5 respectively). Unplug/replug the Nucleo and try to erase the flash as above. +### Fail to connect or program (flash) your target -If this still does not work, the Nucleo might actually been damaged, or that the problem is the usb-cable or host machine related. +- Make sure you have the latest version of the [stlink](https://www.st.com/en/development-tools/stsw-link007.html) firmware (2.37.27 or later). +- Check that your stlink nucleo programmer is found by the host. + + ```shell + > lsusb + ... + Bus 003 Device 013: ID 0483:374b STMicroelectronics ST-LINK/V2.1 + ... + ``` + + If not check your USB cable. Notice, you need a USB data cable (not a USB charging cable). + If the problem is still there, there might be a USB issue with the host (or VM if you run Linux under a VM that is). + +- If you get a connection error similar to the below: + + ```shell + > openocd -f openocd.cfg + Open On-Chip Debugger 0.10.0+dev-01157-gd6541a811-dirty (2020-03-28-18:34) + 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 2000 kHz + Info : STLINK V2J37M26 (API v2) VID:PID 0483:374B + Info : Target voltage: 3.243627 + Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints + Info : Listening on port 3333 for gdb connections + Error: jtag status contains invalid mode value - communication failure + Polling target stm32f4x.cpu failed, trying to reexamine + Examination failed, GDB will be halted. Polling again in 100ms + Info : Previous state query failed, trying to reconnect + Error: jtag status contains invalid mode value - communication failure + Polling target stm32f4x.cpu failed, trying to reexamine + ``` + + - First thing to try is holding the reset button while connecting. + + - If this does not work you can try to erase the flash memory (the program running on the STM32F401/F11). + + ``` shell + > st-util erase + st-flash 1.6.1 + 2021-01-11T16:02:14 INFO common.c: F4xx (Dynamic Efficency): 96 KiB SRAM, 512 KiB flash in at least 16 KiB pages. + Mass erasing....... + ``` + + - If this still does not work you can connect `Boot0` to `VDD` (found on CN7 pins 7, and 5 respectively). Unplug/replug the Nucleo and try to erase the flash as above. + + - If this still does not work, the Nucleo might actually been damaged, or that the problem is the usb-cable or host machine related. diff --git a/examples/allocator.rs b/examples/allocator.rs deleted file mode 100644 index 53c3023857164497ee010fc4c75ad119dc118125..0000000000000000000000000000000000000000 --- a/examples/allocator.rs +++ /dev/null @@ -1,56 +0,0 @@ -//! How to use the heap and a dynamic memory allocator -//! -//! This example depends on the alloc-cortex-m crate so you'll have to add it to your Cargo.toml: -//! -//! ``` text -//! # or edit the Cargo.toml file manually -//! $ cargo add alloc-cortex-m -//! ``` -//! -//! --- - -#![feature(alloc_error_handler)] -#![no_main] -#![no_std] - -extern crate alloc; -use panic_halt as _; - -use self::alloc::vec; -use core::alloc::Layout; - -use alloc_cortex_m::CortexMHeap; -use cortex_m::asm; -use cortex_m_rt::entry; -use cortex_m_semihosting::{hprintln, debug}; - -// this is the allocator the application will use -#[global_allocator] -static ALLOCATOR: CortexMHeap = CortexMHeap::empty(); - -const HEAP_SIZE: usize = 1024; // in bytes - -#[entry] -fn main() -> ! { - // Initialize the allocator BEFORE you use it - unsafe { ALLOCATOR.init(cortex_m_rt::heap_start() as usize, HEAP_SIZE) } - - // Growable array allocated on the heap - let xs = vec![0, 1, 2]; - - hprintln!("{:?}", xs).unwrap(); - - // exit QEMU - // NOTE do not run this on hardware; it can corrupt OpenOCD state - debug::exit(debug::EXIT_SUCCESS); - - loop {} -} - -// define what happens in an Out Of Memory (OOM) condition -#[alloc_error_handler] -fn alloc_error(_layout: Layout) -> ! { - asm::bkpt(); - - loop {} -} diff --git a/examples/crash.rs b/examples/crash.rs deleted file mode 100644 index ab2d47bae20288a47dce7a6179ab4ce066f9d610..0000000000000000000000000000000000000000 --- a/examples/crash.rs +++ /dev/null @@ -1,96 +0,0 @@ -//! Debugging a crash (exception) -//! -//! Most crash conditions trigger a hard fault exception, whose handler is defined via -//! `exception!(HardFault, ..)`. The `HardFault` handler has access to the exception frame, a -//! snapshot of the CPU registers at the moment of the exception. -//! -//! This program crashes and the `HardFault` handler prints to the console the contents of the -//! `ExceptionFrame` and then triggers a breakpoint. From that breakpoint one can see the backtrace -//! that led to the exception. -//! -//! ``` text -//! (gdb) continue -//! Program received signal SIGTRAP, Trace/breakpoint trap. -//! __bkpt () at asm/bkpt.s:3 -//! 3 bkpt -//! -//! (gdb) backtrace -//! #0 __bkpt () at asm/bkpt.s:3 -//! #1 0x080030b4 in cortex_m::asm::bkpt () at $$/cortex-m-0.5.0/src/asm.rs:19 -//! #2 rust_begin_unwind (args=..., file=..., line=99, col=5) at $$/panic-semihosting-0.2.0/src/lib.rs:87 -//! #3 0x08001d06 in core::panicking::panic_fmt () at libcore/panicking.rs:71 -//! #4 0x080004a6 in crash::hard_fault (ef=0x20004fa0) at examples/crash.rs:99 -//! #5 0x08000548 in UserHardFault (ef=0x20004fa0) at <exception macros>:10 -//! #6 0x0800093a in HardFault () at asm.s:5 -//! Backtrace stopped: previous frame identical to this frame (corrupt stack?) -//! ``` -//! -//! In the console output one will find the state of the Program Counter (PC) register at the time -//! of the exception. -//! -//! ``` text -//! panicked at 'HardFault at ExceptionFrame { -//! r0: 0x2fffffff, -//! r1: 0x2fffffff, -//! r2: 0x080051d4, -//! r3: 0x080051d4, -//! r12: 0x20000000, -//! lr: 0x08000435, -//! pc: 0x08000ab6, -//! xpsr: 0x61000000 -//! }', examples/crash.rs:106:5 -//! ``` -//! -//! This register contains the address of the instruction that caused the exception. In GDB one can -//! disassemble the program around this address to observe the instruction that caused the -//! exception. -//! -//! ``` text -//! (gdb) disassemble/m 0x08000ab6 -//! Dump of assembler code for function core::ptr::read_volatile: -//! 451 pub unsafe fn read_volatile<T>(src: *const T) -> T { -//! 0x08000aae <+0>: sub sp, #16 -//! 0x08000ab0 <+2>: mov r1, r0 -//! 0x08000ab2 <+4>: str r0, [sp, #8] -//! -//! 452 intrinsics::volatile_load(src) -//! 0x08000ab4 <+6>: ldr r0, [sp, #8] -//! -> 0x08000ab6 <+8>: ldr r0, [r0, #0] -//! 0x08000ab8 <+10>: str r0, [sp, #12] -//! 0x08000aba <+12>: ldr r0, [sp, #12] -//! 0x08000abc <+14>: str r1, [sp, #4] -//! 0x08000abe <+16>: str r0, [sp, #0] -//! 0x08000ac0 <+18>: b.n 0x8000ac2 <core::ptr::read_volatile+20> -//! -//! 453 } -//! 0x08000ac2 <+20>: ldr r0, [sp, #0] -//! 0x08000ac4 <+22>: add sp, #16 -//! 0x08000ac6 <+24>: bx lr -//! -//! End of assembler dump. -//! ``` -//! -//! `ldr r0, [r0, #0]` caused the exception. This instruction tried to load (read) a 32-bit word -//! from the address stored in the register `r0`. Looking again at the contents of `ExceptionFrame` -//! we see that the `r0` contained the address `0x2FFF_FFFF` when this instruction was executed. -//! -//! --- - -#![no_main] -#![no_std] - -use panic_halt as _; - -use core::ptr; - -use cortex_m_rt::entry; - -#[entry] -fn main() -> ! { - unsafe { - // read an address outside of the RAM region; this causes a HardFault exception - ptr::read_volatile(0x2FFF_FFFF as *const u32); - } - - loop {} -} diff --git a/examples/device.rs b/examples/device.rs deleted file mode 100644 index a1a219c568a2f30f6621f45db985288c08c45328..0000000000000000000000000000000000000000 --- a/examples/device.rs +++ /dev/null @@ -1,62 +0,0 @@ -//! Using a device crate -//! -//! Crates generated using [`svd2rust`] are referred to as device crates. These crates provide an -//! API to access the peripherals of a device. -//! -//! [`svd2rust`]: https://crates.io/crates/svd2rust -//! -//! This example depends on the [`stm32f3`] crate so you'll have to -//! uncomment it in your Cargo.toml. -//! -//! [`stm32f3`]: https://crates.io/crates/stm32f3 -//! -//! ``` -//! $ edit Cargo.toml && tail $_ -//! [dependencies.stm32f3] -//! features = ["stm32f303", "rt"] -//! version = "0.7.1" -//! ``` -//! -//! You also need to set the build target to thumbv7em-none-eabihf, -//! typically by editing `.cargo/config` and uncommenting the relevant target line. -//! -//! --- - -#![no_main] -#![no_std] - -#[allow(unused_extern_crates)] -use panic_halt as _; - -use cortex_m::peripheral::syst::SystClkSource; -use cortex_m_rt::entry; -use cortex_m_semihosting::hprint; -use stm32f3::stm32f303::{interrupt, Interrupt, NVIC}; - -#[entry] -fn main() -> ! { - let p = cortex_m::Peripherals::take().unwrap(); - - let mut syst = p.SYST; - let mut nvic = p.NVIC; - - nvic.enable(Interrupt::EXTI0); - - // configure the system timer to wrap around every second - syst.set_clock_source(SystClkSource::Core); - syst.set_reload(8_000_000); // 1s - syst.enable_counter(); - - loop { - // busy wait until the timer wraps around - while !syst.has_wrapped() {} - - // trigger the `EXTI0` interrupt - NVIC::pend(Interrupt::EXTI0); - } -} - -#[interrupt] -fn EXTI0() { - hprint!(".").unwrap(); -} diff --git a/examples/exception.rs b/examples/exception.rs deleted file mode 100644 index 5edb487d31d2b8f535302052b1ad29b4749153a0..0000000000000000000000000000000000000000 --- a/examples/exception.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! Overriding an exception handler -//! -//! You can override an exception handler using the [`#[exception]`][1] attribute. -//! -//! [1]: https://rust-embedded.github.io/cortex-m-rt/0.6.1/cortex_m_rt_macros/fn.exception.html -//! -//! --- - -#![deny(unsafe_code)] -#![no_main] -#![no_std] - -use panic_halt as _; - -use cortex_m::peripheral::syst::SystClkSource; -use cortex_m::Peripherals; -use cortex_m_rt::{entry, exception}; -use cortex_m_semihosting::hprint; - -#[entry] -fn main() -> ! { - let p = Peripherals::take().unwrap(); - let mut syst = p.SYST; - - // configures the system timer to trigger a SysTick exception every second - syst.set_clock_source(SystClkSource::Core); - syst.set_reload(8_000_000); // period = 1s - syst.enable_counter(); - syst.enable_interrupt(); - - loop {} -} - -#[exception] -fn SysTick() { - hprint!(".").unwrap(); -} diff --git a/examples/hello.rs b/examples/hello.rs deleted file mode 100644 index 334592dfa62570ed144379b95738a1cb024f7614..0000000000000000000000000000000000000000 --- a/examples/hello.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! Prints "Hello, world!" on the host console using semihosting - -#![no_main] -#![no_std] - -use panic_halt as _; - -use cortex_m_rt::entry; -use cortex_m_semihosting::{debug, hprintln}; - -#[entry] -fn main() -> ! { - hprintln!("Hello, world!!").unwrap(); - - loop {} -} diff --git a/examples/itm.rs b/examples/itm.rs deleted file mode 100644 index e70922678d7fe6251a0411e12d426d96e528dea4..0000000000000000000000000000000000000000 --- a/examples/itm.rs +++ /dev/null @@ -1,34 +0,0 @@ -//! Sends "Hello, world!" through the ITM port 0 -//! -//! ITM is much faster than semihosting. Like 4 orders of magnitude or so. -//! -//! **NOTE** Cortex-M0 chips don't support ITM. -//! -//! You'll have to connect the microcontroller's SWO pin to the SWD interface. Note that some -//! development boards don't provide this option. -//! -//! You'll need [`itmdump`] to receive the message on the host plus you'll need to uncomment two -//! `monitor` commands in the `.gdbinit` file. -//! -//! [`itmdump`]: https://docs.rs/itm/0.2.1/itm/ -//! -//! --- - -#![no_main] -#![no_std] - -use panic_halt as _; - -use cortex_m::{iprintln, Peripherals}; -use cortex_m_rt::entry; -use stm32f4 as _; // to get interrupt vectors - -#[entry] -fn main() -> ! { - let mut p = Peripherals::take().unwrap(); - let stim = &mut p.ITM.stim[0]; - - iprintln!(stim, "Hello, world!"); - - loop {} -} diff --git a/examples/itm_rtic_hello.rs b/examples/itm_rtic_hello.rs new file mode 100644 index 0000000000000000000000000000000000000000..963183d7c35ac2f2eb38e6be1cadde636cc71d51 --- /dev/null +++ b/examples/itm_rtic_hello.rs @@ -0,0 +1,18 @@ +#![no_main] +#![no_std] + +use cortex_m::iprintln; +use panic_halt as _; +use stm32f4; + +#[rtic::app(device = stm32f4)] +const APP: () = { + #[init] + fn init(cx: init::Context) { + let mut p = cx.core; + let stim = &mut p.ITM.stim[0]; + for a in 0..=10 { + iprintln!(stim, "RTIC Hello, world!! {}", a); + } + } +}; diff --git a/examples/rtic_crash.rs b/examples/rtic_crash.rs new file mode 100644 index 0000000000000000000000000000000000000000..1b1a2e0c56944b474ac63a5a7fbcafca95877988 --- /dev/null +++ b/examples/rtic_crash.rs @@ -0,0 +1,33 @@ +#![no_main] +#![no_std] + +use core::ptr; +use panic_halt as _; +use stm32f4; + +#[rtic::app(device = stm32f4)] +const APP: () = { + #[init] + fn init(_cx: init::Context) { + unsafe { + // read an address outside of the RAM region; this causes a HardFault exception + ptr::read_volatile(0x2FFF_FFFF as *const u32); + } + } +}; + +// Here you can inspect the call stack (found to the left in vscode). +// +// The default implementation for `HardFault` exception is just an infinite loop. +// Press the pause symbol to halt the processor: +// +// The upmost item in CALL STACK, is the current frame: +// (the infinite loop loop) +// +// The bottom most item is the start of the program (the generated main). +// +// In between, you can see the calls made +// main->init->read_volatile->HardFault->compiler_fence +// +// Click on init, and you will see that line 14 in this application caused the +// erroneous read operation. diff --git a/examples/rtic_hello.rs b/examples/rtic_hello.rs new file mode 100644 index 0000000000000000000000000000000000000000..89b4e69ce84afd85643aac46cb208c76b850504d --- /dev/null +++ b/examples/rtic_hello.rs @@ -0,0 +1,16 @@ +#![no_main] +#![no_std] + +use cortex_m_semihosting::hprintln; +use panic_halt as _; +use stm32f4; + +#[rtic::app(device = stm32f4)] +const APP: () = { + #[init] + fn init(_cx: init::Context) { + for a in 0..11 { + hprintln!("RTIC Says Hello, to all students!! {}", a).unwrap(); + } + } +}; diff --git a/examples/rtic_panic.rs b/examples/rtic_panic.rs new file mode 100644 index 0000000000000000000000000000000000000000..f782dc7f927a1d5bd102ebb621521d8233669305 --- /dev/null +++ b/examples/rtic_panic.rs @@ -0,0 +1,27 @@ +#![no_main] +#![no_std] + +use cortex_m_semihosting::hprintln; + +// Pick one of these panic handlers: + +// `panic!` halts execution; the panic message is ignored +// use panic_halt as _; + +// Reports panic messages to the host stderr using semihosting +use panic_semihosting as _; + +// Logs panic messages using the ITM (Instrumentation Trace Macrocell) +// use panic_itm as _; + +use stm32f4; + +#[rtic::app(device = stm32f4)] +const APP: () = { + #[init] + fn init(_cx: init::Context) { + for i in 0..10 { + hprintln!("RTIC Says Hello, world {}!!", 100 / (5 - i)).ok(); + } + } +};