From ca262675e860816b73567069116d3461c872016f Mon Sep 17 00:00:00 2001 From: Mirabellensaft Date: Fri, 7 Jan 2022 17:24:21 +0100 Subject: [PATCH] info! -> println! --- advanced/firmware/src/bin/events.rs | 12 +- advanced/firmware/src/bin/hello.rs | 2 +- .../firmware/src/bin/resource-solution.rs | 8 +- advanced/firmware/src/bin/resource.rs | 8 +- advanced/firmware/src/bin/rtic-hello.rs | 6 +- advanced/firmware/src/bin/stack_overflow.rs | 2 +- advanced/firmware/src/bin/usb-1-solution.rs | 77 ++-- advanced/firmware/src/bin/usb-1.rs | 54 ++- advanced/firmware/src/bin/usb-2-solution.rs | 160 ++++---- advanced/firmware/src/bin/usb-2.rs | 150 +++---- advanced/firmware/src/bin/usb-3-solution.rs | 165 ++++---- advanced/firmware/src/bin/usb-3.rs | 143 +++---- advanced/firmware/src/bin/usb-4-solution.rs | 313 +++++++------- advanced/firmware/src/bin/usb-4.rs | 208 +++++----- advanced/firmware/src/bin/usb-5-solution.rs | 385 +++++++++--------- advanced/firmware/src/bin/vec.rs | 6 +- beginner/apps/src/bin/blinky.rs | 2 +- beginner/apps/src/bin/hello.rs | 2 +- beginner/apps/src/bin/panic.rs | 4 +- beginner/apps/src/bin/radio-puzzle-1.rs | 4 +- beginner/apps/src/bin/radio-puzzle-2.rs | 4 +- beginner/apps/src/bin/radio-puzzle-3.rs | 2 +- beginner/apps/src/bin/radio-puzzle-4.rs | 4 +- beginner/apps/src/bin/radio-puzzle-5.rs | 4 +- beginner/apps/src/bin/radio-puzzle-6.rs | 4 +- beginner/apps/src/bin/radio-puzzle-7.rs | 6 +- .../apps/src/bin/radio-puzzle-solution-2.rs | 6 +- .../apps/src/bin/radio-puzzle-solution.rs | 6 +- beginner/apps/src/bin/radio-puzzle.rs | 4 +- beginner/apps/src/bin/radio-recv.rs | 4 +- beginner/apps/src/bin/radio-send.rs | 2 +- beginner/apps/src/bin/stack_overflow.rs | 2 +- boards/dk/src/lib.rs | 5 +- boards/dk/src/usbd.rs | 6 +- embedded-workshop-book/src/interfaces.md | 2 +- embedded-workshop-book/src/messages.md | 8 +- .../src/radio-puzzle-help.md | 2 +- embedded-workshop-book/src/time.md | 2 +- 38 files changed, 931 insertions(+), 853 deletions(-) diff --git a/advanced/firmware/src/bin/events.rs b/advanced/firmware/src/bin/events.rs index bf8d40d..aee1170 100644 --- a/advanced/firmware/src/bin/events.rs +++ b/advanced/firmware/src/bin/events.rs @@ -23,7 +23,7 @@ const APP: () = { w.usbdetected().set_bit() }); - defmt::info!("USBDETECTED interrupt enabled"); + defmt::println!("USBDETECTED interrupt enabled"); // read the whole 32-bit usb supply register // the `read()` method returns a reader which can then be used to access the register content @@ -31,19 +31,19 @@ const APP: () = { // (the layout of the USBREGSTATUS register can be found in section 5.3.7.13 of the PS) let regstatus: u32 = power.usbregstatus.read().bits(); // ^^^^ complete register content - defmt::info!("USBREGSTATUS: {:b}", regstatus); + defmt::println!("USBREGSTATUS: {:b}", regstatus); // read the 1-bit VBUSDETECT field that is part of the USBREGSTATUS register content // to show that its contents reflect our usb connection status // (the USBDETECTED event that will trigger `on_power_event()` is derived from this information) let vbusdetect: bool = power.usbregstatus.read().vbusdetect().bits(); // ^^^^^^^^^^ bitfield name - defmt::info!("USBREGSTATUS.VBUSDETECT: {}", vbusdetect); + defmt::println!("USBREGSTATUS.VBUSDETECT: {}", vbusdetect); } #[idle] fn main(_cx: main::Context) -> ! { - defmt::info!("idle: going to sleep"); + defmt::println!("idle: going to sleep"); // sleep in the background loop { @@ -53,7 +53,7 @@ const APP: () = { #[task(binds = POWER_CLOCK)] fn on_power_event(_cx: on_power_event::Context) { - defmt::info!("POWER event occurred"); - dk::exit() + defmt::println!("POWER event occurred"); + asm::bkpt(); } }; diff --git a/advanced/firmware/src/bin/hello.rs b/advanced/firmware/src/bin/hello.rs index af489e8..71b7b06 100644 --- a/advanced/firmware/src/bin/hello.rs +++ b/advanced/firmware/src/bin/hello.rs @@ -11,7 +11,7 @@ fn main() -> ! { // board initialization dk::init().unwrap(); - defmt::info!("Hello, world!"); + defmt::println!("Hello, world!"); loop { asm::bkpt(); diff --git a/advanced/firmware/src/bin/resource-solution.rs b/advanced/firmware/src/bin/resource-solution.rs index ecc0b66..f5e3367 100644 --- a/advanced/firmware/src/bin/resource-solution.rs +++ b/advanced/firmware/src/bin/resource-solution.rs @@ -21,7 +21,7 @@ const APP: () = { power.intenset.write(|w| w.usbdetected().set_bit()); - defmt::info!("USBDETECTED interrupt enabled"); + defmt::println!("USBDETECTED interrupt enabled"); init::LateResources { power, @@ -32,9 +32,9 @@ const APP: () = { #[idle] fn main(_cx: main::Context) -> ! { loop { - defmt::info!("idle: going to sleep"); + defmt::println!("idle: going to sleep"); asm::wfi(); - defmt::info!("idle: woke up"); + defmt::println!("idle: woke up"); } } @@ -48,7 +48,7 @@ const APP: () = { *counter += 1; let n = *counter; - defmt::info!( + defmt::println!( "on_power_event: cable connected {} time{}", n, if n != 1 { "s" } else { "" } diff --git a/advanced/firmware/src/bin/resource.rs b/advanced/firmware/src/bin/resource.rs index b43e6c7..96ff984 100644 --- a/advanced/firmware/src/bin/resource.rs +++ b/advanced/firmware/src/bin/resource.rs @@ -20,7 +20,7 @@ const APP: () = { power.intenset.write(|w| w.usbdetected().set_bit()); - defmt::info!("USBDETECTED interrupt enabled"); + defmt::println!("USBDETECTED interrupt enabled"); init::LateResources { power, // <- resource initialization @@ -30,16 +30,16 @@ const APP: () = { #[idle] fn main(_cx: main::Context) -> ! { loop { - defmt::info!("idle: going to sleep"); + defmt::println!("idle: going to sleep"); asm::wfi(); - defmt::info!("idle: woke up"); + defmt::println!("idle: woke up"); } } #[task(binds = POWER_CLOCK, resources = [power])] // ^^^^^^^ resource access list fn on_power_event(cx: on_power_event::Context) { - defmt::info!("POWER event occurred"); + defmt::println!("POWER event occurred"); // resources available to this task let resources = cx.resources; diff --git a/advanced/firmware/src/bin/rtic-hello.rs b/advanced/firmware/src/bin/rtic-hello.rs index 9c4889c..cd57d3a 100644 --- a/advanced/firmware/src/bin/rtic-hello.rs +++ b/advanced/firmware/src/bin/rtic-hello.rs @@ -5,7 +5,7 @@ // this imports `beginner/apps/lib.rs` to retrieve our global logger + panicking-behavior use firmware as _; -#[rtic::app(device = dk, peripherals = true)] +#[rtic::app(device = dk, peripherals = false)] mod app { use cortex_m::asm; use dk::Peripherals; @@ -23,13 +23,13 @@ mod app { fn init(_cx: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) { dk::init().unwrap(); - defmt::info!("Hello"); + defmt::println!("Hello"); (MySharedResources {}, MyLocalResources {}, init::Monotonics()) } #[idle] fn idle(_cx: idle::Context) -> ! { - defmt::info!("world!"); + defmt::println!("world!"); loop { asm::bkpt(); diff --git a/advanced/firmware/src/bin/stack_overflow.rs b/advanced/firmware/src/bin/stack_overflow.rs index ab08067..35d37df 100644 --- a/advanced/firmware/src/bin/stack_overflow.rs +++ b/advanced/firmware/src/bin/stack_overflow.rs @@ -22,7 +22,7 @@ fn main() -> ! { fn fib(n: u32) -> u32 { // allocate and initialize one kilobyte of stack memory to provoke stack overflow let use_stack = [0xAA; 1024]; - defmt::info!("allocating [{}; 1024]; round #{}", use_stack[1023], n); + defmt::println!("allocating [{}; 1024]; round #{}", use_stack[1023], n); if n < 2 { 1 diff --git a/advanced/firmware/src/bin/usb-1-solution.rs b/advanced/firmware/src/bin/usb-1-solution.rs index a8e35bf..91ef9d1 100644 --- a/advanced/firmware/src/bin/usb-1-solution.rs +++ b/advanced/firmware/src/bin/usb-1-solution.rs @@ -1,52 +1,67 @@ #![no_main] #![no_std] -use dk::{ - peripheral::USBD, - usbd::{self, Event}, -}; + // this imports `beginner/apps/lib.rs` to retrieve our global logger + panicking-behavior use firmware as _; -#[rtic::app(device = dk)] -const APP: () = { - struct Resources { +#[rtic::app(device = dk, peripherals = false)] +mod app { + use dk::{ + peripheral::USBD, + usbd::{self, Event}, + Peripherals, + }; + + #[local] + struct MyLocalResources { usbd: USBD, } - #[init] - fn init(_cx: init::Context) -> init::LateResources { - let board = dk::init().unwrap(); - - usbd::init(board.power, &board.usbd); - - init::LateResources { usbd: board.usbd } + #[shared] + struct MySharedResources { + } - #[task(binds = USBD, resources = [usbd])] + #[init] + fn init(_cx: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) { + let board = dk::init().unwrap(); + + // initialize the USBD peripheral + // NOTE this will block if the USB cable is not connected to port J3 + dk::usbd::init(board.power, &board.usbd); + + defmt::println!("USBD initialized"); + + (MySharedResources {}, MyLocalResources {usbd: board.usbd }, init::Monotonics()) + } + + #[task(binds = USBD, local = [usbd])] fn main(cx: main::Context) { - let usbd = cx.resources.usbd; + let usbd = cx.local.usbd; while let Some(event) = usbd::next_event(usbd) { on_event(usbd, event) } } -}; -fn on_event(_usbd: &USBD, event: Event) { - defmt::info!("USB: {:?}", event); - - match event { - Event::UsbReset => { - // going from the Default state to the Default state is a no-operation - defmt::info!("returning to the Default state"); - } - - Event::UsbEp0DataDone => todo!(), - - Event::UsbEp0Setup => { - defmt::info!("goal reached; move to the next section"); - dk::exit() + fn on_event(_usbd: &USBD, event: Event) { + defmt::println("USB: {:?}", event); + + match event { + Event::UsbReset => { + // going from the Default state to the Default state is a no-operation + defmt::println("returning to the Default state"); + } + + Event::UsbEp0DataDone => todo!(), + + Event::UsbEp0Setup => { + defmt::println("goal reached; move to the next section"); + dk::exit() + } } } } + + diff --git a/advanced/firmware/src/bin/usb-1.rs b/advanced/firmware/src/bin/usb-1.rs index 0f6dd2e..a5293e1 100644 --- a/advanced/firmware/src/bin/usb-1.rs +++ b/advanced/firmware/src/bin/usb-1.rs @@ -8,46 +8,60 @@ use dk::{ // this imports `beginner/apps/lib.rs` to retrieve our global logger + panicking-behavior use firmware as _; -#[rtic::app(device = dk)] -const APP: () = { - struct Resources { +#[rtic::app(device = dk, peripherals = false)] +mod app { + use dk::{ + peripheral::USBD, + usbd::{self, Event}, + Peripherals, + }; + + #[local] + struct MyLocalResources { usbd: USBD, } + #[shared] + struct MySharedResources { + + } + #[init] - fn init(_cx: init::Context) -> init::LateResources { + fn init(_cx: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) { let board = dk::init().unwrap(); // initialize the USBD peripheral // NOTE this will block if the USB cable is not connected to port J3 usbd::init(board.power, &board.usbd); - defmt::info!("USBD initialized"); + defmt::println!("USBD initialized"); - init::LateResources { usbd: board.usbd } + (MySharedResources {}, MyLocalResources { usbd: board.usbd }, init::Monotonics()) } - #[task(binds = USBD, resources = [usbd])] + #[task(binds = USBD, local = [usbd])] fn main(cx: main::Context) { - let usbd = cx.resources.usbd; + let usbd = cx.local.usbd; while let Some(event) = usbd::next_event(usbd) { on_event(usbd, event) } } -}; -fn on_event(_usbd: &USBD, event: Event) { - defmt::info!("USB: {:?} @ {:?}", event, dk::uptime()); - - match event { - Event::UsbReset => todo!(), - - Event::UsbEp0DataDone => todo!(), - // leave this at it is for now. - Event::UsbEp0Setup => { - defmt::info!("goal reached; move to the next section"); - dk::exit() + fn on_event(_usbd: &USBD, event: Event) { + defmt::println!("USB: {:?} @ {:?}", event, dk::uptime()); + + match event { + Event::UsbReset => todo!(), + + Event::UsbEp0DataDone => todo!(), + // leave this at it is for now. + Event::UsbEp0Setup => { + defmt::println!("goal reached; move to the next section"); + dk::exit() + } } } } + + diff --git a/advanced/firmware/src/bin/usb-2-solution.rs b/advanced/firmware/src/bin/usb-2-solution.rs index cd8a858..323a004 100644 --- a/advanced/firmware/src/bin/usb-2-solution.rs +++ b/advanced/firmware/src/bin/usb-2-solution.rs @@ -1,102 +1,112 @@ #![no_main] #![no_std] -use dk::{ - peripheral::USBD, - usbd::{self, Event}, -}; // this imports `beginner/apps/lib.rs` to retrieve our global logger + panicking-behavior use firmware as _; -use usb::{Descriptor, Request}; -#[rtic::app(device = dk)] -const APP: () = { - struct Resources { +#[rtic::app(device = dk, peripherals = false)] +mod app { + use dk::{ + peripheral::USBD, + usbd::{self, Event}, + Peripherals, + }; + + use usb::{Descriptor, Request}; + + #[local] + struct MyLocalResources { usbd: USBD, } + #[shared] + struct MySharedResources { + + } + #[init] - fn init(_cx: init::Context) -> init::LateResources { + fn init(_cx: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) { let board = dk::init().unwrap(); usbd::init(board.power, &board.usbd); - init::LateResources { usbd: board.usbd } + (MySharedResources {}, MyLocalResources { usbd: board.usbd }, init::Monotonics()) } - #[task(binds = USBD, resources = [usbd])] + #[task(binds = USBD, local = [usbd])] fn main(cx: main::Context) { - let usbd = cx.resources.usbd; + let usbd = cx.local.usbd; while let Some(event) = usbd::next_event(usbd) { on_event(usbd, event) } } -}; - -fn on_event(usbd: &USBD, event: Event) { - defmt::info!("USB: {:?} @ {:?}", event, dk::uptime()); - - match event { - Event::UsbReset => { - // nothing to do here at the moment - } - - Event::UsbEp0DataDone => todo!(), - - Event::UsbEp0Setup => { - // the BMREQUESTTYPE register contains information about data recipient, transfer type and direction - let bmrequesttype = usbd.bmrequesttype.read().bits() as u8; - // the BREQUEST register stores the type of the current request (e.g. SET_ADDRESS, GET_DESCRIPTOR, ...) - let brequest = usbd.brequest.read().brequest().bits(); - // wLength denotes the number of bytes to transfer (if any) - // composed of a high register (WLENGTHH) and a low register (WLENGTHL) - let wlength = (u16::from(usbd.wlengthh.read().wlengthh().bits()) << 8) - | u16::from(usbd.wlengthl.read().wlengthl().bits()); - // wIndex is a generic index field whose meaning depends on the request type - // composed of a high register (WINDEXH) and a low register (WINDEXL) - let windex = (u16::from(usbd.windexh.read().windexh().bits()) << 8) - | u16::from(usbd.windexl.read().windexl().bits()); - // wValue is a generic paremeter field meaning depends on the request type (e.g. contains the device - // address in SET_ADRESS requests) - // composed of a high register (WVALUEH) and a low register (WVALUEL) - let wvalue = (u16::from(usbd.wvalueh.read().wvalueh().bits()) << 8) - | u16::from(usbd.wvaluel.read().wvaluel().bits()); - - // NOTE the `dk` crate contains helper functions for the above operations - // let bmrequesttype = usbd::bmrequesttype(usbd); - // let brequest = usbd::brequest(usbd); - // let wlength = usbd::wlength(usbd); - // let windex = usbd::windex(usbd); - // let wvalue = usbd::wvalue(usbd); - - defmt::info!( - "SETUP: bmrequesttype: {}, brequest: {}, wlength: {}, windex: {}, wvalue: {}", - bmrequesttype, - brequest, - wlength, - windex, - wvalue - ); - - let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength) - .expect("Error parsing request"); - match request { - Request::GetDescriptor { descriptor, length } - if descriptor == Descriptor::Device => - { - defmt::info!("GET_DESCRIPTOR Device [length={}]", length); - - defmt::info!("Goal reached; move to the next section"); - dk::exit() + fn on_event(usbd: &USBD, event: Event) { + defmt::println!("USB: {:?} @ {:?}", event, dk::uptime()); + + match event { + Event::UsbReset => { + // nothing to do here at the moment + } + + Event::UsbEp0DataDone => todo!(), + + Event::UsbEp0Setup => { + // the BMREQUESTTYPE register contains information about data recipient, transfer type and direction + let bmrequesttype = usbd.bmrequesttype.read().bits() as u8; + // the BREQUEST register stores the type of the current request (e.g. SET_ADDRESS, GET_DESCRIPTOR, ...) + let brequest = usbd.brequest.read().brequest().bits(); + // wLength denotes the number of bytes to transfer (if any) + // composed of a high register (WLENGTHH) and a low register (WLENGTHL) + let wlength = (u16::from(usbd.wlengthh.read().wlengthh().bits()) << 8) + | u16::from(usbd.wlengthl.read().wlengthl().bits()); + // wIndex is a generic index field whose meaning depends on the request type + // composed of a high register (WINDEXH) and a low register (WINDEXL) + let windex = (u16::from(usbd.windexh.read().windexh().bits()) << 8) + | u16::from(usbd.windexl.read().windexl().bits()); + // wValue is a generic paremeter field meaning depends on the request type (e.g. contains the device + // address in SET_ADRESS requests) + // composed of a high register (WVALUEH) and a low register (WVALUEL) + let wvalue = (u16::from(usbd.wvalueh.read().wvalueh().bits()) << 8) + | u16::from(usbd.wvaluel.read().wvaluel().bits()); + + // NOTE the `dk` crate contains helper functions for the above operations + // let bmrequesttype = usbd::bmrequesttype(usbd); + // let brequest = usbd::brequest(usbd); + // let wlength = usbd::wlength(usbd); + // let windex = usbd::windex(usbd); + // let wvalue = usbd::wvalue(usbd); + + defmt::println!( + "SETUP: bmrequesttype: {}, brequest: {}, wlength: {}, windex: {}, wvalue: {}", + bmrequesttype, + brequest, + wlength, + windex, + wvalue + ); + + let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength) + .expect("Error parsing request"); + match request { + Request::GetDescriptor { descriptor, length } + if descriptor == Descriptor::Device => + { + defmt::println!("GET_DESCRIPTOR Device [length={}]", length); + + defmt::println!("Goal reached; move to the next section"); + dk::exit() + } + Request::SetAddress { .. } => { + // On Mac OS you'll get this request before the GET_DESCRIPTOR request so we + // need to catch it here. We'll properly handle this request later + // but for now it's OK to do nothing. + } + _ => unreachable!(), // we don't handle any other Requests } - Request::SetAddress { .. } => { - // On Mac OS you'll get this request before the GET_DESCRIPTOR request so we - // need to catch it here. We'll properly handle this request later - // but for now it's OK to do nothing. - } - _ => unreachable!(), // we don't handle any other Requests } } } + } + diff --git a/advanced/firmware/src/bin/usb-2.rs b/advanced/firmware/src/bin/usb-2.rs index 648c475..8c827a1 100644 --- a/advanced/firmware/src/bin/usb-2.rs +++ b/advanced/firmware/src/bin/usb-2.rs @@ -1,98 +1,108 @@ #![no_main] #![no_std] -use dk::{ - peripheral::USBD, - usbd::{self, Event}, -}; + // this imports `beginner/apps/lib.rs` to retrieve our global logger + panicking-behavior use firmware as _; -use usb::{Descriptor, Request}; +#[rtic::app(device = dk, peripherals = false)] +mod app { + use dk::{ + peripheral::USBD, + usbd::{self, Event}, + Peripherals, + }; -#[rtic::app(device = dk)] -const APP: () = { - struct Resources { + use usb::{Descriptor, Request}; + + #[local] + struct MyLocalResources { usbd: USBD, } + #[shared] + struct MySharedResources { + + } + #[init] - fn init(_cx: init::Context) -> init::LateResources { + fn init(_cx: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) { let board = dk::init().unwrap(); usbd::init(board.power, &board.usbd); - init::LateResources { usbd: board.usbd } + (MySharedResources {}, MyLocalResources { usbd: board.usbd }, init::Monotonics()) } - #[task(binds = USBD, resources = [usbd])] + #[task(binds = USBD, local = [usbd])] fn main(cx: main::Context) { - let usbd = cx.resources.usbd; + let usbd = cx.local.usbd; while let Some(event) = usbd::next_event(usbd) { on_event(usbd, event) } } -}; -fn on_event(_usbd: &USBD, event: Event) { - defmt::info!("USB: {:?} @ {:?}", event, dk::uptime()); - - match event { - Event::UsbReset => { - // nothing to do here at the moment - } - - Event::UsbEp0DataDone => todo!(), - - Event::UsbEp0Setup => { - // TODO read USBD registers - - // the BMREQUESTTYPE register contains information about data recipient, transfer type and direction - let bmrequesttype: u8 = 0; - // the BREQUEST register stores the type of the current request (e.g. SET_ADDRESS, GET_DESCRIPTOR, ...) - let brequest: u8 = 0; - // wLength denotes the number of bytes to transfer (if any) - // composed of a high register (WLENGTHH) and a low register (WLENGTHL) - let wlength: u16 = 0; - // wIndex is a generic index field whose meaning depends on the request type - // composed of a high register (WINDEXH) and a low register (WINDEXL) - let windex: u16 = 0; - // wValue is a generic paremeter field meaning depends on the request type (e.g. contains the device - // address in SET_ADRESS requests) - // composed of a high register (WVALUEH) and a low register (WVALUEL) - let wvalue: u16 = 0; - - defmt::info!( - "SETUP: bmrequesttype: {}, brequest: {}, wlength: {}, windex: {}, wvalue: {}", - bmrequesttype, - brequest, - wlength, - windex, - wvalue - ); - - let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength) - .expect("Error parsing request"); - match request { - Request::GetDescriptor { descriptor, length } - if descriptor == Descriptor::Device => - { - // TODO modify `Request::parse()` in `advanced/common/usb/lib.rs` - // so that this branch is reached - - defmt::info!("GET_DESCRIPTOR Device [length={}]", length); - - defmt::info!("Goal reached; move to the next section"); - dk::exit() + fn on_event(_usbd: &USBD, event: Event) { + defmt::println!("USB: {:?} @ {:?}", event, dk::uptime()); + + match event { + Event::UsbReset => { + // nothing to do here at the moment + } + + Event::UsbEp0DataDone => todo!(), + + Event::UsbEp0Setup => { + // TODO read USBD registers + + // the BMREQUESTTYPE register contains information about data recipient, transfer type and direction + let bmrequesttype: u8 = 0; + // the BREQUEST register stores the type of the current request (e.g. SET_ADDRESS, GET_DESCRIPTOR, ...) + let brequest: u8 = 0; + // wLength denotes the number of bytes to transfer (if any) + // composed of a high register (WLENGTHH) and a low register (WLENGTHL) + let wlength: u16 = 0; + // wIndex is a generic index field whose meaning depends on the request type + // composed of a high register (WINDEXH) and a low register (WINDEXL) + let windex: u16 = 0; + // wValue is a generic paremeter field meaning depends on the request type (e.g. contains the device + // address in SET_ADRESS requests) + // composed of a high register (WVALUEH) and a low register (WVALUEL) + let wvalue: u16 = 0; + + defmt::println!( + "SETUP: bmrequesttype: {}, brequest: {}, wlength: {}, windex: {}, wvalue: {}", + bmrequesttype, + brequest, + wlength, + windex, + wvalue + ); + + let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength) + .expect("Error parsing request"); + match request { + Request::GetDescriptor { descriptor, length } + if descriptor == Descriptor::Device => + { + // TODO modify `Request::parse()` in `advanced/common/usb/lib.rs` + // so that this branch is reached + + defmt::println!("GET_DESCRIPTOR Device [length={}]", length); + + defmt::println!("Goal reached; move to the next section"); + dk::exit() + } + Request::SetAddress { .. } => { + // On Mac OS you'll get this request before the GET_DESCRIPTOR request so we + // need to catch it here. We'll properly handle this request later + // but for now it's OK to do nothing. + } + _ => unreachable!(), // we don't handle any other Requests } - Request::SetAddress { .. } => { - // On Mac OS you'll get this request before the GET_DESCRIPTOR request so we - // need to catch it here. We'll properly handle this request later - // but for now it's OK to do nothing. - } - _ => unreachable!(), // we don't handle any other Requests } } - } + } } + diff --git a/advanced/firmware/src/bin/usb-3-solution.rs b/advanced/firmware/src/bin/usb-3-solution.rs index f5a4476..d784282 100644 --- a/advanced/firmware/src/bin/usb-3-solution.rs +++ b/advanced/firmware/src/bin/usb-3-solution.rs @@ -1,108 +1,115 @@ #![no_main] #![no_std] -use dk::{ - peripheral::USBD, - usbd::{self, Ep0In, Event}, -}; // this imports `beginner/apps/lib.rs` to retrieve our global logger + panicking-behavior use firmware as _; -use usb::{Descriptor, Request}; -#[rtic::app(device = dk)] -const APP: () = { - struct Resources { +#[rtic::app(device = dk, peripherals = false)] +mod app { + use dk::{ + peripheral::USBD, + usbd::{self, Ep0In, Event}, + Peripherals, + }; + use usb::{Descriptor, Request}; + + #[local] + struct MyLocalResources { usbd: USBD, ep0in: Ep0In, } + #[shared] + struct MySharedResources { + + } + #[init] - fn init(_cx: init::Context) -> init::LateResources { + fn init(_cx: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) { let board = dk::init().unwrap(); usbd::init(board.power, &board.usbd); - init::LateResources { - ep0in: board.ep0in, - usbd: board.usbd, - } + (MySharedResources {}, MyLocalResources { usbd: board.usbd, ep0in: board.ep0in, }, init::Monotonics()) } - #[task(binds = USBD, resources = [usbd, ep0in])] + #[task(binds = USBD, local = [usbd, ep0in])] fn main(cx: main::Context) { - let usbd = cx.resources.usbd; - let ep0in = cx.resources.ep0in; + let usbd = cx.local.usbd; + let ep0in = cx.local.ep0in; while let Some(event) = usbd::next_event(usbd) { on_event(usbd, ep0in, event) } } -}; -fn on_event(usbd: &USBD, ep0in: &mut Ep0In, event: Event) { - defmt::info!("USB: {:?} @ {:?}", event, dk::uptime()); - - match event { - Event::UsbReset => { - // nothing to do here at the moment - } - - Event::UsbEp0DataDone => ep0in.end(usbd), - - Event::UsbEp0Setup => { - let bmrequesttype = usbd.bmrequesttype.read().bits() as u8; - let brequest = usbd.brequest.read().brequest().bits(); - let wlength = usbd::wlength(usbd); - let windex = usbd::windex(usbd); - let wvalue = usbd::wvalue(usbd); - - defmt::info!( - "SETUP: bmrequesttype: {}, brequest: {}, wlength: {}, windex: {}, wvalue: {}", - bmrequesttype, - brequest, - wlength, - windex, - wvalue - ); - - let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength).expect( - "Error parsing request (goal achieved if GET_DESCRIPTOR Device was handled before)", - ); - match request { - Request::GetDescriptor { descriptor, length } - if descriptor == Descriptor::Device => - { - defmt::info!("GET_DESCRIPTOR Device [length={}]", length); - - let desc = usb2::device::Descriptor { - bDeviceClass: 0, - bDeviceProtocol: 0, - bDeviceSubClass: 0, - bMaxPacketSize0: usb2::device::bMaxPacketSize0::B64, - bNumConfigurations: core::num::NonZeroU8::new(1).unwrap(), - bcdDevice: 0x01_00, // 1.00 - iManufacturer: None, - iProduct: None, - iSerialNumber: None, - idProduct: consts::PID, - idVendor: consts::VID, - }; - let desc_bytes = desc.bytes(); - let resp = &desc_bytes[..core::cmp::min(desc_bytes.len(), usize::from(length))]; - ep0in.start(&resp, usbd); - } - Request::SetAddress { .. } => { - // On Mac OS you'll get this request before the GET_DESCRIPTOR request so we - // need to catch it here. We'll properly handle this request later - // but for now it's OK to do nothing. - } - _ => { - defmt::error!( - "unknown request (goal achieved if GET_DESCRIPTOR Device was handled before)" - ); - dk::exit() + fn on_event(usbd: &USBD, ep0in: &mut Ep0In, event: Event) { + defmt::println!("USB: {:?} @ {:?}", event, dk::uptime()); + + match event { + Event::UsbReset => { + // nothing to do here at the moment + } + + Event::UsbEp0DataDone => ep0in.end(usbd), + + Event::UsbEp0Setup => { + let bmrequesttype = usbd.bmrequesttype.read().bits() as u8; + let brequest = usbd.brequest.read().brequest().bits(); + let wlength = usbd::wlength(usbd); + let windex = usbd::windex(usbd); + let wvalue = usbd::wvalue(usbd); + + defmt::println!( + "SETUP: bmrequesttype: {}, brequest: {}, wlength: {}, windex: {}, wvalue: {}", + bmrequesttype, + brequest, + wlength, + windex, + wvalue + ); + + let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength).expect( + "Error parsing request (goal achieved if GET_DESCRIPTOR Device was handled before)", + ); + match request { + Request::GetDescriptor { descriptor, length } + if descriptor == Descriptor::Device => + { + defmt::println!("GET_DESCRIPTOR Device [length={}]", length); + + let desc = usb2::device::Descriptor { + bDeviceClass: 0, + bDeviceProtocol: 0, + bDeviceSubClass: 0, + bMaxPacketSize0: usb2::device::bMaxPacketSize0::B64, + bNumConfigurations: core::num::NonZeroU8::new(1).unwrap(), + bcdDevice: 0x01_00, // 1.00 + iManufacturer: None, + iProduct: None, + iSerialNumber: None, + idProduct: consts::PID, + idVendor: consts::VID, + }; + let desc_bytes = desc.bytes(); + let resp = &desc_bytes[..core::cmp::min(desc_bytes.len(), usize::from(length))]; + ep0in.start(&resp, usbd); + } + Request::SetAddress { .. } => { + // On Mac OS you'll get this request before the GET_DESCRIPTOR request so we + // need to catch it here. We'll properly handle this request later + // but for now it's OK to do nothing. + } + _ => { + defmt::error!( + "unknown request (goal achieved if GET_DESCRIPTOR Device was handled before)" + ); + dk::exit() + } } } } } + } + diff --git a/advanced/firmware/src/bin/usb-3.rs b/advanced/firmware/src/bin/usb-3.rs index a88ad46..4336183 100644 --- a/advanced/firmware/src/bin/usb-3.rs +++ b/advanced/firmware/src/bin/usb-3.rs @@ -1,99 +1,102 @@ #![no_main] #![no_std] -use dk::{ - peripheral::USBD, - usbd::{self, Ep0In, Event}, -}; // this imports `beginner/apps/lib.rs` to retrieve our global logger + panicking-behavior use firmware as _; -use usb::{Descriptor, Request}; -#[rtic::app(device = dk)] -const APP: () = { - struct Resources { +#[rtic::app(device = dk, peripherals = false)] +mod app { + use dk::{ + peripheral::USBD, + usbd::{self, Ep0In, Event}, + Peripherals, + }; + use usb::{Descriptor, Request}; + + #[local] + struct MyLocalResources { usbd: USBD, ep0in: Ep0In, } + #[shared] + struct MySharedResources { + + } #[init] - fn init(_cx: init::Context) -> init::LateResources { + fn init(_cx: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) { let board = dk::init().unwrap(); usbd::init(board.power, &board.usbd); - init::LateResources { - ep0in: board.ep0in, - usbd: board.usbd, - } + (MySharedResources {}, MyLocalResources { usbd: board.usbd, ep0in: board.ep0in, }, init::Monotonics()) } - #[task(binds = USBD, resources = [usbd, ep0in])] + #[task(binds = USBD, local = [usbd, ep0in])] fn main(cx: main::Context) { - let usbd = cx.resources.usbd; - let ep0in = cx.resources.ep0in; + let usbd = cx.local.usbd; + let ep0in = cx.local.ep0in; while let Some(event) = usbd::next_event(usbd) { on_event(usbd, ep0in, event) } } -}; -fn on_event(usbd: &USBD, ep0in: &mut Ep0In, event: Event) { - defmt::info!("USB: {:?} @ {:?}", event, dk::uptime()); - - match event { - Event::UsbReset => { - // nothing to do here at the moment - } - - Event::UsbEp0DataDone => todo!(), // <- TODO - - Event::UsbEp0Setup => { - let bmrequesttype = usbd::bmrequesttype(usbd); - let brequest = usbd::brequest(usbd); - let wlength = usbd::wlength(usbd); - let windex = usbd::windex(usbd); - let wvalue = usbd::wvalue(usbd); - - defmt::info!( - "SETUP: bmrequesttype: {}, brequest: {}, wlength: {}, windex: {}, wvalue: {}", - bmrequesttype, - brequest, - wlength, - windex, - wvalue - ); - - let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength).expect( - "Error parsing request (goal achieved if GET_DESCRIPTOR Device was handled before)", - ); - match request { - Request::GetDescriptor { descriptor, length } - if descriptor == Descriptor::Device => - { - defmt::info!("GET_DESCRIPTOR Device [length={}]", length); - - // TODO send back a valid device descriptor, truncated to `length` bytes - // let desc = usb2::device::Descriptor { .. }; - let resp = []; - - // ensure we're not overstepping boundaries - assert!(resp.len() <= length as usize); - ep0in.start(&resp, usbd); - } - Request::SetAddress { .. } => { - // On Mac OS you'll get this request before the GET_DESCRIPTOR request so we - // need to catch it here. We'll properly handle this request later - // but for now it's OK to do nothing. - } - _ => { - defmt::error!( - "unknown request (goal achieved if GET_DESCRIPTOR Device was handled before)" - ); - dk::exit() + fn on_event(usbd: &USBD, ep0in: &mut Ep0In, event: Event) { + defmt::println!("USB: {:?} @ {:?}", event, dk::uptime()); + + match event { + Event::UsbReset => { + // nothing to do here at the moment + } + + Event::UsbEp0DataDone => todo!(), // <- TODO + + Event::UsbEp0Setup => { + let bmrequesttype = usbd::bmrequesttype(usbd); + let brequest = usbd::brequest(usbd); + let wlength = usbd::wlength(usbd); + let windex = usbd::windex(usbd); + let wvalue = usbd::wvalue(usbd); + + defmt::println!( + "SETUP: bmrequesttype: {}, brequest: {}, wlength: {}, windex: {}, wvalue: {}", + bmrequesttype, + brequest, + wlength, + windex, + wvalue + ); + + let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength).expect( + "Error parsing request (goal achieved if GET_DESCRIPTOR Device was handled before)", + ); + match request { + Request::GetDescriptor { descriptor, length } + if descriptor == Descriptor::Device => + { + defmt::println!("GET_DESCRIPTOR Device [length={}]", length); + + // TODO send back a valid device descriptor, truncated to `length` bytes + // let desc = usb2::device::Descriptor { .. }; + let resp = []; + ep0in.start(&resp, usbd); + } + Request::SetAddress { .. } => { + // On Mac OS you'll get this request before the GET_DESCRIPTOR request so we + // need to catch it here. We'll properly handle this request later + // but for now it's OK to do nothing. + } + _ => { + defmt::error!( + "unknown request (goal achieved if GET_DESCRIPTOR Device was handled before)" + ); + dk::exit() + } } } } } + } + diff --git a/advanced/firmware/src/bin/usb-4-solution.rs b/advanced/firmware/src/bin/usb-4-solution.rs index 53c30e2..51035a9 100644 --- a/advanced/firmware/src/bin/usb-4-solution.rs +++ b/advanced/firmware/src/bin/usb-4-solution.rs @@ -1,187 +1,192 @@ #![no_main] #![no_std] -use core::num::NonZeroU8; - -use dk::{ - peripheral::USBD, - usbd::{self, Ep0In, Event}, -}; // this imports `beginner/apps/lib.rs` to retrieve our global logger + panicking-behavior use firmware as _; -use usb2::{GetDescriptor as Descriptor, StandardRequest as Request, State}; -#[rtic::app(device = dk)] -const APP: () = { - struct Resources { +#[rtic::app(device = dk, peripherals = false)] +mod app { + + use core::num::NonZeroU8; + + use dk::{ + peripheral::USBD, + usbd::{self, Ep0In, Event}, + Peripherals, + }; + use usb2::{GetDescriptor as Descriptor, StandardRequest as Request, State}; + + #[local] + struct MyLocalResources { usbd: USBD, ep0in: Ep0In, state: State, } + #[shared] + struct MySharedResources { + + } #[init] - fn init(_cx: init::Context) -> init::LateResources { + fn init(_cx: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) { let board = dk::init().unwrap(); usbd::init(board.power, &board.usbd); - - init::LateResources { - usbd: board.usbd, - state: State::Default, - ep0in: board.ep0in, - } + + (MySharedResources {}, MyLocalResources { usbd: board.usbd, ep0in: board.ep0in, state: State::Default, }, init::Monotonics()) } - #[task(binds = USBD, resources = [usbd, ep0in, state])] + #[task(binds = USBD, local = [usbd, ep0in, state])] fn main(cx: main::Context) { - let usbd = cx.resources.usbd; - let ep0in = cx.resources.ep0in; - let state = cx.resources.state; + let usbd = cx.local.usbd; + let ep0in = cx.local.ep0in; + let state = cx.local.state; while let Some(event) = usbd::next_event(usbd) { on_event(usbd, ep0in, state, event) } } -}; - -fn on_event(usbd: &USBD, ep0in: &mut Ep0In, state: &mut State, event: Event) { - defmt::info!("USB: {:?} @ {:?}", event, dk::uptime()); - - match event { - Event::UsbReset => { - defmt::info!("USB reset condition detected"); - *state = State::Default; - } - - Event::UsbEp0DataDone => { - defmt::info!("EP0IN: transfer complete"); - ep0in.end(usbd); - } - - Event::UsbEp0Setup => { - if ep0setup(usbd, ep0in, state).is_err() { - defmt::warn!("EP0IN: unexpected request; stalling the endpoint"); - usbd::ep0stall(usbd); + fn on_event(usbd: &USBD, ep0in: &mut Ep0In, state: &mut State, event: Event) { + defmt::println!("USB: {:?} @ {:?}", event, dk::uptime()); + + match event { + Event::UsbReset => { + defmt::println!("USB reset condition detected"); + *state = State::Default; + } + + Event::UsbEp0DataDone => { + defmt::println!("EP0IN: transfer complete"); + ep0in.end(usbd); + } + + Event::UsbEp0Setup => { + if ep0setup(usbd, ep0in, state).is_err() { + defmt::warn!("EP0IN: unexpected request; stalling the endpoint"); + usbd::ep0stall(usbd); + } } } } -} - -/// The `bConfigurationValue` of the only supported configuration -const CONFIG_VAL: u8 = 42; - -fn ep0setup(usbd: &USBD, ep0in: &mut Ep0In, state: &mut State) -> Result<(), ()> { - let bmrequesttype = usbd.bmrequesttype.read().bits() as u8; - let brequest = usbd.brequest.read().brequest().bits(); - let wlength = usbd::wlength(usbd); - let windex = usbd::windex(usbd); - let wvalue = usbd::wvalue(usbd); - - defmt::info!( - "bmrequesttype: {}, brequest: {}, wlength: {}, windex: {}, wvalue: {}", - bmrequesttype, - brequest, - wlength, - windex, - wvalue - ); - - let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength) - .expect("Error parsing request"); - defmt::info!("EP0: {:?}", defmt::Debug2Format(&request)); - // ^^^^^^^^^^^^^^^^^^^ this adapter is currently needed to log - // `StandardRequest` with `defmt` - match request { - // section 9.4.3 - // this request is valid in any state - Request::GetDescriptor { descriptor, length } => match descriptor { - Descriptor::Device => { - let desc = usb2::device::Descriptor { - bDeviceClass: 0, - bDeviceProtocol: 0, - bDeviceSubClass: 0, - bMaxPacketSize0: usb2::device::bMaxPacketSize0::B64, - bNumConfigurations: core::num::NonZeroU8::new(1).unwrap(), - bcdDevice: 0x01_00, // 1.00 - iManufacturer: None, - iProduct: None, - iSerialNumber: None, - idProduct: consts::PID, - idVendor: consts::VID, - }; - let bytes = desc.bytes(); - let _ = ep0in.start(&bytes[..core::cmp::min(bytes.len(), length.into())], usbd); - } - - Descriptor::Configuration { index } => { - if index == 0 { - let mut resp = heapless::Vec::::new(); - - let conf_desc = usb2::configuration::Descriptor { - wTotalLength: (usb2::configuration::Descriptor::SIZE - + usb2::interface::Descriptor::SIZE) - .into(), - bNumInterfaces: NonZeroU8::new(1).unwrap(), - bConfigurationValue: core::num::NonZeroU8::new(CONFIG_VAL).unwrap(), - iConfiguration: None, - bmAttributes: usb2::configuration::bmAttributes { - self_powered: true, - remote_wakeup: false, - }, - bMaxPower: 250, // 500 mA + + /// The `bConfigurationValue` of the only supported configuration + const CONFIG_VAL: u8 = 42; + + fn ep0setup(usbd: &USBD, ep0in: &mut Ep0In, state: &mut State) -> Result<(), ()> { + let bmrequesttype = usbd.bmrequesttype.read().bits() as u8; + let brequest = usbd.brequest.read().brequest().bits(); + let wlength = usbd::wlength(usbd); + let windex = usbd::windex(usbd); + let wvalue = usbd::wvalue(usbd); + + defmt::println!( + "bmrequesttype: {}, brequest: {}, wlength: {}, windex: {}, wvalue: {}", + bmrequesttype, + brequest, + wlength, + windex, + wvalue + ); + + let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength) + .expect("Error parsing request"); + defmt::println!("EP0: {:?}", defmt::Debug2Format(&request)); + // ^^^^^^^^^^^^^^^^^^^ this adapter is currently needed to log + // `StandardRequest` with `defmt` + match request { + // section 9.4.3 + // this request is valid in any state + Request::GetDescriptor { descriptor, length } => match descriptor { + Descriptor::Device => { + let desc = usb2::device::Descriptor { + bDeviceClass: 0, + bDeviceProtocol: 0, + bDeviceSubClass: 0, + bMaxPacketSize0: usb2::device::bMaxPacketSize0::B64, + bNumConfigurations: core::num::NonZeroU8::new(1).unwrap(), + bcdDevice: 0x01_00, // 1.00 + iManufacturer: None, + iProduct: None, + iSerialNumber: None, + idProduct: consts::PID, + idVendor: consts::VID, }; - - let iface_desc = usb2::interface::Descriptor { - bInterfaceNumber: 0, - bAlternativeSetting: 0, - bNumEndpoints: 0, - bInterfaceClass: 0, - bInterfaceSubClass: 0, - bInterfaceProtocol: 0, - iInterface: None, - }; - - resp.extend_from_slice(&conf_desc.bytes()).unwrap(); - resp.extend_from_slice(&iface_desc.bytes()).unwrap(); - ep0in.start(&resp[..core::cmp::min(resp.len(), length.into())], usbd); - } else { - // out of bounds access: stall the endpoint - return Err(()); + let bytes = desc.bytes(); + let _ = ep0in.start(&bytes[..core::cmp::min(bytes.len(), length.into())], usbd); } + + Descriptor::Configuration { index } => { + if index == 0 { + let mut resp = heapless::Vec::::new(); + + let conf_desc = usb2::configuration::Descriptor { + wTotalLength: (usb2::configuration::Descriptor::SIZE + + usb2::interface::Descriptor::SIZE) + .into(), + bNumInterfaces: NonZeroU8::new(1).unwrap(), + bConfigurationValue: core::num::NonZeroU8::new(CONFIG_VAL).unwrap(), + iConfiguration: None, + bmAttributes: usb2::configuration::bmAttributes { + self_powered: true, + remote_wakeup: false, + }, + bMaxPower: 250, // 500 mA + }; + + let iface_desc = usb2::interface::Descriptor { + bInterfaceNumber: 0, + bAlternativeSetting: 0, + bNumEndpoints: 0, + bInterfaceClass: 0, + bInterfaceSubClass: 0, + bInterfaceProtocol: 0, + iInterface: None, + }; + + resp.extend_from_slice(&conf_desc.bytes()).unwrap(); + resp.extend_from_slice(&iface_desc.bytes()).unwrap(); + ep0in.start(&resp[..core::cmp::min(resp.len(), length.into())], usbd); + } else { + // out of bounds access: stall the endpoint + return Err(()); + } + } + + _ => return Err(()), + }, + + Request::SetAddress { address } => { + match state { + State::Default => { + if let Some(address) = address { + *state = State::Address(address); + } else { + // stay in the default state + } + } + + State::Address(..) => { + if let Some(address) = address { + // use the new address + *state = State::Address(address); + } else { + *state = State::Default; + } + } + + // unspecified behavior + State::Configured { .. } => return Err(()), + } + + // the response to this request is handled in hardware } - + + // stall any other request _ => return Err(()), - }, - - Request::SetAddress { address } => { - match state { - State::Default => { - if let Some(address) = address { - *state = State::Address(address); - } else { - // stay in the default state - } - } - - State::Address(..) => { - if let Some(address) = address { - // use the new address - *state = State::Address(address); - } else { - *state = State::Default; - } - } - - // unspecified behavior - State::Configured { .. } => return Err(()), - } - - // the response to this request is handled in hardware } - - // stall any other request - _ => return Err(()), + + Ok(()) } - - Ok(()) + } + diff --git a/advanced/firmware/src/bin/usb-4.rs b/advanced/firmware/src/bin/usb-4.rs index a9c1e14..3746502 100644 --- a/advanced/firmware/src/bin/usb-4.rs +++ b/advanced/firmware/src/bin/usb-4.rs @@ -1,135 +1,143 @@ #![no_main] #![no_std] -use dk::{ - peripheral::USBD, - usbd::{self, Ep0In, Event}, -}; // this imports `beginner/apps/lib.rs` to retrieve our global logger + panicking-behavior use firmware as _; -use usb2::State; -// HEADS UP to use *your* USB packet parser uncomment line 12 and remove line 13 -// use usb::{Request, Descriptor}; -use usb2::{GetDescriptor as Descriptor, StandardRequest as Request}; -#[rtic::app(device = dk)] -const APP: () = { - struct Resources { +#[rtic::app(device = dk, peripherals = false)] +mod app { + + use core::num::NonZeroU8; + + use dk::{ + peripheral::USBD, + usbd::{self, Ep0In, Event}, + Peripherals, + }; + use usb2::State; + // HEADS UP to use *your* USB packet parser uncomment line 12 and remove line 13 + // use usb::{Request, Descriptor}; + use usb2::{GetDescriptor as Descriptor, StandardRequest as Request}; + + #[local] + struct MyLocalResources { usbd: USBD, ep0in: Ep0In, state: State, } + #[shared] + struct MySharedResources { + } + #[init] - fn init(_cx: init::Context) -> init::LateResources { + fn init(_cx: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) { let board = dk::init().unwrap(); usbd::init(board.power, &board.usbd); - init::LateResources { - usbd: board.usbd, - state: State::Default, - ep0in: board.ep0in, - } + (MySharedResources {}, MyLocalResources { usbd: board.usbd, ep0in: board.ep0in, state: State::Default, }, init::Monotonics()) } - #[task(binds = USBD, resources = [usbd, ep0in, state])] + #[task(binds = USBD, local = [usbd, ep0in, state])] fn main(cx: main::Context) { - let usbd = cx.resources.usbd; - let ep0in = cx.resources.ep0in; - let state = cx.resources.state; + let usbd = cx.local.usbd; + let ep0in = cx.local.ep0in; + let state = cx.local.state; while let Some(event) = usbd::next_event(usbd) { on_event(usbd, ep0in, state, event) } } -}; -fn on_event(usbd: &USBD, ep0in: &mut Ep0In, state: &mut State, event: Event) { - defmt::info!("USB: {:?} @ {:?}", event, dk::uptime()); - - match event { - // TODO change `state` as specified in chapter 9.1 USB Device States, of the USB specification - Event::UsbReset => { - defmt::info!("USB reset condition detected"); - todo!(); - } - - Event::UsbEp0DataDone => { - defmt::info!("EP0IN: transfer complete"); - ep0in.end(usbd); - } - - Event::UsbEp0Setup => { - if ep0setup(usbd, ep0in, state).is_err() { - // unsupported or invalid request: - // TODO: add code to stall the endpoint - defmt::warn!("EP0IN: unexpected request; stalling the endpoint"); + fn on_event(usbd: &USBD, ep0in: &mut Ep0In, state: &mut State, event: Event) { + defmt::println!("USB: {:?} @ {:?}", event, dk::uptime()); + + match event { + // TODO change `state` as specified in chapter 9.1 USB Device States, of the USB specification + Event::UsbReset => { + defmt::println!("USB reset condition detected"); + todo!(); + } + + Event::UsbEp0DataDone => { + defmt::println!("EP0IN: transfer complete"); + ep0in.end(usbd); + } + + Event::UsbEp0Setup => { + if ep0setup(usbd, ep0in, state).is_err() { + // unsupported or invalid request: + // TODO: add code to stall the endpoint + defmt::warn!("EP0IN: unexpected request; stalling the endpoint"); + } } } } -} - -fn ep0setup(usbd: &USBD, ep0in: &mut Ep0In, _state: &mut State) -> Result<(), ()> { - let bmrequesttype = usbd.bmrequesttype.read().bits() as u8; - let brequest = usbd.brequest.read().brequest().bits(); - let wlength = usbd::wlength(usbd); - let windex = usbd::windex(usbd); - let wvalue = usbd::wvalue(usbd); - - defmt::info!( - "bmrequesttype: {}, brequest: {}, wlength: {}, windex: {}, wvalue: {}", - bmrequesttype, - brequest, - wlength, - windex, - wvalue - ); - - let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength) - .expect("Error parsing request"); - defmt::info!("EP0: {:?}", defmt::Debug2Format(&request)); - // ^^^^^^^^^^^^^^^^^^^ this adapter is currently needed to log - // `StandardRequest` with `defmt` - - match request { - Request::GetDescriptor { descriptor, length } => match descriptor { - Descriptor::Device => { - let desc = usb2::device::Descriptor { - bDeviceClass: 0, - bDeviceProtocol: 0, - bDeviceSubClass: 0, - bMaxPacketSize0: usb2::device::bMaxPacketSize0::B64, - bNumConfigurations: core::num::NonZeroU8::new(1).unwrap(), - bcdDevice: 0x01_00, // 1.00 - iManufacturer: None, - iProduct: None, - iSerialNumber: None, - idProduct: consts::PID, - idVendor: consts::VID, - }; - let bytes = desc.bytes(); - let _ = ep0in.start(&bytes[..core::cmp::min(bytes.len(), length.into())], usbd); + + fn ep0setup(usbd: &USBD, ep0in: &mut Ep0In, _state: &mut State) -> Result<(), ()> { + let bmrequesttype = usbd.bmrequesttype.read().bits() as u8; + let brequest = usbd.brequest.read().brequest().bits(); + let wlength = usbd::wlength(usbd); + let windex = usbd::windex(usbd); + let wvalue = usbd::wvalue(usbd); + + defmt::println!( + "bmrequesttype: {}, brequest: {}, wlength: {}, windex: {}, wvalue: {}", + bmrequesttype, + brequest, + wlength, + windex, + wvalue + ); + + let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength) + .expect("Error parsing request"); + defmt::println!("EP0: {:?}", defmt::Debug2Format(&request)); + // ^^^^^^^^^^^^^^^^^^^ this adapter is currently needed to log + // `StandardRequest` with `defmt` + + match request { + Request::GetDescriptor { descriptor, length } => match descriptor { + Descriptor::Device => { + let desc = usb2::device::Descriptor { + bDeviceClass: 0, + bDeviceProtocol: 0, + bDeviceSubClass: 0, + bMaxPacketSize0: usb2::device::bMaxPacketSize0::B64, + bNumConfigurations: core::num::NonZeroU8::new(1).unwrap(), + bcdDevice: 0x01_00, // 1.00 + iManufacturer: None, + iProduct: None, + iSerialNumber: None, + idProduct: consts::PID, + idVendor: consts::VID, + }; + let bytes = desc.bytes(); + let _ = ep0in.start(&bytes[..core::cmp::min(bytes.len(), length.into())], usbd); + } + + // TODO implement Configuration descriptor + // Descriptor::Configuration { .. } => todo!(), + + // stall any other request + _ => return Err(()), + }, + Request::SetAddress { .. } => { + // On Mac OS you'll get this request before the GET_DESCRIPTOR request so we + // need to catch it here. + + // TODO: handle this request properly now. + todo!() } - - // TODO implement Configuration descriptor - // Descriptor::Configuration { .. } => todo!(), - + // stall any other request _ => return Err(()), - }, - Request::SetAddress { .. } => { - // On Mac OS you'll get this request before the GET_DESCRIPTOR request so we - // need to catch it here. - - // TODO: handle this request properly now. - todo!() } - - // stall any other request - _ => return Err(()), + + Ok(()) } - - Ok(()) + } + diff --git a/advanced/firmware/src/bin/usb-5-solution.rs b/advanced/firmware/src/bin/usb-5-solution.rs index bf12ddf..bacff4d 100644 --- a/advanced/firmware/src/bin/usb-5-solution.rs +++ b/advanced/firmware/src/bin/usb-5-solution.rs @@ -1,235 +1,240 @@ #![no_main] #![no_std] -use core::num::NonZeroU8; - -use dk::{ - peripheral::USBD, - usbd::{self, Ep0In, Event}, -}; // this imports `beginner/apps/lib.rs` to retrieve our global logger + panicking-behavior use firmware as _; -use usb2::{GetDescriptor as Descriptor, StandardRequest as Request, State}; -#[rtic::app(device = dk)] -const APP: () = { - struct Resources { +#[rtic::app(device = dk, peripherals = false)] +mod app { + + use core::num::NonZeroU8; + + use dk::{ + peripheral::USBD, + usbd::{self, Ep0In, Event}, + Peripherals, + }; + use usb2::{GetDescriptor as Descriptor, StandardRequest as Request, State}; + + #[local] + struct MyLocalResources { usbd: USBD, ep0in: Ep0In, state: State, } + #[shared] + struct MySharedResources { + + } #[init] - fn init(_cx: init::Context) -> init::LateResources { + fn init(_cx: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) { let board = dk::init().unwrap(); usbd::init(board.power, &board.usbd); - init::LateResources { - usbd: board.usbd, - state: State::Default, - ep0in: board.ep0in, - } + (MySharedResources {}, MyLocalResources { usbd: board.usbd, ep0in: board.ep0in, state: State::Default, }, init::Monotonics()) } - #[task(binds = USBD, resources = [usbd, ep0in, state])] + #[task(binds = USBD, local = [usbd, ep0in, state])] fn main(cx: main::Context) { - let usbd = cx.resources.usbd; - let ep0in = cx.resources.ep0in; - let state = cx.resources.state; + let usbd = cx.local.usbd; + let ep0in = cx.local.ep0in; + let state = cx.local.state; while let Some(event) = usbd::next_event(usbd) { on_event(usbd, ep0in, state, event) } } -}; - -fn on_event(usbd: &USBD, ep0in: &mut Ep0In, state: &mut State, event: Event) { - defmt::info!("USB: {:?} @ {:?}", event, dk::uptime()); - - match event { - Event::UsbReset => { - defmt::info!("USB reset condition detected"); - *state = State::Default; - } - - Event::UsbEp0DataDone => { - defmt::info!("EP0IN: transfer complete"); - ep0in.end(usbd); - } - - Event::UsbEp0Setup => { - if ep0setup(usbd, ep0in, state).is_err() { - defmt::warn!("EP0IN: unexpected request; stalling the endpoint"); - usbd::ep0stall(usbd); + fn on_event(usbd: &USBD, ep0in: &mut Ep0In, state: &mut State, event: Event) { + defmt::println!("USB: {:?} @ {:?}", event, dk::uptime()); + + match event { + Event::UsbReset => { + defmt::println!("USB reset condition detected"); + *state = State::Default; + } + + Event::UsbEp0DataDone => { + defmt::println!("EP0IN: transfer complete"); + ep0in.end(usbd); + } + + Event::UsbEp0Setup => { + if ep0setup(usbd, ep0in, state).is_err() { + defmt::warn!("EP0IN: unexpected request; stalling the endpoint"); + usbd::ep0stall(usbd); + } } } } -} - -/// The `bConfigurationValue` of the only supported configuration -const CONFIG_VAL: u8 = 42; - -fn ep0setup(usbd: &USBD, ep0in: &mut Ep0In, state: &mut State) -> Result<(), ()> { - let bmrequesttype = usbd.bmrequesttype.read().bits() as u8; - let brequest = usbd.brequest.read().brequest().bits(); - let wlength = usbd::wlength(usbd); - let windex = usbd::windex(usbd); - let wvalue = usbd::wvalue(usbd); - - defmt::info!( - "bmrequesttype: {}, brequest: {}, wlength: {}, windex: {}, wvalue: {}", - bmrequesttype, - brequest, - wlength, - windex, - wvalue - ); - - let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength) - .expect("Error parsing request"); - defmt::info!("EP0: {:?}", defmt::Debug2Format(&request)); - // ^^^^^^^^^^^^^^^^^^^ this adapter is currently needed to log - // `StandardRequest` with `defmt` - - match request { - // section 9.4.3 - // this request is valid in any state - Request::GetDescriptor { descriptor, length } => match descriptor { - Descriptor::Device => { - let desc = usb2::device::Descriptor { - bDeviceClass: 0, - bDeviceProtocol: 0, - bDeviceSubClass: 0, - bMaxPacketSize0: usb2::device::bMaxPacketSize0::B64, - bNumConfigurations: core::num::NonZeroU8::new(1).unwrap(), - bcdDevice: 0x01_00, // 1.00 - iManufacturer: None, - iProduct: None, - iSerialNumber: None, - idProduct: consts::PID, - idVendor: consts::VID, - }; - let bytes = desc.bytes(); - let _ = ep0in.start(&bytes[..core::cmp::min(bytes.len(), length.into())], usbd); - } - - Descriptor::Configuration { index } => { - if index == 0 { - let mut resp = heapless::Vec::::new(); - - let conf_desc = usb2::configuration::Descriptor { - wTotalLength: (usb2::configuration::Descriptor::SIZE - + usb2::interface::Descriptor::SIZE) - .into(), - bNumInterfaces: NonZeroU8::new(1).unwrap(), - bConfigurationValue: core::num::NonZeroU8::new(CONFIG_VAL).unwrap(), - iConfiguration: None, - bmAttributes: usb2::configuration::bmAttributes { - self_powered: true, - remote_wakeup: false, - }, - bMaxPower: 250, // 500 mA + + /// The `bConfigurationValue` of the only supported configuration + const CONFIG_VAL: u8 = 42; + + fn ep0setup(usbd: &USBD, ep0in: &mut Ep0In, state: &mut State) -> Result<(), ()> { + let bmrequesttype = usbd.bmrequesttype.read().bits() as u8; + let brequest = usbd.brequest.read().brequest().bits(); + let wlength = usbd::wlength(usbd); + let windex = usbd::windex(usbd); + let wvalue = usbd::wvalue(usbd); + + defmt::println!( + "bmrequesttype: {}, brequest: {}, wlength: {}, windex: {}, wvalue: {}", + bmrequesttype, + brequest, + wlength, + windex, + wvalue + ); + + let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength) + .expect("Error parsing request"); + defmt::println!("EP0: {:?}", defmt::Debug2Format(&request)); + // ^^^^^^^^^^^^^^^^^^^ this adapter is currently needed to log + // `StandardRequest` with `defmt` + + match request { + // section 9.4.3 + // this request is valid in any state + Request::GetDescriptor { descriptor, length } => match descriptor { + Descriptor::Device => { + let desc = usb2::device::Descriptor { + bDeviceClass: 0, + bDeviceProtocol: 0, + bDeviceSubClass: 0, + bMaxPacketSize0: usb2::device::bMaxPacketSize0::B64, + bNumConfigurations: core::num::NonZeroU8::new(1).unwrap(), + bcdDevice: 0x01_00, // 1.00 + iManufacturer: None, + iProduct: None, + iSerialNumber: None, + idProduct: consts::PID, + idVendor: consts::VID, }; - - let iface_desc = usb2::interface::Descriptor { - bInterfaceNumber: 0, - bAlternativeSetting: 0, - bNumEndpoints: 0, - bInterfaceClass: 0, - bInterfaceSubClass: 0, - bInterfaceProtocol: 0, - iInterface: None, - }; - - resp.extend_from_slice(&conf_desc.bytes()).unwrap(); - resp.extend_from_slice(&iface_desc.bytes()).unwrap(); - ep0in.start(&resp[..core::cmp::min(resp.len(), length.into())], usbd); - } else { - // out of bounds access: stall the endpoint - return Err(()); + let bytes = desc.bytes(); + let _ = ep0in.start(&bytes[..core::cmp::min(bytes.len(), length.into())], usbd); } - } - - _ => return Err(()), - }, - - Request::SetAddress { address } => { - match state { - State::Default => { - if let Some(address) = address { - *state = State::Address(address); + + Descriptor::Configuration { index } => { + if index == 0 { + let mut resp = heapless::Vec::::new(); + + let conf_desc = usb2::configuration::Descriptor { + wTotalLength: (usb2::configuration::Descriptor::SIZE + + usb2::interface::Descriptor::SIZE) + .into(), + bNumInterfaces: NonZeroU8::new(1).unwrap(), + bConfigurationValue: core::num::NonZeroU8::new(CONFIG_VAL).unwrap(), + iConfiguration: None, + bmAttributes: usb2::configuration::bmAttributes { + self_powered: true, + remote_wakeup: false, + }, + bMaxPower: 250, // 500 mA + }; + + let iface_desc = usb2::interface::Descriptor { + bInterfaceNumber: 0, + bAlternativeSetting: 0, + bNumEndpoints: 0, + bInterfaceClass: 0, + bInterfaceSubClass: 0, + bInterfaceProtocol: 0, + iInterface: None, + }; + + resp.extend_from_slice(&conf_desc.bytes()).unwrap(); + resp.extend_from_slice(&iface_desc.bytes()).unwrap(); + ep0in.start(&resp[..core::cmp::min(resp.len(), length.into())], usbd); } else { - // stay in the default state + // out of bounds access: stall the endpoint + return Err(()); } } - - State::Address(..) => { - if let Some(address) = address { - // use the new address - *state = State::Address(address); - } else { - *state = State::Default; - } - } - - // unspecified behavior - State::Configured { .. } => return Err(()), - } - - // the response to this request is handled in hardware - } - - Request::SetConfiguration { value } => { - match *state { - // unspecified behavior - State::Default => return Err(()), - - State::Address(address) => { - if let Some(value) = value { - if value.get() == CONFIG_VAL { - defmt::info!("entering the configured state"); - *state = State::Configured { address, value }; + + _ => return Err(()), + }, + + Request::SetAddress { address } => { + match state { + State::Default => { + if let Some(address) = address { + *state = State::Address(address); } else { - defmt::error!("unsupported configuration value"); - return Err(()); + // stay in the default state } - } else { - // stay in the address mode } + + State::Address(..) => { + if let Some(address) = address { + // use the new address + *state = State::Address(address); + } else { + *state = State::Default; + } + } + + // unspecified behavior + State::Configured { .. } => return Err(()), } - - State::Configured { - address, - value: curr_value, - } => { - if let Some(new_value) = value { - if new_value.get() == CONFIG_VAL { - if new_value != curr_value { - defmt::info!("changing configuration"); - *state = State::Configured { - address, - value: new_value, - }; + + // the response to this request is handled in hardware + } + + Request::SetConfiguration { value } => { + match *state { + // unspecified behavior + State::Default => return Err(()), + + State::Address(address) => { + if let Some(value) = value { + if value.get() == CONFIG_VAL { + defmt::println!("entering the configured state"); + *state = State::Configured { address, value }; + } else { + defmt::error!("unsupported configuration value"); + return Err(()); } } else { - defmt::error!("unsupported configuration value"); - return Err(()); + // stay in the address mode + } + } + + State::Configured { + address, + value: curr_value, + } => { + if let Some(new_value) = value { + if new_value.get() == CONFIG_VAL { + if new_value != curr_value { + defmt::println!("changing configuration"); + *state = State::Configured { + address, + value: new_value, + }; + } + } else { + defmt::error!("unsupported configuration value"); + return Err(()); + } + } else { + defmt::println!("returned to the address state"); + *state = State::Address(address); } - } else { - defmt::info!("returned to the address state"); - *state = State::Address(address); } } + + usbd.tasks_ep0status + .write(|w| w.tasks_ep0status().set_bit()); } - - usbd.tasks_ep0status - .write(|w| w.tasks_ep0status().set_bit()); + + // stall any other request + _ => return Err(()), } - - // stall any other request - _ => return Err(()), + + Ok(()) } - - Ok(()) + } + diff --git a/advanced/firmware/src/bin/vec.rs b/advanced/firmware/src/bin/vec.rs index f009ee6..3206b18 100644 --- a/advanced/firmware/src/bin/vec.rs +++ b/advanced/firmware/src/bin/vec.rs @@ -17,13 +17,13 @@ fn main() -> ! { // `heapless::Vec` exposes the same API surface as `std::Vec` but some of its methods return a // `Result` to indicate whether the operation failed due to the `heapless::Vec` being full - defmt::info!("start: {:?}", buffer); + defmt::println!("start: {:?}", buffer); buffer.push(0).expect("buffer full"); - defmt::info!("after `push`: {:?}", buffer); + defmt::println!("after `push`: {:?}", buffer); buffer.extend_from_slice(&[1, 2, 3]).expect("buffer full"); - defmt::info!("after `extend`: {:?}", &buffer); + defmt::println!("after `extend`: {:?}", &buffer); // TODO try this operation // buffer.extend_from_slice(&[4, 5, 6, 7]).expect("buffer full"); diff --git a/beginner/apps/src/bin/blinky.rs b/beginner/apps/src/bin/blinky.rs index a3e10b1..54fdca4 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::info!("LED toggled at {:?}", dk::uptime()); + defmt::println!("LED toggled at {:?}", dk::uptime()); } dk::exit() diff --git a/beginner/apps/src/bin/hello.rs b/beginner/apps/src/bin/hello.rs index 0c40dce..42b4269 100644 --- a/beginner/apps/src/bin/hello.rs +++ b/beginner/apps/src/bin/hello.rs @@ -19,7 +19,7 @@ fn main() -> ! { // initializes the peripherals dk::init().unwrap(); - defmt::info!("Hello, world!"); // :wave: + defmt::println!("Hello, world!"); // :wave: loop { // breakpoint: halts the program's execution diff --git a/beginner/apps/src/bin/panic.rs b/beginner/apps/src/bin/panic.rs index b065acb..befa1c7 100644 --- a/beginner/apps/src/bin/panic.rs +++ b/beginner/apps/src/bin/panic.rs @@ -4,7 +4,7 @@ use cortex_m::asm; use cortex_m_rt::entry; // this imports `beginner/apps/lib.rs` to retrieve our global logger + panicking-behavior -use apps as _; +// use apps as _; #[entry] fn main() -> ! { @@ -29,7 +29,7 @@ fn bar() { let array = [0, 1, 2]; let x = array[i]; // out of bounds access - defmt::info!("{}", x); + defmt::println!("{}", x); } fn index() -> usize { diff --git a/beginner/apps/src/bin/radio-puzzle-1.rs b/beginner/apps/src/bin/radio-puzzle-1.rs index 95f1946..3ced295 100644 --- a/beginner/apps/src/bin/radio-puzzle-1.rs +++ b/beginner/apps/src/bin/radio-puzzle-1.rs @@ -38,9 +38,9 @@ fn main() -> ! { if packet.len() == 1 { let destination = packet[0]; - defmt::info!("{} -> {}", source, destination); + defmt::println!("{} -> {}", source, destination); // or cast to `char` for a more readable output - defmt::info!("{:?} -> {:?}", source as char, destination as char); + defmt::println!("{:?} -> {:?}", source as char, destination as char); } else { defmt::error!("response packet was not a single byte"); dk::exit() diff --git a/beginner/apps/src/bin/radio-puzzle-2.rs b/beginner/apps/src/bin/radio-puzzle-2.rs index edab631..57637ca 100644 --- a/beginner/apps/src/bin/radio-puzzle-2.rs +++ b/beginner/apps/src/bin/radio-puzzle-2.rs @@ -27,9 +27,9 @@ fn main() -> ! { let key = b'A'; let value = dict[&key]; // the key needs to be passed by reference - defmt::info!("{} -> {}", key, value); + defmt::println!("{} -> {}", key, value); // more readable - defmt::info!("{:?} -> {:?}", key as char, value as char); + defmt::println!("{:?} -> {:?}", key as char, value as char); // TODO try another insertion // TODO try looking up a key not contained in the dictionary diff --git a/beginner/apps/src/bin/radio-puzzle-3.rs b/beginner/apps/src/bin/radio-puzzle-3.rs index 96f9e39..10529f4 100644 --- a/beginner/apps/src/bin/radio-puzzle-3.rs +++ b/beginner/apps/src/bin/radio-puzzle-3.rs @@ -46,7 +46,7 @@ fn main() -> ! { } } - defmt::info!("{:?}", defmt::Debug2Format(&dict)); + defmt::println!("{:?}", defmt::Debug2Format(&dict)); // ^^^^^^^^^^^^^^^^^^^ this adapter is currently needed to log `heapless` // data structures (like `LinearMap` here) with `defmt` diff --git a/beginner/apps/src/bin/radio-puzzle-4.rs b/beginner/apps/src/bin/radio-puzzle-4.rs index e4a8c69..49fa4e0 100644 --- a/beginner/apps/src/bin/radio-puzzle-4.rs +++ b/beginner/apps/src/bin/radio-puzzle-4.rs @@ -22,11 +22,11 @@ fn main() -> ! { buffer.push(b'i').expect("buffer full"); // look into the contents so far - defmt::info!("{:?}", buffer); + defmt::println!("{:?}", buffer); // or more readable // NOTE utf-8 conversion works as long as you only push bytes in the ASCII range (0..=127) - defmt::info!( + defmt::println!( "{}", str::from_utf8(&buffer).expect("content was not UTF-8") ); diff --git a/beginner/apps/src/bin/radio-puzzle-5.rs b/beginner/apps/src/bin/radio-puzzle-5.rs index e46643a..d90699a 100644 --- a/beginner/apps/src/bin/radio-puzzle-5.rs +++ b/beginner/apps/src/bin/radio-puzzle-5.rs @@ -32,7 +32,7 @@ fn main() -> ! { dk::exit() } - defmt::info!( + defmt::println!( "ciphertext: {}", str::from_utf8(&packet).expect("packet was not valid UTF-8") ); @@ -48,7 +48,7 @@ fn main() -> ! { buf.push(output).expect("buffer full"); } - defmt::info!( + defmt::println!( "plaintext: {}", str::from_utf8(&buf).expect("buffer contains non-UTF-8 data") ); diff --git a/beginner/apps/src/bin/radio-puzzle-6.rs b/beginner/apps/src/bin/radio-puzzle-6.rs index d1c326c..172d093 100644 --- a/beginner/apps/src/bin/radio-puzzle-6.rs +++ b/beginner/apps/src/bin/radio-puzzle-6.rs @@ -56,7 +56,7 @@ fn main() -> ! { dk::exit() } - defmt::info!( + defmt::println!( "ciphertext: {}", str::from_utf8(&packet).expect("packet was not valid UTF-8") ); @@ -72,7 +72,7 @@ fn main() -> ! { buffer.push(value).expect("buffer full"); } - defmt::info!( + defmt::println!( "plaintext: {}", str::from_utf8(&buffer).expect("buffer contains non-UTF-8 data") ); diff --git a/beginner/apps/src/bin/radio-puzzle-7.rs b/beginner/apps/src/bin/radio-puzzle-7.rs index 9116db8..80171e2 100644 --- a/beginner/apps/src/bin/radio-puzzle-7.rs +++ b/beginner/apps/src/bin/radio-puzzle-7.rs @@ -56,7 +56,7 @@ fn main() -> ! { dk::exit() } - defmt::info!( + defmt::println!( "ciphertext: {}", str::from_utf8(&packet).expect("packet was not valid UTF-8") ); @@ -72,7 +72,7 @@ fn main() -> ! { buffer.push(value).expect("buffer full"); } - defmt::info!( + defmt::println!( "plaintext: {}", str::from_utf8(&buffer).expect("buffer contains non-UTF-8 data") ); @@ -87,7 +87,7 @@ fn main() -> ! { dk::exit() } - defmt::info!( + defmt::println!( "Dongle response: {}", str::from_utf8(&packet).expect("response was not UTF-8") ); diff --git a/beginner/apps/src/bin/radio-puzzle-solution-2.rs b/beginner/apps/src/bin/radio-puzzle-solution-2.rs index 6007f0f..6f809a0 100644 --- a/beginner/apps/src/bin/radio-puzzle-solution-2.rs +++ b/beginner/apps/src/bin/radio-puzzle-solution-2.rs @@ -57,7 +57,7 @@ fn main() -> ! { dk::exit() } - defmt::info!( + defmt::println!( "ciphertext: {}", str::from_utf8(&packet).expect("packet was not valid UTF-8") ); @@ -75,7 +75,7 @@ fn main() -> ! { *spot = plainletter; } - defmt::info!( + defmt::println!( "plaintext: {}", str::from_utf8(&packet).expect("buffer contains non-UTF-8 data") ); @@ -88,7 +88,7 @@ fn main() -> ! { dk::exit() } - defmt::info!( + defmt::println!( "Dongle response: {}", str::from_utf8(&packet).expect("response was not UTF-8") ); diff --git a/beginner/apps/src/bin/radio-puzzle-solution.rs b/beginner/apps/src/bin/radio-puzzle-solution.rs index 4a7e00f..7874052 100644 --- a/beginner/apps/src/bin/radio-puzzle-solution.rs +++ b/beginner/apps/src/bin/radio-puzzle-solution.rs @@ -60,7 +60,7 @@ fn main() -> ! { dk::exit() } - defmt::info!( + defmt::println!( "ciphertext: {}", str::from_utf8(&packet).expect("packet was not valid UTF-8") ); @@ -77,7 +77,7 @@ fn main() -> ! { buffer.push(plainletter).expect("buffer full"); } - defmt::info!( + defmt::println!( "plaintext: {}", str::from_utf8(&buffer).expect("buffer contains non-UTF-8 data") ); @@ -92,7 +92,7 @@ fn main() -> ! { dk::exit() } - defmt::info!( + defmt::println!( "Dongle response: {}", str::from_utf8(&packet).expect("response was not UTF-8") ); diff --git a/beginner/apps/src/bin/radio-puzzle.rs b/beginner/apps/src/bin/radio-puzzle.rs index 522cb99..859bd54 100644 --- a/beginner/apps/src/bin/radio-puzzle.rs +++ b/beginner/apps/src/bin/radio-puzzle.rs @@ -34,14 +34,14 @@ fn main() -> ! { // let msg = b"Hello?"; packet.copy_from_slice(msg); - defmt::info!( + defmt::println!( "sending: {}", str::from_utf8(msg).expect("msg was not valid UTF-8 data") ); radio.send(&mut packet); if radio.recv_timeout(&mut packet, &mut timer, TEN_MS).is_ok() { - defmt::info!( + defmt::println!( "received: {}", str::from_utf8(&packet).expect("response was not valid UTF-8 data") ); diff --git a/beginner/apps/src/bin/radio-recv.rs b/beginner/apps/src/bin/radio-recv.rs index e3642b0..5338d3f 100644 --- a/beginner/apps/src/bin/radio-recv.rs +++ b/beginner/apps/src/bin/radio-recv.rs @@ -25,7 +25,7 @@ fn main() -> ! { let msg = b"olleh"; packet.copy_from_slice(msg); - defmt::info!( + defmt::println!( "sending: {}", str::from_utf8(msg).expect("message is not valid UTF-8") ); @@ -38,7 +38,7 @@ fn main() -> ! { match res { Ok(crc) => { - defmt::info!( + defmt::println!( "received: {} (CRC = {:X})", // ^^ print as uppercase hexadecimal str::from_utf8(&*packet).expect("response is not valid UTF-8"), diff --git a/beginner/apps/src/bin/radio-send.rs b/beginner/apps/src/bin/radio-send.rs index 4d09180..7d34d98 100644 --- a/beginner/apps/src/bin/radio-send.rs +++ b/beginner/apps/src/bin/radio-send.rs @@ -26,7 +26,7 @@ fn main() -> ! { // let msg: &[u8; 5] = &[b'H', b'e', b'l', b'l', b'o']; // let msg: &[u8; 5] = b"Hello"; - defmt::info!( + defmt::println!( "sending: {}", str::from_utf8(msg).expect("msg is not valid UTF-8 data") ); diff --git a/beginner/apps/src/bin/stack_overflow.rs b/beginner/apps/src/bin/stack_overflow.rs index 24c73da..ff4b37c 100644 --- a/beginner/apps/src/bin/stack_overflow.rs +++ b/beginner/apps/src/bin/stack_overflow.rs @@ -22,7 +22,7 @@ fn main() -> ! { fn fib(n: u32) -> u32 { // allocate and initialize one kilobyte of stack memory to provoke stack overflow let use_stack = [0xAA; 1024]; - defmt::info!("allocating [{}; 1024]; round #{}", use_stack[1023], n); + defmt::println!("allocating [{}; 1024]; round #{}", use_stack[1023], n); if n < 2 { 1 diff --git a/boards/dk/src/lib.rs b/boards/dk/src/lib.rs index a368db6..3ece095 100644 --- a/boards/dk/src/lib.rs +++ b/boards/dk/src/lib.rs @@ -14,7 +14,8 @@ use cortex_m::{asm, peripheral::NVIC}; use embedded_hal::digital::v2::{OutputPin as _, StatefulOutputPin}; #[cfg(feature = "beginner")] pub use hal::ieee802154; -pub use hal::pac::{interrupt, Interrupt, NVIC_PRIO_BITS, RTC0}; +#[doc(hidden)] +pub use hal::pac::{Peripherals, interrupt, Interrupt, NVIC_PRIO_BITS, RTC0}; use hal::{ clocks::{self, Clocks}, gpio::{p0, Level, Output, Pin, Port, PushPull}, @@ -289,7 +290,7 @@ fn RTC0() { /// Exits the application and prints a backtrace when the program is executed through the `probe-run` /// Cargo runner pub fn exit() -> ! { - defmt::info!("`dk::exit()` called; exiting ..."); + defmt::println!("`dk::exit()` called; exiting ..."); // force any pending memory operation to complete before the BKPT instruction that follows atomic::compiler_fence(Ordering::SeqCst); loop { diff --git a/boards/dk/src/usbd.rs b/boards/dk/src/usbd.rs index d1ee75c..ae77157 100644 --- a/boards/dk/src/usbd.rs +++ b/boards/dk/src/usbd.rs @@ -51,7 +51,7 @@ impl Ep0In { self.busy = true; - defmt::info!("EP0IN: start {}B transfer", n); + defmt::println!("EP0IN: start {}B transfer", n); // start DMA transfer dma_start(); @@ -75,7 +75,7 @@ impl Ep0In { usbd.events_ep0datadone.reset(); self.busy = false; - defmt::info!("EP0IN: transfer done"); + defmt::println!("EP0IN: transfer done"); } } } @@ -110,7 +110,7 @@ pub fn init(power: POWER, usbd: &USBD) { // wait until the USB cable has been connected while power.events_usbdetected.read().bits() == 0 { if once { - defmt::info!("waiting for USB connection on port J3"); + defmt::println!("waiting for USB connection on port J3"); once = false; } diff --git a/embedded-workshop-book/src/interfaces.md b/embedded-workshop-book/src/interfaces.md index 56f942d..9f1f518 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 (`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 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::println!`-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 c6df898..7da4948 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; -defmt::info!("{:?}", slice); // length = 3 +defmt::println!("{:?}", slice); // length = 3 // now point to the other array slice = &array2; -defmt::info!("{:?}", slice); // length = 4 +defmt::println!("{:?}", 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 `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. +You'll note that `defmt::println!("{:?}", 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: `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 +Something similar will happen with byte literals: `defmt::println!("{}", 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::println!("{}", 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 f529514..86e71f6 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 ... */ - defmt::info!("got response"); + defmt::println!("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 91b6cc5..7598df6 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 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. +❗If you set the duration to below 2ms, try removing the `defmt::println!` 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.