Merge pull request #453 from jannic/update-jmp-offset

simplify jump offset calculation when loading PIO programs
This commit is contained in:
Jan Niehusmann 2022-09-27 22:25:22 +02:00 committed by GitHub
commit 8d9b4538c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -156,7 +156,7 @@ impl<P: PIOExt> PIO<P> {
} }
/// Tries to find an appropriate offset for the instructions, in range 0..=31. /// Tries to find an appropriate offset for the instructions, in range 0..=31.
fn find_offset_for_instructions(&self, i: &[u16], origin: Option<u8>) -> Option<usize> { fn find_offset_for_instructions(&self, i: &[u16], origin: Option<u8>) -> Option<u8> {
if i.len() > PIO_INSTRUCTION_COUNT || i.is_empty() { if i.len() > PIO_INSTRUCTION_COUNT || i.is_empty() {
None None
} else { } else {
@ -167,10 +167,10 @@ impl<P: PIOExt> PIO<P> {
{ {
None None
} else { } else {
Some(origin as usize) Some(origin)
} }
} else { } else {
for i in (0..=32 - i.len()).rev() { for i in (0..=32 - (i.len() as u8)).rev() {
if self.used_instruction_space & (mask << i) == 0 { if self.used_instruction_space & (mask << i) == 0 {
return Some(i); return Some(i);
} }
@ -195,32 +195,24 @@ impl<P: PIOExt> PIO<P> {
.iter() .iter()
.cloned() .cloned()
.map(|instr| { .map(|instr| {
if let Some(Instruction { if instr & 0b1110_0000_0000_0000 == 0 {
operands: InstructionOperands::JMP { condition, address }, // this is a JMP instruction -> add offset to address
delay, let address = (instr & 0b11111) as u8;
side_set, let address = address + offset;
}) = Instruction::decode(instr, p.side_set)
{
// JMP instruction. We need to apply offset here
let address = address + offset as u8;
assert!( assert!(
address < pio::RP2040_MAX_PROGRAM_SIZE as u8, address < pio::RP2040_MAX_PROGRAM_SIZE as u8,
"Invalid JMP out of the program after offset addition" "Invalid JMP out of the program after offset addition"
); );
instr & (!0b11111) | address as u16
Instruction {
operands: InstructionOperands::JMP { condition, address },
delay,
side_set,
}
.encode(p.side_set)
} else { } else {
// this is not a JMP instruction -> keep it unchanged
instr instr
} }
}) })
.enumerate() .enumerate()
.for_each(|(i, instr)| { .for_each(|(i, instr)| {
self.pio.instr_mem[i + offset].write(|w| unsafe { w.instr_mem0().bits(instr) }) self.pio.instr_mem[i + offset as usize]
.write(|w| unsafe { w.instr_mem0().bits(instr) })
}); });
self.used_instruction_space |= Self::instruction_mask(p.code.len()) << offset; self.used_instruction_space |= Self::instruction_mask(p.code.len()) << offset;
Ok(InstalledProgram { Ok(InstalledProgram {