Skip to content
Snippets Groups Projects
Commit 8906f26e authored by Per Lindgren's avatar Per Lindgren
Browse files

example/device and SVD

parent 2c6d32a2
No related branches found
No related tags found
No related merge requests found
......@@ -16,6 +16,7 @@
"target/stm32f4x.cfg"
],
"postLaunchCommands": [
// sets the MCU to 64Mhz
"monitor reset init"
],
"swoConfig": {
......@@ -95,6 +96,37 @@
},
"cwd": "${workspaceRoot}"
},
{
"type": "cortex-debug",
"request": "launch",
"servertype": "openocd",
"name": "device (debug)",
"preLaunchTask": "cargo build --example device --features stm32f4",
"executable": "./target/thumbv7em-none-eabihf/debug/examples/device",
// uses local config files
"configFiles": [
"./stlink.cfg",
"./stm32f4x.cfg"
],
"postLaunchCommands": [
"monitor arm semihosting enable"
],
"swoConfig": {
"enabled": true,
"cpuFrequency": 16000000,
"swoFrequency": 2000000,
"source": "probe",
"decoders": [
{
"type": "console",
"label": "ITM",
"port": 0
}
]
},
"svdFile": "STM32F413.svd",
"cwd": "${workspaceRoot}"
},
{
"type": "cortex-debug",
"request": "launch",
......
......@@ -63,5 +63,17 @@
"isDefault": true
}
},
{
"type": "shell",
"label": "cargo build --example device --features stm32f4",
"command": "cargo build --example device --features stm32f4",
"problemMatcher": [
"$rustc"
],
"group": {
"kind": "build",
"isDefault": true
}
},
]
}
\ No newline at end of file
......@@ -7,12 +7,11 @@ version = "0.1.0"
[dependencies]
cortex-m = "0.5.8"
cortex-m-rt = "0.6.5"
cortex-m-rt = "0.6.7"
cortex-m-semihosting = "0.3.2"
panic-halt = "0.2.0"
# panic-abort = "0.3.1"
# panic-abort = "0.3.1" # requires nightly toolchain
# Uncomment for the panic example.
panic-semihosting = "0.5.1"
panic-itm = "0.4.0"
bare-metal = "0.2.4"
......@@ -20,10 +19,14 @@ bare-metal = "0.2.4"
# Uncomment for the allocator example.
# alloc-cortex-m = "0.3.5"
# Uncomment for the device example.
# [dependencies.stm32f30x]
# features = ["rt"]
# version = "0.7.1"
[dependencies.stm32f4]
version = "0.5.0"
features = ["stm32f411", "rt"]
optional = true
[[example]]
name = "device"
required-features = ["stm32f4"]
# this lets you use `cargo fix`!
[[bin]]
......@@ -39,3 +42,4 @@ codegen-units = 1 # better optimizations
debug = true # symbols are nice and they don't increase the size on Flash
lto = true # better optimizations
panic = "abort"
......@@ -198,8 +198,79 @@ they gain access to the `ITM` periphereal. In the first case we *steal* the whol
In case the execution of an intstruction fails, a `HardFault` exception is raised by the hardware, and the `HardFault` handler is executed. We can define our own handler as in example `crash.rs`. In `main` we attempt to read an illegal address, causing a `HardFault`, and we hit a breakpoint (`openocd.gdb` script sets a breakbpoint at the `HardFualt` handler). From there you can print the exception frame, reflecting the state of the MCU when the error occured. You can use `gdb` to give a `back trace` of the call-stack leading up to the error. See the example for detailed information.
---
### Device Crates and System View Descriptions (SVDs)
Besides the ARM provided *core* peripherals the STM32F401re/STM32F411re MCUs has numerous vendor specific peripherals (GPIOs, Timers, USARTs etc.). The vendor provides a System View Description (SVD) specifying the register block layouts (fields, enumerated values, etc.). Using the `svd2rust` tool we can derive a `Device Crate` providing an API that allow us to access each register according to the vendors specification. The `device.rs` example showcase how a `Device Crate` for the STM32F401re/STM32F411re MCUs can be added. (These MCUs have the same set of peripherals, only the the maximum clock rating differs.)
The example output a `.` each second over `semihosting` and `ITM`.
Looking at the `Corgo.toml` file we find:
``` toml
[package]
authors = ["Per Lindgren <per.lindgren@ltu.se>"]
edition = "2018"
readme = "README.md"
name = "app"
version = "0.1.0"
[dependencies]
cortex-m = "0.5.8"
cortex-m-rt = "0.6.7"
cortex-m-semihosting = "0.3.2"
panic-halt = "0.2.0"
# panic-abort = "0.3.1" # requires nightly toolchain
panic-semihosting = "0.5.1"
panic-itm = "0.4.0"
bare-metal = "0.2.4"
# Uncomment for the allocator example.
# alloc-cortex-m = "0.3.5"
[dependencies.stm32f4]
version = "0.5.0"
features = ["stm32f411", "rt"]
optional = true
[[example]]
name = "device"
required-features = ["stm32f4"]
# this lets you use `cargo fix`!
[[bin]]
name = "app"
test = false
bench = false
[profile.dev]
panic = "abort"
[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
panic = "abort"
```
Of particular interest here is the *optional* dependency to [dependencies.stm32f4], where `"stm32f4"` is a `required-feature` for the example `"device"`. In effect, you need to compile `device` as:
``` console
cargo build --example device --features stm32f4
```
In turn:
``` toml
[dependencies.stm32f4]
version = "0.5.0"
features = ["stm32f411", "rt"]
optional = true
```
Compiles `stm32f4` (a generic library for all STMF4 MCUs) with `features = features = ["stm32f411", "rt"]`, which indicates the specific MCU with `rt` (run-time support) enabled. By having the `Device Crate` as an optional dependency, we did not need to compile it (unless we need it, and as you might have experienced already compiling the `Device Crate` takes a bit of time initially). (An SVD file is typically > 50k lines, amounting to the same (or more) lines of Rust code.)
---
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
//! 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
//!
//! Device crates also provide an `interrupt!` macro (behind the "rt" feature) to register interrupt
//! handlers.
//!
//! This example depends on the [`stm32f103xx`] crate so you'll have to add it to your Cargo.toml.
//!
//! [`stm32f103xx`]: https://crates.io/crates/stm32f103xx
//!
//! ```
//! $ edit Cargo.toml && tail $_
//! [dependencies.stm32f103xx]
//! features = ["rt"]
//! version = "0.10.0"
//! ```
//!
//! ---
#![no_main]
#![no_std]
#[allow(unused_extern_crates)]
extern crate panic_halt;
use cortex_m::{iprint, peripheral::syst::SystClkSource};
use cortex_m_rt::entry;
use cortex_m_semihosting::hprintln;
use stm32f4::stm32f411::{interrupt, Interrupt, ITM, 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(16_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);
}
}
// try commenting out this line: you'll end in `default_handler` instead of in `exti0`
#[interrupt]
fn EXTI0() {
hprintln!(".").unwrap();
let itm = unsafe { &mut *ITM::ptr() };
let stim = &mut itm.stim[0];
iprint!(stim, ".");
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment