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.
This commit is contained in:
pennae 2023-05-06 20:53:06 +02:00
parent 374c7513f9
commit b38d496d51
3 changed files with 11 additions and 13 deletions

View file

@ -855,13 +855,14 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
{
let mut used_mask = 0;
for (i, instr) in instrs.enumerate() {
let addr = (i + start) as u8;
let mask = 1 << (addr as usize);
if self.instructions_used & mask != 0 {
return Err(addr as usize);
// wrapping around the end of program memory is valid, let's make use of that.
let addr = (i + start) % 32;
let mask = 1 << addr;
if (self.instructions_used | used_mask) & mask != 0 {
return Err(addr);
}
unsafe {
PIO::PIO.instr_mem(addr as usize).write(|w| {
PIO::PIO.instr_mem(addr).write(|w| {
w.set_instr_mem(instr);
});
}

View file

@ -26,11 +26,7 @@ where
Some(if instr & 0b1110_0000_0000_0000 == 0 {
// this is a JMP instruction -> add offset to address
let address = (instr & 0b1_1111) as u8;
let address = address + self.offset;
assert!(
address < pio::RP2040_MAX_PROGRAM_SIZE as u8,
"Invalid JMP out of the program after offset addition"
);
let address = address.wrapping_add(self.offset) % 32;
instr & (!0b11111) | address as u16
} else {
instr
@ -62,8 +58,8 @@ impl<'a, const PROGRAM_SIZE: usize> RelocatedProgram<'a, PROGRAM_SIZE> {
let wrap = self.program.wrap;
let origin = self.origin;
Wrap {
source: wrap.source + origin,
target: wrap.target + origin,
source: wrap.source.wrapping_add(origin) % 32,
target: wrap.target.wrapping_add(origin) % 32,
}
}

View file

@ -95,6 +95,7 @@ impl<'l> HD44780<'l> {
let prg = pio_proc::pio_asm!(
r#"
.side_set 1 opt
.origin 20
loop:
out x, 24
@ -148,7 +149,7 @@ impl<'l> HD44780<'l> {
// many side sets are only there to free up a delay bit!
let prg = pio_proc::pio_asm!(
r#"
.origin 7
.origin 27
.side_set 1
.wrap_target