diff options
| author | pennae <[email protected]> | 2023-07-28 18:45:57 +0200 |
|---|---|---|
| committer | pennae <[email protected]> | 2023-07-28 19:33:02 +0200 |
| commit | cbc8871a0bb40eb5fec82e7c27ed4c0127844c3c (patch) | |
| tree | 333ab4bc2d1893d42529c6a378ea51c42f8c8d22 /tests/rp | |
| parent | d752a3f9808ec9be64c720d3f80f152f0b7507df (diff) | |
rp: relocate programs implicitly during load
this removed the RelocatedProgram construction step from pio uses.
there's not all that much to be said for the extra step because the
origin can be set on the input program itself, and the remaining
information exposed by RelocatedProgram can be exposed from
LoadedProgram instead (even though it's already available on the pio_asm
programs, albeit perhaps less convenient). we do lose access to the
relocated instruction iterator, but we also cannot think of anything
this iterator would actually be useful for outside of program loading.
Diffstat (limited to 'tests/rp')
| -rw-r--r-- | tests/rp/src/bin/pio_irq.rs | 4 | ||||
| -rw-r--r-- | tests/rp/src/bin/pio_multi_load.rs | 126 |
2 files changed, 127 insertions, 3 deletions
diff --git a/tests/rp/src/bin/pio_irq.rs b/tests/rp/src/bin/pio_irq.rs index 45004424a..bdea63eaa 100644 --- a/tests/rp/src/bin/pio_irq.rs +++ b/tests/rp/src/bin/pio_irq.rs | |||
| @@ -9,7 +9,6 @@ use embassy_executor::Spawner; | |||
| 9 | use embassy_rp::bind_interrupts; | 9 | use embassy_rp::bind_interrupts; |
| 10 | use embassy_rp::peripherals::PIO0; | 10 | use embassy_rp::peripherals::PIO0; |
| 11 | use embassy_rp::pio::{Config, InterruptHandler, Pio}; | 11 | use embassy_rp::pio::{Config, InterruptHandler, Pio}; |
| 12 | use embassy_rp::relocate::RelocatedProgram; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 13 | ||
| 15 | bind_interrupts!(struct Irqs { | 14 | bind_interrupts!(struct Irqs { |
| @@ -35,9 +34,8 @@ async fn main(_spawner: Spawner) { | |||
| 35 | "irq wait 1", | 34 | "irq wait 1", |
| 36 | ); | 35 | ); |
| 37 | 36 | ||
| 38 | let relocated = RelocatedProgram::new(&prg.program); | ||
| 39 | let mut cfg = Config::default(); | 37 | let mut cfg = Config::default(); |
| 40 | cfg.use_program(&common.load_program(&relocated), &[]); | 38 | cfg.use_program(&common.load_program(&prg.program), &[]); |
| 41 | sm.set_config(&cfg); | 39 | sm.set_config(&cfg); |
| 42 | sm.set_enable(true); | 40 | sm.set_enable(true); |
| 43 | 41 | ||
diff --git a/tests/rp/src/bin/pio_multi_load.rs b/tests/rp/src/bin/pio_multi_load.rs new file mode 100644 index 000000000..356f16795 --- /dev/null +++ b/tests/rp/src/bin/pio_multi_load.rs | |||
| @@ -0,0 +1,126 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | #[path = "../common.rs"] | ||
| 5 | mod common; | ||
| 6 | |||
| 7 | use defmt::info; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_rp::bind_interrupts; | ||
| 10 | use embassy_rp::peripherals::PIO0; | ||
| 11 | use embassy_rp::pio::{Config, InterruptHandler, LoadError, Pio}; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | bind_interrupts!(struct Irqs { | ||
| 15 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 16 | }); | ||
| 17 | |||
| 18 | #[embassy_executor::main] | ||
| 19 | async fn main(_spawner: Spawner) { | ||
| 20 | let p = embassy_rp::init(Default::default()); | ||
| 21 | let pio = p.PIO0; | ||
| 22 | let Pio { | ||
| 23 | mut common, | ||
| 24 | mut sm0, | ||
| 25 | mut sm1, | ||
| 26 | mut sm2, | ||
| 27 | irq_flags, | ||
| 28 | .. | ||
| 29 | } = Pio::new(pio, Irqs); | ||
| 30 | |||
| 31 | // load with explicit origin works | ||
| 32 | let prg1 = pio_proc::pio_asm!( | ||
| 33 | ".origin 4" | ||
| 34 | "nop", | ||
| 35 | "nop", | ||
| 36 | "nop", | ||
| 37 | "nop", | ||
| 38 | "nop", | ||
| 39 | "nop", | ||
| 40 | "nop", | ||
| 41 | "irq 0", | ||
| 42 | "nop", | ||
| 43 | "nop", | ||
| 44 | ); | ||
| 45 | let loaded1 = common.load_program(&prg1.program); | ||
| 46 | assert_eq!(loaded1.origin, 4); | ||
| 47 | assert_eq!(loaded1.wrap.source, 13); | ||
| 48 | assert_eq!(loaded1.wrap.target, 4); | ||
| 49 | |||
| 50 | // load without origin chooses a free space | ||
| 51 | let prg2 = pio_proc::pio_asm!("nop", "nop", "nop", "nop", "nop", "nop", "nop", "irq 1", "nop", "nop",); | ||
| 52 | let loaded2 = common.load_program(&prg2.program); | ||
| 53 | assert_eq!(loaded2.origin, 14); | ||
| 54 | assert_eq!(loaded2.wrap.source, 23); | ||
| 55 | assert_eq!(loaded2.wrap.target, 14); | ||
| 56 | |||
| 57 | // wrapping around the end of program space automatically works | ||
| 58 | let prg3 = | ||
| 59 | pio_proc::pio_asm!("nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "irq 2",); | ||
| 60 | let loaded3 = common.load_program(&prg3.program); | ||
| 61 | assert_eq!(loaded3.origin, 24); | ||
| 62 | assert_eq!(loaded3.wrap.source, 3); | ||
| 63 | assert_eq!(loaded3.wrap.target, 24); | ||
| 64 | |||
| 65 | // check that the programs actually work | ||
| 66 | { | ||
| 67 | let mut cfg = Config::default(); | ||
| 68 | cfg.use_program(&loaded1, &[]); | ||
| 69 | sm0.set_config(&cfg); | ||
| 70 | sm0.set_enable(true); | ||
| 71 | while !irq_flags.check(0) {} | ||
| 72 | sm0.set_enable(false); | ||
| 73 | } | ||
| 74 | { | ||
| 75 | let mut cfg = Config::default(); | ||
| 76 | cfg.use_program(&loaded2, &[]); | ||
| 77 | sm1.set_config(&cfg); | ||
| 78 | sm1.set_enable(true); | ||
| 79 | while !irq_flags.check(1) {} | ||
| 80 | sm1.set_enable(false); | ||
| 81 | } | ||
| 82 | { | ||
| 83 | let mut cfg = Config::default(); | ||
| 84 | cfg.use_program(&loaded3, &[]); | ||
| 85 | sm2.set_config(&cfg); | ||
| 86 | sm2.set_enable(true); | ||
| 87 | while !irq_flags.check(2) {} | ||
| 88 | sm2.set_enable(false); | ||
| 89 | } | ||
| 90 | |||
| 91 | // instruction memory is full now. all loads should fail. | ||
| 92 | { | ||
| 93 | let prg = pio_proc::pio_asm!(".origin 0", "nop"); | ||
| 94 | match common.try_load_program(&prg.program) { | ||
| 95 | Err(LoadError::AddressInUse(0)) => (), | ||
| 96 | _ => panic!("program loaded when it shouldn't"), | ||
| 97 | }; | ||
| 98 | |||
| 99 | let prg = pio_proc::pio_asm!("nop"); | ||
| 100 | match common.try_load_program(&prg.program) { | ||
| 101 | Err(LoadError::InsufficientSpace) => (), | ||
| 102 | _ => panic!("program loaded when it shouldn't"), | ||
| 103 | }; | ||
| 104 | } | ||
| 105 | |||
| 106 | // freeing some memory should allow further loads though. | ||
| 107 | unsafe { | ||
| 108 | common.free_instr(loaded3.used_memory); | ||
| 109 | } | ||
| 110 | { | ||
| 111 | let prg = pio_proc::pio_asm!(".origin 0", "nop"); | ||
| 112 | match common.try_load_program(&prg.program) { | ||
| 113 | Ok(_) => (), | ||
| 114 | _ => panic!("program didn't loaded when it shouldn"), | ||
| 115 | }; | ||
| 116 | |||
| 117 | let prg = pio_proc::pio_asm!("nop"); | ||
| 118 | match common.try_load_program(&prg.program) { | ||
| 119 | Ok(_) => (), | ||
| 120 | _ => panic!("program didn't loaded when it shouldn"), | ||
| 121 | }; | ||
| 122 | } | ||
| 123 | |||
| 124 | info!("Test OK"); | ||
| 125 | cortex_m::asm::bkpt(); | ||
| 126 | } | ||
