USB: Use updated PeripheralMutex
This commit is contained in:
parent
a39dea4d98
commit
615bb33dcb
@ -69,6 +69,12 @@ impl<'a> RingBuffer<'a> {
|
|||||||
self.empty = self.start == self.end;
|
self.empty = self.start == self.end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.start = 0;
|
||||||
|
self.end = 0;
|
||||||
|
self.empty = true;
|
||||||
|
}
|
||||||
|
|
||||||
fn wrap(&self, n: usize) -> usize {
|
fn wrap(&self, n: usize) -> usize {
|
||||||
assert!(n <= self.buf.len());
|
assert!(n <= self.buf.len());
|
||||||
if n == self.buf.len() {
|
if n == self.buf.len() {
|
||||||
|
@ -9,7 +9,7 @@ use crate::pac::NVIC_PRIO_BITS;
|
|||||||
|
|
||||||
// Re-exports
|
// Re-exports
|
||||||
pub use cortex_m::interrupt::{CriticalSection, Mutex};
|
pub use cortex_m::interrupt::{CriticalSection, Mutex};
|
||||||
pub use embassy::interrupt::{declare, take, Interrupt};
|
pub use embassy::interrupt::{declare, take, Interrupt, InterruptExt};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
@ -12,7 +12,7 @@ use embassy::executor::{task, Executor};
|
|||||||
use embassy::io::{AsyncBufReadExt, AsyncWriteExt};
|
use embassy::io::{AsyncBufReadExt, AsyncWriteExt};
|
||||||
use embassy::time::{Duration, Timer};
|
use embassy::time::{Duration, Timer};
|
||||||
use embassy::util::Forever;
|
use embassy::util::Forever;
|
||||||
use embassy_stm32f4::interrupt::OwnedInterrupt;
|
use embassy_stm32f4::interrupt::InterruptExt;
|
||||||
use embassy_stm32f4::usb::Usb;
|
use embassy_stm32f4::usb::Usb;
|
||||||
use embassy_stm32f4::usb_serial::UsbSerial;
|
use embassy_stm32f4::usb_serial::UsbSerial;
|
||||||
use embassy_stm32f4::{interrupt, pac, rtc};
|
use embassy_stm32f4::{interrupt, pac, rtc};
|
||||||
|
@ -11,7 +11,7 @@ use defmt::panic;
|
|||||||
use embassy::executor::{task, Executor};
|
use embassy::executor::{task, Executor};
|
||||||
use embassy::io::{AsyncBufReadExt, AsyncWriteExt};
|
use embassy::io::{AsyncBufReadExt, AsyncWriteExt};
|
||||||
use embassy::util::Forever;
|
use embassy::util::Forever;
|
||||||
use embassy_stm32f4::interrupt::OwnedInterrupt;
|
use embassy_stm32f4::interrupt::InterruptExt;
|
||||||
use embassy_stm32f4::usb::Usb;
|
use embassy_stm32f4::usb::Usb;
|
||||||
use embassy_stm32f4::usb_serial::UsbSerial;
|
use embassy_stm32f4::usb_serial::UsbSerial;
|
||||||
use embassy_stm32f4::{interrupt, pac};
|
use embassy_stm32f4::{interrupt, pac};
|
||||||
|
@ -32,6 +32,8 @@ stm32f479 = ["stm32f4xx-hal/stm32f469", "embassy-stm32/stm32f479"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
embassy = { version = "0.1.0", path = "../embassy" }
|
embassy = { version = "0.1.0", path = "../embassy" }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" }
|
embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" }
|
||||||
|
embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
|
||||||
|
|
||||||
defmt = { version = "0.2.0", optional = true }
|
defmt = { version = "0.2.0", optional = true }
|
||||||
log = { version = "0.4.11", optional = true }
|
log = { version = "0.4.11", optional = true }
|
||||||
cortex-m-rt = "0.6.13"
|
cortex-m-rt = "0.6.13"
|
||||||
|
@ -318,7 +318,6 @@ pub mod rtc;
|
|||||||
pub mod serial;
|
pub mod serial;
|
||||||
pub mod usb;
|
pub mod usb;
|
||||||
pub mod usb_serial;
|
pub mod usb_serial;
|
||||||
pub mod util;
|
|
||||||
|
|
||||||
pub(crate) mod cdc_acm;
|
pub(crate) mod cdc_acm;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use usb_device::device::UsbDevice;
|
|||||||
|
|
||||||
use crate::interrupt;
|
use crate::interrupt;
|
||||||
use crate::usb_serial::{ReadInterface, UsbSerial, WriteInterface};
|
use crate::usb_serial::{ReadInterface, UsbSerial, WriteInterface};
|
||||||
use crate::util::peripheral::{PeripheralMutex, PeripheralState};
|
use embassy_extras::peripheral::{PeripheralMutex, PeripheralState};
|
||||||
|
|
||||||
pub struct State<'bus, B, T>
|
pub struct State<'bus, B, T>
|
||||||
where
|
where
|
||||||
@ -36,7 +36,7 @@ where
|
|||||||
pub fn new<S: IntoClassSet<B, T>>(
|
pub fn new<S: IntoClassSet<B, T>>(
|
||||||
device: UsbDevice<'bus, B>,
|
device: UsbDevice<'bus, B>,
|
||||||
class_set: S,
|
class_set: S,
|
||||||
irq: interrupt::OTG_FSInterrupt,
|
irq: interrupt::OTG_FS,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let state = State {
|
let state = State {
|
||||||
device,
|
device,
|
||||||
@ -54,7 +54,7 @@ where
|
|||||||
let mutex = unsafe { Pin::new_unchecked(&mut *mutex) };
|
let mutex = unsafe { Pin::new_unchecked(&mut *mutex) };
|
||||||
|
|
||||||
// Use inner to register the irq
|
// Use inner to register the irq
|
||||||
mutex.with(|_, _| {});
|
mutex.register_interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ where
|
|||||||
B: UsbBus,
|
B: UsbBus,
|
||||||
T: ClassSet<B>,
|
T: ClassSet<B>,
|
||||||
{
|
{
|
||||||
type Interrupt = interrupt::OTG_FSInterrupt;
|
type Interrupt = interrupt::OTG_FS;
|
||||||
fn on_interrupt(&mut self) {
|
fn on_interrupt(&mut self) {
|
||||||
self.classes.poll_all(&mut self.device);
|
self.classes.poll_all(&mut self.device);
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@ use usb_device::UsbError;
|
|||||||
|
|
||||||
use crate::cdc_acm::CdcAcmClass;
|
use crate::cdc_acm::CdcAcmClass;
|
||||||
use crate::usb::{ClassSet, SerialState, State};
|
use crate::usb::{ClassSet, SerialState, State};
|
||||||
use crate::util::peripheral::PeripheralMutex;
|
use embassy_extras::peripheral::PeripheralMutex;
|
||||||
use crate::util::ring_buffer::RingBuffer;
|
use embassy_extras::ring_buffer::RingBuffer;
|
||||||
|
|
||||||
pub struct ReadInterface<'a, 'bus, 'c, I, B, T>
|
pub struct ReadInterface<'a, 'bus, 'c, I, B, T>
|
||||||
where
|
where
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
pub mod peripheral;
|
|
||||||
pub mod ring_buffer;
|
|
||||||
|
|
||||||
/// Low power blocking wait loop using WFE/SEV.
|
|
||||||
pub fn low_power_wait_until(mut condition: impl FnMut() -> bool) {
|
|
||||||
while !condition() {
|
|
||||||
// WFE might "eat" an event that would have otherwise woken the executor.
|
|
||||||
cortex_m::asm::wfe();
|
|
||||||
}
|
|
||||||
// Retrigger an event to be transparent to the executor.
|
|
||||||
cortex_m::asm::sev();
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
use core::cell::UnsafeCell;
|
|
||||||
use core::marker::{PhantomData, PhantomPinned};
|
|
||||||
use core::pin::Pin;
|
|
||||||
use core::sync::atomic::{compiler_fence, Ordering};
|
|
||||||
|
|
||||||
use crate::interrupt::OwnedInterrupt;
|
|
||||||
|
|
||||||
pub trait PeripheralState {
|
|
||||||
type Interrupt: OwnedInterrupt;
|
|
||||||
fn on_interrupt(&mut self);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PeripheralMutex<S: PeripheralState> {
|
|
||||||
inner: Option<(UnsafeCell<S>, S::Interrupt)>,
|
|
||||||
_not_send: PhantomData<*mut ()>,
|
|
||||||
_pinned: PhantomPinned,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: PeripheralState> PeripheralMutex<S> {
|
|
||||||
pub fn new(state: S, irq: S::Interrupt) -> Self {
|
|
||||||
Self {
|
|
||||||
inner: Some((UnsafeCell::new(state), irq)),
|
|
||||||
_not_send: PhantomData,
|
|
||||||
_pinned: PhantomPinned,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with<R>(self: Pin<&mut Self>, f: impl FnOnce(&mut S, &mut S::Interrupt) -> R) -> R {
|
|
||||||
let this = unsafe { self.get_unchecked_mut() };
|
|
||||||
let (state, irq) = unwrap!(this.inner.as_mut());
|
|
||||||
|
|
||||||
irq.disable();
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
|
|
||||||
irq.set_handler(
|
|
||||||
|p| {
|
|
||||||
// Safety: it's OK to get a &mut to the state, since
|
|
||||||
// - We're in the IRQ, no one else can't preempt us
|
|
||||||
// - We can't have preempted a with() call because the irq is disabled during it.
|
|
||||||
let state = unsafe { &mut *(p as *mut S) };
|
|
||||||
state.on_interrupt();
|
|
||||||
},
|
|
||||||
state.get() as *mut (),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Safety: it's OK to get a &mut to the state, since the irq is disabled.
|
|
||||||
let state = unsafe { &mut *state.get() };
|
|
||||||
|
|
||||||
let r = f(state, irq);
|
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
irq.enable();
|
|
||||||
|
|
||||||
r
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_free(self: Pin<&mut Self>) -> Option<(S, S::Interrupt)> {
|
|
||||||
let this = unsafe { self.get_unchecked_mut() };
|
|
||||||
this.inner.take().map(|(state, irq)| {
|
|
||||||
irq.disable();
|
|
||||||
irq.remove_handler();
|
|
||||||
(state.into_inner(), irq)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn free(self: Pin<&mut Self>) -> (S, S::Interrupt) {
|
|
||||||
unwrap!(self.try_free())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: PeripheralState> Drop for PeripheralMutex<S> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if let Some((_state, irq)) = &mut self.inner {
|
|
||||||
irq.disable();
|
|
||||||
irq.remove_handler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
use crate::fmt::{assert, *};
|
|
||||||
|
|
||||||
pub struct RingBuffer<'a> {
|
|
||||||
buf: &'a mut [u8],
|
|
||||||
start: usize,
|
|
||||||
end: usize,
|
|
||||||
empty: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> RingBuffer<'a> {
|
|
||||||
pub fn new(buf: &'a mut [u8]) -> Self {
|
|
||||||
Self {
|
|
||||||
buf,
|
|
||||||
start: 0,
|
|
||||||
end: 0,
|
|
||||||
empty: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_buf(&mut self) -> &mut [u8] {
|
|
||||||
if self.start == self.end && !self.empty {
|
|
||||||
trace!(" ringbuf: push_buf empty");
|
|
||||||
return &mut self.buf[..0];
|
|
||||||
}
|
|
||||||
|
|
||||||
let n = if self.start <= self.end {
|
|
||||||
self.buf.len() - self.end
|
|
||||||
} else {
|
|
||||||
self.start - self.end
|
|
||||||
};
|
|
||||||
|
|
||||||
trace!(" ringbuf: push_buf {:?}..{:?}", self.end, self.end + n);
|
|
||||||
&mut self.buf[self.end..self.end + n]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, n: usize) {
|
|
||||||
trace!(" ringbuf: push {:?}", n);
|
|
||||||
if n == 0 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.end = self.wrap(self.end + n);
|
|
||||||
self.empty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pop_buf(&mut self) -> &mut [u8] {
|
|
||||||
if self.empty {
|
|
||||||
trace!(" ringbuf: pop_buf empty");
|
|
||||||
return &mut self.buf[..0];
|
|
||||||
}
|
|
||||||
|
|
||||||
let n = if self.end <= self.start {
|
|
||||||
self.buf.len() - self.start
|
|
||||||
} else {
|
|
||||||
self.end - self.start
|
|
||||||
};
|
|
||||||
|
|
||||||
trace!(" ringbuf: pop_buf {:?}..{:?}", self.start, self.start + n);
|
|
||||||
&mut self.buf[self.start..self.start + n]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pop(&mut self, n: usize) {
|
|
||||||
trace!(" ringbuf: pop {:?}", n);
|
|
||||||
if n == 0 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.start = self.wrap(self.start + n);
|
|
||||||
self.empty = self.start == self.end;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
|
||||||
self.start = 0;
|
|
||||||
self.end = 0;
|
|
||||||
self.empty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn wrap(&self, n: usize) -> usize {
|
|
||||||
assert!(n <= self.buf.len());
|
|
||||||
if n == self.buf.len() {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user