mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-10-01 14:20:44 +00:00
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:
parent
f6e69b06d0
commit
eb1b295116
@ -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)
|
- Added touch pad support for esp32 (#1873, #1956)
|
||||||
- Allow configuration of period updating method for MCPWM timers (#1898)
|
- Allow configuration of period updating method for MCPWM timers (#1898)
|
||||||
- Add self-testing mode for TWAI peripheral. (#1929)
|
- 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
|
### 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)
|
- 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)
|
- 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)
|
- Peripherals (where possible) are now explicitly reset and enabled in their constructors (#1893)
|
||||||
|
- Reset peripherals in driver constructors where missing (#1893, #1961)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ impl<'d> InterruptConfigurable for DebugAssist<'d> {
|
|||||||
#[cfg(assist_debug_sp_monitor)]
|
#[cfg(assist_debug_sp_monitor)]
|
||||||
impl<'d> DebugAssist<'d> {
|
impl<'d> DebugAssist<'d> {
|
||||||
/// Enable SP monitoring on main core. When the SP exceeds the
|
/// 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.
|
/// pointer and generate an interrupt.
|
||||||
pub fn enable_sp_monitor(&mut self, lower_bound: u32, upper_bound: u32) {
|
pub fn enable_sp_monitor(&mut self, lower_bound: u32, upper_bound: u32) {
|
||||||
self.debug_assist
|
self.debug_assist
|
||||||
@ -150,8 +150,8 @@ impl<'d> DebugAssist<'d> {
|
|||||||
|
|
||||||
#[cfg(all(assist_debug_sp_monitor, multi_core))]
|
#[cfg(all(assist_debug_sp_monitor, multi_core))]
|
||||||
impl<'d> DebugAssist<'d> {
|
impl<'d> DebugAssist<'d> {
|
||||||
/// Enable SP monitoring on secondondary core. When the SP exceeds the
|
/// Enable SP monitoring on secondary 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.
|
/// pointer and generate an interrupt.
|
||||||
pub fn enable_core1_sp_monitor(&mut self, lower_bound: u32, upper_bound: u32) {
|
pub fn enable_core1_sp_monitor(&mut self, lower_bound: u32, upper_bound: u32) {
|
||||||
self.debug_assist
|
self.debug_assist
|
||||||
@ -384,7 +384,7 @@ impl<'d> DebugAssist<'d> {
|
|||||||
.bit_is_set()
|
.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 {
|
pub fn get_region_monitor_pc(&self) -> u32 {
|
||||||
self.debug_assist
|
self.debug_assist
|
||||||
.core_0_area_pc()
|
.core_0_area_pc()
|
||||||
@ -550,7 +550,7 @@ impl<'d> DebugAssist<'d> {
|
|||||||
.bit_is_set()
|
.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 {
|
pub fn get_core1_region_monitor_pc(&self) -> u32 {
|
||||||
self.debug_assist
|
self.debug_assist
|
||||||
.core_1_area_pc()
|
.core_1_area_pc()
|
||||||
|
36
esp-hal/src/debugger.rs
Normal file
36
esp-hal/src/debugger.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -241,6 +241,8 @@ pub mod uart;
|
|||||||
#[cfg(usb_device)]
|
#[cfg(usb_device)]
|
||||||
pub mod usb_serial_jtag;
|
pub mod usb_serial_jtag;
|
||||||
|
|
||||||
|
pub mod debugger;
|
||||||
|
|
||||||
/// State of the CPU saved when entering exception or interrupt
|
/// State of the CPU saved when entering exception or interrupt
|
||||||
pub mod trapframe {
|
pub mod trapframe {
|
||||||
#[cfg(riscv)]
|
#[cfg(riscv)]
|
||||||
|
@ -273,7 +273,8 @@ where
|
|||||||
M: Mode,
|
M: Mode,
|
||||||
{
|
{
|
||||||
fn new_inner(_usb_device: impl Peripheral<P = USB_DEVICE> + 'd) -> Self {
|
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);
|
PeripheralClockControl::enable(crate::system::Peripheral::UsbDevice);
|
||||||
|
|
||||||
USB_DEVICE::disable_tx_interrupts();
|
USB_DEVICE::disable_tx_interrupts();
|
||||||
@ -311,7 +312,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Split the USB Serial JTAG peripheral into a transmitter and receiver,
|
/// 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.
|
/// transmitting and receiving.
|
||||||
pub fn split(self) -> (UsbSerialJtagTx<'d, M>, UsbSerialJtagRx<'d, M>) {
|
pub fn split(self) -> (UsbSerialJtagTx<'d, M>, UsbSerialJtagRx<'d, M>) {
|
||||||
(self.tx, self.rx)
|
(self.tx, self.rx)
|
||||||
|
@ -100,6 +100,10 @@ harness = false
|
|||||||
name = "uart"
|
name = "uart"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
|
[[test]]
|
||||||
|
name = "usb_serial_jtag"
|
||||||
|
harness = false
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "uart_async"
|
name = "uart_async"
|
||||||
harness = false
|
harness = false
|
||||||
|
45
hil-test/tests/usb_serial_jtag.rs
Normal file
45
hil-test/tests/usb_serial_jtag.rs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user