Initial commit

This commit is contained in:
JP Stringham
2026-02-21 22:39:12 -05:00
commit 6751fb88ef
7 changed files with 1408 additions and 0 deletions

39
.cargo/config.toml Normal file
View File

@@ -0,0 +1,39 @@
[build]
target = "thumbv6m-none-eabi"
# Target specific options
[target.thumbv6m-none-eabi]
# Pass some extra options to rustc, some of which get passed on to the linker.
#
# * linker argument --nmagic turns off page alignment of sections (which saves
# flash space)
# * linker argument -Tlink.x tells the linker to use link.x as the linker
# script. This is usually provided by the cortex-m-rt crate, and by default
# the version in that crate will include a file called `memory.x` which
# describes the particular memory layout for your specific chip.
# * no-vectorize-loops turns off the loop vectorizer (seeing as the M0+ doesn't
# have SIMD)
rustflags = [
"-C", "linker=flip-link",
"-C", "link-arg=--nmagic",
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-Tdefmt.x",
# Code-size optimizations.
# trap unreachable can save a lot of space, but requires nightly compiler.
# uncomment the next line if you wish to enable it
# "-Z", "trap-unreachable=no",
"-C", "no-vectorize-loops",
]
# This runner will make a UF2 file and then copy it to a mounted RP2040 in USB
# Bootloader mode:
# runner = "elf2uf2-rs -d"
# This runner will find a supported SWD debug probe and flash your RP2040 over
# SWD:
runner = "probe-rs run --chip RP2040 --protocol swd --speed 150"
[env]
DEFMT_RTT_BUFFER_SIZE = { value = "8192", force = true }
DEFMT_LOG = { value = "info", force = true }

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target

6
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"rust-analyzer.cargo.target": "thumbv6m-none-eabi",
"rust-analyzer.check.allTargets": false,
"editor.defaultFormatter": "rust-lang.rust-analyzer",
"editor.formatOnSave": true,
}

1181
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

21
Cargo.toml Normal file
View File

@@ -0,0 +1,21 @@
[package]
name = "pico-pio-tests"
version = "0.1.0"
edition = "2024"
[dependencies]
cortex-m = { version = "0.7.7", features = [ "critical-section-single-core" ] }
cortex-m-rt = "0.7.5"
defmt = "1.0.1"
defmt-rtt = "1.1.0"
embedded-hal = "1.0.0"
panic-probe = { version = "1.0.0", features = [ "print-rtt" ]}
pio = "0.3.0"
rp2040-boot2 = "0.3.0"
rp2040-hal = "0.12.0"
sh1106-pico-rs = { path = "../sh1106-pico-rs" }
[features]
logging = []

13
memory.x Normal file
View File

@@ -0,0 +1,13 @@
MEMORY {
BOOT_LOADER : ORIGIN = 0x10000000, LENGTH = 0x100
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
RAM : ORIGIN = 0x20000000, LENGTH = 256K
}
SECTIONS {
/* ### Boot loader */
.boot_loader ORIGIN(BOOT_LOADER) :
{
KEEP(*(.boot_loader));
} > BOOT_LOADER
} INSERT BEFORE .text;

147
src/main.rs Normal file
View File

@@ -0,0 +1,147 @@
//! This example toggles the GPIO25 pin, using a PIO program compiled via pio::pio_asm!().
//!
//! If a LED is connected to that pin, like on a Pico board, the LED should blink.
#![no_std]
#![no_main]
use defmt::println;
use defmt_rtt as _;
use hal::Sio;
use hal::gpio::{FunctionPio0, Pin};
use hal::pac;
use hal::pio::PIOExt;
use panic_probe as _;
use rp2040_hal as hal;
#[unsafe(link_section = ".boot_loader")]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
const WAVE_TABLE: [i8; 256] = [
0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 62, 65, 68, 70,
73, 75, 78, 80, 83, 85, 87, 90, 92, 94, 96, 98, 100, 102, 104, 105, 107, 109, 110, 112, 113,
115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 124, 125, 125, 126, 126, 126, 126, 126, 126,
126, 126, 126, 126, 125, 125, 124, 124, 123, 123, 122, 121, 120, 119, 118, 117, 115, 114, 113,
111, 110, 108, 106, 105, 103, 101, 99, 97, 95, 93, 91, 89, 86, 84, 82, 79, 77, 74, 72, 69, 66,
64, 61, 58, 56, 53, 50, 47, 44, 41, 38, 35, 32, 29, 26, 23, 20, 17, 14, 11, 8, 4, 1, -1, -4,
-7, -10, -13, -16, -20, -23, -26, -29, -32, -35, -38, -41, -44, -47, -50, -52, -55, -58, -61,
-63, -66, -69, -71, -74, -76, -79, -81, -84, -86, -88, -90, -93, -95, -97, -99, -101, -103,
-104, -106, -108, -109, -111, -112, -114, -115, -116, -118, -119, -120, -121, -122, -122, -123,
-124, -124, -125, -125, -126, -126, -126, -126, -126, -126, -126, -126, -126, -126, -125, -125,
-124, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -113, -112, -110, -109, -107,
-106, -104, -102, -100, -98, -96, -94, -92, -90, -88, -85, -83, -81, -78, -76, -73, -71, -68,
-65, -63, -60, -57, -54, -52, -49, -46, -43, -40, -37, -34, -31, -28, -25, -22, -19, -16, -12,
-9, -6, -3, 0,
];
/// Entry point to our bare-metal application.
///
/// The `#[rp2040_hal::entry]` macro ensures the Cortex-M start-up code calls this function
/// as soon as all global variables and the spinlock are initialised.
#[rp2040_hal::entry]
fn main() -> ! {
let mut pac = pac::Peripherals::take().unwrap();
let sio = Sio::new(pac.SIO);
let pins = hal::gpio::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);
// configure LED pin for Pio0.
let led: Pin<_, FunctionPio0, _> = pins.gpio25.into_function();
// PIN id for use inside of PIO
let led_pin_id = led.id().num;
// Define a PIO program which reads data from the TX FIFO bit by bit
let program = pio::pio_asm!(
".wrap_target",
" out pins, 8",
" out pins, 8",
" out pins, 8",
" out pins, 8",
".wrap"
);
let dyn_pin_array = [
pins.gpio3.into_function::<FunctionPio0>().into_dyn_pin(),
pins.gpio4.into_function::<FunctionPio0>().into_dyn_pin(),
pins.gpio5.into_function::<FunctionPio0>().into_dyn_pin(),
pins.gpio6.into_function::<FunctionPio0>().into_dyn_pin(),
pins.gpio7.into_function::<FunctionPio0>().into_dyn_pin(),
pins.gpio8.into_function::<FunctionPio0>().into_dyn_pin(),
pins.gpio9.into_function::<FunctionPio0>().into_dyn_pin(),
pins.gpio10.into_function::<FunctionPio0>().into_dyn_pin(),
pins.gpio11.into_function::<FunctionPio0>().into_dyn_pin(),
pins.gpio12.into_function::<FunctionPio0>().into_dyn_pin(),
pins.gpio13.into_function::<FunctionPio0>().into_dyn_pin(),
];
// Initialize and start PIO
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
let installed = pio.install(&program.program).unwrap();
let (int, frac) = (1, 0);
let (mut sm, _, mut tx) = rp2040_hal::pio::PIOBuilder::from_installed_program(installed)
.set_pins(led_pin_id, 1)
.out_pins(dyn_pin_array[3].id().num, 8)
.out_shift_direction(rp2040_hal::pio::ShiftDirection::Left)
.out_sticky(true)
.autopull(true)
.buffers(rp2040_hal::pio::Buffers::OnlyTx)
.clock_divisor_fixed_point(int, frac)
.build(sm0);
// The GPIO pin needs to be configured as an output.
sm.set_pindirs([(led_pin_id, hal::pio::PinDir::Output)]);
let mut pindirs: [(u8, hal::pio::PinDir); 12] = [(0, hal::pio::PinDir::Output); 12];
dyn_pin_array.iter().enumerate().for_each(|(i, p)| {
pindirs[i] = (p.id().num, hal::pio::PinDir::Output);
});
sm.set_pindirs(pindirs);
tx.write(0b1111_1111_1111_1111_1111_1111_1111_1111);
sm.start();
// let pgroup: PinGroup = PinGroup::new();
// let pgroup = pgroup.add_pin(pins.gpio3.into_push_pull_output());
// let pgroup = pgroup.add_pin(pins.gpio4.into_push_pull_output());
// let pgroup = pgroup.add_pin(pins.gpio5.into_push_pull_output());
// let pgroup = pgroup.add_pin(pins.gpio6.into_push_pull_output());
// let pgroup = pgroup.add_pin(pins.gpio7.into_push_pull_output());
// let pgroup = pgroup.add_pin(pins.gpio8.into_push_pull_output());
// let pgroup = pgroup.add_pin(pins.gpio9.into_push_pull_output());
// let pgroup = pgroup.add_pin(pins.gpio10.into_push_pull_output());
// let pgroup = pgroup.add_pin(pins.gpio11.into_push_pull_output());
// let pgroup = pgroup.add_pin(pins.gpio12.into_push_pull_output());
// let mut pgroup = pgroup.add_pin(pins.gpio13.into_push_pull_output());
let mut processed_wave_table = [0u32; 256];
for (i, w) in WAVE_TABLE.iter().enumerate() {
processed_wave_table[i] = ((*w as i32) + 127) as u32;
}
println!("alive");
println!("{:?}", processed_wave_table);
let mut tick = 0usize;
// PIO runs in background, independently from CPU
loop {
while !tx.is_full() {
let mut out = 0;
for i in 0..4 {
let val = processed_wave_table[tick % 256];
out |= val.rotate_right(8 * i);
// out |= ((tick % 256) as u32).rotate_right(8 * i);
tick = tick.wrapping_add(1);
// println!("{}", val);
}
tx.write(out);
}
// pgroup.set_u32(out.rotate_left(6));
}
}