Skip to content

Commit 4fff5fb

Browse files
committed
Align I2C and PIO on rp2040 and rp2350
1 parent 3d2e138 commit 4fff5fb

File tree

4 files changed

+267
-22
lines changed

4 files changed

+267
-22
lines changed

rp2040-hal/src/pio.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,8 @@ impl<SM: ValidStateMachine, State> StateMachine<SM, State> {
665665
pub fn clear_fifos(&mut self) {
666666
// Safety: all accesses to these registers are controlled by this instance
667667
unsafe {
668-
let sm = &self.sm.sm();
669-
let sm_shiftctrl = &sm.sm_shiftctrl();
668+
let sm = self.sm.sm();
669+
let sm_shiftctrl = sm.sm_shiftctrl();
670670
let mut current = false;
671671
// Toggling the FIFO join state clears the fifo
672672
sm_shiftctrl.modify(|r, w| {
@@ -700,10 +700,10 @@ impl<SM: ValidStateMachine, State> StateMachine<SM, State> {
700700

701701
// Safety: all accesses to these registers are controlled by this instance
702702
unsafe {
703-
let sm = &self.sm.sm();
704-
let sm_pinctrl = &sm.sm_pinctrl();
705-
let sm_instr = &sm.sm_instr();
706-
let fstat = &self.sm.pio().fstat();
703+
let sm = self.sm.sm();
704+
let sm_pinctrl = sm.sm_pinctrl();
705+
let sm_instr = sm.sm_instr();
706+
let fstat = self.sm.pio().fstat();
707707

708708
let operands = if sm.sm_shiftctrl().read().autopull().bit_is_set() {
709709
OUT
@@ -792,9 +792,9 @@ impl<SM: ValidStateMachine> StateMachine<SM, Stopped> {
792792
// Safety: all accesses to these registers are controlled by this instance
793793
unsafe {
794794
let sm = self.sm.sm();
795-
let sm_pinctrl = &sm.sm_pinctrl();
796-
let sm_execctrl = &sm.sm_execctrl();
797-
let sm_instr = &sm.sm_instr();
795+
let sm_pinctrl = sm.sm_pinctrl();
796+
let sm_execctrl = sm.sm_execctrl();
797+
let sm_instr = sm.sm_instr();
798798

799799
// sideset_count is implicitly set to 0 when the set_base/set_count are written (rather
800800
// than modified)
@@ -1292,8 +1292,8 @@ impl<SM: ValidStateMachine> StateMachine<SM, Running> {
12921292
// Safety: all accesses to these registers are controlled by this instance
12931293
unsafe {
12941294
let sm = self.sm.sm();
1295-
let sm_pinctrl = &sm.sm_pinctrl();
1296-
let sm_instr = &sm.sm_instr();
1295+
let sm_pinctrl = sm.sm_pinctrl();
1296+
let sm_instr = sm.sm_instr();
12971297

12981298
// save exec_ctrl & make side_set optional
12991299
let mut saved_sideset_count = 0;

rp235x-hal/src/i2c/peripheral.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,10 @@ impl<T: Deref<Target = RegisterBlock>, PINS> Iterator for I2C<T, PINS, Periphera
210210
}
211211
}
212212
impl<T: Deref<Target = RegisterBlock>, PINS> I2C<T, PINS, Peripheral> {
213-
/// Returns the next i2c event if any.
214-
pub fn next_event(&mut self) -> Option<Event> {
215-
let stat = self.i2c.ic_raw_intr_stat().read();
216-
213+
fn internal_next_event(
214+
&mut self,
215+
stat: rp235x_pac::i2c0::ic_raw_intr_stat::R,
216+
) -> Option<Event> {
217217
match self.mode.state {
218218
State::Idle if stat.start_det().bit_is_set() => {
219219
self.i2c.ic_clr_start_det().read();
@@ -241,7 +241,7 @@ impl<T: Deref<Target = RegisterBlock>, PINS> I2C<T, PINS, Peripheral> {
241241
State::Read if stat.rd_req().bit_is_set() => Some(Event::TransferRead),
242242
State::Write if !self.rx_fifo_empty() => Some(Event::TransferWrite),
243243

244-
State::Read | State::Write if stat.restart_det().bit_is_set() => {
244+
State::Read | State::Write | State::Active if stat.restart_det().bit_is_set() => {
245245
self.i2c.ic_clr_restart_det().read();
246246
self.i2c.ic_clr_start_det().read();
247247
self.mode.state = State::Active;
@@ -258,6 +258,13 @@ impl<T: Deref<Target = RegisterBlock>, PINS> I2C<T, PINS, Peripheral> {
258258
_ => None,
259259
}
260260
}
261+
262+
/// Returns the next i2c event if any.
263+
pub fn next_event(&mut self) -> Option<Event> {
264+
let stat = self.i2c.ic_raw_intr_stat().read();
265+
266+
self.internal_next_event(stat)
267+
}
261268
}
262269

263270
macro_rules! impl_wakeable {
@@ -291,12 +298,13 @@ where
291298
{
292299
/// Asynchronously waits for an Event.
293300
pub async fn wait_next(&mut self) -> Event {
301+
let mut stat = self.i2c.ic_raw_intr_stat().read();
294302
loop {
295-
if let Some(evt) = self.next_event() {
303+
if let Some(evt) = self.internal_next_event(stat) {
296304
return evt;
297305
}
298306

299-
CancellablePollFn::new(
307+
stat = CancellablePollFn::new(
300308
self,
301309
|me| {
302310
let stat = me.i2c.ic_raw_intr_stat().read();
@@ -306,7 +314,7 @@ where
306314
|| stat.rd_req().bit_is_set()
307315
|| stat.rx_full().bit_is_set()
308316
{
309-
Poll::Ready(())
317+
Poll::Ready(stat)
310318
} else {
311319
Poll::Pending
312320
}

rp235x-hal/src/pio.rs

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use crate::{
1515
typelevel::Sealed,
1616
};
1717

18+
mod non_blocking;
19+
1820
const PIO_INSTRUCTION_COUNT: usize = 32;
1921

2022
impl Sealed for PIO0 {}
@@ -23,9 +25,18 @@ impl Sealed for PIO2 {}
2325

2426
/// PIO Instance
2527
pub trait PIOExt: Deref<Target = RegisterBlock> + SubsystemReset + Sized + Send + Sealed {
28+
/// RX FIFO depth
29+
const RX_FIFO_DEPTH: usize;
30+
31+
/// TX FIFO depth
32+
const TX_FIFO_DEPTH: usize;
33+
2634
/// Associated Pin Function.
2735
type PinFunction: Function;
2836

37+
/// Returns a pointer to the PIO’s Register Block
38+
fn ptr() -> *const RegisterBlock;
39+
2940
/// Create a new PIO wrapper and split the state machines into individual objects.
3041
#[allow(clippy::type_complexity)] // Required for symmetry with PIO::free().
3142
fn split(
@@ -78,13 +89,23 @@ pub trait PIOExt: Deref<Target = RegisterBlock> + SubsystemReset + Sized + Send
7889
}
7990

8091
impl PIOExt for PIO0 {
92+
const RX_FIFO_DEPTH: usize = 4;
93+
const TX_FIFO_DEPTH: usize = 4;
8194
type PinFunction = FunctionPio0;
95+
fn ptr() -> *const RegisterBlock {
96+
PIO0::ptr()
97+
}
8298
fn id() -> usize {
8399
0
84100
}
85101
}
86102
impl PIOExt for PIO1 {
103+
const RX_FIFO_DEPTH: usize = 4;
104+
const TX_FIFO_DEPTH: usize = 4;
87105
type PinFunction = FunctionPio1;
106+
fn ptr() -> *const RegisterBlock {
107+
PIO1::ptr()
108+
}
88109
fn id() -> usize {
89110
1
90111
}
@@ -601,9 +622,9 @@ pub struct Running;
601622
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
602623
pub enum PioIRQ {
603624
#[allow(missing_docs)]
604-
Irq0,
625+
Irq0 = 0,
605626
#[allow(missing_docs)]
606-
Irq1,
627+
Irq1 = 1,
607628
}
608629
impl PioIRQ {
609630
const fn to_index(self) -> usize {
@@ -1408,6 +1429,32 @@ impl<SM: ValidStateMachine, RxSize: TransferSize> Rx<SM, RxSize> {
14081429
unsafe { self.block().fstat().read().rxfull().bits() & (1 << SM::id()) != 0 }
14091430
}
14101431

1432+
/// Reads the number of word in the fifo
1433+
pub fn fifo_level(&self) -> usize {
1434+
// Safety: read-only access without side-effect
1435+
let flevel = unsafe { self.block().flevel().read() };
1436+
(match SM::id() {
1437+
0 => flevel.rx0().bits(),
1438+
1 => flevel.rx1().bits(),
1439+
2 => flevel.rx2().bits(),
1440+
3 => flevel.rx3().bits(),
1441+
_ => unreachable!(),
1442+
}) as usize
1443+
}
1444+
1445+
/// Returns the FIFO depth.
1446+
pub fn fifo_depth(&self) -> usize {
1447+
// Safety: read-only access without side-effect
1448+
let block = unsafe { self.block() };
1449+
let join_rx = block.sm(SM::id()).sm_shiftctrl().read().fjoin_rx().bit();
1450+
let depth = block.dbg_cfginfo().read().fifo_depth().bits() as usize;
1451+
if join_rx {
1452+
depth * 2
1453+
} else {
1454+
depth
1455+
}
1456+
}
1457+
14111458
/// Enable RX FIFO not empty interrupt.
14121459
///
14131460
/// This interrupt is raised when the RX FIFO is not empty, i.e. one could read more data from it.
@@ -1526,7 +1573,7 @@ impl<SM: ValidStateMachine, TxSize: TransferSize> Tx<SM, TxSize> {
15261573
/// This is a value between 0 and 39. Each FIFO on each state machine on
15271574
/// each PIO has a unique value.
15281575
pub fn dreq_value(&self) -> u8 {
1529-
if self.block as usize == 0x5020_0000usize {
1576+
if self.block == PIO0::ptr() {
15301577
TREQ_SEL_A::PIO0_TX0 as u8 + (SM::id() as u8)
15311578
} else if self.block as usize == 0x5030_0000usize {
15321579
TREQ_SEL_A::PIO1_TX0 as u8 + (SM::id() as u8)
@@ -1619,6 +1666,32 @@ impl<SM: ValidStateMachine, TxSize: TransferSize> Tx<SM, TxSize> {
16191666
unsafe { self.block().fstat().read().txfull().bits() & (1 << SM::id()) != 0 }
16201667
}
16211668

1669+
/// Reads the number of word in the FIFO
1670+
pub fn fifo_level(&self) -> usize {
1671+
// Safety: read-only access without side-effect
1672+
let flevel = unsafe { self.block().flevel().read() };
1673+
(match SM::id() {
1674+
0 => flevel.tx0().bits(),
1675+
1 => flevel.tx1().bits(),
1676+
2 => flevel.tx2().bits(),
1677+
3 => flevel.tx3().bits(),
1678+
_ => unreachable!(),
1679+
}) as usize
1680+
}
1681+
1682+
/// Returns the FIFO depth.
1683+
pub fn fifo_depth(&self) -> usize {
1684+
// Safety: read-only access without side-effect
1685+
let block = unsafe { self.block() };
1686+
let join_tx = block.sm(SM::id()).sm_shiftctrl().read().fjoin_tx().bit();
1687+
let depth = block.dbg_cfginfo().read().fifo_depth().bits() as usize;
1688+
if join_tx {
1689+
depth * 2
1690+
} else {
1691+
depth
1692+
}
1693+
}
1694+
16221695
/// Enable TX FIFO not full interrupt.
16231696
///
16241697
/// This interrupt is raised when the TX FIFO is not full, i.e. one could push more data to it.

0 commit comments

Comments
 (0)