Fixed Rust drivers

This commit is contained in:
Kevin Thomas
2026-04-02 11:36:06 -04:00
parent 2792583302
commit 9834d5c96c
245 changed files with 1110 additions and 650 deletions
+74 -1
View File
@@ -32,7 +32,7 @@ use fugit::RateExtU32;
// Clock trait for accessing system clock frequency
use hal::Clock;
// GPIO pin types and function selectors
use hal::gpio::{FunctionNull, FunctionUart, Pin, PullDown, PullNone};
use hal::gpio::{FunctionI2C, FunctionNull, FunctionUart, Pin, PullDown, PullNone, PullUp};
// UART configuration and peripheral types
use hal::uart::{DataBits, Enabled, StopBits, UartConfig, UartPeripheral};
@@ -190,4 +190,77 @@ pub(crate) fn probe_addr(i2c: &mut impl I2c, addr: u8) -> bool {
i2c.read(addr, &mut dummy).is_ok()
}
/// Initialise all peripherals and run the I2C bus scanner demo.
///
/// # Arguments
///
/// * `pac` - PAC Peripherals singleton (consumed).
pub(crate) fn run(mut pac: hal::pac::Peripherals) -> ! {
let mut wd = hal::Watchdog::new(pac.WATCHDOG);
let clocks = init_clocks(pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut wd);
let pins = init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
let uart = init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
let mut delay = init_delay(&clocks);
let mut i2c = init_i2c(pac.I2C1, pins.gpio2, pins.gpio3, &mut pac.RESETS, &clocks);
uart.write_full_blocking(b"I2C driver initialized: I2C1 @ 100000 Hz SDA=GPIO2 SCL=GPIO3\r\n");
scan_loop(&uart, &mut i2c, &mut delay)
}
/// Initialise I2C1 on SDA=GPIO2 / SCL=GPIO3.
///
/// # Arguments
///
/// * `i2c1` - PAC I2C1 peripheral singleton.
/// * `sda` - Default GPIO 2 pin (will be reconfigured for I2C).
/// * `scl` - Default GPIO 3 pin (will be reconfigured for I2C).
/// * `resets` - Mutable reference to the RESETS peripheral.
/// * `clocks` - Reference to the initialised clock configuration.
///
/// # Returns
///
/// Configured I2C1 bus controller.
fn init_i2c(
i2c1: hal::pac::I2C1,
sda: Pin<hal::gpio::bank0::Gpio2, FunctionNull, PullDown>,
scl: Pin<hal::gpio::bank0::Gpio3, FunctionNull, PullDown>,
resets: &mut hal::pac::RESETS,
clocks: &hal::clocks::ClocksManager,
) -> impl I2c {
let sda = sda.reconfigure::<FunctionI2C, PullUp>();
let scl = scl.reconfigure::<FunctionI2C, PullUp>();
hal::I2C::i2c1(i2c1, sda, scl, I2C_BAUD.Hz(), resets, clocks.system_clock.freq())
}
/// Run the I2C address scan loop forever.
///
/// # Arguments
///
/// * `uart` - Reference to the enabled UART peripheral for serial output.
/// * `i2c` - Mutable reference to the I2C bus controller.
/// * `delay` - Mutable reference to the blocking delay provider.
fn scan_loop(uart: &EnabledUart, i2c: &mut impl I2c, delay: &mut cortex_m::delay::Delay) -> ! {
let mut buf = [0u8; 80];
loop {
let n = crate::i2c::format_scan_header(&mut buf);
uart.write_full_blocking(&buf[..n]);
scan_addresses(uart, i2c, &mut buf);
delay.delay_ms(SCAN_DELAY_MS);
}
}
/// Scan all 128 addresses and print the formatted result.
///
/// # Arguments
///
/// * `uart` - Reference to the enabled UART peripheral for serial output.
/// * `i2c` - Mutable reference to the I2C bus controller.
/// * `buf` - Scratch buffer for formatting output.
fn scan_addresses(uart: &EnabledUart, i2c: &mut impl I2c, buf: &mut [u8; 80]) {
for addr in 0u8..128 {
let found = !crate::i2c::is_reserved(addr) && probe_addr(i2c, addr);
let n = crate::i2c::format_scan_entry(buf, addr, found);
uart.write_full_blocking(&buf[..n]);
}
}
// End of file
+27 -24
View File
@@ -87,33 +87,36 @@ pub fn format_scan_header(buf: &mut [u8]) -> usize {
///
/// Number of bytes written into the buffer.
pub fn format_scan_entry(buf: &mut [u8], addr: u8, found: bool) -> usize {
let mut pos = 0;
if addr % 16 == 0 {
buf[pos] = hex_digit((addr >> 4) & 0x0F); pos += 1;
buf[pos] = hex_digit(addr & 0x0F); pos += 1;
buf[pos] = b':'; pos += 1;
buf[pos] = b' '; pos += 1;
}
if is_reserved(addr) {
buf[pos] = b' '; pos += 1;
buf[pos] = b' '; pos += 1;
buf[pos] = b' '; pos += 1;
} else if found {
buf[pos] = hex_digit((addr >> 4) & 0x0F); pos += 1;
buf[pos] = hex_digit(addr & 0x0F); pos += 1;
buf[pos] = b' '; pos += 1;
} else {
buf[pos] = b'-'; pos += 1;
buf[pos] = b'-'; pos += 1;
buf[pos] = b' '; pos += 1;
}
if addr % 16 == 15 {
buf[pos] = b'\r'; pos += 1;
buf[pos] = b'\n'; pos += 1;
}
let mut pos = format_row_prefix(buf, addr);
pos += format_cell(&mut buf[pos..], addr, found);
if addr % 16 == 15 { buf[pos] = b'\r'; pos += 1; buf[pos] = b'\n'; pos += 1; }
pos
}
/// Write the row prefix ("XX: ") if addr is at a 16-byte boundary.
fn format_row_prefix(buf: &mut [u8], addr: u8) -> usize {
if addr % 16 != 0 { return 0; }
buf[0] = hex_digit((addr >> 4) & 0x0F);
buf[1] = hex_digit(addr & 0x0F);
buf[2] = b':';
buf[3] = b' ';
4
}
/// Write a single cell: "XX " if found, "-- " if not, " " if reserved.
fn format_cell(buf: &mut [u8], addr: u8, found: bool) -> usize {
let cell = cell_bytes(addr, found);
buf[..3].copy_from_slice(&cell);
3
}
/// Return the 3-byte cell content for an I2C scan address.
fn cell_bytes(addr: u8, found: bool) -> [u8; 3] {
if is_reserved(addr) { return [b' ', b' ', b' ']; }
if found { [hex_digit((addr >> 4) & 0x0F), hex_digit(addr & 0x0F), b' '] }
else { [b'-', b'-', b' '] }
}
#[cfg(test)]
mod tests {
// Import all parent module items
+1 -40
View File
@@ -56,14 +56,8 @@ use panic_halt as _;
#[cfg(target_arch = "arm")]
use panic_probe as _;
// Rate extension trait for .Hz() baud rate construction
use fugit::RateExtU32;
// Clock trait for accessing system clock frequency
use hal::Clock;
// HAL entry-point macro
use hal::entry;
// GPIO traits for I2C pin reconfiguration
use hal::gpio::{FunctionI2C, PullUp};
// Alias our HAL crate
#[cfg(rp2350)]
@@ -84,42 +78,9 @@ pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
/// Application entry point for the I2C bus scanner demo.
///
/// Initializes I2C1 at 100 kHz on SDA=GPIO2 / SCL=GPIO3 and prints
/// a formatted hex table of all responding device addresses over UART,
/// repeating every 5 seconds.
///
/// # Returns
///
/// Does not return.
#[entry]
fn main() -> ! {
let mut pac = hal::pac::Peripherals::take().unwrap();
let clocks = board::init_clocks(
pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS,
&mut hal::Watchdog::new(pac.WATCHDOG),
);
let pins = board::init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
let uart = board::init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
let mut delay = board::init_delay(&clocks);
let sda_pin = pins.gpio2.reconfigure::<FunctionI2C, PullUp>();
let scl_pin = pins.gpio3.reconfigure::<FunctionI2C, PullUp>();
let mut i2c = hal::I2C::i2c1(
pac.I2C1, sda_pin, scl_pin, board::I2C_BAUD.Hz(),
&mut pac.RESETS, clocks.system_clock.freq(),
);
uart.write_full_blocking(b"I2C driver initialized: I2C1 @ 100000 Hz SDA=GPIO2 SCL=GPIO3\r\n");
let mut buf = [0u8; 80];
loop {
let n = i2c::format_scan_header(&mut buf);
uart.write_full_blocking(&buf[..n]);
for addr in 0u8..128 {
let found = !i2c::is_reserved(addr) && board::probe_addr(&mut i2c, addr);
let n = i2c::format_scan_entry(&mut buf, addr, found);
uart.write_full_blocking(&buf[..n]);
}
delay.delay_ms(board::SCAN_DELAY_MS);
}
board::run(hal::pac::Peripherals::take().unwrap())
}
// Picotool binary info metadata