Browse Source

Added rtic example with modified ws2812-pio

master
Weird Constructor 1 year ago
parent
commit
802d726c3b
  1. 2
      README.md
  2. 19
      rtic_ws2812_pio/.cargo/config
  3. 16
      rtic_ws2812_pio/.gitignore
  4. 94
      rtic_ws2812_pio/Cargo.toml
  5. 31
      rtic_ws2812_pio/build.rs
  6. 13
      rtic_ws2812_pio/memory.x
  7. 281
      rtic_ws2812_pio/src/main.rs
  8. 2
      sd_card_spi/Cargo.toml
  9. 37
      sd_card_spi/src/main.rs

2
README.md

@ -7,3 +7,5 @@ An overview of this repository:
- [8-Bit PWM DAC with an RC filter synthesizing sine and saw waveforms](pwm_dac_saw_sampling)
- [WS2812 on the Raspberry Pi Pico with Rust](ws2812_led_cube)
- [SD/MMC Card with FAT32 filesystem via SPI on Raspberry Pi Pico](sd_card_spi)
If you search for a nicer documented example also have a look at my PR
for `rp-hal`: https://github.com/WeirdConstructor/rp-hal/blob/pico_sd_card_example/boards/rp-pico/examples/pico_spi_sd_card.rs

19
rtic_ws2812_pio/.cargo/config

@ -0,0 +1,19 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "probe-run-rp --chip RP2040"
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", "inline-threshold=5",
"-C", "no-vectorize-loops",
]
[build]
target = "thumbv6m-none-eabi"

16
rtic_ws2812_pio/.gitignore vendored

@ -0,0 +1,16 @@
**/*.rs.bk
.#*
.gdb_history
Cargo.lock
target/
# editor files
.vscode/*
!.vscode/*.md
!.vscode/*.svd
!.vscode/launch.json
!.vscode/tasks.json
!.vscode/extensions.json
!.vscode/settings.json
*.history

94
rtic_ws2812_pio/Cargo.toml

@ -0,0 +1,94 @@
[package]
authors = ["Weird Constructor"]
edition = "2018"
readme = "README.md"
name = "rp2040-rtic-ws2812-led"
version = "0.1.0"
resolver = "2"
[dependencies]
cortex-m = "0.7.3"
cortex-m-rt = "0.7.0"
embedded-hal = { version = "0.2.5", features=["unproven"] }
embedded-time = "0.12.0"
cortex-m-rtic = "0.6.0-rc.4"
defmt = "0.2.0"
defmt-rtt = "0.2.0"
panic-probe = { version = "0.2.0", features = ["print-defmt"] }
#rp2040-hal = { git = "https://github.com/rp-rs/rp-hal", branch="main", features=["rt"] }
rp2040-boot2 = { git = "https://github.com/rp-rs/rp2040-boot2-rs", branch="main" }
pico = { git = "https://github.com/rp-rs/rp-hal.git", branch="main" }
smart-leds = "0.3.0"
ws2812-pio = { path = "../../ws2812-pio-rs/" }
nb = "1.0"
[features]
default = [
"defmt-default",
]
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true
incremental = false
opt-level = 3
overflow-checks = true
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false
incremental = false
lto = 'fat'
opt-level = 3
overflow-checks = false
# do not optimize proc-macro crates = faster builds from scratch
[profile.dev.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false
[profile.release.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false
# cargo test
[profile.test]
codegen-units = 1
debug = 2
debug-assertions = true
incremental = false
opt-level = 3
overflow-checks = true
# cargo test --release
[profile.bench]
codegen-units = 1
debug = 2
debug-assertions = false
incremental = false
lto = 'fat'
opt-level = 3
[dependencies.num-traits]
version = "0.2.14"
default-features = false

31
rtic_ws2812_pio/build.rs

@ -0,0 +1,31 @@
//! This build script copies the `memory.x` file from the crate root into
//! a directory where the linker can always find it at build time.
//! For many projects this is optional, as the linker always searches the
//! project root directory -- wherever `Cargo.toml` is. However, if you
//! are using a workspace or have a more complicated build setup, this
//! build script becomes required. Additionally, by requesting that
//! Cargo re-run the build script whenever `memory.x` is changed,
//! updating `memory.x` ensures a rebuild of the application with the
//! new memory settings.
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
fn main() {
// Put `memory.x` in our output directory and ensure it's
// on the linker search path.
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
File::create(out.join("memory.x"))
.unwrap()
.write_all(include_bytes!("memory.x"))
.unwrap();
println!("cargo:rustc-link-search={}", out.display());
// By default, Cargo will re-run a build script whenever
// any file in the project changes. By specifying `memory.x`
// here, we ensure the build script is only re-run when
// `memory.x` is changed.
println!("cargo:rerun-if-changed=memory.x");
}

13
rtic_ws2812_pio/memory.x

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

281
rtic_ws2812_pio/src/main.rs

@ -0,0 +1,281 @@
#![no_std]
#![no_main]
//use cortex_m_rt::entry;
//use embedded_time::duration::*;
//use embedded_hal::timer::CountDown;
use panic_probe as _;
//
//use embedded_hal::adc::OneShot;
//use pico::hal::{
// pac,
// clocks::{Clock, init_clocks_and_plls},
// sio::Sio,
// adc::Adc,
// watchdog::Watchdog,
// timer::Timer,
//};
//
//use pico::hal::pio::PIOExt;
////use rp2040_hal::pio::PIOExt;
//use smart_leds::{brightness, SmartLedsWrite, RGB8};
//use ws2812_pio::Ws2812;
//
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
const LEN : usize = 302;
pub fn hsv2rgb(hue: f32, sat: f32, val: f32) -> (f32, f32, f32) {
let c = val * sat;
let v = (hue / 60.0) % 2.0 - 1.0;
let v = if v < 0.0 { -v } else { v };
let x = c * (1.0 - v);
let m = val - c;
let (r, g, b) = if hue < 60.0 {
(c, x, 0.0)
} else if hue < 120.0 {
(x, c, 0.0)
} else if hue < 180.0 {
(0.0, c, x)
} else if hue < 240.0 {
(0.0, x, c)
} else if hue < 300.0 {
(x, 0.0, c)
} else {
(c, 0.0, x)
};
(r + m, g + m, b + m)
}
pub fn hsv2rgb_u8(h: f32, s: f32, v: f32) -> (u8, u8, u8) {
let r = hsv2rgb(h, s, v);
(
(r.0 * 255.0) as u8,
(r.1 * 255.0) as u8,
(r.2 * 255.0) as u8
)
}
//#[entry]
//fn main() -> ! {
// info!("Program start");
// let mut pac = pac::Peripherals::take().unwrap();
// let _core = pac::CorePeripherals::take().unwrap();
// let mut watchdog = Watchdog::new(pac.WATCHDOG);
// let sio = Sio::new(pac.SIO);
//
// // External high-speed crystal on the pico board is 12Mhz
// let external_xtal_freq_hz = 12_000_000u32;
// let clocks =
// init_clocks_and_plls(
// external_xtal_freq_hz,
// pac.XOSC,
// pac.CLOCKS,
// pac.PLL_SYS,
// pac.PLL_USB,
// &mut pac.RESETS,
// &mut watchdog)
// .ok()
// .unwrap();
//
// let pins = pico::Pins::new(
// pac.IO_BANK0,
// pac.PADS_BANK0,
// sio.gpio_bank0,
// &mut pac.RESETS,
// );
//
// let timer = Timer::new(pac.TIMER, &mut pac.RESETS);
// let mut delay = timer.count_down();
//
// let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
// let mut ws = Ws2812::new(
// pins.gpio16.into_mode(),
// &mut pio,
// sm0,
// clocks.peripheral_clock.freq(),
// timer.count_down(),
// );
//
// let mut adc = Adc::new(pac.ADC, &mut pac.RESETS);
// let mut adc_pin_0 = pins.gpio26.into_floating_input();
//
//
// let mut n: u8 = 0;
// let mut leds_off : [RGB8; LEN] = [(0,0,0).into(); LEN];
// let mut leds : [RGB8; LEN] = [(0,0,0).into(); LEN];
//
// for i in 0..LEN {
// leds[i] = (255, 128, 64).into();
// }
//// leds[149] = (255, 255, 255).into();
//// leds[70] = (255, 0, 255).into();
//// leds[100] = (255, 0, 0).into();
//
// let colors : [RGB8; 3] = [
// hsv2rgb_u8(0.0, 1.0, 1.0).into(),
// (0, 255, 0).into(),
// (0, 0, 255).into(),
// ];
//
// let amperes = 8.0;
// let all_on_amp = (LEN as f32 * 3.0 * 60.0) / 1000.0;
//
// let vbrightness = ((amperes / all_on_amp) * 255.0) as u8;
// info!("brightness={} / 255", vbrightness);
// ws.write(brightness(leds_off.iter().copied(), vbrightness)).unwrap();
//
//// for i in 0..LEN {
//// leds[i] = colors[1];
//// }
//// info!("LEDS={}", leds.len());
//
// let mut cnt = 0;
//
// let mut j = 0;
//
// loop {
// cnt += 1;
// if cnt > 400 {
// cnt = 0;
// }
//
// let clr = hsv2rgb_u8((cnt as f32 / 400.0) * 360.0, 0.0, 1.0);
//// info!("[{}] clr : {}", cnt, clr);
// for i in 0..LEN {
// leds[i] = clr.into();
// }
//
// ws.write(brightness(leds.iter().copied(), vbrightness)).unwrap();
// delay.start(16.milliseconds());
// let _ = nb::block!(delay.wait());
// }
//}
//use panic_halt as _;
#[rtic::app(device = pico::hal::pac, peripherals = true)]
mod app {
use super::*;
use defmt::*;
use defmt_rtt as _;
use embedded_hal::digital::v2::OutputPin;
use embedded_time::duration::Extensions;
use pico::{
hal::{
self,
clocks::Clock,
clocks::init_clocks_and_plls,
watchdog::Watchdog,
sio::Sio,
pio::SM0,
timer::Timer
},
XOSC_CRYSTAL_FREQ,
};
use smart_leds::{brightness, SmartLedsWrite, RGB8};
use ws2812_pio::Ws2812Driver;
use pico::hal::pio::PIOExt;
const SCAN_TIME_US: u32 = 1000000;
#[shared]
struct Shared {
timer: Timer,
alarm: hal::timer::Alarm0,
led: hal::gpio::Pin<hal::gpio::pin::bank0::Gpio25, hal::gpio::PushPullOutput>,
ws: Ws2812Driver<pico::hal::pac::PIO0, SM0, hal::gpio::pin::bank0::Gpio4>,
}
#[local]
struct Local {}
#[init]
fn init(c: init::Context) -> (Shared, Local, init::Monotonics) {
let mut resets = c.device.RESETS;
let mut watchdog = Watchdog::new(c.device.WATCHDOG);
let clocks = init_clocks_and_plls(
XOSC_CRYSTAL_FREQ,
c.device.XOSC,
c.device.CLOCKS,
c.device.PLL_SYS,
c.device.PLL_USB,
&mut resets,
&mut watchdog,
)
.ok()
.unwrap();
let sio = Sio::new(c.device.SIO);
let pins = pico::Pins::new(
c.device.IO_BANK0,
c.device.PADS_BANK0,
sio.gpio_bank0,
&mut resets,
);
let mut led = pins.led.into_push_pull_output();
led.set_low().unwrap();
let mut timer = Timer::new(c.device.TIMER, &mut resets);
let mut alarm = timer.alarm_0().unwrap();
let _ = alarm.schedule(SCAN_TIME_US.microseconds());
alarm.enable_interrupt(&mut timer);
let (mut pio, sm0, _, _, _) = c.device.PIO0.split(&mut resets);
let ws = Ws2812Driver::new(
pins.gpio4.into_mode(),
&mut pio,
sm0,
clocks.peripheral_clock.freq(),
);
(Shared { timer, alarm, led, ws }, Local {}, init::Monotonics())
}
#[task(
binds = TIMER_IRQ_0,
priority = 1,
shared = [timer, alarm, ws],
local = [],
)]
fn timer_irq(mut c: timer_irq::Context) {
let clr : RGB8 = (255, 0, 255).into();
c.shared.ws.lock(|ws|
ws.write([clr].iter().copied()).unwrap());
let timer = c.shared.timer;
let alarm = c.shared.alarm;
(timer, alarm).lock(|t, a| {
a.clear_interrupt(t);
let _ = a.schedule(SCAN_TIME_US.microseconds());
});
}
#[idle(local = [x: u32 = 0])]
fn idle(cx: idle::Context) -> ! {
// Locals in idle have lifetime 'static
let _x: &'static mut u32 = cx.local.x;
// hprintln!("idle").unwrap();
info!("Idle started!");
// debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
// let timer = Timer::new(cx.device.TIMER, &mut pac.RESETS);
// let mut delay = timer.count_down();
loop {
cortex_m::asm::nop();
// delay.start(16.milliseconds());
// let _ = nb::block!(delay.wait());
}
}
}

2
sd_card_spi/Cargo.toml

@ -20,7 +20,7 @@ panic-probe = { version = "0.2.0", features = ["print-defmt"] }
rp2040-hal = { git = "https://github.com/rp-rs/rp-hal", branch="main", features=["rt"] }
rp2040-boot2 = { git = "https://github.com/rp-rs/rp2040-boot2-rs", branch="main" }
pico = { git = "https://github.com/rp-rs/rp-hal.git", branch="main" }
rp-pico = { git = "https://github.com/rp-rs/rp-hal.git", branch="main" }
nb = "1.0"

37
sd_card_spi/src/main.rs

@ -11,11 +11,12 @@ use embedded_hal::digital::v2::OutputPin;
use panic_probe as _;
use embedded_sdmmc;
use embedded_sdmmc::filesystem::Mode;
use rp2040_hal as rphal;
use pico::hal::{
use rp_pico::hal::{
pac,
gpio,
spi,
clocks::{Clock, init_clocks_and_plls},
sio::Sio,
watchdog::Watchdog,
@ -26,16 +27,10 @@ use pico::hal::{
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
#[derive(Default)]
pub struct DummyTimesource {
}
impl DummyTimesource {
pub fn new() -> Self {
Self {
}
}
}
impl embedded_sdmmc::TimeSource for DummyTimesource {
fn get_timestamp(&self) -> embedded_sdmmc::Timestamp {
embedded_sdmmc::Timestamp {
@ -71,7 +66,7 @@ fn main() -> ! {
.ok()
.unwrap();
let pins = pico::Pins::new(
let pins = rp_pico::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
@ -83,11 +78,11 @@ fn main() -> ! {
// let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
let _spi_sclk = pins.gpio2.into_mode::<rphal::gpio::FunctionSpi>();
let _spi_mosi = pins.gpio3.into_mode::<rphal::gpio::FunctionSpi>();
let _spi_miso = pins.gpio4.into_mode::<rphal::gpio::FunctionSpi>();
let _spi_sclk = pins.gpio2.into_mode::<gpio::FunctionSpi>();
let _spi_mosi = pins.gpio3.into_mode::<gpio::FunctionSpi>();
let _spi_miso = pins.gpio4.into_mode::<gpio::FunctionSpi>();
let spi_cs = pins.gpio5.into_push_pull_output();
let spi = rphal::spi::Spi::<_, _, 8>::new(pac.SPI0);
let spi = spi::Spi::<_, _, 8>::new(pac.SPI0);
// Exchange the uninitialised SPI driver for an initialised one
let spi = spi.init(
@ -102,7 +97,7 @@ fn main() -> ! {
info!("Aquire BlockDevice ok!");
let mut cont =
embedded_sdmmc::Controller::new(block, DummyTimesource::new());
embedded_sdmmc::Controller::new(block, DummyTimesource::default());
info!("Init SD card...");
info!("OK!\nCard size...");
@ -118,6 +113,7 @@ fn main() -> ! {
match cont.open_root_dir(&v) {
Ok(dir) => {
info!("Root!");
cont.iterate_dir(&v, &dir, |ent| {
info!("/{}.{}",
core::str::from_utf8(ent.name.base_name()).unwrap(),
@ -127,17 +123,18 @@ fn main() -> ! {
let mut file =
cont.open_file_in_dir(
&mut v, &dir, "O.TST",
embedded_sdmmc::filesystem::Mode::ReadOnly).unwrap();
Mode::ReadOnly).unwrap();
let mut buf = [0u8; 32];
let nr = cont.read(&mut v, &mut file, &mut buf).unwrap();
info!("READ {} bytes: {}", nr, buf);
cont.close_file(&v, file).unwrap();
info!("READ {} bytes: {}", nr, buf);
let mut file =
cont.open_file_in_dir(
&mut v, &dir, "O.TST",
// embedded_sdmmc::filesystem::Mode::ReadWriteCreateOrAppend).unwrap();
embedded_sdmmc::filesystem::Mode::ReadWriteCreateOrTruncate).unwrap();
Mode::ReadWriteCreateOrTruncate).unwrap();
cont.write(&mut v, &mut file, b"foobar123\n").unwrap();
cont.close_file(&v, file).unwrap();
},

Loading…
Cancel
Save