#![doc = crate::before_snippet!()]
#![doc = crate::before_snippet!()]
use core::{convert::Infallible, marker::PhantomData, task::Poll};
use embassy_sync::waitqueue::AtomicWaker;
use procmacros::handler;
use crate::{
peripheral::{Peripheral, PeripheralRef},
peripherals::{usb_device::RegisterBlock, Interrupt, USB_DEVICE},
system::PeripheralClockControl,
Async,
Blocking,
Cpu,
InterruptConfigurable,
Mode,
};
type Error = Infallible;
pub struct UsbSerialJtag<'d, M> {
rx: UsbSerialJtagRx<'d, M>,
tx: UsbSerialJtagTx<'d, M>,
}
pub struct UsbSerialJtagTx<'d, M> {
peripheral: PeripheralRef<'d, USB_DEVICE>,
phantom: PhantomData<M>,
}
pub struct UsbSerialJtagRx<'d, M> {
peripheral: PeripheralRef<'d, USB_DEVICE>,
phantom: PhantomData<M>,
}
impl<'d, M> UsbSerialJtagTx<'d, M>
where
M: Mode,
{
fn new_inner(peripheral: impl Peripheral<P = USB_DEVICE> + 'd) -> Self {
crate::into_ref!(peripheral);
Self {
peripheral,
phantom: PhantomData,
}
}
pub fn write_bytes(&mut self, data: &[u8]) -> Result<(), Error> {
let reg_block = USB_DEVICE::register_block();
for chunk in data.chunks(64) {
for byte in chunk {
reg_block
.ep1()
.write(|w| unsafe { w.rdwr_byte().bits(*byte) });
}
reg_block.ep1_conf().modify(|_, w| w.wr_done().set_bit());
while reg_block.ep1_conf().read().bits() & 0b011 == 0b000 {
}
}
Ok(())
}
pub fn write_byte_nb(&mut self, word: u8) -> nb::Result<(), Error> {
let reg_block = USB_DEVICE::register_block();
if reg_block
.ep1_conf()
.read()
.serial_in_ep_data_free()
.bit_is_set()
{
unsafe {
reg_block.ep1().write(|w| w.rdwr_byte().bits(word));
}
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
pub fn flush_tx(&mut self) -> Result<(), Error> {
let reg_block = USB_DEVICE::register_block();
reg_block.ep1_conf().modify(|_, w| w.wr_done().set_bit());
while reg_block.ep1_conf().read().bits() & 0b011 == 0b000 {
}
Ok(())
}
pub fn flush_tx_nb(&mut self) -> nb::Result<(), Error> {
let reg_block = USB_DEVICE::register_block();
reg_block.ep1_conf().modify(|_, w| w.wr_done().set_bit());
if reg_block.ep1_conf().read().bits() & 0b011 == 0b000 {
Err(nb::Error::WouldBlock)
} else {
Ok(())
}
}
}
impl<'d, M> UsbSerialJtagRx<'d, M>
where
M: Mode,
{
fn new_inner(peripheral: impl Peripheral<P = USB_DEVICE> + 'd) -> Self {
crate::into_ref!(peripheral);
Self {
peripheral,
phantom: PhantomData,
}
}
pub fn read_byte(&mut self) -> nb::Result<u8, Error> {
let reg_block = USB_DEVICE::register_block();
if reg_block
.ep1_conf()
.read()
.serial_out_ep_data_avail()
.bit_is_set()
{
let value = reg_block.ep1().read().rdwr_byte().bits();
Ok(value)
} else {
Err(nb::Error::WouldBlock)
}
}
pub fn drain_rx_fifo(&mut self, buf: &mut [u8]) -> usize {
let mut count = 0;
while let Ok(value) = self.read_byte() {
buf[count] = value;
count += 1;
if count == buf.len() {
break;
}
}
count
}
pub fn listen_rx_packet_recv_interrupt(&mut self) {
USB_DEVICE::register_block()
.int_ena()
.modify(|_, w| w.serial_out_recv_pkt().set_bit());
}
pub fn unlisten_rx_packet_recv_interrupt(&mut self) {
USB_DEVICE::register_block()
.int_ena()
.modify(|_, w| w.serial_out_recv_pkt().clear_bit());
}
pub fn rx_packet_recv_interrupt_set(&mut self) -> bool {
USB_DEVICE::register_block()
.int_st()
.read()
.serial_out_recv_pkt()
.bit_is_set()
}
pub fn reset_rx_packet_recv_interrupt(&mut self) {
USB_DEVICE::register_block()
.int_clr()
.write(|w| w.serial_out_recv_pkt().clear_bit_by_one());
}
}
impl<'d> UsbSerialJtag<'d, Blocking> {
pub fn new(usb_device: impl Peripheral<P = USB_DEVICE> + 'd) -> Self {
Self::new_inner(usb_device)
}
pub fn into_async(mut self) -> UsbSerialJtag<'d, Async> {
self.set_interrupt_handler(async_interrupt_handler);
UsbSerialJtag {
rx: UsbSerialJtagRx {
peripheral: self.rx.peripheral,
phantom: PhantomData,
},
tx: UsbSerialJtagTx {
peripheral: self.tx.peripheral,
phantom: PhantomData,
},
}
}
}
impl crate::private::Sealed for UsbSerialJtag<'_, Blocking> {}
impl InterruptConfigurable for UsbSerialJtag<'_, Blocking> {
fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
for core in crate::Cpu::other() {
crate::interrupt::disable(core, Interrupt::USB_DEVICE);
}
unsafe { crate::interrupt::bind_interrupt(Interrupt::USB_DEVICE, handler.handler()) };
unwrap!(crate::interrupt::enable(
Interrupt::USB_DEVICE,
handler.priority()
));
}
}
impl<'d, M> UsbSerialJtag<'d, M>
where
M: Mode,
{
fn new_inner(usb_device: impl Peripheral<P = USB_DEVICE> + 'd) -> Self {
PeripheralClockControl::enable(crate::system::Peripheral::UsbDevice);
USB_DEVICE::disable_tx_interrupts();
USB_DEVICE::disable_rx_interrupts();
#[cfg(any(esp32c3, esp32s3))]
{
use crate::soc::efuse::*;
if Efuse::read_bit(USB_EXCHG_PINS) {
USB_DEVICE::register_block().conf0().modify(|_, w| {
w.pad_pull_override().set_bit();
w.dm_pullup().clear_bit();
w.dp_pullup().set_bit()
});
}
}
crate::into_ref!(usb_device);
Self {
rx: UsbSerialJtagRx::new_inner(unsafe { usb_device.clone_unchecked() }),
tx: UsbSerialJtagTx::new_inner(usb_device),
}
}
pub fn split(self) -> (UsbSerialJtagRx<'d, M>, UsbSerialJtagTx<'d, M>) {
(self.rx, self.tx)
}
pub fn write_bytes(&mut self, data: &[u8]) -> Result<(), Error> {
self.tx.write_bytes(data)
}
pub fn write_byte_nb(&mut self, word: u8) -> nb::Result<(), Error> {
self.tx.write_byte_nb(word)
}
pub fn flush_tx(&mut self) -> Result<(), Error> {
self.tx.flush_tx()
}
pub fn flush_tx_nb(&mut self) -> nb::Result<(), Error> {
self.tx.flush_tx_nb()
}
pub fn read_byte(&mut self) -> nb::Result<u8, Error> {
self.rx.read_byte()
}
pub fn listen_rx_packet_recv_interrupt(&mut self) {
self.rx.listen_rx_packet_recv_interrupt()
}
pub fn unlisten_rx_packet_recv_interrupt(&mut self) {
self.rx.unlisten_rx_packet_recv_interrupt()
}
pub fn rx_packet_recv_interrupt_set(&mut self) -> bool {
self.rx.rx_packet_recv_interrupt_set()
}
pub fn reset_rx_packet_recv_interrupt(&mut self) {
self.rx.reset_rx_packet_recv_interrupt()
}
}
pub trait Instance: crate::private::Sealed {
fn register_block() -> &'static RegisterBlock;
fn disable_tx_interrupts() {
Self::register_block()
.int_ena()
.modify(|_, w| w.serial_in_empty().clear_bit());
Self::register_block()
.int_clr()
.write(|w| w.serial_in_empty().clear_bit_by_one());
}
fn disable_rx_interrupts() {
Self::register_block()
.int_ena()
.modify(|_, w| w.serial_out_recv_pkt().clear_bit());
Self::register_block()
.int_clr()
.write(|w| w.serial_out_recv_pkt().clear_bit_by_one());
}
}
impl Instance for USB_DEVICE {
#[inline(always)]
fn register_block() -> &'static RegisterBlock {
unsafe { &*USB_DEVICE::ptr() }
}
}
impl<M> core::fmt::Write for UsbSerialJtag<'_, M>
where
M: Mode,
{
fn write_str(&mut self, s: &str) -> core::fmt::Result {
core::fmt::Write::write_str(&mut self.tx, s)
}
}
impl<M> core::fmt::Write for UsbSerialJtagTx<'_, M>
where
M: Mode,
{
fn write_str(&mut self, s: &str) -> core::fmt::Result {
self.write_bytes(s.as_bytes())
.map_err(|_| core::fmt::Error)?;
Ok(())
}
}
impl<M> ufmt_write::uWrite for UsbSerialJtag<'_, M>
where
M: Mode,
{
type Error = Error;
#[inline]
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
ufmt_write::uWrite::write_str(&mut self.tx, s)
}
#[inline]
fn write_char(&mut self, ch: char) -> Result<(), Self::Error> {
ufmt_write::uWrite::write_char(&mut self.tx, ch)
}
}
impl<M> ufmt_write::uWrite for UsbSerialJtagTx<'_, M>
where
M: Mode,
{
type Error = Error;
#[inline]
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
self.write_bytes(s.as_bytes())?;
Ok(())
}
#[inline]
fn write_char(&mut self, ch: char) -> Result<(), Self::Error> {
let mut buffer = [0u8; 4];
self.write_bytes(ch.encode_utf8(&mut buffer).as_bytes())?;
Ok(())
}
}
impl<M> embedded_hal_02::serial::Read<u8> for UsbSerialJtag<'_, M>
where
M: Mode,
{
type Error = Error;
fn read(&mut self) -> nb::Result<u8, Self::Error> {
embedded_hal_02::serial::Read::read(&mut self.rx)
}
}
impl<M> embedded_hal_02::serial::Read<u8> for UsbSerialJtagRx<'_, M>
where
M: Mode,
{
type Error = Error;
fn read(&mut self) -> nb::Result<u8, Self::Error> {
self.read_byte()
}
}
impl<M> embedded_hal_02::serial::Write<u8> for UsbSerialJtag<'_, M>
where
M: Mode,
{
type Error = Error;
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
embedded_hal_02::serial::Write::write(&mut self.tx, word)
}
fn flush(&mut self) -> nb::Result<(), Self::Error> {
embedded_hal_02::serial::Write::flush(&mut self.tx)
}
}
impl<M> embedded_hal_02::serial::Write<u8> for UsbSerialJtagTx<'_, M>
where
M: Mode,
{
type Error = Error;
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
self.write_byte_nb(word)
}
fn flush(&mut self) -> nb::Result<(), Self::Error> {
self.flush_tx_nb()
}
}
impl<M> embedded_hal_nb::serial::ErrorType for UsbSerialJtag<'_, M>
where
M: Mode,
{
type Error = Error;
}
impl<M> embedded_hal_nb::serial::ErrorType for UsbSerialJtagTx<'_, M>
where
M: Mode,
{
type Error = Error;
}
impl<M> embedded_hal_nb::serial::ErrorType for UsbSerialJtagRx<'_, M>
where
M: Mode,
{
type Error = Error;
}
impl<M> embedded_hal_nb::serial::Read for UsbSerialJtag<'_, M>
where
M: Mode,
{
fn read(&mut self) -> nb::Result<u8, Self::Error> {
embedded_hal_nb::serial::Read::read(&mut self.rx)
}
}
impl<M> embedded_hal_nb::serial::Read for UsbSerialJtagRx<'_, M>
where
M: Mode,
{
fn read(&mut self) -> nb::Result<u8, Self::Error> {
self.read_byte()
}
}
impl<M> embedded_hal_nb::serial::Write for UsbSerialJtag<'_, M>
where
M: Mode,
{
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
embedded_hal_nb::serial::Write::write(&mut self.tx, word)
}
fn flush(&mut self) -> nb::Result<(), Self::Error> {
embedded_hal_nb::serial::Write::flush(&mut self.tx)
}
}
impl<M> embedded_hal_nb::serial::Write for UsbSerialJtagTx<'_, M>
where
M: Mode,
{
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
self.write_byte_nb(word)
}
fn flush(&mut self) -> nb::Result<(), Self::Error> {
self.flush_tx_nb()
}
}
impl<M> embedded_io::ErrorType for UsbSerialJtag<'_, M>
where
M: Mode,
{
type Error = Error;
}
impl<M> embedded_io::ErrorType for UsbSerialJtagTx<'_, M>
where
M: Mode,
{
type Error = Error;
}
impl<M> embedded_io::ErrorType for UsbSerialJtagRx<'_, M>
where
M: Mode,
{
type Error = Error;
}
impl<M> embedded_io::Read for UsbSerialJtag<'_, M>
where
M: Mode,
{
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
embedded_io::Read::read(&mut self.rx, buf)
}
}
impl<M> embedded_io::Read for UsbSerialJtagRx<'_, M>
where
M: Mode,
{
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
loop {
let count = self.drain_rx_fifo(buf);
if count > 0 {
return Ok(count);
}
}
}
}
impl<M> embedded_io::Write for UsbSerialJtag<'_, M>
where
M: Mode,
{
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
embedded_io::Write::write(&mut self.tx, buf)
}
fn flush(&mut self) -> Result<(), Self::Error> {
embedded_io::Write::flush(&mut self.tx)
}
}
impl<M> embedded_io::Write for UsbSerialJtagTx<'_, M>
where
M: Mode,
{
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.write_bytes(buf)?;
Ok(buf.len())
}
fn flush(&mut self) -> Result<(), Self::Error> {
self.flush_tx()
}
}
static WAKER_TX: AtomicWaker = AtomicWaker::new();
static WAKER_RX: AtomicWaker = AtomicWaker::new();
#[must_use = "futures do nothing unless you `.await` or poll them"]
struct UsbSerialJtagWriteFuture<'d> {
_peripheral: PeripheralRef<'d, USB_DEVICE>,
}
impl<'d> UsbSerialJtagWriteFuture<'d> {
fn new(_peripheral: impl Peripheral<P = USB_DEVICE> + 'd) -> Self {
crate::into_ref!(_peripheral);
USB_DEVICE::register_block()
.int_ena()
.modify(|_, w| w.serial_in_empty().set_bit());
Self { _peripheral }
}
fn event_bit_is_clear(&self) -> bool {
USB_DEVICE::register_block()
.int_ena()
.read()
.serial_in_empty()
.bit_is_clear()
}
}
impl core::future::Future for UsbSerialJtagWriteFuture<'_> {
type Output = ();
fn poll(
self: core::pin::Pin<&mut Self>,
cx: &mut core::task::Context<'_>,
) -> core::task::Poll<Self::Output> {
WAKER_TX.register(cx.waker());
if self.event_bit_is_clear() {
Poll::Ready(())
} else {
Poll::Pending
}
}
}
#[must_use = "futures do nothing unless you `.await` or poll them"]
struct UsbSerialJtagReadFuture<'d> {
_peripheral: PeripheralRef<'d, USB_DEVICE>,
}
impl<'d> UsbSerialJtagReadFuture<'d> {
fn new(_peripheral: impl Peripheral<P = USB_DEVICE> + 'd) -> Self {
crate::into_ref!(_peripheral);
USB_DEVICE::register_block()
.int_ena()
.modify(|_, w| w.serial_out_recv_pkt().set_bit());
Self { _peripheral }
}
fn event_bit_is_clear(&self) -> bool {
USB_DEVICE::register_block()
.int_ena()
.read()
.serial_out_recv_pkt()
.bit_is_clear()
}
}
impl core::future::Future for UsbSerialJtagReadFuture<'_> {
type Output = ();
fn poll(
self: core::pin::Pin<&mut Self>,
cx: &mut core::task::Context<'_>,
) -> core::task::Poll<Self::Output> {
WAKER_RX.register(cx.waker());
if self.event_bit_is_clear() {
Poll::Ready(())
} else {
Poll::Pending
}
}
}
impl<'d> UsbSerialJtag<'d, Async> {
pub fn into_blocking(self) -> UsbSerialJtag<'d, Blocking> {
crate::interrupt::disable(Cpu::current(), Interrupt::USB_DEVICE);
UsbSerialJtag {
rx: UsbSerialJtagRx {
peripheral: self.rx.peripheral,
phantom: PhantomData,
},
tx: UsbSerialJtagTx {
peripheral: self.tx.peripheral,
phantom: PhantomData,
},
}
}
}
impl UsbSerialJtagTx<'_, Async> {
async fn write_bytes_async(&mut self, words: &[u8]) -> Result<(), Error> {
let reg_block = USB_DEVICE::register_block();
for chunk in words.chunks(64) {
for byte in chunk {
reg_block
.ep1()
.write(|w| unsafe { w.rdwr_byte().bits(*byte) });
}
reg_block.ep1_conf().modify(|_, w| w.wr_done().set_bit());
UsbSerialJtagWriteFuture::new(self.peripheral.reborrow()).await;
}
Ok(())
}
async fn flush_tx_async(&mut self) -> Result<(), Error> {
if USB_DEVICE::register_block()
.jfifo_st()
.read()
.out_fifo_empty()
.bit_is_clear()
{
UsbSerialJtagWriteFuture::new(self.peripheral.reborrow()).await;
}
Ok(())
}
}
impl UsbSerialJtagRx<'_, Async> {
async fn read_bytes_async(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
if buf.is_empty() {
return Ok(0);
}
loop {
let read_bytes = self.drain_rx_fifo(buf);
if read_bytes > 0 {
return Ok(read_bytes);
}
UsbSerialJtagReadFuture::new(self.peripheral.reborrow()).await;
}
}
}
impl embedded_io_async::Write for UsbSerialJtag<'_, Async> {
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
embedded_io_async::Write::write(&mut self.tx, buf).await
}
async fn flush(&mut self) -> Result<(), Self::Error> {
embedded_io_async::Write::flush(&mut self.tx).await
}
}
impl embedded_io_async::Write for UsbSerialJtagTx<'_, Async> {
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.write_bytes_async(buf).await?;
Ok(buf.len())
}
async fn flush(&mut self) -> Result<(), Self::Error> {
self.flush_tx_async().await
}
}
impl embedded_io_async::Read for UsbSerialJtag<'_, Async> {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
embedded_io_async::Read::read(&mut self.rx, buf).await
}
}
impl embedded_io_async::Read for UsbSerialJtagRx<'_, Async> {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.read_bytes_async(buf).await
}
}
#[handler]
fn async_interrupt_handler() {
let usb = USB_DEVICE::register_block();
let interrupts = usb.int_st().read();
let tx = interrupts.serial_in_empty().bit_is_set();
let rx = interrupts.serial_out_recv_pkt().bit_is_set();
if tx {
usb.int_ena().modify(|_, w| w.serial_in_empty().clear_bit());
}
if rx {
usb.int_ena()
.modify(|_, w| w.serial_out_recv_pkt().clear_bit());
}
usb.int_clr().write(|w| {
w.serial_in_empty()
.clear_bit_by_one()
.serial_out_recv_pkt()
.clear_bit_by_one()
});
if rx {
WAKER_RX.wake();
}
if tx {
WAKER_TX.wake();
}
}