Skip to content

Commit 8571a3e

Browse files
committed
Add non-blocking Write
1 parent 1baaffd commit 8571a3e

File tree

1 file changed

+66
-4
lines changed

1 file changed

+66
-4
lines changed

esp-hal-common/src/usb_serial_jtag.rs

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1+
use core::convert::Infallible;
2+
13
use crate::pac::{usb_device::RegisterBlock, USB_DEVICE};
24

35
pub struct UsbSerialJtag<T> {
46
usb_serial: T,
57
}
68

79
/// Custom USB serial error type
8-
#[derive(Debug)]
9-
pub enum Error {}
10+
type Error = Infallible;
1011

1112
impl<T> UsbSerialJtag<T>
1213
where
@@ -26,11 +27,11 @@ where
2627
self.usb_serial
2728
}
2829

30+
/// Write data to the serial output in chunks of up to 64 bytes
2931
pub fn write_bytes(&mut self, data: &[u8]) -> Result<(), Error> {
3032
let reg_block = self.usb_serial.register_block();
3133

32-
// TODO: 64 byte chunks max
33-
for chunk in data.chunks(32) {
34+
for chunk in data.chunks(64) {
3435
unsafe {
3536
for &b in chunk {
3637
reg_block.ep1.write(|w| w.rdwr_byte().bits(b.into()))
@@ -46,6 +47,52 @@ where
4647
Ok(())
4748
}
4849

50+
/// Write data to the serial output in a non-blocking manner
51+
/// Requires manual flushing (automatically flushed every 64 bytes)
52+
pub fn write_byte_nb(&mut self, word: u8) -> nb::Result<(), Error> {
53+
let reg_block = self.usb_serial.register_block();
54+
55+
if reg_block
56+
.ep1_conf
57+
.read()
58+
.serial_in_ep_data_free()
59+
.bit_is_set()
60+
{
61+
// the FIFO is not full
62+
63+
unsafe {
64+
reg_block.ep1.write(|w| w.rdwr_byte().bits(word.into()));
65+
}
66+
Ok(())
67+
} else {
68+
Err(nb::Error::WouldBlock)
69+
}
70+
}
71+
72+
/// Flush the output FIFO and block until it has been sent
73+
pub fn flush_tx(&mut self) -> Result<(), Error> {
74+
let reg_block = self.usb_serial.register_block();
75+
reg_block.ep1_conf.write(|w| w.wr_done().set_bit());
76+
77+
while reg_block.ep1_conf.read().bits() & 0b011 == 0b000 {
78+
// wait
79+
}
80+
81+
Ok(())
82+
}
83+
84+
/// Flush the output FIFO but don't block if it isn't ready immediately
85+
pub fn flush_tx_nb(&mut self) -> nb::Result<(), Error> {
86+
let reg_block = self.usb_serial.register_block();
87+
reg_block.ep1_conf.write(|w| w.wr_done().set_bit());
88+
89+
if reg_block.ep1_conf.read().bits() & 0b011 == 0b000 {
90+
Err(nb::Error::WouldBlock)
91+
} else {
92+
Ok(())
93+
}
94+
}
95+
4996
pub fn read_byte(&mut self) -> nb::Result<u8, Error> {
5097
let reg_block = self.usb_serial.register_block();
5198

@@ -165,3 +212,18 @@ where
165212
self.read_byte()
166213
}
167214
}
215+
216+
impl<T> embedded_hal::serial::Write<u8> for UsbSerialJtag<T>
217+
where
218+
T: Instance,
219+
{
220+
type Error = Error;
221+
222+
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
223+
self.write_byte_nb(word)
224+
}
225+
226+
fn flush(&mut self) -> nb::Result<(), Self::Error> {
227+
self.flush_tx_nb()
228+
}
229+
}

0 commit comments

Comments
 (0)