Compare commits
7 Commits
8416bd0fa4
...
c5788c5b2e
Author | SHA1 | Date | |
---|---|---|---|
|
c5788c5b2e | ||
|
e27c5e7803 | ||
|
5b3cce5ea5 | ||
|
685ed323f7 | ||
|
7c3fcdabcc | ||
|
b1dd7eea9d | ||
|
18a3368565 |
45
src/lib.rs
45
src/lib.rs
|
@ -133,24 +133,24 @@ impl<const L: usize> UsbBus for UsbDevice<L> {
|
|||
|
||||
fn force_reset(&self) -> UsbResult<()> {
|
||||
free(|cs| {
|
||||
let usbcon = &self.usb.borrow(cs).usbcon;
|
||||
usbcon.modify(|_, w| w.usbe().set_bit());
|
||||
self.usb.borrow(cs).usbcon.modify(|_, w| w.usbe().set_bit());
|
||||
});
|
||||
|
||||
delay_cycles(ONE_MS_16_MGHZ);
|
||||
|
||||
free(|cs| {
|
||||
let usbcon = &self.usb.borrow(cs).usbcon;
|
||||
usbcon.modify(|_, w| w.usbe().set_bit());
|
||||
self.usb.borrow(cs).usbcon.modify(|_, w| w.usbe().set_bit());
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_stalled(&self, ep_addr: EndpointAddress) -> bool {
|
||||
free(|cs| match self.select_endpoint(cs, ep_addr.index()) {
|
||||
Ok(_) => self.usb.borrow(cs).ueconx.read().stallrq().bit_is_set(),
|
||||
Err(_) => false,
|
||||
free(|cs| {
|
||||
if self.select_endpoint(cs, ep_addr.index()).is_ok() {
|
||||
return self.usb.borrow(cs).ueconx.read().stallrq().bit_is_set();
|
||||
}
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,7 @@ impl<const L: usize> UsbBus for UsbDevice<L> {
|
|||
|
||||
if usbint.vbusti().bit_is_set() {
|
||||
usb.usbint
|
||||
.write(|w| unsafe { w.bits(0x01) }.vbusti().clear_bit());
|
||||
.write(|w| w.clear_interrupts().vbusti().clear_bit());
|
||||
if usb.usbsta.read().vbus().bit_is_set() {
|
||||
return PollResult::Resume;
|
||||
} else {
|
||||
|
@ -183,8 +183,7 @@ impl<const L: usize> UsbBus for UsbDevice<L> {
|
|||
}
|
||||
|
||||
if udint.sofi().bit_is_set() {
|
||||
usb.udint
|
||||
.write(|w| unsafe { w.bits(0x7d) }.sofi().clear_bit());
|
||||
usb.udint.write(|w| w.clear_interrupts().sofi().clear_bit());
|
||||
}
|
||||
|
||||
if usb.usbcon.read().frzclk().bit_is_clear() {
|
||||
|
@ -226,8 +225,8 @@ impl<const L: usize> UsbBus for UsbDevice<L> {
|
|||
free(|cs| {
|
||||
let usb = self.usb.borrow(cs);
|
||||
|
||||
if let Err(error) = self.select_endpoint(cs, ep_addr.index()) {
|
||||
Err(error)
|
||||
if let Err(usb_error) = self.select_endpoint(cs, ep_addr.index()) {
|
||||
Err(usb_error)
|
||||
} else {
|
||||
let ep = &self.ep_table[ep_addr.index()];
|
||||
|
||||
|
@ -248,7 +247,7 @@ impl<const L: usize> UsbBus for UsbDevice<L> {
|
|||
}
|
||||
|
||||
usb.ueintx.write(|w| {
|
||||
unsafe { w.bits(0xdf) }
|
||||
w.clear_interrupts()
|
||||
.rxouti()
|
||||
.clear_bit()
|
||||
.rxstpi()
|
||||
|
@ -261,14 +260,14 @@ impl<const L: usize> UsbBus for UsbDevice<L> {
|
|||
return Err(UsbError::WouldBlock);
|
||||
}
|
||||
usb.ueintx
|
||||
.write(|w| unsafe { w.bits(0xdf) }.rxouti().clear_bit());
|
||||
.write(|w| w.clear_interrupts().rxouti().clear_bit());
|
||||
|
||||
let mut bytes_read = 0;
|
||||
for slot in buf {
|
||||
for data in buf {
|
||||
if usb.ueintx.read().rwal().bit_is_clear() {
|
||||
break;
|
||||
}
|
||||
*slot = usb.uedatx.read().bits();
|
||||
*data = usb.uedatx.read().bits();
|
||||
bytes_read += 1;
|
||||
}
|
||||
|
||||
|
@ -277,7 +276,7 @@ impl<const L: usize> UsbBus for UsbDevice<L> {
|
|||
}
|
||||
|
||||
usb.ueintx
|
||||
.write(|w| unsafe { w.bits(0xdf) }.fifocon().clear_bit());
|
||||
.write(|w| w.clear_interrupts().fifocon().clear_bit());
|
||||
Ok(bytes_read)
|
||||
}
|
||||
}
|
||||
|
@ -297,7 +296,7 @@ impl<const L: usize> UsbBus for UsbDevice<L> {
|
|||
// Clear resume informations. //
|
||||
|
||||
usb.udint.write(|w| {
|
||||
unsafe { w.bits(0x7d) }
|
||||
w.clear_interrupts()
|
||||
.wakeupi()
|
||||
.clear_bit()
|
||||
.suspi()
|
||||
|
@ -325,7 +324,7 @@ impl<const L: usize> UsbBus for UsbDevice<L> {
|
|||
usb.usbcon.modify(|_, w| w.frzclk().clear_bit());
|
||||
|
||||
usb.udint.write(|w| {
|
||||
unsafe { w.bits(0x7d) }
|
||||
w.clear_interrupts()
|
||||
.wakeupi()
|
||||
.clear_bit()
|
||||
.suspi()
|
||||
|
@ -369,7 +368,7 @@ impl<const L: usize> UsbBus for UsbDevice<L> {
|
|||
let (usb, pll) = (self.usb.borrow(cs), self.pll.borrow(cs));
|
||||
|
||||
usb.udint.write(|w| {
|
||||
unsafe { w.bits(0x7d) }
|
||||
w.clear_interrupts()
|
||||
.wakeupi()
|
||||
.clear_bit()
|
||||
.suspi()
|
||||
|
@ -416,13 +415,13 @@ impl<const L: usize> UsbBus for UsbDevice<L> {
|
|||
}
|
||||
|
||||
usb.ueintx
|
||||
.write(|w| unsafe { w.bits(0xdf) }.txini().clear_bit());
|
||||
.write(|w| w.clear_interrupts().txini().clear_bit());
|
||||
} else {
|
||||
if usb.ueintx.read().txini().bit_is_clear() {
|
||||
return Err(UsbError::WouldBlock);
|
||||
}
|
||||
usb.ueintx.write(|w| {
|
||||
unsafe { w.bits(0xdf) }
|
||||
w.clear_interrupts()
|
||||
.txini()
|
||||
.clear_bit()
|
||||
.rxouti()
|
||||
|
@ -438,7 +437,7 @@ impl<const L: usize> UsbBus for UsbDevice<L> {
|
|||
}
|
||||
|
||||
usb.ueintx.write(|w| {
|
||||
unsafe { w.bits(0xdf) }
|
||||
w.clear_interrupts()
|
||||
.rxouti()
|
||||
.clear_bit()
|
||||
.fifocon()
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use core::cell::Cell;
|
||||
|
||||
use avr_device::{
|
||||
atmega32u4::usb_device::{
|
||||
udint::W as UDINTWriter, ueintx::W as UEINTXWriter, usbint::W as USBINTWriter,
|
||||
},
|
||||
atmega32u4::{PLL, USB_DEVICE},
|
||||
interrupt::{CriticalSection, Mutex},
|
||||
};
|
||||
|
@ -81,6 +84,36 @@ pub(crate) const DPRAM_SIZE: u16 = 832;
|
|||
pub(crate) const ENDPOINTS_ALLOC_LAYOUT: [u16; MAX_ENDPOINTS] = [64, 256, 64, 64, 64, 64, 64];
|
||||
pub(crate) const ONE_MS_16_MGHZ: u32 = 16000;
|
||||
|
||||
const UDINT_BYTE: u8 = 0x7d;
|
||||
const USBINT_BYTE: u8 = 0x01;
|
||||
const UEINTX_BYTE: u8 = 0xdf;
|
||||
const UENUM_MASK: u8 = 0b111;
|
||||
|
||||
pub(crate) trait InterruptCleaner {
|
||||
fn clear_interrupts(&mut self) -> &mut Self;
|
||||
}
|
||||
|
||||
impl InterruptCleaner for UDINTWriter {
|
||||
#[inline]
|
||||
fn clear_interrupts(&mut self) -> &mut Self {
|
||||
unsafe { self.bits(UDINT_BYTE) }
|
||||
}
|
||||
}
|
||||
|
||||
impl InterruptCleaner for USBINTWriter {
|
||||
#[inline]
|
||||
fn clear_interrupts(&mut self) -> &mut Self {
|
||||
unsafe { self.bits(USBINT_BYTE) }
|
||||
}
|
||||
}
|
||||
|
||||
impl InterruptCleaner for UEINTXWriter {
|
||||
#[inline]
|
||||
fn clear_interrupts(&mut self) -> &mut Self {
|
||||
unsafe { self.bits(UEINTX_BYTE) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<const L: usize> UsbDevice<L> {
|
||||
#[inline]
|
||||
pub(crate) fn get_size(&self, cs: CriticalSection<'_>) -> usize {
|
||||
|
@ -114,9 +147,8 @@ impl<const L: usize> UsbDevice<L> {
|
|||
endpoint_index: usize,
|
||||
) -> Result<(), UsbError> {
|
||||
let usb = self.usb.borrow(cs);
|
||||
let endpoint_index = endpoint_index as u8;
|
||||
|
||||
if endpoint_index >= 7 {
|
||||
if endpoint_index >= MAX_ENDPOINTS {
|
||||
return Err(UsbError::InvalidEndpoint);
|
||||
}
|
||||
|
||||
|
@ -124,9 +156,9 @@ impl<const L: usize> UsbDevice<L> {
|
|||
return Err(UsbError::InvalidState);
|
||||
}
|
||||
|
||||
usb.uenum.write(|w| w.bits(endpoint_index));
|
||||
usb.uenum.write(|w| w.bits(endpoint_index as u8));
|
||||
|
||||
if usb.uenum.read().bits() & 7 /* 0b111 */ != endpoint_index {
|
||||
if usb.uenum.read().bits() & UENUM_MASK != endpoint_index as u8 {
|
||||
return Err(UsbError::InvalidEndpoint);
|
||||
}
|
||||
|
||||
|
@ -141,41 +173,42 @@ impl<const L: usize> UsbDevice<L> {
|
|||
let usb = self.usb.borrow(cs);
|
||||
let current_endpoint = self.ep_table[endpoint_index];
|
||||
|
||||
match self.select_endpoint(cs, endpoint_index) {
|
||||
Ok(_) => {
|
||||
// Enable endpoint. //
|
||||
let select_endpoint_result = self.select_endpoint(cs, endpoint_index);
|
||||
|
||||
usb.ueconx.modify(|_, w| w.epen().set_bit());
|
||||
usb.uecfg1x.modify(|_, w| w.alloc().clear_bit());
|
||||
if select_endpoint_result.is_err() {
|
||||
select_endpoint_result
|
||||
} else {
|
||||
// Enable endpoint. //
|
||||
|
||||
// Set markered endpoint parameters to uecfg0x/1x register. //
|
||||
usb.ueconx.modify(|_, w| w.epen().set_bit());
|
||||
usb.uecfg1x.modify(|_, w| w.alloc().clear_bit());
|
||||
|
||||
usb.uecfg0x.modify(|_, w| {
|
||||
w.epdir()
|
||||
.bit(current_endpoint.ep_dir)
|
||||
.eptype()
|
||||
.bits(current_endpoint.ep_type)
|
||||
});
|
||||
// Set markered endpoint parameters to uecfg0x/1x register. //
|
||||
|
||||
usb.uecfg1x.modify(|_, w| {
|
||||
w.epbk()
|
||||
.bits(0)
|
||||
.epsize()
|
||||
.bits(current_endpoint.size)
|
||||
.alloc()
|
||||
.set_bit()
|
||||
});
|
||||
usb.uecfg0x.modify(|_, w| {
|
||||
w.epdir()
|
||||
.bit(current_endpoint.ep_dir)
|
||||
.eptype()
|
||||
.bits(current_endpoint.ep_type)
|
||||
});
|
||||
|
||||
if usb.uesta0x.read().cfgok().bit_is_clear() {
|
||||
Err(UsbError::EndpointMemoryOverflow)
|
||||
} else {
|
||||
usb.ueienx
|
||||
.modify(|_, w| w.rxoute().set_bit().rxstpe().set_bit());
|
||||
usb.uecfg1x.modify(|_, w| {
|
||||
w.epbk()
|
||||
.bits(0)
|
||||
.epsize()
|
||||
.bits(current_endpoint.size)
|
||||
.alloc()
|
||||
.set_bit()
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
if usb.uesta0x.read().cfgok().bit_is_clear() {
|
||||
Err(UsbError::EndpointMemoryOverflow)
|
||||
} else {
|
||||
usb.ueienx
|
||||
.modify(|_, w| w.rxoute().set_bit().rxstpe().set_bit());
|
||||
|
||||
select_endpoint_result
|
||||
}
|
||||
Err(exception) => Err(exception),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue