diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index b6e4213e8cb..f3663c6979f 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added touch pad support for esp32 (#1873) - Allow configuration of period updating method for MCPWM timers (#1898) - Add self-testing mode for TWAI peripheral. (#1929) -- Added a `PeripheralClockControl::reset` to the driver constructors where missing (#1893) +- Added `debugger::debugger_connected`. (#1961) ### Changed @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allow DMA to/from psram for esp32s3 (#1827) - DMA buffers now don't require a static lifetime. Make sure to never `mem::forget` an in-progress DMA transfer (consider using `#[deny(clippy::mem_forget)]`) (#1837) - Peripherals (where possible) are now explicitly reset and enabled in their constructors (#1893) +- Reset peripherals in driver constructors where missing (#1893, #1961) ### Fixed diff --git a/esp-hal/src/assist_debug.rs b/esp-hal/src/assist_debug.rs index 91128407b7f..4e5fe1e8c90 100644 --- a/esp-hal/src/assist_debug.rs +++ b/esp-hal/src/assist_debug.rs @@ -68,7 +68,7 @@ impl<'d> InterruptConfigurable for DebugAssist<'d> { #[cfg(assist_debug_sp_monitor)] impl<'d> DebugAssist<'d> { /// Enable SP monitoring on main core. When the SP exceeds the - /// `lower_bound` or `upper_bound` treshold, the module will record the PC + /// `lower_bound` or `upper_bound` threshold, the module will record the PC /// pointer and generate an interrupt. pub fn enable_sp_monitor(&mut self, lower_bound: u32, upper_bound: u32) { self.debug_assist @@ -150,8 +150,8 @@ impl<'d> DebugAssist<'d> { #[cfg(all(assist_debug_sp_monitor, multi_core))] impl<'d> DebugAssist<'d> { - /// Enable SP monitoring on secondondary core. When the SP exceeds the - /// `lower_bound` or `upper_bound` treshold, the module will record the PC + /// Enable SP monitoring on secondary core. When the SP exceeds the + /// `lower_bound` or `upper_bound` threshold, the module will record the PC /// pointer and generate an interrupt. pub fn enable_core1_sp_monitor(&mut self, lower_bound: u32, upper_bound: u32) { self.debug_assist @@ -384,7 +384,7 @@ impl<'d> DebugAssist<'d> { .bit_is_set() } - /// Get region monotoring PC value on main core. + /// Get region monitoring PC value on main core. pub fn get_region_monitor_pc(&self) -> u32 { self.debug_assist .core_0_area_pc() @@ -550,7 +550,7 @@ impl<'d> DebugAssist<'d> { .bit_is_set() } - /// Get region monotoring PC value on secondary core. + /// Get region monitoring PC value on secondary core. pub fn get_core1_region_monitor_pc(&self) -> u32 { self.debug_assist .core_1_area_pc() diff --git a/esp-hal/src/debugger.rs b/esp-hal/src/debugger.rs new file mode 100644 index 00000000000..4c970f82693 --- /dev/null +++ b/esp-hal/src/debugger.rs @@ -0,0 +1,36 @@ +//! Debugger utilities + +/// Checks if a debugger is connected. +pub fn debugger_connected() -> bool { + #[cfg(xtensa)] + { + xtensa_lx::is_debugger_attached() + } + + #[cfg(riscv)] + { + use crate::peripherals::ASSIST_DEBUG; + let assist_debug = unsafe { &*ASSIST_DEBUG::ptr() }; + #[cfg(feature = "esp32c2")] + { + assist_debug + .core_0_debug_mode() + .read() + .core_0_debug_module_active() + .bit_is_set() + } + #[cfg(not(feature = "esp32c2"))] + { + assist_debug + .c0re_0_debug_mode() + .read() + .core_0_debug_module_active() + .bit_is_set() + } + } + + #[cfg(not(any(xtensa, riscv)))] + { + false + } +} diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index 67030eca416..d43566cb785 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -241,6 +241,8 @@ pub mod uart; #[cfg(usb_device)] pub mod usb_serial_jtag; +pub mod debugger; + /// State of the CPU saved when entering exception or interrupt pub mod trapframe { #[cfg(riscv)] diff --git a/esp-hal/src/usb_serial_jtag.rs b/esp-hal/src/usb_serial_jtag.rs index 83df2bb043d..188e3843ae2 100644 --- a/esp-hal/src/usb_serial_jtag.rs +++ b/esp-hal/src/usb_serial_jtag.rs @@ -273,7 +273,8 @@ where M: Mode, { fn new_inner(_usb_device: impl Peripheral

+ 'd) -> Self { - PeripheralClockControl::reset(crate::system::Peripheral::UsbDevice); + // Do NOT reset the peripheral. Doing so will result in a broken USB JTAG + // connection. PeripheralClockControl::enable(crate::system::Peripheral::UsbDevice); USB_DEVICE::disable_tx_interrupts(); @@ -311,7 +312,7 @@ where } /// Split the USB Serial JTAG peripheral into a transmitter and receiver, - /// which is particuarly useful when having two tasks correlating to + /// which is particularly useful when having two tasks correlating to /// transmitting and receiving. pub fn split(self) -> (UsbSerialJtagTx<'d, M>, UsbSerialJtagRx<'d, M>) { (self.tx, self.rx) diff --git a/hil-test/Cargo.toml b/hil-test/Cargo.toml index ad57357f18f..ad26f1326a2 100644 --- a/hil-test/Cargo.toml +++ b/hil-test/Cargo.toml @@ -100,6 +100,10 @@ harness = false name = "uart" harness = false +[[test]] +name = "usb_serial_jtag" +harness = false + [[test]] name = "uart_async" harness = false diff --git a/hil-test/tests/usb_serial_jtag.rs b/hil-test/tests/usb_serial_jtag.rs new file mode 100644 index 00000000000..2b1fe40ec92 --- /dev/null +++ b/hil-test/tests/usb_serial_jtag.rs @@ -0,0 +1,45 @@ +//! USB Serial JTAG tests + +//% CHIPS: esp32c3 esp32c6 esp32h2 esp32s3 + +#![no_std] +#![no_main] + +#[cfg(test)] +#[embedded_test::tests] +mod tests { + use defmt_rtt as _; + use esp_backtrace as _; + use esp_hal::{ + clock::ClockControl, + peripherals::Peripherals, + system::SystemControl, + timer::{timg::TimerGroup, ErasedTimer, OneShotTimer}, + usb_serial_jtag::UsbSerialJtag, + }; + + // When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html + macro_rules! mk_static { + ($t:ty,$val:expr) => {{ + static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new(); + #[deny(unused_attributes)] + let x = STATIC_CELL.uninit().write(($val)); + x + }}; + } + + #[test] + fn creating_peripheral_does_not_break_debug_connection() { + let peripherals = Peripherals::take(); + let system = SystemControl::new(peripherals.SYSTEM); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timer0: ErasedTimer = timg0.timer0.into(); + let timers = [OneShotTimer::new(timer0)]; + let timers = mk_static!([OneShotTimer; 1], timers); + esp_hal_embassy::init(&clocks, timers); + + _ = UsbSerialJtag::new_async(peripherals.USB_DEVICE).split(); + } +}