Do not reset UsbSerialJtag peripheral (#1961)

* Fix typos

* Add a function to detect debugger connection

* Do not reset USB peripheral

* Changelog

* Fix different register names

* Reuse xtensa_lx::is_debugger_attached
This commit is contained in:
Dániel Buga 2024-08-16 16:51:34 +02:00 committed by GitHub
parent f6e69b06d0
commit eb1b295116
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 97 additions and 8 deletions

View File

@ -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, #1956)
- 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

View File

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

36
esp-hal/src/debugger.rs Normal file
View File

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

View File

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

View File

@ -273,7 +273,8 @@ where
M: Mode,
{
fn new_inner(_usb_device: impl Peripheral<P = USB_DEVICE> + '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)

View File

@ -100,6 +100,10 @@ harness = false
name = "uart"
harness = false
[[test]]
name = "usb_serial_jtag"
harness = false
[[test]]
name = "uart_async"
harness = false

View File

@ -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<ErasedTimer>; 1], timers);
esp_hal_embassy::init(&clocks, timers);
_ = UsbSerialJtag::new_async(peripherals.USB_DEVICE).split();
}
}