aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpennae <[email protected]>2023-05-06 20:53:06 +0200
committerpennae <[email protected]>2023-05-06 21:08:20 +0200
commitb38d496d519f87d7f455e6c6b32f5d6379af44a5 (patch)
tree68d682e82887b33e910dda7b37cf7f8e4957a257
parent374c7513f905fcbf353bee2987e78d68fe8ea303 (diff)
rp/pio: allow wrap-around program loading
execution wraps around after the end of instruction memory and wrapping works with this, so we may as well allow program loading across this boundary. could be useful for reusing chunks of instruction memory.
-rw-r--r--embassy-rp/src/pio.rs11
-rw-r--r--embassy-rp/src/relocate.rs10
-rw-r--r--examples/rp/src/bin/pio_hd44780.rs3
3 files changed, 11 insertions, 13 deletions
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs
index 5fed4f1fa..fe66d9aef 100644
--- a/embassy-rp/src/pio.rs
+++ b/embassy-rp/src/pio.rs
@@ -855,13 +855,14 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
855 { 855 {
856 let mut used_mask = 0; 856 let mut used_mask = 0;
857 for (i, instr) in instrs.enumerate() { 857 for (i, instr) in instrs.enumerate() {
858 let addr = (i + start) as u8; 858 // wrapping around the end of program memory is valid, let's make use of that.
859 let mask = 1 << (addr as usize); 859 let addr = (i + start) % 32;
860 if self.instructions_used & mask != 0 { 860 let mask = 1 << addr;
861 return Err(addr as usize); 861 if (self.instructions_used | used_mask) & mask != 0 {
862 return Err(addr);
862 } 863 }
863 unsafe { 864 unsafe {
864 PIO::PIO.instr_mem(addr as usize).write(|w| { 865 PIO::PIO.instr_mem(addr).write(|w| {
865 w.set_instr_mem(instr); 866 w.set_instr_mem(instr);
866 }); 867 });
867 } 868 }
diff --git a/embassy-rp/src/relocate.rs b/embassy-rp/src/relocate.rs
index f36170e03..9cb279ccd 100644
--- a/embassy-rp/src/relocate.rs
+++ b/embassy-rp/src/relocate.rs
@@ -26,11 +26,7 @@ where
26 Some(if instr & 0b1110_0000_0000_0000 == 0 { 26 Some(if instr & 0b1110_0000_0000_0000 == 0 {
27 // this is a JMP instruction -> add offset to address 27 // this is a JMP instruction -> add offset to address
28 let address = (instr & 0b1_1111) as u8; 28 let address = (instr & 0b1_1111) as u8;
29 let address = address + self.offset; 29 let address = address.wrapping_add(self.offset) % 32;
30 assert!(
31 address < pio::RP2040_MAX_PROGRAM_SIZE as u8,
32 "Invalid JMP out of the program after offset addition"
33 );
34 instr & (!0b11111) | address as u16 30 instr & (!0b11111) | address as u16
35 } else { 31 } else {
36 instr 32 instr
@@ -62,8 +58,8 @@ impl<'a, const PROGRAM_SIZE: usize> RelocatedProgram<'a, PROGRAM_SIZE> {
62 let wrap = self.program.wrap; 58 let wrap = self.program.wrap;
63 let origin = self.origin; 59 let origin = self.origin;
64 Wrap { 60 Wrap {
65 source: wrap.source + origin, 61 source: wrap.source.wrapping_add(origin) % 32,
66 target: wrap.target + origin, 62 target: wrap.target.wrapping_add(origin) % 32,
67 } 63 }
68 } 64 }
69 65
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs
index 61c5565d3..088fd5649 100644
--- a/examples/rp/src/bin/pio_hd44780.rs
+++ b/examples/rp/src/bin/pio_hd44780.rs
@@ -95,6 +95,7 @@ impl<'l> HD44780<'l> {
95 let prg = pio_proc::pio_asm!( 95 let prg = pio_proc::pio_asm!(
96 r#" 96 r#"
97 .side_set 1 opt 97 .side_set 1 opt
98 .origin 20
98 99
99 loop: 100 loop:
100 out x, 24 101 out x, 24
@@ -148,7 +149,7 @@ impl<'l> HD44780<'l> {
148 // many side sets are only there to free up a delay bit! 149 // many side sets are only there to free up a delay bit!
149 let prg = pio_proc::pio_asm!( 150 let prg = pio_proc::pio_asm!(
150 r#" 151 r#"
151 .origin 7 152 .origin 27
152 .side_set 1 153 .side_set 1
153 154
154 .wrap_target 155 .wrap_target