Merge branch 'embassy-rs:master' into master
This commit is contained in:
commit
ff6748a0d8
@ -617,6 +617,28 @@ mod eh02 {
|
|||||||
self.blocking_write_read(address, bytes, buffer)
|
self.blocking_write_read(address, bytes, buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Transactional for I2c<'d, T, M> {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn exec(
|
||||||
|
&mut self,
|
||||||
|
address: u8,
|
||||||
|
operations: &mut [embedded_hal_02::blocking::i2c::Operation<'_>],
|
||||||
|
) -> Result<(), Self::Error> {
|
||||||
|
Self::setup(address.into())?;
|
||||||
|
for i in 0..operations.len() {
|
||||||
|
let last = i == operations.len() - 1;
|
||||||
|
match &mut operations[i] {
|
||||||
|
embedded_hal_02::blocking::i2c::Operation::Read(buf) => {
|
||||||
|
self.read_blocking_internal(buf, false, last)?
|
||||||
|
}
|
||||||
|
embedded_hal_02::blocking::i2c::Operation::Write(buf) => self.write_blocking_internal(buf, last)?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable-traits")]
|
#[cfg(feature = "unstable-traits")]
|
||||||
|
178
embassy-stm32/src/ipcc.rs
Normal file
178
embassy-stm32/src/ipcc.rs
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
|
||||||
|
|
||||||
|
use crate::ipcc::sealed::Instance;
|
||||||
|
use crate::peripherals::IPCC;
|
||||||
|
use crate::rcc::sealed::RccPeripheral;
|
||||||
|
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[derive(Clone, Copy, Default)]
|
||||||
|
pub struct Config {
|
||||||
|
// TODO: add IPCC peripheral configuration, if any, here
|
||||||
|
// reserved for future use
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub enum IpccChannel {
|
||||||
|
Channel1 = 0,
|
||||||
|
Channel2 = 1,
|
||||||
|
Channel3 = 2,
|
||||||
|
Channel4 = 3,
|
||||||
|
Channel5 = 4,
|
||||||
|
Channel6 = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) mod sealed {
|
||||||
|
pub trait Instance: crate::rcc::RccPeripheral {
|
||||||
|
fn regs() -> crate::pac::ipcc::Ipcc;
|
||||||
|
fn set_cpu2(enabled: bool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Ipcc<'d> {
|
||||||
|
_peri: PeripheralRef<'d, IPCC>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> Ipcc<'d> {
|
||||||
|
pub fn new(peri: impl Peripheral<P = IPCC> + 'd, _config: Config) -> Self {
|
||||||
|
into_ref!(peri);
|
||||||
|
|
||||||
|
Self { _peri: peri }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(&mut self) {
|
||||||
|
IPCC::enable();
|
||||||
|
IPCC::reset();
|
||||||
|
IPCC::set_cpu2(true);
|
||||||
|
|
||||||
|
unsafe { _configure_pwr() };
|
||||||
|
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
regs.cpu(0).cr().modify(|w| {
|
||||||
|
w.set_rxoie(true);
|
||||||
|
w.set_txfie(true);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c1_set_rx_channel(&mut self, channel: IpccChannel, enabled: bool) {
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
// If bit is set to 1 then interrupt is disabled
|
||||||
|
unsafe { regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, !enabled)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c1_get_rx_channel(&self, channel: IpccChannel) -> bool {
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
// If bit is set to 1 then interrupt is disabled
|
||||||
|
unsafe { !regs.cpu(0).mr().read().chom(channel as usize) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c2_set_rx_channel(&mut self, channel: IpccChannel, enabled: bool) {
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
// If bit is set to 1 then interrupt is disabled
|
||||||
|
unsafe { regs.cpu(1).mr().modify(|w| w.set_chom(channel as usize, !enabled)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c2_get_rx_channel(&self, channel: IpccChannel) -> bool {
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
// If bit is set to 1 then interrupt is disabled
|
||||||
|
unsafe { !regs.cpu(1).mr().read().chom(channel as usize) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c1_set_tx_channel(&mut self, channel: IpccChannel, enabled: bool) {
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
// If bit is set to 1 then interrupt is disabled
|
||||||
|
unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c1_get_tx_channel(&self, channel: IpccChannel) -> bool {
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
// If bit is set to 1 then interrupt is disabled
|
||||||
|
unsafe { !regs.cpu(0).mr().read().chfm(channel as usize) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c2_set_tx_channel(&mut self, channel: IpccChannel, enabled: bool) {
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
// If bit is set to 1 then interrupt is disabled
|
||||||
|
unsafe { regs.cpu(1).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c2_get_tx_channel(&self, channel: IpccChannel) -> bool {
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
// If bit is set to 1 then interrupt is disabled
|
||||||
|
unsafe { !regs.cpu(1).mr().read().chfm(channel as usize) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// clears IPCC receive channel status for CPU1
|
||||||
|
pub fn c1_clear_flag_channel(&mut self, channel: IpccChannel) {
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// clears IPCC receive channel status for CPU2
|
||||||
|
pub fn c2_clear_flag_channel(&mut self, channel: IpccChannel) {
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
unsafe { regs.cpu(1).scr().write(|w| w.set_chc(channel as usize, true)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c1_set_flag_channel(&mut self, channel: IpccChannel) {
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
unsafe { regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c2_set_flag_channel(&mut self, channel: IpccChannel) {
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
unsafe { regs.cpu(1).scr().write(|w| w.set_chs(channel as usize, true)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c1_is_active_flag(&self, channel: IpccChannel) -> bool {
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
unsafe { regs.cpu(0).sr().read().chf(channel as usize) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c2_is_active_flag(&self, channel: IpccChannel) -> bool {
|
||||||
|
let regs = IPCC::regs();
|
||||||
|
|
||||||
|
unsafe { regs.cpu(1).sr().read().chf(channel as usize) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_tx_pending(&self, channel: IpccChannel) -> bool {
|
||||||
|
!self.c1_is_active_flag(channel) && self.c1_get_tx_channel(channel)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_rx_pending(&self, channel: IpccChannel) -> bool {
|
||||||
|
self.c2_is_active_flag(channel) && self.c1_get_rx_channel(channel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl sealed::Instance for crate::peripherals::IPCC {
|
||||||
|
fn regs() -> crate::pac::ipcc::Ipcc {
|
||||||
|
crate::pac::IPCC
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_cpu2(enabled: bool) {
|
||||||
|
unsafe { crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn _configure_pwr() {
|
||||||
|
let rcc = crate::pac::RCC;
|
||||||
|
|
||||||
|
// set RF wake-up clock = LSE
|
||||||
|
rcc.csr().modify(|w| w.set_rfwkpsel(0b01));
|
||||||
|
}
|
@ -44,6 +44,8 @@ pub mod i2c;
|
|||||||
#[cfg(crc)]
|
#[cfg(crc)]
|
||||||
pub mod crc;
|
pub mod crc;
|
||||||
pub mod flash;
|
pub mod flash;
|
||||||
|
#[cfg(stm32wb)]
|
||||||
|
pub mod ipcc;
|
||||||
pub mod pwm;
|
pub mod pwm;
|
||||||
#[cfg(quadspi)]
|
#[cfg(quadspi)]
|
||||||
pub mod qspi;
|
pub mod qspi;
|
||||||
|
@ -497,28 +497,24 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
if !enable_idle_line_detection {
|
if enable_idle_line_detection {
|
||||||
transfer.await;
|
// clear idle flag
|
||||||
|
let sr = sr(r).read();
|
||||||
|
// This read also clears the error and idle interrupt flags on v1.
|
||||||
|
rdr(r).read_volatile();
|
||||||
|
clear_interrupt_flags(r, sr);
|
||||||
|
|
||||||
return Ok(ReadCompletionEvent::DmaCompleted);
|
// enable idle interrupt
|
||||||
|
r.cr1().modify(|w| {
|
||||||
|
w.set_idleie(true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear idle flag
|
|
||||||
let sr = sr(r).read();
|
|
||||||
// This read also clears the error and idle interrupt flags on v1.
|
|
||||||
rdr(r).read_volatile();
|
|
||||||
clear_interrupt_flags(r, sr);
|
|
||||||
|
|
||||||
// enable idle interrupt
|
|
||||||
r.cr1().modify(|w| {
|
|
||||||
w.set_idleie(true);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
// future which completes when idle line is detected
|
// future which completes when idle line or error is detected
|
||||||
let idle = poll_fn(move |cx| {
|
let abort = poll_fn(move |cx| {
|
||||||
let s = T::state();
|
let s = T::state();
|
||||||
|
|
||||||
s.rx_waker.register(cx.waker());
|
s.rx_waker.register(cx.waker());
|
||||||
@ -554,7 +550,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if sr.idle() {
|
if enable_idle_line_detection && sr.idle() {
|
||||||
// Idle line detected
|
// Idle line detected
|
||||||
return Poll::Ready(Ok(()));
|
return Poll::Ready(Ok(()));
|
||||||
}
|
}
|
||||||
@ -565,7 +561,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||||||
// wait for the first of DMA request or idle line detected to completes
|
// wait for the first of DMA request or idle line detected to completes
|
||||||
// select consumes its arguments
|
// select consumes its arguments
|
||||||
// when transfer is dropped, it will stop the DMA request
|
// when transfer is dropped, it will stop the DMA request
|
||||||
let r = match select(transfer, idle).await {
|
let r = match select(transfer, abort).await {
|
||||||
// DMA transfer completed first
|
// DMA transfer completed first
|
||||||
Either::Left(((), _)) => Ok(ReadCompletionEvent::DmaCompleted),
|
Either::Left(((), _)) => Ok(ReadCompletionEvent::DmaCompleted),
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user