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

continue; and exception

parent 9f49f9eb
No related branches found
No related tags found
No related merge requests found
...@@ -189,18 +189,17 @@ A third alternative would be to store the panic message in some non-volatile mem ...@@ -189,18 +189,17 @@ A third alternative would be to store the panic message in some non-volatile mem
### Exception Handling and Core Peripheral Access ### Exception Handling and Core Peripheral Access
The ARM Cortex-M processors features a set of *core* peripherpherals and *exception* handlers. These offer basic functionality independent of vendor (NXP, STM, ...). The `SysTick` perihperal is a 24-bit countdown timer, that raises a `SysTick` exception when hitting 0 and reloads the set value. Seen as a real-time system, we can dispatch the `SysTick` task in a periodic fashion (without accumulated drift under some additional constraints). The ARM Cortex-M processors features a set of *core* peripherals and *exception* handlers. These offer basic functionality independent of vendor (NXP, STM, ...). The `SysTick` peripheral is a 24-bit countdown timer, that raises a `SysTick` exception when hitting 0 and reloads the set value. Seen as a real-time system, we can dispatch the `SysTick` task in a periodic fashion (without accumulated drift under some additional constraints).
In the `exception.rs` example a `.` is emitted by the `SysTick` handler using `semihosting`. Running the example should give you a periodic updated of the `openocd` console. In the `exception.rs` example a `.` is emitted by the `SysTick` handler using `semihosting`. Running the example should give you a periodic updated of the `openocd` console.
The `exception_itm.rs` and `exception_itm_raw.rs` uses the ITM instead. The difference is the way The `exception_itm.rs` and `exception_itm_raw.rs` uses the ITM instead. The difference is the way they gain access to the `ITM` peripheral. In the first case we *steal* the whole set of core peripherals, while the in the second case we use *raw* pointer access to the `ITM`. In both cases, the code is *unsafe*, as there is no guarantee that other tasks may access the peripheral simultaneously (causing a conflict/race). Later we will see how the concurrency problem is solved in RTFM to offer safe access to peripherals.
they gain access to the `ITM` periphereal. In the first case we *steal* the whole set of core peripherals (stealing works only in `--release` mode), while the in the second case we use *raw* pointer access to the `ITM`. In both cases, the code is *unsafe*, as there is no guarantee that other tasks may access the peripheral simultaneously (causing a conflict/race). Later we will see how the concurrency problem is solved in RTFM to offer safe access to peripherals.
--- ---
### Crash - Analysing the Exception Frame ### Crash - Analyzing the Exception Frame
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. In case the execution of an instruction 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 breakpoint at the `HardFualt` handler). From there you can print the exception frame, reflecting the state of the MCU when the error occurred. You can use `gdb` to give a `back trace` of the call-stack leading up to the error. See the example for detailed information.
--- ---
......
//! 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]
extern crate panic_halt;
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(16_000_000); // period = 1s
syst.enable_counter();
syst.enable_interrupt();
loop {
continue;
}
}
#[exception]
fn SysTick() {
hprint!(".").unwrap();
}
//! 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
//!
//! Notice, steal will panic! in debug mode, due to a `debug_assert` (ignored in release).
//! ---
#![no_main]
#![no_std]
extern crate panic_halt;
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::{iprint, iprintln, Peripherals};
use cortex_m_rt::{entry, exception};
#[entry]
fn main() -> ! {
let mut p = Peripherals::take().unwrap();
let mut syst = p.SYST;
let stim = &mut p.ITM.stim[0];
iprintln!(stim, "exception_itm");
// configures the system timer to trigger a SysTick exception every second
syst.set_clock_source(SystClkSource::Core);
syst.set_reload(16_000_000); // period = 1s
syst.enable_counter();
syst.enable_interrupt();
loop {
continue;
}
}
#[exception]
fn SysTick() {
// Here we steal all the peripherals.
//
// This is unsafe, as some other task/tasks may access the peripherals
// simultaneously, causing a conflict/race.
//
let mut p = unsafe { cortex_m::Peripherals::steal() };
let stim = &mut p.ITM.stim[0];
iprint!(stim, ".");
}
//! 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
//!
#![no_main]
#![no_std]
extern crate panic_halt;
use cortex_m::peripheral::{syst::SystClkSource, ITM};
use cortex_m::{iprint, iprintln, Peripherals};
use cortex_m_rt::{entry, exception};
#[entry]
fn main() -> ! {
let mut p = Peripherals::take().unwrap();
let mut syst = p.SYST;
let stim = &mut p.ITM.stim[0];
iprintln!(stim, "exception_itm_raw");
// configures the system timer to trigger a SysTick exception every second
syst.set_clock_source(SystClkSource::Core);
syst.set_reload(16_000_000); // period = 1s
syst.enable_counter();
syst.enable_interrupt();
loop {}
}
#[exception]
fn SysTick() {
// here we access `ITM` using a *raw* pointer
// this is unsafe, as there may be other tasks accessing the peripheral
// simultaneously (and that might cause a conflict/race)
let itm = unsafe { &mut *ITM::ptr() };
let stim = &mut itm.stim[0];
iprint!(stim, ".");
}
...@@ -11,5 +11,7 @@ use cortex_m_semihosting::hprintln; ...@@ -11,5 +11,7 @@ use cortex_m_semihosting::hprintln;
#[entry] #[entry]
fn main() -> ! { fn main() -> ! {
hprintln!("Hello, world!").unwrap(); hprintln!("Hello, world!").unwrap();
loop {} loop {
continue;
}
} }
...@@ -22,5 +22,7 @@ fn main() -> ! { ...@@ -22,5 +22,7 @@ fn main() -> ! {
let stim = &mut p.ITM.stim[0]; let stim = &mut p.ITM.stim[0];
iprintln!(stim, "Hello, again!"); iprintln!(stim, "Hello, again!");
loop {} loop {
continue;
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment