Skip to content

Commit ed7148a

Browse files
authored
Take possible PIO program length of 32 into account (rp-rs#350)
Avoid overflow of left-shift operation by special-casing the value 32. Fixes rp-rs#349
1 parent d66b479 commit ed7148a

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

rp2040-hal/src/pio.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,21 @@ impl<P: PIOExt> PIO<P> {
148148
.write(|w| unsafe { w.irq_force().bits(flags) });
149149
}
150150

151+
/// Calculates a mask with the `len` right-most bits set.
152+
fn instruction_mask(len: usize) -> u32 {
153+
if len < 32 {
154+
(1 << len) - 1
155+
} else {
156+
0xffffffff
157+
}
158+
}
159+
160+
/// Tries to find an appropriate offset for the instructions, in range 0..=31.
151161
fn find_offset_for_instructions(&self, i: &[u16], origin: Option<u8>) -> Option<usize> {
152-
if i.len() > PIO_INSTRUCTION_COUNT {
162+
if i.len() > PIO_INSTRUCTION_COUNT || i.is_empty() {
153163
None
154164
} else {
155-
let mask = (1 << i.len()) - 1;
165+
let mask = Self::instruction_mask(i.len());
156166
if let Some(origin) = origin {
157167
if origin as usize > PIO_INSTRUCTION_COUNT - i.len()
158168
|| self.used_instruction_space & (mask << origin) != 0
@@ -208,7 +218,7 @@ impl<P: PIOExt> PIO<P> {
208218
{
209219
self.pio.instr_mem[i + offset].write(|w| unsafe { w.bits(instr as u32) })
210220
}
211-
self.used_instruction_space |= ((1 << p.code.len()) - 1) << offset;
221+
self.used_instruction_space |= Self::instruction_mask(p.code.len()) << offset;
212222
Ok(InstalledProgram {
213223
offset: offset as u8,
214224
length: p.code.len() as u8,
@@ -223,7 +233,7 @@ impl<P: PIOExt> PIO<P> {
223233

224234
/// Removes the specified program from instruction memory, freeing the allocated space.
225235
pub fn uninstall(&mut self, p: InstalledProgram<P>) {
226-
let instr_mask = ((1 << p.length as u32) - 1) << p.offset as u32;
236+
let instr_mask = Self::instruction_mask(p.length as usize) << p.offset as u32;
227237
self.used_instruction_space &= !instr_mask;
228238
}
229239
}

0 commit comments

Comments
 (0)