Restrict PIO FIFO writes to unsigned integers (#318)

* Change pio::Tx::write to write u32 instead of <T>*

* Add replicated u8/u16 writes to pio::Tx::write

* Switching back to generic version of pio::fifo.write()

* Fix links to make cargo doc happy

Co-authored-by: Jan Niehusmann <jan@gondor.com>

Co-authored-by: Jan Niehusmann <jan@gondor.com>
This commit is contained in:
9names 2022-06-01 06:13:33 +10:00 committed by GitHub
parent 895bae90b5
commit e9f367f26c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1187,6 +1187,74 @@ impl<SM: ValidStateMachine> Tx<SM> {
true true
} }
/// Write a replicated u8 value to TX FIFO.
///
/// Memory mapped register writes that are smaller than 32bits will trigger
/// "Narrow IO Register Write" behaviour in RP2040 - the value written will
/// be replicated to the rest of the register as described in
/// [RP2040 Datasheet: 2.1.4. - Narrow IO Register Writes][section_2_1_4]
///
///
/// This 8bit write will set all 4 bytes of the FIFO to `value`
/// Eg: if you write `0xBA` the value written to the the FIFO will be
/// `0xBABABABA`
///
/// If you wish to write an 8bit number without replication,
/// use `write(my_u8 as u32)` instead.
///
/// Returns `true` if the value was written to FIFO, `false` otherwise.
///
/// [section_2_1_4]: <https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf#_narrow_io_register_writes>
pub fn write_u8_replicated(&mut self, value: u8) -> bool {
// Safety: The register is never written by software.
let is_full = self.is_full();
if is_full {
return false;
}
unsafe {
let reg_ptr = self.register_block().txf[SM::id()].as_ptr() as *mut u8;
reg_ptr.write_volatile(value);
}
true
}
/// Write a replicated 16bit value to TX FIFO.
///
/// Memory mapped register writes that are smaller than 32bits will trigger
/// "Narrow IO Register Write" behaviour in RP2040 - the value written will
/// be replicated to the rest of the register as described in
/// [RP2040 Datasheet: 2.1.4. - Narrow IO Register Writes][section_2_1_4]
///
/// This 16bit write will set both the upper and lower half of the FIFO entry to `value`.
///
/// For example, if you write `0xC0DA` the value written to the FIFO will be
/// `0xC0DAC0DA`
///
/// If you wish to write a 16bit number without replication,
/// use `write(my_u16 as u32)` instead.
///
/// Returns `true` if the value was written to FIFO, `false` otherwise.
///
/// [section_2_1_4]: <https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf#_narrow_io_register_writes>
pub fn write_u16_replicated(&mut self, value: u16) -> bool {
// Safety: The register is never written by software.
let is_full = self.is_full();
if is_full {
return false;
}
unsafe {
let reg_ptr = self.register_block().txf[SM::id()].as_ptr() as *mut u16;
reg_ptr.write_volatile(value);
}
true
}
/// Checks if the state machine has stalled on empty TX FIFO during a blocking PULL, or an OUT /// Checks if the state machine has stalled on empty TX FIFO during a blocking PULL, or an OUT
/// with autopull enabled. /// with autopull enabled.
/// ///