Skip to content

Commit cb04212

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

File tree

4 files changed

+305
-22
lines changed

4 files changed

+305
-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: 81 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,19 +89,34 @@ 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
}
91112
}
92113
impl PIOExt for PIO2 {
114+
const RX_FIFO_DEPTH: usize = 4;
115+
const TX_FIFO_DEPTH: usize = 4;
93116
type PinFunction = FunctionPio2;
117+
fn ptr() -> *const RegisterBlock {
118+
PIO1::ptr()
119+
}
94120
fn id() -> usize {
95121
2
96122
}
@@ -601,9 +627,9 @@ pub struct Running;
601627
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
602628
pub enum PioIRQ {
603629
#[allow(missing_docs)]
604-
Irq0,
630+
Irq0 = 0,
605631
#[allow(missing_docs)]
606-
Irq1,
632+
Irq1 = 1,
607633
}
608634
impl PioIRQ {
609635
const fn to_index(self) -> usize {
@@ -1408,6 +1434,32 @@ impl<SM: ValidStateMachine, RxSize: TransferSize> Rx<SM, RxSize> {
14081434
unsafe { self.block().fstat().read().rxfull().bits() & (1 << SM::id()) != 0 }
14091435
}
14101436

1437+
/// Reads the number of word in the fifo
1438+
pub fn fifo_level(&self) -> usize {
1439+
// Safety: read-only access without side-effect
1440+
let flevel = unsafe { self.block().flevel().read() };
1441+
(match SM::id() {
1442+
0 => flevel.rx0().bits(),
1443+
1 => flevel.rx1().bits(),
1444+
2 => flevel.rx2().bits(),
1445+
3 => flevel.rx3().bits(),
1446+
_ => unreachable!(),
1447+
}) as usize
1448+
}
1449+
1450+
/// Returns the FIFO depth.
1451+
pub fn fifo_depth(&self) -> usize {
1452+
// Safety: read-only access without side-effect
1453+
let block = unsafe { self.block() };
1454+
let join_rx = block.sm(SM::id()).sm_shiftctrl().read().fjoin_rx().bit();
1455+
let depth = block.dbg_cfginfo().read().fifo_depth().bits() as usize;
1456+
if join_rx {
1457+
depth * 2
1458+
} else {
1459+
depth
1460+
}
1461+
}
1462+
14111463
/// Enable RX FIFO not empty interrupt.
14121464
///
14131465
/// This interrupt is raised when the RX FIFO is not empty, i.e. one could read more data from it.
@@ -1526,7 +1578,7 @@ impl<SM: ValidStateMachine, TxSize: TransferSize> Tx<SM, TxSize> {
15261578
/// This is a value between 0 and 39. Each FIFO on each state machine on
15271579
/// each PIO has a unique value.
15281580
pub fn dreq_value(&self) -> u8 {
1529-
if self.block as usize == 0x5020_0000usize {
1581+
if self.block == PIO0::ptr() {
15301582
TREQ_SEL_A::PIO0_TX0 as u8 + (SM::id() as u8)
15311583
} else if self.block as usize == 0x5030_0000usize {
15321584
TREQ_SEL_A::PIO1_TX0 as u8 + (SM::id() as u8)
@@ -1619,6 +1671,32 @@ impl<SM: ValidStateMachine, TxSize: TransferSize> Tx<SM, TxSize> {
16191671
unsafe { self.block().fstat().read().txfull().bits() & (1 << SM::id()) != 0 }
16201672
}
16211673

1674+
/// Reads the number of word in the FIFO
1675+
pub fn fifo_level(&self) -> usize {
1676+
// Safety: read-only access without side-effect
1677+
let flevel = unsafe { self.block().flevel().read() };
1678+
(match SM::id() {
1679+
0 => flevel.tx0().bits(),
1680+
1 => flevel.tx1().bits(),
1681+
2 => flevel.tx2().bits(),
1682+
3 => flevel.tx3().bits(),
1683+
_ => unreachable!(),
1684+
}) as usize
1685+
}
1686+
1687+
/// Returns the FIFO depth.
1688+
pub fn fifo_depth(&self) -> usize {
1689+
// Safety: read-only access without side-effect
1690+
let block = unsafe { self.block() };
1691+
let join_tx = block.sm(SM::id()).sm_shiftctrl().read().fjoin_tx().bit();
1692+
let depth = block.dbg_cfginfo().read().fifo_depth().bits() as usize;
1693+
if join_tx {
1694+
depth * 2
1695+
} else {
1696+
depth
1697+
}
1698+
}
1699+
16221700
/// Enable TX FIFO not full interrupt.
16231701
///
16241702
/// 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)