From db907a914c7e84176a15da70385af871c9b97cf6 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 14 May 2023 23:02:49 +0200 Subject: [PATCH] cyw43-pio: add `overclock` feature flag. --- ci.sh | 5 +++ cyw43-pio/Cargo.toml | 5 +++ cyw43-pio/src/lib.rs | 77 +++++++++++++++++++++------------- examples/rpi-pico-w/Cargo.toml | 4 +- 4 files changed, 60 insertions(+), 31 deletions(-) diff --git a/ci.sh b/ci.sh index d41b3aa8..91683820 100755 --- a/ci.sh +++ b/ci.sh @@ -1,7 +1,9 @@ #!/bin/bash set -euxo pipefail +cd $(dirname $0) +export CARGO_TARGET_DIR=$(pwd)/target export DEFMT_LOG=trace # build examples @@ -18,3 +20,6 @@ cargo build --target thumbv6m-none-eabi --features 'log' cargo build --target thumbv6m-none-eabi --features 'defmt' cargo build --target thumbv6m-none-eabi --features 'log,firmware-logs' cargo build --target thumbv6m-none-eabi --features 'defmt,firmware-logs' + +(cd cyw43-pio; cargo build --target thumbv6m-none-eabi --features '') +(cd cyw43-pio; cargo build --target thumbv6m-none-eabi --features 'overclock') diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index dd50e02b..2238f761 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -3,6 +3,11 @@ name = "cyw43-pio" version = "0.1.0" edition = "2021" +[features] +# If disabled, SPI runs at 31.25MHz +# If enabled, SPI runs at 62.5MHz, which is 25% higher than 50Mhz which is the maximum according to the CYW43439 datasheet. +overclock = [] + [dependencies] cyw43 = { path = "../" } embassy-rp = { version = "0.1.0", features = ["unstable-traits", "nightly", "unstable-pac", "time-driver"] } diff --git a/cyw43-pio/src/lib.rs b/cyw43-pio/src/lib.rs index 2c17b151..dca30c74 100644 --- a/cyw43-pio/src/lib.rs +++ b/cyw43-pio/src/lib.rs @@ -40,24 +40,46 @@ where DIO: PioPin, CLK: PioPin, { + #[cfg(feature = "overclock")] let program = pio_asm!( ".side_set 1" ".wrap_target" // write out x-1 bits - "lp:", + "lp:" "out pins, 1 side 0" "jmp x-- lp side 1" // switch directions "set pindirs, 0 side 0" - // these nops seem to be necessary for fast clkdiv - //"nop side 1" - //"nop side 0" - "nop side 1" + "nop side 1" // necessary for clkdiv=1. + "nop side 0" // read in y-1 bits "lp2:" - "in pins, 1 side 0" - "jmp y-- lp2 side 1" + "in pins, 1 side 1" + "jmp y-- lp2 side 0" + + // wait for event and irq host + "wait 1 pin 0 side 0" + "irq 0 side 0" + + ".wrap" + ); + #[cfg(not(feature = "overclock"))] + let program = pio_asm!( + ".side_set 1" + + ".wrap_target" + // write out x-1 bits + "lp:" + "out pins, 1 side 0" + "jmp x-- lp side 1" + // switch directions + "set pindirs, 0 side 0" + "nop side 0" + // read in y-1 bits + "lp2:" + "in pins, 1 side 1" + "jmp y-- lp2 side 0" // wait for event and irq host "wait 1 pin 0 side 0" @@ -72,8 +94,8 @@ where pin_io.set_pull(Pull::None); pin_io.set_schmitt(true); pin_io.set_input_sync_bypass(true); - //pin_io.set_drive_strength(Drive::_12mA); - //pin_io.set_slew_rate(SlewRate::Fast); + pin_io.set_drive_strength(Drive::_12mA); + pin_io.set_slew_rate(SlewRate::Fast); let mut pin_clk = common.make_pio_pin(clk); pin_clk.set_drive_strength(Drive::_12mA); @@ -91,27 +113,24 @@ where cfg.shift_in.auto_fill = true; //cfg.shift_in.threshold = 32; - // theoretical maximum according to data sheet, 100Mhz Pio => 50Mhz SPI Freq - // seems to cause random corruption, probably due to jitter due to the fractional divider. - // cfg.clock_divider = FixedU32::from_bits(0x0140); + #[cfg(feature = "overclock")] + { + // 125mhz Pio => 62.5Mhz SPI Freq. 25% higher than theoretical maximum according to + // data sheet, but seems to work fine. + cfg.clock_divider = FixedU32::from_bits(0x0100); + } - // same speed as pico-sdk, 62.5Mhz - cfg.clock_divider = FixedU32::from_bits(0x0200); - - // 32 Mhz - // cfg.clock_divider = FixedU32::from_bits(0x03E8); - - // 16 Mhz - // cfg.clock_divider = FixedU32::from_bits(0x07d0); - - // 8Mhz - // cfg.clock_divider = FixedU32::from_bits(0x0a_00); - - // 1Mhz - // cfg.clock_divider = FixedU32::from_bits(0x7d_00); - - // slowest possible - // cfg.clock_divider = FixedU32::from_bits(0xffff_00); + #[cfg(not(feature = "overclock"))] + { + // same speed as pico-sdk, 62.5Mhz + // This is actually the fastest we can go without overclocking. + // According to data sheet, the theoretical maximum is 100Mhz Pio => 50Mhz SPI Freq. + // However, the PIO uses a fractional divider, which works by introducing jitter when + // the divider is not an integer. It does some clocks at 125mhz and others at 62.5mhz + // so that it averages out to the desired frequency of 100mhz. The 125mhz clock cycles + // violate the maximum from the data sheet. + cfg.clock_divider = FixedU32::from_bits(0x0200); + } sm.set_config(&cfg); diff --git a/examples/rpi-pico-w/Cargo.toml b/examples/rpi-pico-w/Cargo.toml index d972bf5a..525e934f 100644 --- a/examples/rpi-pico-w/Cargo.toml +++ b/examples/rpi-pico-w/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] cyw43 = { path = "../../", features = ["defmt", "firmware-logs"] } -cyw43-pio = { path = "../../cyw43-pio", features = ["defmt"] } +cyw43-pio = { path = "../../cyw43-pio", features = ["defmt", "overclock"] } embassy-executor = { version = "0.2.0", features = ["defmt", "integrated-timers", "executor-thread", "arch-cortex-m"] } embassy-time = { version = "0.1.0", features = ["defmt", "defmt-timestamp-uptime"] } embassy-rp = { version = "0.1.0", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver"] } @@ -48,7 +48,7 @@ debug = 1 debug-assertions = false incremental = false lto = 'fat' -opt-level = 'z' +opt-level = 's' overflow-checks = false # do not optimize proc-macro crates = faster builds from scratch