Skip to content

Commit 41e7be5

Browse files
committed
Add typestate-based control over the PIO RX buffer access
Fixes #935.
1 parent 38d28bd commit 41e7be5

File tree

3 files changed

+472
-73
lines changed

3 files changed

+472
-73
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
//! This example drives a LED matrix consisting of 8x8 LEDs with the following
2+
//! configuration:
3+
//!
4+
//! - LED anodes are wired to pins 4..=11, with appropriate resistors.
5+
//! - LED cathodes are wired to the outputs of a 74HC164 shift register,
6+
//! gated through a 2N7000 NFET transistor (this is important: if you do
7+
//! not use a transistor, you'll have to invert the sideset data bits
8+
//! in the PIO program (and you may fry your 74HC164)).
9+
//! - Pin 0 is the clock to the 74HC164, and Pin 1 is the value to be
10+
//! shifted into it.
11+
//!
12+
//! The display shown by the LEDs is controlled by writing bits into the RX
13+
//! buffer, which is configured as random-access memory instead of as a FIFO.
14+
#![no_std]
15+
#![no_main]
16+
17+
use rp235x_hal as hal;
18+
19+
use hal::gpio::FunctionPio0;
20+
use hal::pio::PIOExt;
21+
use hal::Sio;
22+
23+
use embedded_hal::delay::DelayNs;
24+
25+
// Ensure we halt the program on panic (if we don't mention this crate it won't
26+
// be linked)
27+
use panic_halt as _;
28+
29+
/// Tell the Boot ROM about our application
30+
#[link_section = ".start_block"]
31+
#[used]
32+
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
33+
34+
/// External high-speed crystal on the Raspberry Pi Pico 2 board is 12 MHz.
35+
/// Adjust if your board has a different frequency
36+
const XTAL_FREQ_HZ: u32 = 12_000_000u32;
37+
38+
/// Entry point to our bare-metal application.
39+
///
40+
/// The `#[hal::entry]` macro ensures the Cortex-M start-up code calls this function
41+
/// as soon as all global variables and the spinlock are initialised.
42+
#[hal::entry]
43+
fn main() -> ! {
44+
let mut pac = hal::pac::Peripherals::take().unwrap();
45+
46+
// Set up the watchdog driver - needed by the clock setup code
47+
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);
48+
49+
let clocks = hal::clocks::init_clocks_and_plls(
50+
XTAL_FREQ_HZ,
51+
pac.XOSC,
52+
pac.CLOCKS,
53+
pac.PLL_SYS,
54+
pac.PLL_USB,
55+
&mut pac.RESETS,
56+
&mut watchdog,
57+
)
58+
.unwrap();
59+
60+
let sio = Sio::new(pac.SIO);
61+
let pins = hal::gpio::Pins::new(
62+
pac.IO_BANK0,
63+
pac.PADS_BANK0,
64+
sio.gpio_bank0,
65+
&mut pac.RESETS,
66+
);
67+
68+
let mut timer = hal::Timer::new_timer0(pac.TIMER0, &mut pac.RESETS, &clocks);
69+
70+
let shift_clk = pins.gpio0.into_function::<FunctionPio0>();
71+
let shift_value = pins.gpio1.into_function::<FunctionPio0>();
72+
73+
let led0 = pins.gpio4.into_function::<FunctionPio0>();
74+
let led1 = pins.gpio5.into_function::<FunctionPio0>();
75+
let led2 = pins.gpio6.into_function::<FunctionPio0>();
76+
let led3 = pins.gpio7.into_function::<FunctionPio0>();
77+
let led4 = pins.gpio8.into_function::<FunctionPio0>();
78+
let led5 = pins.gpio9.into_function::<FunctionPio0>();
79+
let led6 = pins.gpio10.into_function::<FunctionPio0>();
80+
let led7 = pins.gpio11.into_function::<FunctionPio0>();
81+
82+
let program = pio::pio_asm!(
83+
".side_set 2",
84+
85+
".wrap_target",
86+
" mov osr, rxfifo[0] side 0b10",
87+
" out pins, 8 side 0b11",
88+
" nop side 0b00",
89+
" out pins, 8 side 0b01",
90+
" nop side 0b00",
91+
" out pins, 8 side 0b01",
92+
" nop side 0b00",
93+
" out pins, 8 side 0b01",
94+
" mov osr, rxfifo[1] side 0b00",
95+
" out pins, 8 side 0b01",
96+
" nop side 0b00",
97+
" out pins, 8 side 0b01",
98+
" nop side 0b00",
99+
" out pins, 8 side 0b01",
100+
" nop side 0b00",
101+
" out pins, 8 side 0b01",
102+
".wrap",
103+
);
104+
105+
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
106+
let installed = pio.install(&program.program).unwrap();
107+
let (mut sm, mut buffer, _) = hal::pio::PIOBuilder::from_installed_program(installed)
108+
.clock_divisor_fixed_point(4096, 0)
109+
.out_sticky(true)
110+
.out_shift_direction(hal::pio::ShiftDirection::Right)
111+
.with_rx_get()
112+
.side_set_pin_base(shift_clk.id().num)
113+
.out_pins(led0.id().num, 8)
114+
.build(sm0);
115+
sm.set_pindirs([
116+
(shift_clk.id().num, hal::pio::PinDir::Output),
117+
(shift_value.id().num, hal::pio::PinDir::Output),
118+
(led0.id().num, hal::pio::PinDir::Output),
119+
(led1.id().num, hal::pio::PinDir::Output),
120+
(led2.id().num, hal::pio::PinDir::Output),
121+
(led3.id().num, hal::pio::PinDir::Output),
122+
(led4.id().num, hal::pio::PinDir::Output),
123+
(led5.id().num, hal::pio::PinDir::Output),
124+
(led6.id().num, hal::pio::PinDir::Output),
125+
(led7.id().num, hal::pio::PinDir::Output),
126+
]);
127+
sm.start();
128+
129+
// PIO runs in background, independently from CPU
130+
loop {
131+
buffer.write_at(0, 0xaaaaaaaa);
132+
buffer.write_at(1, 0xaaaaaaaa);
133+
timer.delay_ms(500);
134+
buffer.write_at(0, 0x55555555);
135+
buffer.write_at(1, 0x55555555);
136+
timer.delay_ms(500);
137+
}
138+
}
139+
140+
/// Program metadata for `picotool info`
141+
#[link_section = ".bi_entries"]
142+
#[used]
143+
pub static PICOTOOL_ENTRIES: [hal::binary_info::EntryAddr; 5] = [
144+
hal::binary_info::rp_cargo_bin_name!(),
145+
hal::binary_info::rp_cargo_version!(),
146+
hal::binary_info::rp_program_description!(c"PIO Side-set Example"),
147+
hal::binary_info::rp_cargo_homepage_url!(),
148+
hal::binary_info::rp_program_build_attribute!(),
149+
];
150+
151+
// End of file

rp235x-hal-examples/src/bin/pio_putget.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use rp235x_hal as hal;
99

1010
use hal::gpio::{FunctionPio0, Pin};
11-
use hal::pio::Buffers;
1211
use hal::pio::PIOExt;
1312
use hal::Sio;
1413

@@ -75,7 +74,7 @@ fn main() -> ! {
7574
let installed = pio.install(&program.program).unwrap();
7675
let (mut sm, _, _) = hal::pio::PIOBuilder::from_installed_program(installed)
7776
.set_pins(led_pin_id, 1)
78-
.buffers(Buffers::RxPutGet)
77+
.with_rx_putget()
7978
.build(sm0);
8079
sm.set_pindirs([(led_pin_id, hal::pio::PinDir::Output)]);
8180
sm.start();

0 commit comments

Comments
 (0)