From 9f49f9eb5932d27f4271b732d9676e6b959750c7 Mon Sep 17 00:00:00 2001
From: Per Lindgren <per.lindgren@ltu.se>
Date: Thu, 30 Jan 2020 16:27:53 +0100
Subject: [PATCH] panic

---
 Cargo.toml        |  1 +
 README.md         | 11 +++++------
 examples/itm.rs   |  5 ++---
 examples/panic.rs | 28 ++++++++++++++++++++++++++++
 openocd.gdb       | 24 ++++++++++++++++++++----
 5 files changed, 56 insertions(+), 13 deletions(-)
 create mode 100644 examples/panic.rs

diff --git a/Cargo.toml b/Cargo.toml
index ab13ba6..1577f79 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,6 +17,7 @@ cortex-m-semihosting    = "0.3.5"
 cortex-m                = "0.6.2"
 aligned                 = "0.3.2"
 ufmt                    = "0.1.0"
+panic-itm = "0.4.1"
 
 [dependencies.cortex-m-rt]
 version          = "0.6.12"
diff --git a/README.md b/README.md
index c3bf7f2..b0e3a53 100644
--- a/README.md
+++ b/README.md
@@ -127,15 +127,14 @@ In a separate terminal:
 
 ``` console
 $ mkfifo /tmp/itm.fifo
-$ itmdump -f /tmp/itm.fifo -F
+$ itmdump -f /tmp/itm.fifo
+Hello, again!
 ```
 
 Now you can compile and run the `itm.rs` application using the same steps as the `hello` program. In the `itmdump` console you should now have the trace output.
 
 ``` console
-$ mkfifo /tmp/itm.log
-$ itmdump -f /tmp/itm.log -F
-Hello, again!
+$ cargo run --example itm
 ```
 
 Under the hood there is much less overhead, the serial transfer rate is set to 2MBit in between the ITM (inside of the MCU) and `stlink` programmer (onboard the Nucleo devkit). So in theory we can transmit some 200kByte/s data over ITM. However, we are limited by the USB interconnection and `openocd` to receive and forward packages.
@@ -146,7 +145,7 @@ The `stlink` programmer, buffers packages but has limited buffer space. Hence in
 
 ### Rust `panic` Handling
 
-The `rust` compiler statically analyses your code, but in cases some errors cannot be detected at compile time (e.g., array indexing out of bounds, division by zore etc.). The `rust` compiler generates code checking such faults at run-time, instead of just crashing (or even worse, continuing with faulty/undefined values like a `C` program would) . A fault in Rust will render a `panic`, whith an associated error message (useful to debugging the application). We can choose how such `panic`s should be treated, e.g., transmitting the error message using `semihosting`, `ITM`, some other channel (e.g. a serial port), or simply aborting the program.
+The `rust` compiler statically analyses your code, but in cases some errors cannot be detected at compile time (e.g., array indexing out of bounds, division by zero etc.). The `rust` compiler generates code checking such faults at run-time, instead of just crashing (or even worse, continuing with faulty/undefined values like a `C` program would) . A fault in Rust will render a `panic`, with an associated error message (useful to debugging the application). We can choose how such `panic`s should be treated, e.g., transmitting the error message using `semihosting`, `ITM`, some other channel (e.g. a serial port), or simply aborting the program.
 
 The `panic` example demonstrates some possible use cases.
 
@@ -169,7 +168,7 @@ Breakpoint 1, rust_begin_unwind (_info=0x20017fb4)
 $1 = core::panic::PanicInfo {payload: core::any::&Any {pointer: 0x8000760 <.Lanon.21a036e607595cc96ffa1870690e4414.142> "\017\004\000", vtable: 0x8000760 <.Lanon.21a036e607595cc96ffa1870690e4414.142>}, message: core::option::Option<&core::fmt::Arguments>::Some(0x20017fd0), location: core::panic::Location {file: <error reading variable>, line: 27, col: 5}}
 ```
 
-Here `p *_info` prints the arument to `rust_begin_unwind`, at the far end you will find `line: 27, col 5`, which correstponds to the source code calling `panic("Ooops")`. (`gdb` is not (yet) Rust aware enough to figure out how the `file` field should be interpreted, but at least we get some useful information).
+Here `p *_info` prints the arument to `rust_begin_unwind`, at the far end you will find `line: 27, col 5`, which corresponds to the source code calling `panic("Ooops")`. (`gdb` is not (yet) Rust aware enough to figure out how the `file` field should be interpreted, but at least we get some useful information).
 
 Alternatively we can trace the panic message over `semihosting` (comment out `extern crate panic_halt` and uncomment `extern crate panic_semihosting`).
 
diff --git a/examples/itm.rs b/examples/itm.rs
index b4c9401..a522c0d 100644
--- a/examples/itm.rs
+++ b/examples/itm.rs
@@ -2,10 +2,9 @@
 //!
 //! ITM is much faster than semihosting. Like 4 orders of magnitude or so.
 //!
-//! You'll need [`itmdump`] to receive the message on the host plus you'll need to uncomment two
-//! `monitor` commands in the `.gdbinit` file.
+//! You'll need [`itmdump`] to view the output.
 //!
-//! [`itmdump`]: https://docs.rs/itm/0.2.1/itm/
+//! [`itmdump`]: https://docs.rs/itm/0.3.1/itm/
 //!
 //! ---
 
diff --git a/examples/panic.rs b/examples/panic.rs
new file mode 100644
index 0000000..27ad333
--- /dev/null
+++ b/examples/panic.rs
@@ -0,0 +1,28 @@
+//! Changing the panicking behavior
+//!
+//! The easiest way to change the panicking behavior is to use a different [panic handler crate][0].
+//!
+//! [0]: https://crates.io/keywords/panic-impl
+
+#![no_main]
+#![no_std]
+
+// Pick one of these panic handlers:
+
+// `panic!` halts execution; the panic message is ignored
+extern crate panic_halt;
+
+// Reports panic messages to the host stderr using semihosting
+// NOTE to use this you need to uncomment the `panic-semihosting` dependency in Cargo.toml
+// extern crate panic_semihosting;
+
+// Logs panic messages using the ITM (Instrumentation Trace Macrocell)
+// NOTE to use this you need to uncomment the `panic-itm` dependency in Cargo.toml
+//extern crate panic_itm;
+
+use cortex_m_rt::entry;
+
+#[entry]
+fn main() -> ! {
+    panic!("Oops")
+}
diff --git a/openocd.gdb b/openocd.gdb
index 92d2058..3d73217 100644
--- a/openocd.gdb
+++ b/openocd.gdb
@@ -1,11 +1,22 @@
 target extended-remote :3333
 
 set print asm-demangle on
+
 monitor arm semihosting enable
 
-monitor tpiu config internal /tmp/itm.fifo uart off 16000000 2000000
+# ITM tracing
+# send captured ITM to the file (or fifo) /tmp/itm.fifo
+# (the microcontroller SWO pin must be connected to the programmer SWO pin)
+# 16000000 must match the core clock frequency
+# in this case the speed of SWO will be negotiated 
+monitor tpiu config internal /tmp/itm.fifo uart off 16000000
+
+# OR: make the microcontroller SWO pin output compatible with UART (8N1)
+# 16000000 must match the core clock frequency
+# 2000000 is the frequency of the SWO pin
+# monitor tpiu config external uart off 16000000 2000000
 
-# enable itm ports
+# enable ITM ports
 monitor itm port 0 on 
 monitor itm port 1 on
 monitor itm port 2 on
@@ -14,12 +25,17 @@ monitor itm port 2 on
 break main
 
 # detect unhandled exceptions, hard faults and panics
+break DefaultHandler
 break HardFault
-break core::panicking::panic_fmt
+break rust_begin_unwind
 
 # un-comment to check that flashing was successful
 # compare-sections
 
+# make sure the processor is reset before loading (flashing)
 monitor reset init
+
 load
-stepi
\ No newline at end of file
+
+# start the process but immediately halt the processor
+stepi
-- 
GitLab