use defmt in training materials

This commit is contained in:
Lotte Steenbrink 2021-04-08 11:27:00 +02:00 committed by Mirabellensaft
parent 62f74005a1
commit b672967d8a
11 changed files with 30 additions and 20 deletions

View file

@ -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"

View file

@ -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()

View file

@ -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);
}

View file

@ -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",
]

View file

@ -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<Board, ()> {
// 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
};

View file

@ -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.

View file

@ -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.">
<p>
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.

View file

@ -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)`.
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)`.

View file

@ -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));

View file

@ -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.

View file

@ -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.