Skip to content

Commit 62be79e

Browse files
committed
Align I2C and PIO on rp2040 and rp2350
1 parent 463d755 commit 62be79e

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| {
@@ -699,10 +699,10 @@ impl<SM: ValidStateMachine, State> StateMachine<SM, State> {
699699

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

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

800800
// sideset_count is implicitly set to 0 when the set_base/set_count are written (rather
801801
// than modified)
@@ -1294,8 +1294,8 @@ impl<SM: ValidStateMachine> StateMachine<SM, Running> {
12941294
// Safety: all accesses to these registers are controlled by this instance
12951295
unsafe {
12961296
let sm = self.sm.sm();
1297-
let sm_pinctrl = &sm.sm_pinctrl();
1298-
let sm_instr = &sm.sm_instr();
1297+
let sm_pinctrl = sm.sm_pinctrl();
1298+
let sm_instr = sm.sm_instr();
12991299

13001300
// save exec_ctrl & make side_set optional
13011301
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,16 +15,27 @@ 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 {}
2123
impl Sealed for PIO1 {}
2224

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

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

7990
impl PIOExt for PIO0 {
91+
const RX_FIFO_DEPTH: usize = 4;
92+
const TX_FIFO_DEPTH: usize = 4;
8093
type PinFunction = FunctionPio0;
94+
fn ptr() -> *const RegisterBlock {
95+
PIO0::ptr()
96+
}
8197
fn id() -> usize {
8298
0
8399
}
84100
}
85101
impl PIOExt for PIO1 {
102+
const RX_FIFO_DEPTH: usize = 4;
103+
const TX_FIFO_DEPTH: usize = 4;
86104
type PinFunction = FunctionPio1;
105+
fn ptr() -> *const RegisterBlock {
106+
PIO1::ptr()
107+
}
87108
fn id() -> usize {
88109
1
89110
}
@@ -586,9 +607,9 @@ pub struct Running;
586607
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
587608
pub enum PioIRQ {
588609
#[allow(missing_docs)]
589-
Irq0,
610+
Irq0 = 0,
590611
#[allow(missing_docs)]
591-
Irq1,
612+
Irq1 = 1,
592613
}
593614
impl PioIRQ {
594615
const fn to_index(self) -> usize {
@@ -1392,6 +1413,32 @@ impl<SM: ValidStateMachine, RxSize: TransferSize> Rx<SM, RxSize> {
13921413
unsafe { self.block().fstat().read().rxfull().bits() & (1 << SM::id()) != 0 }
13931414
}
13941415

1416+
/// Reads the number of word in the fifo
1417+
pub fn fifo_level(&self) -> usize {
1418+
// Safety: read-only access without side-effect
1419+
let flevel = unsafe { self.block().flevel().read() };
1420+
(match SM::id() {
1421+
0 => flevel.rx0().bits(),
1422+
1 => flevel.rx1().bits(),
1423+
2 => flevel.rx2().bits(),
1424+
3 => flevel.rx3().bits(),
1425+
_ => unreachable!(),
1426+
}) as usize
1427+
}
1428+
1429+
/// Returns the FIFO depth.
1430+
pub fn fifo_depth(&self) -> usize {
1431+
// Safety: read-only access without side-effect
1432+
let block = unsafe { self.block() };
1433+
let join_rx = block.sm(SM::id()).sm_shiftctrl().read().fjoin_rx().bit();
1434+
let depth = block.dbg_cfginfo().read().fifo_depth().bits() as usize;
1435+
if join_rx {
1436+
depth * 2
1437+
} else {
1438+
depth
1439+
}
1440+
}
1441+
13951442
/// Enable RX FIFO not empty interrupt.
13961443
///
13971444
/// This interrupt is raised when the RX FIFO is not empty, i.e. one could read more data from it.
@@ -1510,7 +1557,7 @@ impl<SM: ValidStateMachine, TxSize: TransferSize> Tx<SM, TxSize> {
15101557
/// This is a value between 0 and 39. Each FIFO on each state machine on
15111558
/// each PIO has a unique value.
15121559
pub fn dreq_value(&self) -> u8 {
1513-
if self.block as usize == 0x5020_0000usize {
1560+
if self.block == PIO0::ptr() {
15141561
TREQ_SEL_A::PIO0_TX0 as u8 + (SM::id() as u8)
15151562
} else {
15161563
TREQ_SEL_A::PIO1_TX0 as u8 + (SM::id() as u8)
@@ -1600,6 +1647,32 @@ impl<SM: ValidStateMachine, TxSize: TransferSize> Tx<SM, TxSize> {
16001647
unsafe { self.block().fstat().read().txfull().bits() & (1 << SM::id()) != 0 }
16011648
}
16021649

1650+
/// Reads the number of word in the FIFO
1651+
pub fn fifo_level(&self) -> usize {
1652+
// Safety: read-only access without side-effect
1653+
let flevel = unsafe { self.block().flevel().read() };
1654+
(match SM::id() {
1655+
0 => flevel.tx0().bits(),
1656+
1 => flevel.tx1().bits(),
1657+
2 => flevel.tx2().bits(),
1658+
3 => flevel.tx3().bits(),
1659+
_ => unreachable!(),
1660+
}) as usize
1661+
}
1662+
1663+
/// Returns the FIFO depth.
1664+
pub fn fifo_depth(&self) -> usize {
1665+
// Safety: read-only access without side-effect
1666+
let block = unsafe { self.block() };
1667+
let join_tx = block.sm(SM::id()).sm_shiftctrl().read().fjoin_tx().bit();
1668+
let depth = block.dbg_cfginfo().read().fifo_depth().bits() as usize;
1669+
if join_tx {
1670+
depth * 2
1671+
} else {
1672+
depth
1673+
}
1674+
}
1675+
16031676
/// Enable TX FIFO not full interrupt.
16041677
///
16051678
/// 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)