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