From b672967d8ab403b04576ac30ab0ae6823bf39539 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Thu, 8 Apr 2021 11:27:00 +0200 Subject: [PATCH] use `defmt` in training materials --- advanced/firmware/Cargo.toml | 4 ++-- beginner/apps/src/bin/blinky.rs | 2 +- beginner/apps/src/bin/panic.rs | 6 +++--- boards/dk/Cargo.toml | 4 ++-- boards/dk/src/lib.rs | 5 +++-- embedded-workshop-book/src/error-handling.md | 4 ++-- embedded-workshop-book/src/interfaces.md | 2 +- embedded-workshop-book/src/messages.md | 8 ++++---- embedded-workshop-book/src/radio-puzzle-help.md | 2 +- embedded-workshop-book/src/time.md | 2 +- embedded-workshop-book/src/using-hal.md | 11 ++++++++++- 11 files changed, 30 insertions(+), 20 deletions(-) diff --git a/advanced/firmware/Cargo.toml b/advanced/firmware/Cargo.toml index 85fd4a6..e8fb0cd 100644 --- a/advanced/firmware/Cargo.toml +++ b/advanced/firmware/Cargo.toml @@ -15,11 +15,11 @@ consts = { path = "../common/consts" } cortex-m = "0.6.4" cortex-m-rt = "0.6.13" cortex-m-rtic = "0.5.1" +defmt = "0.2.1" +defmt-rtt = "0.2.0" dk = { path = "../../boards/dk", features = ["advanced"] } heapless = "0.5.5" panic-probe = { version = "0.2.0", features = ["print-defmt"] } -defmt = "0.2.1" -defmt-rtt = "0.2.0" usb = { path = "../common/usb" } usb2 = "0.0.1" diff --git a/beginner/apps/src/bin/blinky.rs b/beginner/apps/src/bin/blinky.rs index abf020c..a3e10b1 100644 --- a/beginner/apps/src/bin/blinky.rs +++ b/beginner/apps/src/bin/blinky.rs @@ -20,7 +20,7 @@ fn main() -> ! { for _ in 0..10 { led.toggle(); timer.wait(Duration::from_secs(1)); - defmt::debug!("LED toggled at {:?}", dk::uptime()); + defmt::info!("LED toggled at {:?}", dk::uptime()); } dk::exit() diff --git a/beginner/apps/src/bin/panic.rs b/beginner/apps/src/bin/panic.rs index 272f2b6..b065acb 100644 --- a/beginner/apps/src/bin/panic.rs +++ b/beginner/apps/src/bin/panic.rs @@ -3,8 +3,8 @@ use cortex_m::asm; use cortex_m_rt::entry; -// use apps as _; // this defines the panicking behaviour - +// this imports `beginner/apps/lib.rs` to retrieve our global logger + panicking-behavior +use apps as _; #[entry] fn main() -> ! { @@ -38,5 +38,5 @@ fn index() -> usize { #[panic_handler] fn panic(info: &core::panic::PanicInfo) -> ! { - defmt::panic!("lalal {}", info); + defmt::panic!("{}", info); } \ No newline at end of file diff --git a/boards/dk/Cargo.toml b/boards/dk/Cargo.toml index 989c418..a4213f6 100644 --- a/boards/dk/Cargo.toml +++ b/boards/dk/Cargo.toml @@ -15,12 +15,12 @@ defmt = "0.3.0" defmt-rtt = "0.3.1" [features] -beginner = [] advanced = [] +beginner = [] # set defmt logging levels here default = [ - "defmt-debug", + "defmt-info", # "dependency-a/defmt-trace", ] diff --git a/boards/dk/src/lib.rs b/boards/dk/src/lib.rs index d010023..a368db6 100644 --- a/boards/dk/src/lib.rs +++ b/boards/dk/src/lib.rs @@ -26,7 +26,6 @@ use defmt; #[cfg(any(feature = "beginner", feature = "advanced"))] use defmt_rtt as _; // global logger - #[cfg(feature = "advanced")] use crate::{ peripheral::{POWER, USBD}, @@ -246,7 +245,9 @@ pub fn init() -> Result { // set TX power to its maximum value radio.set_txpower(ieee802154::TxPower::Pos8dBm); - defmt::debug!("Radio initialized and configured with TX power set to the maximum value"); + defmt::debug!( + "Radio initialized and configured with TX power set to the maximum value" + ); radio }; diff --git a/embedded-workshop-book/src/error-handling.md b/embedded-workshop-book/src/error-handling.md index fc7b2e6..3f7937a 100644 --- a/embedded-workshop-book/src/error-handling.md +++ b/embedded-workshop-book/src/error-handling.md @@ -10,7 +10,7 @@ fn on_event(/* parameters */) { if ep0setup(/* arguments */).is_err() { // unsupported or invalid request: // TODO add code to stall the endpoint - log::warn!("EP0: unexpected request; stalling the endpoint"); + defmt::warn!("EP0IN: unexpected request; stalling the endpoint"); } } } @@ -32,4 +32,4 @@ Note that there's a difference between the error handling done here and the erro (3) stopping the program, and e.g. requiring the user to reset it to make it work again, may not be desirable behavior. For these reasons in embedded software errors tend to be handled as early as possible rather than propagated all the way up. -This does not preclude error *reporting*. The above snippet includes error reporting in the form of a `log::warn!` statement. This log statement may not be included in the final release of the program as it may not be useful, or even visible, to an end user but it is useful during development. +This does not preclude error *reporting*. The above snippet includes error reporting in the form of a `defmt::warn!` statement. This log statement may not be included in the final release of the program as it may not be useful, or even visible, to an end user but it is useful during development. diff --git a/embedded-workshop-book/src/interfaces.md b/embedded-workshop-book/src/interfaces.md index 2d639fb..56f942d 100644 --- a/embedded-workshop-book/src/interfaces.md +++ b/embedded-workshop-book/src/interfaces.md @@ -10,7 +10,7 @@ Inside the 'configuration 1' rectangle there are two rectangles labeled 'control Inside the 'interface 0' rectangle there are three rectangles labeled 'endpoint 1 IN', 'endpoint 2 IN' and 'endpoint 2 OUT'. Between these three rectangle there is a label that says 'bNumEndpoints=3'; it indicates that this interface has only three endpoints.">

-An interface is closest to a USB device's function. For example, a USB mouse may expose a single HID (Human Interface Device) interface to report user input to the host. USB devices can expose multiple interfaces within a configuration. For example, the nRF52840 Dongle could expose both a CDC ACM interface (AKA virtual serial port) *and* a HID interface; the first interface could be used for (`log::info!`-style) logs; and the second one could provide a RPC (Remote Procedure Call) interface to the host for controlling the nRF52840's radio. +An interface is closest to a USB device's function. For example, a USB mouse may expose a single HID (Human Interface Device) interface to report user input to the host. USB devices can expose multiple interfaces within a configuration. For example, the nRF52840 Dongle could expose both a CDC ACM interface (AKA virtual serial port) *and* a HID interface; the first interface could be used for (`defmt::info!`-style) logs; and the second one could provide a RPC (Remote Procedure Call) interface to the host for controlling the nRF52840's radio. An interface is made up of one or more *endpoints*. To give an example, a HID interface can use two (interrupt) endpoints, one IN and one OUT, for bidirectional communication with the host. A single endpoint cannot be used by more than one interface with the exception of the special "endpoint 0", which can be (and usually is) shared by all interfaces. diff --git a/embedded-workshop-book/src/messages.md b/embedded-workshop-book/src/messages.md index c0a765d..c6df898 100644 --- a/embedded-workshop-book/src/messages.md +++ b/embedded-workshop-book/src/messages.md @@ -32,11 +32,11 @@ let array1: [u8; 3] = [0, 1, 2]; let array2: [u8; 4] = [0, 1, 2, 3]; let mut slice: &[u8] = &array1; -log::info!("{:?}", slice); // length = 3 +defmt::info!("{:?}", slice); // length = 3 // now point to the other array slice = &array2; -log::info!("{:?}", slice); // length = 4 +defmt::info!("{:?}", slice); // length = 4 ``` ## Byte literals @@ -82,8 +82,8 @@ On the other hand, `"Hello"` is a string literal with type `&str`. `str` strings In this workshop we'll work with ASCII strings so byte string literals that contain no escaped characters are OK to use as packet payloads. -You'll note that `log::info!("{:?}", b"Hello")` will print `[72, 101, 108, 108, 111]` rather than `"Hello"` and that the `{}` format specifier (`Display`) does not work. This is because the type of the literal is `&[u8; N]` and in Rust this type means "bytes"; those bytes could be ASCII data, UTF-8 data or something else. +You'll note that `defmt::info!("{:?}", b"Hello")` will print `[72, 101, 108, 108, 111]` rather than `"Hello"` and that the `{}` format specifier (`Display`) does not work. This is because the type of the literal is `&[u8; N]` and in Rust this type means "bytes"; those bytes could be ASCII data, UTF-8 data or something else. To print this you'll need to convert the slice `&[u8]` into a string (`&str`) using the `str::from_utf8` function. This function will verify that the slice contains well formed UTF-8 data and interpret it as a UTF-8 string (`&str`). As long as we use ASCII data (printable ASCII characters) this conversion will not fail. -Something similar will happen with byte literals: `log::info!("{}", b'A')` will print `65` rather than `A`. To get the `A` output you can cast the byte literal (`u8` value) to the `char` type: `log::info!("{}", b'A' as char)`. \ No newline at end of file +Something similar will happen with byte literals: `defmt::info!("{}", b'A')` will print `65` rather than `A`. To get the `A` output you can cast the byte literal (`u8` value) to the `char` type: `defmt::info!("{}", b'A' as char)`. \ No newline at end of file diff --git a/embedded-workshop-book/src/radio-puzzle-help.md b/embedded-workshop-book/src/radio-puzzle-help.md index f94eb7f..f529514 100644 --- a/embedded-workshop-book/src/radio-puzzle-help.md +++ b/embedded-workshop-book/src/radio-puzzle-help.md @@ -56,7 +56,7 @@ fn main() -> ! { for plainletter in 0..=127 { /* ... send letter to dongle ... */ - log::info!("got response"); + defmt::info!("got response"); /* ... store output ... */ timer.wait(Duration::from_millis(20)); diff --git a/embedded-workshop-book/src/time.md b/embedded-workshop-book/src/time.md index 7992495..91b6cc5 100644 --- a/embedded-workshop-book/src/time.md +++ b/embedded-workshop-book/src/time.md @@ -12,4 +12,4 @@ The other time related API exposed by the `dk` HAL is the `dk::uptime` function. ✅ Try changing the `Duration` value passed to `Timer.wait`. Try values larger than one second and smaller than one second. What values of `Duration` make the blinking imperceptible? -❗If you set the duration to below 100ms, try removing the `log::info!` command in the loop. Too much logging will fill the logging buffer and cause the loop to slow down, resulting in the blink frequency to reduce after a while. +❗If you set the duration to below 2ms, try removing the `defmt::info!` command in the loop. Too much logging will fill the logging buffer and cause the loop to slow down, resulting in the blink frequency to reduce after a while. diff --git a/embedded-workshop-book/src/using-hal.md b/embedded-workshop-book/src/using-hal.md index a6f9dc1..1537497 100644 --- a/embedded-workshop-book/src/using-hal.md +++ b/embedded-workshop-book/src/using-hal.md @@ -28,7 +28,16 @@ $ cargo doc -p dk --open ✅ Check the API docs of the `Led` abstraction. Change the `led` program, so that the bottom two LEDs are turned on, and the top two are turned off. -✅ Uncomment the `log::set_max_level` line. This will make the logs more verbose; they will now include logs from the board initialization function (`dk::init`) and from the `Led` API. +🔎 If you want to see logs from Led API of the `dk` Hardware Abstraction Layer, go to `boards/dk/Cargo.toml` and change the log level of the `dk` crate: + +```diff +# set defmt logging levels here +default = [ +- "defmt-debug", ++ "defmt-trace", + # "dependency-a/defmt-trace", +] +``` Among the logs you'll find the line "I/O pins have been configured for digital output". At this point the electrical pins of the nRF52840 microcontroller have been configured to drive the 4 LEDs on the board.