diff options
| author | pennae <[email protected]> | 2023-05-06 11:36:07 +0200 |
|---|---|---|
| committer | pennae <[email protected]> | 2023-05-06 17:23:41 +0200 |
| commit | 8e4d65e163bd484efc4fb31d20b14e6ac4a88de7 (patch) | |
| tree | 0d1623f5b7711993ee549041881601193e782984 /examples | |
| parent | 2873cb93ee3111d984c35287ea9d98f1218d1024 (diff) | |
rp/pio: configure state machines with Config struct
the many individual sets aren't very efficient, and almost no checks
were done to ensure that the configuration written to the hardware was
actually valid. this adresses both of these.
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/rp/Cargo.toml | 2 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_async.rs | 37 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_dma.rs | 27 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_hd44780.rs | 42 | ||||
| -rw-r--r-- | examples/rp/src/bin/ws2812-pio.rs | 39 |
5 files changed, 83 insertions, 64 deletions
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 57f6f5c67..d2829df99 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml | |||
| @@ -22,6 +22,8 @@ lorawan = { version = "0.7.3", default-features = false, features = ["default-cr | |||
| 22 | 22 | ||
| 23 | defmt = "0.3" | 23 | defmt = "0.3" |
| 24 | defmt-rtt = "0.4" | 24 | defmt-rtt = "0.4" |
| 25 | fixed = "1.23.1" | ||
| 26 | fixed-macro = "1.2" | ||
| 25 | 27 | ||
| 26 | #cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | 28 | #cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } |
| 27 | cortex-m = { version = "0.7.6", features = ["inline-asm"] } | 29 | cortex-m = { version = "0.7.6", features = ["inline-asm"] } |
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 9f47c2316..12484e882 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs | |||
| @@ -2,10 +2,13 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 4 | use defmt::info; | 4 | use defmt::info; |
| 5 | use embassy_embedded_hal::SetConfig; | ||
| 5 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 6 | use embassy_rp::peripherals::PIO0; | 7 | use embassy_rp::peripherals::PIO0; |
| 7 | use embassy_rp::pio::{Common, Irq, Pio, PioPin, ShiftDirection, StateMachine}; | 8 | use embassy_rp::pio::{Common, Config, Irq, Pio, PioPin, ShiftDirection, StateMachine}; |
| 8 | use embassy_rp::relocate::RelocatedProgram; | 9 | use embassy_rp::relocate::RelocatedProgram; |
| 10 | use fixed::traits::ToFixed; | ||
| 11 | use fixed_macro::types::U56F8; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 13 | ||
| 11 | fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 0>, pin: impl PioPin) { | 14 | fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 0>, pin: impl PioPin) { |
| @@ -21,15 +24,14 @@ fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, | |||
| 21 | ); | 24 | ); |
| 22 | 25 | ||
| 23 | let relocated = RelocatedProgram::new(&prg.program); | 26 | let relocated = RelocatedProgram::new(&prg.program); |
| 24 | sm.use_program(&pio.load_program(&relocated), &[]); | 27 | let mut cfg = Config::default(); |
| 28 | cfg.use_program(&pio.load_program(&relocated), &[]); | ||
| 25 | let out_pin = pio.make_pio_pin(pin); | 29 | let out_pin = pio.make_pio_pin(pin); |
| 26 | let pio_pins = [&out_pin]; | 30 | cfg.set_out_pins(&[&out_pin]); |
| 27 | sm.set_out_pins(&pio_pins); | 31 | cfg.set_set_pins(&[&out_pin]); |
| 28 | sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32); | 32 | cfg.clock_divider = (U56F8!(125_000_000) / 20 / 200).to_fixed(); |
| 29 | sm.set_set_range(0, 1); | 33 | cfg.shift_out.auto_fill = true; |
| 30 | 34 | sm.set_config(&cfg); | |
| 31 | sm.set_autopull(true); | ||
| 32 | sm.set_out_shift_dir(ShiftDirection::Left); | ||
| 33 | } | 35 | } |
| 34 | 36 | ||
| 35 | #[embassy_executor::task] | 37 | #[embassy_executor::task] |
| @@ -51,11 +53,12 @@ fn setup_pio_task_sm1<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, | |||
| 51 | let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); | 53 | let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); |
| 52 | 54 | ||
| 53 | let relocated = RelocatedProgram::new(&prg.program); | 55 | let relocated = RelocatedProgram::new(&prg.program); |
| 54 | sm.use_program(&pio.load_program(&relocated), &[]); | 56 | let mut cfg = Config::default(); |
| 55 | sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); | 57 | cfg.use_program(&pio.load_program(&relocated), &[]); |
| 56 | sm.set_set_range(0, 0); | 58 | cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed(); |
| 57 | sm.set_autopush(true); | 59 | cfg.shift_in.auto_fill = true; |
| 58 | sm.set_in_shift_dir(ShiftDirection::Right); | 60 | cfg.shift_in.direction = ShiftDirection::Right; |
| 61 | sm.set_config(&cfg); | ||
| 59 | } | 62 | } |
| 60 | 63 | ||
| 61 | #[embassy_executor::task] | 64 | #[embassy_executor::task] |
| @@ -81,8 +84,10 @@ fn setup_pio_task_sm2<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, | |||
| 81 | ".wrap", | 84 | ".wrap", |
| 82 | ); | 85 | ); |
| 83 | let relocated = RelocatedProgram::new(&prg.program); | 86 | let relocated = RelocatedProgram::new(&prg.program); |
| 84 | sm.use_program(&pio.load_program(&relocated), &[]); | 87 | let mut cfg = Config::default(); |
| 85 | sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); | 88 | cfg.use_program(&pio.load_program(&relocated), &[]); |
| 89 | cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed(); | ||
| 90 | sm.set_config(&cfg); | ||
| 86 | } | 91 | } |
| 87 | 92 | ||
| 88 | #[embassy_executor::task] | 93 | #[embassy_executor::task] |
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 1c4e127c7..7f85288bf 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs | |||
| @@ -2,11 +2,14 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 4 | use defmt::info; | 4 | use defmt::info; |
| 5 | use embassy_embedded_hal::SetConfig; | ||
| 5 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 7 | use embassy_futures::join::join; |
| 7 | use embassy_rp::pio::{Pio, ShiftDirection}; | 8 | use embassy_rp::pio::{Config, Pio, ShiftConfig, ShiftDirection}; |
| 8 | use embassy_rp::relocate::RelocatedProgram; | 9 | use embassy_rp::relocate::RelocatedProgram; |
| 9 | use embassy_rp::Peripheral; | 10 | use embassy_rp::Peripheral; |
| 11 | use fixed::traits::ToFixed; | ||
| 12 | use fixed_macro::types::U56F8; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 14 | ||
| 12 | fn swap_nibbles(v: u32) -> u32 { | 15 | fn swap_nibbles(v: u32) -> u32 { |
| @@ -38,15 +41,21 @@ async fn main(_spawner: Spawner) { | |||
| 38 | ); | 41 | ); |
| 39 | 42 | ||
| 40 | let relocated = RelocatedProgram::new(&prg.program); | 43 | let relocated = RelocatedProgram::new(&prg.program); |
| 41 | sm.use_program(&common.load_program(&relocated), &[]); | 44 | let mut cfg = Config::default(); |
| 42 | sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); | 45 | cfg.use_program(&common.load_program(&relocated), &[]); |
| 43 | sm.set_autopull(true); | 46 | cfg.clock_divider = (U56F8!(125_000_000) / U56F8!(10_000)).to_fixed(); |
| 44 | sm.set_autopush(true); | 47 | cfg.shift_in = ShiftConfig { |
| 45 | sm.set_pull_threshold(32); | 48 | auto_fill: true, |
| 46 | sm.set_push_threshold(32); | 49 | threshold: 32, |
| 47 | sm.set_out_shift_dir(ShiftDirection::Right); | 50 | direction: ShiftDirection::Left, |
| 48 | sm.set_in_shift_dir(ShiftDirection::Left); | 51 | }; |
| 52 | cfg.shift_out = ShiftConfig { | ||
| 53 | auto_fill: true, | ||
| 54 | threshold: 32, | ||
| 55 | direction: ShiftDirection::Right, | ||
| 56 | }; | ||
| 49 | 57 | ||
| 58 | sm.set_config(&cfg); | ||
| 50 | sm.set_enable(true); | 59 | sm.set_enable(true); |
| 51 | 60 | ||
| 52 | let mut dma_out_ref = p.DMA_CH0.into_ref(); | 61 | let mut dma_out_ref = p.DMA_CH0.into_ref(); |
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 40dee1c4d..61c5565d3 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs | |||
| @@ -4,11 +4,12 @@ | |||
| 4 | 4 | ||
| 5 | use core::fmt::Write; | 5 | use core::fmt::Write; |
| 6 | 6 | ||
| 7 | use embassy_embedded_hal::SetConfig; | ||
| 7 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 8 | use embassy_rp::dma::{AnyChannel, Channel}; | 9 | use embassy_rp::dma::{AnyChannel, Channel}; |
| 9 | use embassy_rp::peripherals::PIO0; | 10 | use embassy_rp::peripherals::PIO0; |
| 10 | use embassy_rp::pio::{Direction, FifoJoin, Pio, PioPin, ShiftDirection, StateMachine}; | 11 | use embassy_rp::pio::{Config, Direction, FifoJoin, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; |
| 11 | use embassy_rp::pwm::{Config, Pwm}; | 12 | use embassy_rp::pwm::{self, Pwm}; |
| 12 | use embassy_rp::relocate::RelocatedProgram; | 13 | use embassy_rp::relocate::RelocatedProgram; |
| 13 | use embassy_rp::{into_ref, Peripheral, PeripheralRef}; | 14 | use embassy_rp::{into_ref, Peripheral, PeripheralRef}; |
| 14 | use embassy_time::{Duration, Instant, Timer}; | 15 | use embassy_time::{Duration, Instant, Timer}; |
| @@ -29,7 +30,7 @@ async fn main(_spawner: Spawner) { | |||
| 29 | let p = embassy_rp::init(Default::default()); | 30 | let p = embassy_rp::init(Default::default()); |
| 30 | 31 | ||
| 31 | let _pwm = Pwm::new_output_b(p.PWM_CH7, p.PIN_15, { | 32 | let _pwm = Pwm::new_output_b(p.PWM_CH7, p.PIN_15, { |
| 32 | let mut c = Config::default(); | 33 | let mut c = pwm::Config::default(); |
| 33 | c.divider = 125.into(); | 34 | c.divider = 125.into(); |
| 34 | c.top = 100; | 35 | c.top = 100; |
| 35 | c.compare_b = 50; | 36 | c.compare_b = 50; |
| @@ -83,7 +84,6 @@ impl<'l> HD44780<'l> { | |||
| 83 | ) -> HD44780<'l> { | 84 | ) -> HD44780<'l> { |
| 84 | into_ref!(dma); | 85 | into_ref!(dma); |
| 85 | 86 | ||
| 86 | let db7pin = db7.pin(); | ||
| 87 | let Pio { | 87 | let Pio { |
| 88 | mut common, | 88 | mut common, |
| 89 | mut irq0, | 89 | mut irq0, |
| @@ -118,13 +118,17 @@ impl<'l> HD44780<'l> { | |||
| 118 | sm0.set_pin_dirs(Direction::Out, &[&rs, &rw, &e, &db4, &db5, &db6, &db7]); | 118 | sm0.set_pin_dirs(Direction::Out, &[&rs, &rw, &e, &db4, &db5, &db6, &db7]); |
| 119 | 119 | ||
| 120 | let relocated = RelocatedProgram::new(&prg.program); | 120 | let relocated = RelocatedProgram::new(&prg.program); |
| 121 | sm0.use_program(&common.load_program(&relocated), &[&e]); | 121 | let mut cfg = Config::default(); |
| 122 | sm0.set_clkdiv(125 * 256); | 122 | cfg.use_program(&common.load_program(&relocated), &[&e]); |
| 123 | sm0.set_out_pins(&[&db4, &db5, &db6, &db7]); | 123 | cfg.clock_divider = 125u8.into(); |
| 124 | sm0.set_out_shift_dir(ShiftDirection::Left); | 124 | cfg.set_out_pins(&[&db4, &db5, &db6, &db7]); |
| 125 | sm0.set_fifo_join(FifoJoin::TxOnly); | 125 | cfg.shift_out = ShiftConfig { |
| 126 | sm0.set_autopull(true); | 126 | auto_fill: true, |
| 127 | sm0.set_pull_threshold(32); | 127 | direction: ShiftDirection::Left, |
| 128 | threshold: 32, | ||
| 129 | }; | ||
| 130 | cfg.fifo_join = FifoJoin::TxOnly; | ||
| 131 | sm0.set_config(&cfg); | ||
| 128 | 132 | ||
| 129 | sm0.set_enable(true); | 133 | sm0.set_enable(true); |
| 130 | // init to 8 bit thrice | 134 | // init to 8 bit thrice |
| @@ -188,13 +192,15 @@ impl<'l> HD44780<'l> { | |||
| 188 | ); | 192 | ); |
| 189 | 193 | ||
| 190 | let relocated = RelocatedProgram::new(&prg.program); | 194 | let relocated = RelocatedProgram::new(&prg.program); |
| 191 | sm0.use_program(&common.load_program(&relocated), &[&e]); | 195 | let mut cfg = Config::default(); |
| 192 | sm0.set_clkdiv(8 * 256); // ~64ns/insn | 196 | cfg.use_program(&common.load_program(&relocated), &[&e]); |
| 193 | sm0.set_jmp_pin(db7pin); | 197 | cfg.clock_divider = 8u8.into(); // ~64ns/insn |
| 194 | sm0.set_set_pins(&[&rs, &rw]); | 198 | cfg.set_jmp_pin(&db7); |
| 195 | sm0.set_out_pins(&[&db4, &db5, &db6, &db7]); | 199 | cfg.set_set_pins(&[&rs, &rw]); |
| 196 | sm0.set_out_shift_dir(ShiftDirection::Left); | 200 | cfg.set_out_pins(&[&db4, &db5, &db6, &db7]); |
| 197 | sm0.set_fifo_join(FifoJoin::TxOnly); | 201 | cfg.shift_out.direction = ShiftDirection::Left; |
| 202 | cfg.fifo_join = FifoJoin::TxOnly; | ||
| 203 | sm0.set_config(&cfg); | ||
| 198 | 204 | ||
| 199 | sm0.set_enable(true); | 205 | sm0.set_enable(true); |
| 200 | 206 | ||
diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index 889970541..d7c4742d8 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs | |||
| @@ -3,10 +3,12 @@ | |||
| 3 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 4 | 4 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_embedded_hal::SetConfig; | ||
| 6 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 7 | use embassy_rp::pio::{Common, FifoJoin, Instance, Pio, PioPin, ShiftDirection, StateMachine}; | 8 | use embassy_rp::pio::{Common, Config, FifoJoin, Instance, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; |
| 8 | use embassy_rp::relocate::RelocatedProgram; | 9 | use embassy_rp::relocate::RelocatedProgram; |
| 9 | use embassy_time::{Duration, Timer}; | 10 | use embassy_time::{Duration, Timer}; |
| 11 | use fixed_macro::fixed; | ||
| 10 | use smart_leds::RGB8; | 12 | use smart_leds::RGB8; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | pub struct Ws2812<'d, P: Instance, const S: usize> { | 14 | pub struct Ws2812<'d, P: Instance, const S: usize> { |
| @@ -43,35 +45,30 @@ impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> { | |||
| 43 | a.bind(&mut wrap_source); | 45 | a.bind(&mut wrap_source); |
| 44 | 46 | ||
| 45 | let prg = a.assemble_with_wrap(wrap_source, wrap_target); | 47 | let prg = a.assemble_with_wrap(wrap_source, wrap_target); |
| 48 | let mut cfg = Config::default(); | ||
| 46 | 49 | ||
| 47 | // Pin config | 50 | // Pin config |
| 48 | let out_pin = pio.make_pio_pin(pin); | 51 | let out_pin = pio.make_pio_pin(pin); |
| 49 | 52 | ||
| 50 | let relocated = RelocatedProgram::new(&prg); | 53 | let relocated = RelocatedProgram::new(&prg); |
| 51 | sm.use_program(&pio.load_program(&relocated), &[&out_pin]); | 54 | cfg.use_program(&pio.load_program(&relocated), &[&out_pin]); |
| 52 | 55 | ||
| 53 | // Clock config | 56 | // Clock config, measured in kHz to avoid overflows |
| 54 | // TODO CLOCK_FREQ should come from embassy_rp | 57 | // TODO CLOCK_FREQ should come from embassy_rp |
| 55 | const CLOCK_FREQ: u32 = 125_000_000; | 58 | let clock_freq = fixed!(125_000: U24F8); |
| 56 | const WS2812_FREQ: u32 = 800_000; | 59 | let ws2812_freq = fixed!(800: U24F8); |
| 57 | 60 | let bit_freq = ws2812_freq * CYCLES_PER_BIT; | |
| 58 | let bit_freq = WS2812_FREQ * CYCLES_PER_BIT; | 61 | cfg.clock_divider = clock_freq / bit_freq; |
| 59 | let mut int = CLOCK_FREQ / bit_freq; | ||
| 60 | let rem = CLOCK_FREQ - (int * bit_freq); | ||
| 61 | let frac = (rem * 256) / bit_freq; | ||
| 62 | // 65536.0 is represented as 0 in the pio's clock divider | ||
| 63 | if int == 65536 { | ||
| 64 | int = 0; | ||
| 65 | } | ||
| 66 | |||
| 67 | sm.set_clkdiv((int << 8) | frac); | ||
| 68 | 62 | ||
| 69 | // FIFO config | 63 | // FIFO config |
| 70 | sm.set_autopull(true); | 64 | cfg.fifo_join = FifoJoin::TxOnly; |
| 71 | sm.set_fifo_join(FifoJoin::TxOnly); | 65 | cfg.shift_out = ShiftConfig { |
| 72 | sm.set_pull_threshold(24); | 66 | auto_fill: true, |
| 73 | sm.set_out_shift_dir(ShiftDirection::Left); | 67 | threshold: 24, |
| 74 | 68 | direction: ShiftDirection::Left, | |
| 69 | }; | ||
| 70 | |||
| 71 | sm.set_config(&cfg); | ||
| 75 | sm.set_enable(true); | 72 | sm.set_enable(true); |
| 76 | 73 | ||
| 77 | Self { sm } | 74 | Self { sm } |
