esp_hal/
usb_serial_jtag.rs

1//! USB Serial/JTAG Controller (USB_SERIAL_JTAG)
2//!
3//! ## Overview
4//!
5//! The USB Serial/JTAG controller can be used to program the SoC's flash, read
6//! program output, or attach a debugger to the running program. This is
7//! possible for any computer with a USB host (hereafter referred to as 'host'),
8//! without any active external components.
9//!
10//! This peripheral integrates the functionality of both a USB-to-serial
11//! converter as well as a USB-to-JTAG adapter. As this device directly
12//! interfaces with an external USB host using only the two data lines required
13//! by USB 2.0, only two pins are required to be dedicated to this functionality
14//! for debugging.
15//!
16//! The USB Serial/JTAG controller boasts the following features:
17//!
18//! - Hardwired for CDC-ACM (Communication Device Class - Abstract Control
19//!   Model) and JTAG adapter functionality
20//! - Integrates CDC-ACM adherent serial port emulation (plug-and-play on most
21//!   modern OSes); supports host controllable chip reset and entry into
22//!   download mode
23//! - Allows fast communication with CPU debugging core using a compact
24//!   representation of JTAG instructions
25//! - Two OUT Endpoints and three IN Endpoints in addition to Control Endpoint
26//!   0; Up to 64-byte data payload size
27//! - Internal PHY means that very few or no external components needed to
28//!   connect to a host computer
29//!
30//! ## Usage
31//!
32//! The USB Serial/JTAG driver implements a number of third-party traits, with
33//! the intention of making the HAL inter-compatible with various device drivers
34//! from the community. This includes, but is not limited to, the [embedded-hal]
35//! and [embedded-io] blocking traits, and the [embedded-hal-async]
36//! and [embedded-io-async] asynchronous traits.
37//!
38//! In addition to the interfaces provided by these traits, native APIs are also
39//! available. See the examples below for more information on how to interact
40//! with this driver.
41//!
42//! ## Examples
43//!
44//! ### Sending and Receiving Data
45//! ```rust, no_run
46#![doc = crate::before_snippet!()]
47//! use esp_hal::usb_serial_jtag::UsbSerialJtag;
48//!
49//! let mut usb_serial = UsbSerialJtag::new(peripherals.USB_DEVICE);
50//!
51//! // Write bytes out over the USB Serial/JTAG:
52//! usb_serial.write(b"Hello, world!")?;
53//! # Ok(())
54//! # }
55//! ```
56//! 
57//! ### Splitting the USB Serial/JTAG into TX and RX Components
58//! ```rust, no_run
59#![doc = crate::before_snippet!()]
60//! use esp_hal::usb_serial_jtag::UsbSerialJtag;
61//!
62//! let mut usb_serial = UsbSerialJtag::new(peripherals.USB_DEVICE);
63//! // The USB Serial/JTAG can be split into separate Transmit and Receive
64//! // components:
65//! let (mut rx, mut tx) = usb_serial.split();
66//!
67//! // Each component can be used individually to interact with the USB
68//! // Serial/JTAG:
69//! tx.write(&[42u8])?;
70//! let byte = rx.read_byte()?;
71//! # Ok(())
72//! # }
73//! ```
74//! 
75//! ### How to output text using USB Serial/JTAG.
76//! ```rust, no_run
77#![doc = crate::before_snippet!()]
78//! # use esp_hal::{delay::Delay, usb_serial_jtag::UsbSerialJtag, Blocking};
79//!
80//! let delay = Delay::new();
81//!
82//! let mut usb_serial = UsbSerialJtag::new(peripherals.USB_DEVICE);
83//! usb_serial.set_interrupt_handler(usb_device);
84//! usb_serial.listen_rx_packet_recv_interrupt();
85//!
86//! critical_section::with(|cs|
87//! USB_SERIAL.borrow_ref_mut(cs).replace(usb_serial));
88//!
89//! loop {
90//!     println!("Send keystrokes to see the interrupt trigger");
91//!     delay.delay(Duration::from_secs(1));
92//! }
93//! # }
94//!
95//! # use critical_section::Mutex;
96//! # use core::{cell::RefCell, fmt::Write};
97//! # use esp_hal::usb_serial_jtag::UsbSerialJtag;
98//! static USB_SERIAL:
99//!     Mutex<RefCell<Option<UsbSerialJtag<'static, esp_hal::Blocking>>>> =
100//!         Mutex::new(RefCell::new(None));
101//!
102//! #[handler]
103//! fn usb_device() {
104//!     critical_section::with(|cs| {
105//!         let mut usb_serial = USB_SERIAL.borrow_ref_mut(cs);
106//!         if let Some(usb_serial) = usb_serial.as_mut() {
107//!             println!("USB serial interrupt");
108//!
109//!             while let nb::Result::Ok(c) = usb_serial.read_byte() {
110//!                 println!("Read byte: {:02x}", c);
111//!             }
112//!
113//!             usb_serial.reset_rx_packet_recv_interrupt();
114//!         }
115//!     });
116//! }
117//! ```
118//! 
119//! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/
120//! [embedded-io]: https://docs.rs/embedded-io/latest/embedded_io/
121//! [embedded-hal-async]: https://docs.rs/embedded-hal-async/latest/embedded_hal_async/
122//! [embedded-io-async]: https://docs.rs/embedded-io-async/latest/embedded_io_async/
123
124#[instability::unstable]
125use core::task::Poll;
126use core::{convert::Infallible, marker::PhantomData};
127
128use procmacros::handler;
129
130use crate::{
131    asynch::AtomicWaker,
132    pac::usb_device::RegisterBlock,
133    peripheral::{Peripheral, PeripheralRef},
134    peripherals::{Interrupt, USB_DEVICE},
135    system::{Cpu, PeripheralClockControl},
136    Async,
137    Blocking,
138    DriverMode,
139};
140
141/// Custom USB serial error type
142type Error = Infallible;
143
144/// USB Serial/JTAG (Full-duplex)
145pub struct UsbSerialJtag<'d, Dm: DriverMode> {
146    rx: UsbSerialJtagRx<'d, Dm>,
147    tx: UsbSerialJtagTx<'d, Dm>,
148}
149
150/// USB Serial/JTAG (Transmit)
151pub struct UsbSerialJtagTx<'d, Dm: DriverMode> {
152    peripheral: PeripheralRef<'d, USB_DEVICE>,
153    phantom: PhantomData<Dm>,
154}
155
156/// USB Serial/JTAG (Receive)
157pub struct UsbSerialJtagRx<'d, Dm: DriverMode> {
158    peripheral: PeripheralRef<'d, USB_DEVICE>,
159    phantom: PhantomData<Dm>,
160}
161
162impl<'d, Dm> UsbSerialJtagTx<'d, Dm>
163where
164    Dm: DriverMode,
165{
166    fn new_inner(peripheral: impl Peripheral<P = USB_DEVICE> + 'd) -> Self {
167        crate::into_ref!(peripheral);
168        Self {
169            peripheral,
170            phantom: PhantomData,
171        }
172    }
173
174    fn regs(&self) -> &RegisterBlock {
175        self.peripheral.register_block()
176    }
177
178    /// Write data to the serial output in chunks of up to 64 bytes
179    pub fn write(&mut self, data: &[u8]) -> Result<(), Error> {
180        for chunk in data.chunks(64) {
181            for byte in chunk {
182                self.regs()
183                    .ep1()
184                    .write(|w| unsafe { w.rdwr_byte().bits(*byte) });
185            }
186            self.regs().ep1_conf().modify(|_, w| w.wr_done().set_bit());
187
188            // FIXME: raw register access
189            while self.regs().ep1_conf().read().bits() & 0b011 == 0b000 {
190                // wait
191            }
192        }
193
194        Ok(())
195    }
196
197    /// Write data to the serial output in a non-blocking manner
198    /// Requires manual flushing (automatically flushed every 64 bytes)
199    pub fn write_byte_nb(&mut self, word: u8) -> nb::Result<(), Error> {
200        if self
201            .regs()
202            .ep1_conf()
203            .read()
204            .serial_in_ep_data_free()
205            .bit_is_set()
206        {
207            // the FIFO is not full
208            unsafe { self.regs().ep1().write(|w| w.rdwr_byte().bits(word)) };
209
210            Ok(())
211        } else {
212            Err(nb::Error::WouldBlock)
213        }
214    }
215
216    /// Flush the output FIFO and block until it has been sent
217    pub fn flush_tx(&mut self) -> Result<(), Error> {
218        self.regs().ep1_conf().modify(|_, w| w.wr_done().set_bit());
219
220        // FIXME: raw register access
221        while self.regs().ep1_conf().read().bits() & 0b011 == 0b000 {
222            // wait
223        }
224
225        Ok(())
226    }
227
228    /// Flush the output FIFO but don't block if it isn't ready immediately
229    pub fn flush_tx_nb(&mut self) -> nb::Result<(), Error> {
230        self.regs().ep1_conf().modify(|_, w| w.wr_done().set_bit());
231
232        // FIXME: raw register access
233        if self.regs().ep1_conf().read().bits() & 0b011 == 0b000 {
234            Err(nb::Error::WouldBlock)
235        } else {
236            Ok(())
237        }
238    }
239}
240
241impl<'d, Dm> UsbSerialJtagRx<'d, Dm>
242where
243    Dm: DriverMode,
244{
245    fn new_inner(peripheral: impl Peripheral<P = USB_DEVICE> + 'd) -> Self {
246        crate::into_ref!(peripheral);
247        Self {
248            peripheral,
249            phantom: PhantomData,
250        }
251    }
252
253    fn regs(&self) -> &RegisterBlock {
254        self.peripheral.register_block()
255    }
256
257    /// Read a byte from the UART in a non-blocking manner
258    pub fn read_byte(&mut self) -> nb::Result<u8, Error> {
259        // Check if there are any bytes to read
260        if self
261            .regs()
262            .ep1_conf()
263            .read()
264            .serial_out_ep_data_avail()
265            .bit_is_set()
266        {
267            let value = self.regs().ep1().read().rdwr_byte().bits();
268
269            Ok(value)
270        } else {
271            Err(nb::Error::WouldBlock)
272        }
273    }
274
275    /// Read all available bytes from the RX FIFO into the provided buffer and
276    /// returns the number of read bytes. Never blocks. May stop early if the
277    /// number of bytes in the FIFO is larger than `buf`.
278    pub fn drain_rx_fifo(&mut self, buf: &mut [u8]) -> usize {
279        let mut count = 0;
280        while let Ok(value) = self.read_byte() {
281            buf[count] = value;
282            count += 1;
283            if count == buf.len() {
284                break;
285            }
286        }
287        count
288    }
289
290    /// Listen for RX-PACKET-RECV interrupts
291    pub fn listen_rx_packet_recv_interrupt(&mut self) {
292        self.regs()
293            .int_ena()
294            .modify(|_, w| w.serial_out_recv_pkt().set_bit());
295    }
296
297    /// Stop listening for RX-PACKET-RECV interrupts
298    pub fn unlisten_rx_packet_recv_interrupt(&mut self) {
299        self.regs()
300            .int_ena()
301            .modify(|_, w| w.serial_out_recv_pkt().clear_bit());
302    }
303
304    /// Checks if RX-PACKET-RECV interrupt is set
305    pub fn rx_packet_recv_interrupt_set(&mut self) -> bool {
306        self.regs()
307            .int_st()
308            .read()
309            .serial_out_recv_pkt()
310            .bit_is_set()
311    }
312
313    /// Reset RX-PACKET-RECV interrupt
314    pub fn reset_rx_packet_recv_interrupt(&mut self) {
315        self.regs()
316            .int_clr()
317            .write(|w| w.serial_out_recv_pkt().clear_bit_by_one());
318    }
319}
320
321impl<'d> UsbSerialJtag<'d, Blocking> {
322    /// Create a new USB serial/JTAG instance with defaults
323    pub fn new(usb_device: impl Peripheral<P = USB_DEVICE> + 'd) -> Self {
324        Self::new_inner(usb_device)
325    }
326
327    /// Reconfigure the USB Serial JTAG peripheral to operate in asynchronous
328    /// mode.
329    pub fn into_async(mut self) -> UsbSerialJtag<'d, Async> {
330        self.set_interrupt_handler(async_interrupt_handler);
331
332        UsbSerialJtag {
333            rx: UsbSerialJtagRx {
334                peripheral: self.rx.peripheral,
335                phantom: PhantomData,
336            },
337            tx: UsbSerialJtagTx {
338                peripheral: self.tx.peripheral,
339                phantom: PhantomData,
340            },
341        }
342    }
343}
344
345impl crate::private::Sealed for UsbSerialJtag<'_, Blocking> {}
346
347#[instability::unstable]
348impl crate::interrupt::InterruptConfigurable for UsbSerialJtag<'_, Blocking> {
349    fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
350        self.set_interrupt_handler(handler);
351    }
352}
353
354impl<'d, Dm> UsbSerialJtag<'d, Dm>
355where
356    Dm: DriverMode,
357{
358    fn new_inner(usb_device: impl Peripheral<P = USB_DEVICE> + 'd) -> Self {
359        // Do NOT reset the peripheral. Doing so will result in a broken USB JTAG
360        // connection.
361        PeripheralClockControl::enable(crate::system::Peripheral::UsbDevice);
362
363        crate::into_ref!(usb_device);
364
365        usb_device.disable_tx_interrupts();
366        usb_device.disable_rx_interrupts();
367
368        #[cfg(any(esp32c3, esp32s3))]
369        {
370            use crate::soc::efuse::*;
371
372            // On the esp32c3, and esp32s3 the USB_EXCHG_PINS efuse is bugged and
373            // doesn't swap the pullups too, this works around that.
374            if Efuse::read_bit(USB_EXCHG_PINS) {
375                usb_device.register_block().conf0().modify(|_, w| {
376                    w.pad_pull_override().set_bit();
377                    w.dm_pullup().clear_bit();
378                    w.dp_pullup().set_bit()
379                });
380            }
381        }
382
383        crate::into_ref!(usb_device);
384
385        Self {
386            rx: UsbSerialJtagRx::new_inner(unsafe { usb_device.clone_unchecked() }),
387            tx: UsbSerialJtagTx::new_inner(usb_device),
388        }
389    }
390    /// Split the USB Serial JTAG peripheral into a transmitter and receiver,
391    /// which is particularly useful when having two tasks correlating to
392    /// transmitting and receiving.
393    pub fn split(self) -> (UsbSerialJtagRx<'d, Dm>, UsbSerialJtagTx<'d, Dm>) {
394        (self.rx, self.tx)
395    }
396
397    /// Write data to the serial output in chunks of up to 64 bytes
398    pub fn write(&mut self, data: &[u8]) -> Result<(), Error> {
399        self.tx.write(data)
400    }
401
402    /// Write data to the serial output in a non-blocking manner
403    /// Requires manual flushing (automatically flushed every 64 bytes)
404    pub fn write_byte_nb(&mut self, word: u8) -> nb::Result<(), Error> {
405        self.tx.write_byte_nb(word)
406    }
407
408    /// Flush the output FIFO and block until it has been sent
409    pub fn flush_tx(&mut self) -> Result<(), Error> {
410        self.tx.flush_tx()
411    }
412
413    /// Flush the output FIFO but don't block if it isn't ready immediately
414    pub fn flush_tx_nb(&mut self) -> nb::Result<(), Error> {
415        self.tx.flush_tx_nb()
416    }
417
418    /// Read a single byte but don't block if it isn't ready immediately
419    pub fn read_byte(&mut self) -> nb::Result<u8, Error> {
420        self.rx.read_byte()
421    }
422
423    /// Listen for RX-PACKET-RECV interrupts
424    pub fn listen_rx_packet_recv_interrupt(&mut self) {
425        self.rx.listen_rx_packet_recv_interrupt()
426    }
427
428    /// Stop listening for RX-PACKET-RECV interrupts
429    pub fn unlisten_rx_packet_recv_interrupt(&mut self) {
430        self.rx.unlisten_rx_packet_recv_interrupt()
431    }
432
433    /// Checks if RX-PACKET-RECV interrupt is set
434    pub fn rx_packet_recv_interrupt_set(&mut self) -> bool {
435        self.rx.rx_packet_recv_interrupt_set()
436    }
437
438    /// Reset RX-PACKET-RECV interrupt
439    pub fn reset_rx_packet_recv_interrupt(&mut self) {
440        self.rx.reset_rx_packet_recv_interrupt()
441    }
442
443    /// Registers an interrupt handler for the USB Serial JTAG peripheral.
444    ///
445    /// Note that this will replace any previously registered interrupt
446    /// handlers.
447    #[instability::unstable]
448    pub fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
449        for core in crate::system::Cpu::other() {
450            crate::interrupt::disable(core, Interrupt::USB_DEVICE);
451        }
452        unsafe { crate::interrupt::bind_interrupt(Interrupt::USB_DEVICE, handler.handler()) };
453        unwrap!(crate::interrupt::enable(
454            Interrupt::USB_DEVICE,
455            handler.priority()
456        ));
457    }
458}
459
460/// USB Serial/JTAG peripheral instance
461#[doc(hidden)]
462pub trait Instance: crate::private::Sealed {
463    /// Get a reference to the peripheral's underlying register block
464    fn register_block(&self) -> &RegisterBlock;
465
466    /// Disable all transmit interrupts for the peripheral
467    fn disable_tx_interrupts(&self) {
468        self.register_block()
469            .int_ena()
470            .modify(|_, w| w.serial_in_empty().clear_bit());
471
472        self.register_block()
473            .int_clr()
474            .write(|w| w.serial_in_empty().clear_bit_by_one());
475    }
476
477    /// Disable all receive interrupts for the peripheral
478    fn disable_rx_interrupts(&self) {
479        self.register_block()
480            .int_ena()
481            .modify(|_, w| w.serial_out_recv_pkt().clear_bit());
482
483        self.register_block()
484            .int_clr()
485            .write(|w| w.serial_out_recv_pkt().clear_bit_by_one());
486    }
487}
488
489impl Instance for USB_DEVICE {
490    #[inline(always)]
491    fn register_block(&self) -> &RegisterBlock {
492        USB_DEVICE::regs()
493    }
494}
495
496impl<Dm> core::fmt::Write for UsbSerialJtag<'_, Dm>
497where
498    Dm: DriverMode,
499{
500    fn write_str(&mut self, s: &str) -> core::fmt::Result {
501        core::fmt::Write::write_str(&mut self.tx, s)
502    }
503}
504
505impl<Dm> core::fmt::Write for UsbSerialJtagTx<'_, Dm>
506where
507    Dm: DriverMode,
508{
509    fn write_str(&mut self, s: &str) -> core::fmt::Result {
510        self.write(s.as_bytes()).map_err(|_| core::fmt::Error)?;
511        Ok(())
512    }
513}
514
515#[instability::unstable]
516impl<Dm> ufmt_write::uWrite for UsbSerialJtag<'_, Dm>
517where
518    Dm: DriverMode,
519{
520    type Error = Error;
521
522    #[inline]
523    fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
524        ufmt_write::uWrite::write_str(&mut self.tx, s)
525    }
526
527    #[inline]
528    fn write_char(&mut self, ch: char) -> Result<(), Self::Error> {
529        ufmt_write::uWrite::write_char(&mut self.tx, ch)
530    }
531}
532
533#[instability::unstable]
534impl<Dm> ufmt_write::uWrite for UsbSerialJtagTx<'_, Dm>
535where
536    Dm: DriverMode,
537{
538    type Error = Error;
539
540    #[inline]
541    fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
542        self.write(s.as_bytes())?;
543        Ok(())
544    }
545
546    #[inline]
547    fn write_char(&mut self, ch: char) -> Result<(), Self::Error> {
548        let mut buffer = [0u8; 4];
549        self.write(ch.encode_utf8(&mut buffer).as_bytes())?;
550
551        Ok(())
552    }
553}
554
555#[instability::unstable]
556impl<Dm> embedded_io::ErrorType for UsbSerialJtag<'_, Dm>
557where
558    Dm: DriverMode,
559{
560    type Error = Error;
561}
562
563#[instability::unstable]
564impl<Dm> embedded_io::ErrorType for UsbSerialJtagTx<'_, Dm>
565where
566    Dm: DriverMode,
567{
568    type Error = Error;
569}
570
571#[instability::unstable]
572impl<Dm> embedded_io::ErrorType for UsbSerialJtagRx<'_, Dm>
573where
574    Dm: DriverMode,
575{
576    type Error = Error;
577}
578
579#[instability::unstable]
580impl<Dm> embedded_io::Read for UsbSerialJtag<'_, Dm>
581where
582    Dm: DriverMode,
583{
584    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
585        embedded_io::Read::read(&mut self.rx, buf)
586    }
587}
588
589#[instability::unstable]
590impl<Dm> embedded_io::Read for UsbSerialJtagRx<'_, Dm>
591where
592    Dm: DriverMode,
593{
594    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
595        loop {
596            let count = self.drain_rx_fifo(buf);
597            if count > 0 {
598                return Ok(count);
599            }
600        }
601    }
602}
603
604#[instability::unstable]
605impl<Dm> embedded_io::Write for UsbSerialJtag<'_, Dm>
606where
607    Dm: DriverMode,
608{
609    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
610        embedded_io::Write::write(&mut self.tx, buf)
611    }
612
613    fn flush(&mut self) -> Result<(), Self::Error> {
614        embedded_io::Write::flush(&mut self.tx)
615    }
616}
617
618#[instability::unstable]
619impl<Dm> embedded_io::Write for UsbSerialJtagTx<'_, Dm>
620where
621    Dm: DriverMode,
622{
623    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
624        self.write(buf)?;
625
626        Ok(buf.len())
627    }
628
629    fn flush(&mut self) -> Result<(), Self::Error> {
630        self.flush_tx()
631    }
632}
633
634// Static instance of the waker for each component of the peripheral:
635static WAKER_TX: AtomicWaker = AtomicWaker::new();
636static WAKER_RX: AtomicWaker = AtomicWaker::new();
637
638#[must_use = "futures do nothing unless you `.await` or poll them"]
639struct UsbSerialJtagWriteFuture<'d> {
640    peripheral: PeripheralRef<'d, USB_DEVICE>,
641}
642
643impl<'d> UsbSerialJtagWriteFuture<'d> {
644    fn new(peripheral: impl Peripheral<P = USB_DEVICE> + 'd) -> Self {
645        crate::into_ref!(peripheral);
646        // Set the interrupt enable bit for the USB_SERIAL_JTAG_SERIAL_IN_EMPTY_INT
647        // interrupt
648        peripheral
649            .register_block()
650            .int_ena()
651            .modify(|_, w| w.serial_in_empty().set_bit());
652
653        Self { peripheral }
654    }
655
656    fn event_bit_is_clear(&self) -> bool {
657        self.peripheral
658            .register_block()
659            .int_ena()
660            .read()
661            .serial_in_empty()
662            .bit_is_clear()
663    }
664}
665
666impl core::future::Future for UsbSerialJtagWriteFuture<'_> {
667    type Output = ();
668
669    fn poll(
670        self: core::pin::Pin<&mut Self>,
671        cx: &mut core::task::Context<'_>,
672    ) -> core::task::Poll<Self::Output> {
673        WAKER_TX.register(cx.waker());
674        if self.event_bit_is_clear() {
675            Poll::Ready(())
676        } else {
677            Poll::Pending
678        }
679    }
680}
681
682#[must_use = "futures do nothing unless you `.await` or poll them"]
683struct UsbSerialJtagReadFuture<'d> {
684    peripheral: PeripheralRef<'d, USB_DEVICE>,
685}
686
687impl<'d> UsbSerialJtagReadFuture<'d> {
688    fn new(peripheral: impl Peripheral<P = USB_DEVICE> + 'd) -> Self {
689        crate::into_ref!(peripheral);
690        // Set the interrupt enable bit for the USB_SERIAL_JTAG_SERIAL_OUT_RECV_PKT
691        // interrupt
692        peripheral
693            .register_block()
694            .int_ena()
695            .modify(|_, w| w.serial_out_recv_pkt().set_bit());
696
697        Self { peripheral }
698    }
699
700    fn event_bit_is_clear(&self) -> bool {
701        self.peripheral
702            .register_block()
703            .int_ena()
704            .read()
705            .serial_out_recv_pkt()
706            .bit_is_clear()
707    }
708}
709
710impl core::future::Future for UsbSerialJtagReadFuture<'_> {
711    type Output = ();
712
713    fn poll(
714        self: core::pin::Pin<&mut Self>,
715        cx: &mut core::task::Context<'_>,
716    ) -> core::task::Poll<Self::Output> {
717        WAKER_RX.register(cx.waker());
718        if self.event_bit_is_clear() {
719            Poll::Ready(())
720        } else {
721            Poll::Pending
722        }
723    }
724}
725
726impl<'d> UsbSerialJtag<'d, Async> {
727    /// Reconfigure the USB Serial JTAG peripheral to operate in blocking
728    /// mode.
729    pub fn into_blocking(self) -> UsbSerialJtag<'d, Blocking> {
730        crate::interrupt::disable(Cpu::current(), Interrupt::USB_DEVICE);
731        UsbSerialJtag {
732            rx: UsbSerialJtagRx {
733                peripheral: self.rx.peripheral,
734                phantom: PhantomData,
735            },
736            tx: UsbSerialJtagTx {
737                peripheral: self.tx.peripheral,
738                phantom: PhantomData,
739            },
740        }
741    }
742}
743
744impl UsbSerialJtagTx<'_, Async> {
745    async fn write_async(&mut self, words: &[u8]) -> Result<(), Error> {
746        for chunk in words.chunks(64) {
747            for byte in chunk {
748                self.regs()
749                    .ep1()
750                    .write(|w| unsafe { w.rdwr_byte().bits(*byte) });
751            }
752            self.regs().ep1_conf().modify(|_, w| w.wr_done().set_bit());
753
754            UsbSerialJtagWriteFuture::new(self.peripheral.reborrow()).await;
755        }
756
757        Ok(())
758    }
759
760    async fn flush_tx_async(&mut self) -> Result<(), Error> {
761        if self
762            .regs()
763            .jfifo_st()
764            .read()
765            .out_fifo_empty()
766            .bit_is_clear()
767        {
768            UsbSerialJtagWriteFuture::new(self.peripheral.reborrow()).await;
769        }
770
771        Ok(())
772    }
773}
774
775impl UsbSerialJtagRx<'_, Async> {
776    async fn read_async(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
777        if buf.is_empty() {
778            return Ok(0);
779        }
780
781        loop {
782            let read = self.drain_rx_fifo(buf);
783            if read > 0 {
784                return Ok(read);
785            }
786            UsbSerialJtagReadFuture::new(self.peripheral.reborrow()).await;
787        }
788    }
789}
790
791#[instability::unstable]
792impl embedded_io_async::Write for UsbSerialJtag<'_, Async> {
793    async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
794        embedded_io_async::Write::write(&mut self.tx, buf).await
795    }
796
797    async fn flush(&mut self) -> Result<(), Self::Error> {
798        embedded_io_async::Write::flush(&mut self.tx).await
799    }
800}
801
802#[instability::unstable]
803impl embedded_io_async::Write for UsbSerialJtagTx<'_, Async> {
804    async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
805        self.write_async(buf).await?;
806
807        Ok(buf.len())
808    }
809
810    async fn flush(&mut self) -> Result<(), Self::Error> {
811        self.flush_tx_async().await
812    }
813}
814
815#[instability::unstable]
816impl embedded_io_async::Read for UsbSerialJtag<'_, Async> {
817    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
818        embedded_io_async::Read::read(&mut self.rx, buf).await
819    }
820}
821
822#[instability::unstable]
823impl embedded_io_async::Read for UsbSerialJtagRx<'_, Async> {
824    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
825        self.read_async(buf).await
826    }
827}
828
829#[handler]
830fn async_interrupt_handler() {
831    let usb = USB_DEVICE::regs();
832    let interrupts = usb.int_st().read();
833
834    let tx = interrupts.serial_in_empty().bit_is_set();
835    let rx = interrupts.serial_out_recv_pkt().bit_is_set();
836
837    if tx {
838        usb.int_ena().modify(|_, w| w.serial_in_empty().clear_bit());
839    }
840    if rx {
841        usb.int_ena()
842            .modify(|_, w| w.serial_out_recv_pkt().clear_bit());
843    }
844
845    usb.int_clr().write(|w| {
846        w.serial_in_empty()
847            .clear_bit_by_one()
848            .serial_out_recv_pkt()
849            .clear_bit_by_one()
850    });
851
852    if rx {
853        WAKER_RX.wake();
854    }
855    if tx {
856        WAKER_TX.wake();
857    }
858}