From e3d9e7dfad54adedc8b6ac0fe6309e46611e74ac Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 27 Sep 2025 15:12:14 +0200 Subject: [PATCH] fix build ,update examples --- Cargo.toml | 2 +- .../embassy/src/bin/dht22-open-drain-pins.rs | 10 +- .../embassy/src/bin/logger-non-blocking.rs | 10 +- examples/embassy/src/bin/pwm.rs | 10 +- examples/embassy/src/main.rs | 75 ++++------ examples/simple/src/bin/gtc-ticks.rs | 8 +- examples/simple/src/bin/logger.rs | 8 +- examples/simple/src/main.rs | 4 +- examples/zedboard/src/bin/ethernet.rs | 10 +- examples/zedboard/src/bin/l3gd20h-i2c-mio.rs | 8 +- examples/zedboard/src/bin/l3gd20h-spi-mio.rs | 8 +- examples/zedboard/src/bin/qspi.rs | 88 +++++------ examples/zedboard/src/bin/uart-blocking.rs | 12 +- .../zedboard/src/bin/uart-non-blocking.rs | 12 +- examples/zedboard/src/main.rs | 97 +++++------- zedboard-fsbl/src/main.rs | 16 +- zedboard-qspi-flasher/Cargo.toml | 14 ++ zedboard-qspi-flasher/src/main.rs | 139 ++++++++++++++++++ zynq7000-hal/src/clocks/mod.rs | 7 +- zynq7000-hal/src/devcfg.rs | 7 +- zynq7000-hal/src/lib.rs | 58 +++++++- zynq7000-hal/src/qspi/mod.rs | 8 +- zynq7000-hal/src/uart/mod.rs | 56 +++---- zynq7000/src/devcfg.rs | 5 +- zynq7000/src/lib.rs | 9 +- 25 files changed, 416 insertions(+), 265 deletions(-) create mode 100644 zedboard-qspi-flasher/Cargo.toml create mode 100644 zedboard-qspi-flasher/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 189dc5e..5c9db71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ members = [ "zynq-mmu", "zedboard-fsbl", "zedboard-bsp", - "zynq-boot-image", + "zynq-boot-image", "zedboard-qspi-flasher", ] exclude = [ diff --git a/examples/embassy/src/bin/dht22-open-drain-pins.rs b/examples/embassy/src/bin/dht22-open-drain-pins.rs index 34ed594..0c66df0 100644 --- a/examples/embassy/src/bin/dht22-open-drain-pins.rs +++ b/examples/embassy/src/bin/dht22-open-drain-pins.rs @@ -17,10 +17,10 @@ use zynq7000_hal::{ gtc::GlobalTimerCounter, l2_cache, time::Hertz, - uart::{ClockConfigRaw, Uart, UartConfig}, + uart::{ClockConfig, Config, Uart}, }; -use zynq7000::PsPeripherals; +use zynq7000::Peripherals; use zynq7000_rt as _; // Define the clock frequency as a constant @@ -44,7 +44,7 @@ const OPEN_DRAIN_PINS_MIO9_TO_MIO14: bool = false; #[embassy_executor::main] #[unsafe(export_name = "main")] async fn main(_spawner: Spawner) -> ! { - let mut dp = PsPeripherals::take().unwrap(); + let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); // Clock was already initialized by PS7 Init TCL script or FSBL, we just read it. @@ -64,12 +64,12 @@ async fn main(_spawner: Spawner) -> ! { zynq7000_embassy::init(clocks.arm_clocks(), gtc); // Set up the UART, we are logging with it. - let uart_clk_config = ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200) + let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; let mut uart = Uart::new_with_mio( dp.uart_1, - UartConfig::new_with_clk_config(uart_clk_config), + Config::new_with_clk_config(uart_clk_config), (mio_pins.mio48, mio_pins.mio49), ) .unwrap(); diff --git a/examples/embassy/src/bin/logger-non-blocking.rs b/examples/embassy/src/bin/logger-non-blocking.rs index 5f5169d..3c09354 100644 --- a/examples/embassy/src/bin/logger-non-blocking.rs +++ b/examples/embassy/src/bin/logger-non-blocking.rs @@ -9,7 +9,7 @@ use embassy_time::{Duration, Ticker}; use embedded_hal::digital::StatefulOutputPin; use embedded_io::Write; use log::{error, info}; -use zynq7000::PsPeripherals; +use zynq7000::Peripherals; use zynq7000_hal::{ BootMode, clocks::Clocks, @@ -18,7 +18,7 @@ use zynq7000_hal::{ gtc::GlobalTimerCounter, l2_cache, time::Hertz, - uart::{ClockConfigRaw, TxAsync, Uart, UartConfig, on_interrupt_tx}, + uart::{ClockConfig, Config, TxAsync, Uart, on_interrupt_tx}, }; use zynq7000_rt as _; @@ -38,7 +38,7 @@ pub extern "C" fn boot_core(cpu_id: u32) -> ! { #[unsafe(export_name = "main")] #[embassy_executor::main] async fn main(spawner: Spawner) -> ! { - let mut dp = PsPeripherals::take().unwrap(); + let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); // Clock was already initialized by PS7 Init TCL script or FSBL, we just read it. @@ -58,12 +58,12 @@ async fn main(spawner: Spawner) -> ! { let mio_pins = mio::Pins::new(dp.gpio); // Set up the UART, we are logging with it. - let uart_clk_config = ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200) + let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; let mut uart = Uart::new_with_mio( dp.uart_1, - UartConfig::new_with_clk_config(uart_clk_config), + Config::new_with_clk_config(uart_clk_config), (mio_pins.mio48, mio_pins.mio49), ) .unwrap(); diff --git a/examples/embassy/src/bin/pwm.rs b/examples/embassy/src/bin/pwm.rs index 6f1a9a1..31f9034 100644 --- a/examples/embassy/src/bin/pwm.rs +++ b/examples/embassy/src/bin/pwm.rs @@ -23,10 +23,10 @@ use zynq7000_hal::{ gtc::GlobalTimerCounter, l2_cache, time::Hertz, - uart::{ClockConfigRaw, Uart, UartConfig}, + uart::{ClockConfig, Config, Uart}, }; -use zynq7000::PsPeripherals; +use zynq7000::Peripherals; use zynq7000_rt as _; // Define the clock frequency as a constant @@ -44,7 +44,7 @@ pub extern "C" fn boot_core(cpu_id: u32) -> ! { #[embassy_executor::main] #[unsafe(export_name = "main")] async fn main(_spawner: Spawner) -> ! { - let mut dp = PsPeripherals::take().unwrap(); + let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); // Clock was already initialized by PS7 Init TCL script or FSBL, we just read it. @@ -71,12 +71,12 @@ async fn main(_spawner: Spawner) -> ! { pwm.set_duty_cycle_percent(50).unwrap(); // Set up the UART, we are logging with it. - let uart_clk_config = ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200) + let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; let mut uart = Uart::new_with_mio( dp.uart_1, - UartConfig::new_with_clk_config(uart_clk_config), + Config::new_with_clk_config(uart_clk_config), (mio_pins.mio48, mio_pins.mio49), ) .unwrap(); diff --git a/examples/embassy/src/main.rs b/examples/embassy/src/main.rs index 19bdfda..afbdfe4 100644 --- a/examples/embassy/src/main.rs +++ b/examples/embassy/src/main.rs @@ -8,18 +8,8 @@ use embassy_time::{Duration, Ticker}; use embedded_hal::digital::StatefulOutputPin; use embedded_io::Write; use log::{error, info}; -use zynq7000_hal::{ - BootMode, - clocks::Clocks, - gic::{GicConfigurator, GicInterruptHelper, Interrupt}, - gpio::{Output, PinState, mio}, - gtc::GlobalTimerCounter, - l2_cache, - time::Hertz, - uart::{ClockConfigRaw, Uart, UartConfig}, -}; +use zynq7000_hal::{clocks, gic, gpio, gtc, time::Hertz, uart, BootMode, InteruptConfig}; -use zynq7000::PsPeripherals; use zynq7000_rt as _; // Define the clock frequency as a constant @@ -37,32 +27,27 @@ pub extern "C" fn boot_core(cpu_id: u32) -> ! { #[embassy_executor::main] #[unsafe(export_name = "main")] async fn main(_spawner: Spawner) -> ! { - let mut dp = PsPeripherals::take().unwrap(); - l2_cache::init_with_defaults(&mut dp.l2c); - - // Clock was already initialized by PS7 Init TCL script or FSBL, we just read it. - let clocks = Clocks::new_from_regs(PS_CLOCK_FREQUENCY).unwrap(); - // Set up the global interrupt controller. - let mut gic = GicConfigurator::new_with_init(dp.gicc, dp.gicd); - gic.enable_all_interrupts(); - gic.set_all_spi_interrupt_targets_cpu0(); - gic.enable(); - unsafe { - gic.enable_interrupts(); - } - let mio_pins = mio::Pins::new(dp.gpio); + let periphs = zynq7000_hal::init(zynq7000_hal::Config { + init_l2_cache: true, + level_shifter_config: Some(zynq7000_hal::LevelShifterConfig::EnableAll), + interrupt_config: Some(InteruptConfig::AllInterruptsToCpu0), + }) + .unwrap(); + let clocks = clocks::Clocks::new_from_regs(PS_CLOCK_FREQUENCY).unwrap(); // Set up global timer counter and embassy time driver. - let gtc = GlobalTimerCounter::new(dp.gtc, clocks.arm_clocks()); + let gtc = gtc::GlobalTimerCounter::new(periphs.gtc, clocks.arm_clocks()); zynq7000_embassy::init(clocks.arm_clocks(), gtc); + let mio_pins = gpio::mio::Pins::new(periphs.gpio); + // Set up the UART, we are logging with it. - let uart_clk_config = ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200) + let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; - let mut uart = Uart::new_with_mio( - dp.uart_1, - UartConfig::new_with_clk_config(uart_clk_config), + let mut uart = uart::Uart::new_with_mio( + periphs.uart_1, + uart::Config::new_with_clk_config(uart_clk_config), (mio_pins.mio48, mio_pins.mio49), ) .unwrap(); @@ -81,7 +66,7 @@ async fn main(_spawner: Spawner) -> ! { info!("Boot mode: {:?}", boot_mode); let mut ticker = Ticker::every(Duration::from_millis(1000)); - let mut led = Output::new_for_mio(mio_pins.mio7, PinState::Low); + let mut led = gpio::Output::new_for_mio(mio_pins.mio7, gpio::PinState::Low); loop { info!("Hello, world!"); led.toggle().unwrap(); @@ -89,42 +74,42 @@ async fn main(_spawner: Spawner) -> ! { } } -#[unsafe(no_mangle)] -pub extern "C" fn _irq_handler() { - let mut gic_helper = GicInterruptHelper::new(); +#[zynq7000_rt::irq] +pub fn irq_handler() { + let mut gic_helper = gic::GicInterruptHelper::new(); let irq_info = gic_helper.acknowledge_interrupt(); match irq_info.interrupt() { - Interrupt::Sgi(_) => (), - Interrupt::Ppi(ppi_interrupt) => { + gic::Interrupt::Sgi(_) => (), + gic::Interrupt::Ppi(ppi_interrupt) => { if ppi_interrupt == zynq7000_hal::gic::PpiInterrupt::GlobalTimer { unsafe { zynq7000_embassy::on_interrupt(); } } } - Interrupt::Spi(_spi_interrupt) => (), - Interrupt::Invalid(_) => (), - Interrupt::Spurious => (), + gic::Interrupt::Spi(_spi_interrupt) => (), + gic::Interrupt::Invalid(_) => (), + gic::Interrupt::Spurious => (), } gic_helper.end_of_interrupt(irq_info); } -#[unsafe(no_mangle)] -pub extern "C" fn _abort_handler() { +#[zynq7000_rt::exception(DataAbort)] +fn data_abort_handler(_faulting_addr: usize) -> ! { loop { nop(); } } -#[unsafe(no_mangle)] -pub extern "C" fn _undefined_handler() { +#[zynq7000_rt::exception(Undefined)] +fn undefined_handler(_faulting_addr: usize) -> ! { loop { nop(); } } -#[unsafe(no_mangle)] -pub extern "C" fn _prefetch_handler() { +#[zynq7000_rt::exception(PrefetchAbort)] +fn prefetch_handler(_faulting_addr: usize) -> ! { loop { nop(); } diff --git a/examples/simple/src/bin/gtc-ticks.rs b/examples/simple/src/bin/gtc-ticks.rs index f591805..895c839 100644 --- a/examples/simple/src/bin/gtc-ticks.rs +++ b/examples/simple/src/bin/gtc-ticks.rs @@ -15,7 +15,7 @@ use zynq7000_hal::{ l2_cache, prelude::*, time::Hertz, - uart::{ClockConfigRaw, Uart, UartConfig}, + uart::{ClockConfig, Config, Uart}, }; use zynq7000_rt as _; @@ -36,7 +36,7 @@ pub extern "C" fn boot_core(cpu_id: u32) -> ! { #[unsafe(export_name = "main")] pub fn main() -> ! { - let mut dp = zynq7000::PsPeripherals::take().unwrap(); + let mut dp = zynq7000::Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); // Clock was already initialized by PS7 Init TCL script or FSBL, we just read it. @@ -49,7 +49,7 @@ pub fn main() -> ! { // Enable interrupt exception. unsafe { gic.enable_interrupts() }; // Set up the UART, we are logging with it. - let uart_clk_config = ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200) + let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; let mut gtc = GlobalTimerCounter::new(dp.gtc, clocks.arm_clocks()); @@ -64,7 +64,7 @@ pub fn main() -> ! { let mio_pins = mio::Pins::new(dp.gpio); let mut uart = Uart::new_with_mio( dp.uart_1, - UartConfig::new_with_clk_config(uart_clk_config), + Config::new_with_clk_config(uart_clk_config), (mio_pins.mio48, mio_pins.mio49), ) .unwrap(); diff --git a/examples/simple/src/bin/logger.rs b/examples/simple/src/bin/logger.rs index 6ec71a3..3e6cd38 100644 --- a/examples/simple/src/bin/logger.rs +++ b/examples/simple/src/bin/logger.rs @@ -16,7 +16,7 @@ use zynq7000_hal::{ l2_cache, prelude::*, time::Hertz, - uart::{ClockConfigRaw, Uart, UartConfig}, + uart::{ClockConfig, Config, Uart}, }; use zynq7000_rt as _; @@ -37,7 +37,7 @@ pub extern "C" fn boot_core(cpu_id: u32) -> ! { #[unsafe(export_name = "main")] pub fn main() -> ! { - let mut dp = zynq7000::PsPeripherals::take().unwrap(); + let mut dp = zynq7000::Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); // Clock was already initialized by PS7 Init TCL script or FSBL, we just read it. @@ -50,7 +50,7 @@ pub fn main() -> ! { // Enable interrupt exception. unsafe { gic.enable_interrupts() }; // Set up the UART, we are logging with it. - let uart_clk_config = ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200) + let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; let mut gtc = GlobalTimerCounter::new(dp.gtc, clocks.arm_clocks()); @@ -64,7 +64,7 @@ pub fn main() -> ! { let mut uart = Uart::new_with_mio( dp.uart_1, - UartConfig::new_with_clk_config(uart_clk_config), + Config::new_with_clk_config(uart_clk_config), (mio_pins.mio48, mio_pins.mio49), ) .unwrap(); diff --git a/examples/simple/src/main.rs b/examples/simple/src/main.rs index 4512126..9c822f0 100644 --- a/examples/simple/src/main.rs +++ b/examples/simple/src/main.rs @@ -5,7 +5,7 @@ use core::panic::PanicInfo; use cortex_ar::asm::nop; use embedded_hal::{delay::DelayNs, digital::StatefulOutputPin}; -use zynq7000::PsPeripherals; +use zynq7000::Peripherals; use zynq7000_hal::{ clocks::Clocks, gpio::{Output, PinState, mio}, @@ -56,7 +56,7 @@ pub fn main() -> ! { } } Lib::Hal => { - let dp = PsPeripherals::take().unwrap(); + let dp = Peripherals::take().unwrap(); let clocks = Clocks::new_from_regs(PS_CLOCK_FREQUENCY).unwrap(); // Unwrap okay, we only call this once on core 0 here. let mut cpu_tim = CpuPrivateTimer::take(clocks.arm_clocks()).unwrap(); diff --git a/examples/zedboard/src/bin/ethernet.rs b/examples/zedboard/src/bin/ethernet.rs index 4e2a27e..6f5eabb 100644 --- a/examples/zedboard/src/bin/ethernet.rs +++ b/examples/zedboard/src/bin/ethernet.rs @@ -46,10 +46,10 @@ use zynq7000_hal::{ gpio::{GpioPins, Output, PinState}, gtc::GlobalTimerCounter, l2_cache, - uart::{ClockConfigRaw, Uart, UartConfig}, + uart::{ClockConfig, Config, Uart}, }; -use zynq7000::{PsPeripherals, slcr::LevelShifterConfig}; +use zynq7000::{Peripherals, slcr::LevelShifterConfig}; use zynq7000_rt::{self as _, mmu::section_attrs::SHAREABLE_DEVICE, mmu_l1_table_mut}; const USE_DHCP: bool = true; @@ -206,7 +206,7 @@ async fn tcp_task(mut tcp: TcpSocket<'static>) -> ! { #[embassy_executor::main] #[unsafe(export_name = "main")] async fn main(spawner: Spawner) -> ! { - let mut dp = PsPeripherals::take().unwrap(); + let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); // Enable PS-PL level shifters. @@ -234,12 +234,12 @@ async fn main(spawner: Spawner) -> ! { zynq7000_embassy::init(clocks.arm_clocks(), gtc); // Set up the UART, we are logging with it. - let uart_clk_config = ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200) + let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; let mut uart = Uart::new_with_mio( dp.uart_1, - UartConfig::new_with_clk_config(uart_clk_config), + Config::new_with_clk_config(uart_clk_config), (gpio_pins.mio.mio48, gpio_pins.mio.mio49), ) .unwrap(); diff --git a/examples/zedboard/src/bin/l3gd20h-i2c-mio.rs b/examples/zedboard/src/bin/l3gd20h-i2c-mio.rs index 20afae3..cfb3e6b 100644 --- a/examples/zedboard/src/bin/l3gd20h-i2c-mio.rs +++ b/examples/zedboard/src/bin/l3gd20h-i2c-mio.rs @@ -29,7 +29,7 @@ use zynq7000_hal::{ uart, }; -use zynq7000::{PsPeripherals, slcr::LevelShifterConfig}; +use zynq7000::{Peripherals, slcr::LevelShifterConfig}; use zynq7000_rt as _; // Define the clock frequency as a constant @@ -48,7 +48,7 @@ pub extern "C" fn boot_core(cpu_id: u32) -> ! { #[embassy_executor::main] #[unsafe(export_name = "main")] async fn main(_spawner: Spawner) -> ! { - let mut dp = PsPeripherals::take().unwrap(); + let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); // Enable PS-PL level shifters. @@ -73,12 +73,12 @@ async fn main(_spawner: Spawner) -> ! { zynq7000_embassy::init(clocks.arm_clocks(), gtc); // Set up the UART, we are logging with it. - let uart_clk_config = uart::ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200) + let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; let mut uart = uart::Uart::new_with_mio( dp.uart_1, - uart::UartConfig::new_with_clk_config(uart_clk_config), + uart::Config::new_with_clk_config(uart_clk_config), (gpio_pins.mio.mio48, gpio_pins.mio.mio49), ) .unwrap(); diff --git a/examples/zedboard/src/bin/l3gd20h-spi-mio.rs b/examples/zedboard/src/bin/l3gd20h-spi-mio.rs index ceee881..14f6bd6 100644 --- a/examples/zedboard/src/bin/l3gd20h-spi-mio.rs +++ b/examples/zedboard/src/bin/l3gd20h-spi-mio.rs @@ -30,7 +30,7 @@ use zynq7000_hal::{ uart::{self, TxAsync, on_interrupt_tx}, }; -use zynq7000::{PsPeripherals, slcr::LevelShifterConfig, spi::DelayControl}; +use zynq7000::{Peripherals, slcr::LevelShifterConfig, spi::DelayControl}; use zynq7000_rt as _; // Define the clock frequency as a constant @@ -51,7 +51,7 @@ pub extern "C" fn boot_core(cpu_id: u32) -> ! { #[embassy_executor::main] #[unsafe(export_name = "main")] async fn main(spawner: Spawner) -> ! { - let mut dp = PsPeripherals::take().unwrap(); + let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); // Enable PS-PL level shifters. @@ -83,12 +83,12 @@ async fn main(spawner: Spawner) -> ! { zynq7000_embassy::init(clocks.arm_clocks(), gtc); // Set up the UART, we are logging with it. - let uart_clk_config = uart::ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200) + let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; let mut uart = uart::Uart::new_with_mio( dp.uart_1, - uart::UartConfig::new_with_clk_config(uart_clk_config), + uart::Config::new_with_clk_config(uart_clk_config), (gpio_pins.mio.mio48, gpio_pins.mio.mio49), ) .unwrap(); diff --git a/examples/zedboard/src/bin/qspi.rs b/examples/zedboard/src/bin/qspi.rs index 9dff48c..7c1e30f 100644 --- a/examples/zedboard/src/bin/qspi.rs +++ b/examples/zedboard/src/bin/qspi.rs @@ -10,23 +10,8 @@ use embedded_io::Write; use log::{error, info}; use zedboard::PS_CLOCK_FREQUENCY; use zedboard_bsp::qspi_spansion; -use zynq7000_hal::{ - BootMode, - clocks::Clocks, - configure_level_shifter, - gic::{GicConfigurator, GicInterruptHelper, Interrupt}, - gpio::{GpioPins, Output, PinState}, - gtc::GlobalTimerCounter, - l2_cache, - prelude::*, - qspi, - uart::{ClockConfigRaw, Uart, UartConfig}, -}; +use zynq7000_hal::{clocks, gic, gpio, gtc, prelude::*, qspi, uart, BootMode}; -use zynq7000::{ - PsPeripherals, - slcr::{LevelShifterConfig, clocks::SrcSelIo}, -}; use zynq7000_rt as _; const INIT_STRING: &str = "-- Zynq 7000 Zedboard QSPI example --\n\r"; @@ -50,35 +35,28 @@ const ERASE_PROGRAM_READ_TEST: bool = false; #[embassy_executor::main] #[unsafe(export_name = "main")] async fn main(_spawner: Spawner) -> ! { - let mut dp = PsPeripherals::take().unwrap(); - l2_cache::init_with_defaults(&mut dp.l2c); - - // Enable PS-PL level shifters. - configure_level_shifter(LevelShifterConfig::EnableAll); - + let periphs = zynq7000_hal::init(zynq7000_hal::Config { + init_l2_cache: true, + level_shifter_config: Some(zynq7000_hal::LevelShifterConfig::EnableAll), + interrupt_config: Some(zynq7000_hal::InteruptConfig::AllInterruptsToCpu0), + }) + .unwrap(); // Clock was already initialized by PS7 Init TCL script or FSBL, we just read it. - let clocks = Clocks::new_from_regs(PS_CLOCK_FREQUENCY).unwrap(); - // Set up the global interrupt controller. - let mut gic = GicConfigurator::new_with_init(dp.gicc, dp.gicd); - gic.enable_all_interrupts(); - gic.set_all_spi_interrupt_targets_cpu0(); - gic.enable(); - unsafe { - gic.enable_interrupts(); - } - let gpio_pins = GpioPins::new(dp.gpio); + let clocks = clocks::Clocks::new_from_regs(PS_CLOCK_FREQUENCY).unwrap(); + + let gpio_pins = gpio::GpioPins::new(periphs.gpio); // Set up global timer counter and embassy time driver. - let gtc = GlobalTimerCounter::new(dp.gtc, clocks.arm_clocks()); + let gtc = gtc::GlobalTimerCounter::new(periphs.gtc, clocks.arm_clocks()); zynq7000_embassy::init(clocks.arm_clocks(), gtc); // Set up the UART, we are logging with it. - let uart_clk_config = ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200) + let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; - let mut uart = Uart::new_with_mio( - dp.uart_1, - UartConfig::new_with_clk_config(uart_clk_config), + let mut uart = uart::Uart::new_with_mio( + periphs.uart_1, + uart::Config::new_with_clk_config(uart_clk_config), (gpio_pins.mio.mio48, gpio_pins.mio.mio49), ) .unwrap(); @@ -96,10 +74,10 @@ async fn main(_spawner: Spawner) -> ! { info!("Boot mode: {:?}", boot_mode); let qspi_clock_config = - qspi::ClockConfig::calculate_with_loopback(SrcSelIo::IoPll, &clocks, 100.MHz()) + qspi::ClockConfig::calculate_with_loopback(qspi::SrcSelIo::IoPll, &clocks, 100.MHz()) .expect("QSPI clock calculation failed"); let qspi = qspi::Qspi::new_single_qspi_with_feedback( - dp.qspi, + periphs.qspi, qspi_clock_config, embedded_hal::spi::MODE_0, qspi::IoType::LvCmos33, @@ -176,7 +154,7 @@ async fn main(_spawner: Spawner) -> ! { let mut ticker = Ticker::every(Duration::from_millis(200)); - let mut mio_led = Output::new_for_mio(gpio_pins.mio.mio7, PinState::Low); + let mut mio_led = gpio::Output::new_for_mio(gpio_pins.mio.mio7, gpio::PinState::Low); loop { mio_led.toggle().unwrap(); @@ -184,42 +162,42 @@ async fn main(_spawner: Spawner) -> ! { } } -#[unsafe(no_mangle)] -pub extern "C" fn _irq_handler() { - let mut gic_helper = GicInterruptHelper::new(); +#[zynq7000_rt::irq] +fn irq_handler() { + let mut gic_helper = gic::GicInterruptHelper::new(); let irq_info = gic_helper.acknowledge_interrupt(); match irq_info.interrupt() { - Interrupt::Sgi(_) => (), - Interrupt::Ppi(ppi_interrupt) => { - if ppi_interrupt == zynq7000_hal::gic::PpiInterrupt::GlobalTimer { + gic::Interrupt::Sgi(_) => (), + gic::Interrupt::Ppi(ppi_interrupt) => { + if ppi_interrupt == gic::PpiInterrupt::GlobalTimer { unsafe { zynq7000_embassy::on_interrupt(); } } } - Interrupt::Spi(_spi_interrupt) => (), - Interrupt::Invalid(_) => (), - Interrupt::Spurious => (), + gic::Interrupt::Spi(_spi_interrupt) => (), + gic::Interrupt::Invalid(_) => (), + gic::Interrupt::Spurious => (), } gic_helper.end_of_interrupt(irq_info); } -#[unsafe(no_mangle)] -pub extern "C" fn _abort_handler() { +#[zynq7000_rt::exception(DataAbort)] +fn data_abort_handler(_faulting_addr: usize) -> ! { loop { nop(); } } -#[unsafe(no_mangle)] -pub extern "C" fn _undefined_handler() { +#[zynq7000_rt::exception(Undefined)] +fn undefined_handler(_faulting_addr: usize) -> ! { loop { nop(); } } -#[unsafe(no_mangle)] -pub extern "C" fn _prefetch_handler() { +#[zynq7000_rt::exception(PrefetchAbort)] +fn prefetch_handler(_faulting_addr: usize) -> ! { loop { nop(); } diff --git a/examples/zedboard/src/bin/uart-blocking.rs b/examples/zedboard/src/bin/uart-blocking.rs index 568d320..afdb631 100644 --- a/examples/zedboard/src/bin/uart-blocking.rs +++ b/examples/zedboard/src/bin/uart-blocking.rs @@ -20,10 +20,10 @@ use zynq7000_hal::{ gpio::{GpioPins, Output, PinState}, gtc::GlobalTimerCounter, l2_cache, - uart::{ClockConfigRaw, Uart, UartConfig}, + uart::{ClockConfig, Config, Uart}, }; -use zynq7000::{PsPeripherals, slcr::LevelShifterConfig}; +use zynq7000::{Peripherals, slcr::LevelShifterConfig}; use zynq7000_rt as _; const INIT_STRING: &str = "-- Zynq 7000 Zedboard blocking UART example --\n\r"; @@ -101,7 +101,7 @@ impl UartMultiplexer { #[embassy_executor::main] #[unsafe(export_name = "main")] async fn main(_spawner: Spawner) -> ! { - let mut dp = PsPeripherals::take().unwrap(); + let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); // Enable PS-PL level shifters. @@ -123,12 +123,12 @@ async fn main(_spawner: Spawner) -> ! { zynq7000_embassy::init(clocks.arm_clocks(), gtc); // Set up the UART, we are logging with it. - let uart_clk_config = ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200) + let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; let mut log_uart = Uart::new_with_mio( dp.uart_1, - UartConfig::new_with_clk_config(uart_clk_config), + Config::new_with_clk_config(uart_clk_config), (gpio_pins.mio.mio48, gpio_pins.mio.mio49), ) .unwrap(); @@ -145,7 +145,7 @@ async fn main(_spawner: Spawner) -> ! { // UART0 routed through EMIO to PL pins. let mut uart_0 = - Uart::new_with_emio(dp.uart_0, UartConfig::new_with_clk_config(uart_clk_config)).unwrap(); + Uart::new_with_emio(dp.uart_0, Config::new_with_clk_config(uart_clk_config)).unwrap(); // Safety: Valid address of AXI UARTLITE. let mut uartlite = unsafe { AxiUartlite::new(AXI_UARTLITE_BASE_ADDR) }; diff --git a/examples/zedboard/src/bin/uart-non-blocking.rs b/examples/zedboard/src/bin/uart-non-blocking.rs index 107be3d..1b3064d 100644 --- a/examples/zedboard/src/bin/uart-non-blocking.rs +++ b/examples/zedboard/src/bin/uart-non-blocking.rs @@ -47,7 +47,7 @@ use zynq7000_hal::{ gtc::GlobalTimerCounter, l2_cache, time::Hertz, - uart::{ClockConfigRaw, Uart, UartConfig}, + uart::{ClockConfig, Config, Uart}, }; pub enum UartMode { @@ -62,7 +62,7 @@ const INIT_STRING: &str = "-- Zynq 7000 Zedboard non-blocking UART example --\n\ #[global_allocator] static HEAP: Heap = Heap::empty(); -use zynq7000::{PsPeripherals, slcr::LevelShifterConfig}; +use zynq7000::{Peripherals, slcr::LevelShifterConfig}; use zynq7000_rt as _; // Define the clock frequency as a constant @@ -166,7 +166,7 @@ impl UartMultiplexer { #[embassy_executor::main] #[unsafe(export_name = "main")] async fn main(spawner: Spawner) -> ! { - let mut dp = PsPeripherals::take().unwrap(); + let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); // Enable PS-PL level shifters. @@ -194,12 +194,12 @@ async fn main(spawner: Spawner) -> ! { zynq7000_embassy::init(clocks.arm_clocks(), gtc); // Set up the UART, we are logging with it. - let uart_clk_config = ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200) + let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; let mut log_uart = Uart::new_with_mio( dp.uart_1, - UartConfig::new_with_clk_config(uart_clk_config), + Config::new_with_clk_config(uart_clk_config), (gpio_pins.mio.mio48, gpio_pins.mio.mio49), ) .unwrap(); @@ -237,7 +237,7 @@ async fn main(spawner: Spawner) -> ! { // UART0 routed through EMIO to PL pins. let uart_0 = - Uart::new_with_emio(dp.uart_0, UartConfig::new_with_clk_config(uart_clk_config)).unwrap(); + Uart::new_with_emio(dp.uart_0, Config::new_with_clk_config(uart_clk_config)).unwrap(); // Safety: Valid address of AXI UARTLITE. let mut uartlite = unsafe { AxiUartlite::new(AXI_UARTLITE_BASE_ADDR) }; // We need to call this before splitting the structure, because the interrupt signal is diff --git a/examples/zedboard/src/main.rs b/examples/zedboard/src/main.rs index 8ee3160..b08c435 100644 --- a/examples/zedboard/src/main.rs +++ b/examples/zedboard/src/main.rs @@ -9,18 +9,8 @@ use embedded_hal::digital::StatefulOutputPin; use embedded_io::Write; use log::{error, info}; use zedboard::PS_CLOCK_FREQUENCY; -use zynq7000_hal::{ - BootMode, - clocks::Clocks, - configure_level_shifter, - gic::{GicConfigurator, GicInterruptHelper, Interrupt}, - gpio::{GpioPins, Output, PinState}, - gtc::GlobalTimerCounter, - l2_cache, - uart::{ClockConfigRaw, Uart, UartConfig}, -}; +use zynq7000_hal::{clocks, gic, gpio, gtc, uart, BootMode}; -use zynq7000::{PsPeripherals, slcr::LevelShifterConfig}; use zynq7000_rt as _; const INIT_STRING: &str = "-- Zynq 7000 Zedboard GPIO blinky example --\n\r"; @@ -37,35 +27,28 @@ pub extern "C" fn boot_core(cpu_id: u32) -> ! { #[embassy_executor::main] #[unsafe(export_name = "main")] async fn main(_spawner: Spawner) -> ! { - let mut dp = PsPeripherals::take().unwrap(); - l2_cache::init_with_defaults(&mut dp.l2c); - - // Enable PS-PL level shifters. - configure_level_shifter(LevelShifterConfig::EnableAll); - + let periphs = zynq7000_hal::init(zynq7000_hal::Config { + init_l2_cache: true, + level_shifter_config: Some(zynq7000_hal::LevelShifterConfig::EnableAll), + interrupt_config: Some(zynq7000_hal::InteruptConfig::AllInterruptsToCpu0), + }) + .unwrap(); // Clock was already initialized by PS7 Init TCL script or FSBL, we just read it. - let clocks = Clocks::new_from_regs(PS_CLOCK_FREQUENCY).unwrap(); - // Set up the global interrupt controller. - let mut gic = GicConfigurator::new_with_init(dp.gicc, dp.gicd); - gic.enable_all_interrupts(); - gic.set_all_spi_interrupt_targets_cpu0(); - gic.enable(); - unsafe { - gic.enable_interrupts(); - } - let mut gpio_pins = GpioPins::new(dp.gpio); + let clocks = clocks::Clocks::new_from_regs(PS_CLOCK_FREQUENCY).unwrap(); + + let mut gpio_pins = gpio::GpioPins::new(periphs.gpio); // Set up global timer counter and embassy time driver. - let gtc = GlobalTimerCounter::new(dp.gtc, clocks.arm_clocks()); + let gtc = gtc::GlobalTimerCounter::new(periphs.gtc, clocks.arm_clocks()); zynq7000_embassy::init(clocks.arm_clocks(), gtc); // Set up the UART, we are logging with it. - let uart_clk_config = ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200) + let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; - let mut uart = Uart::new_with_mio( - dp.uart_1, - UartConfig::new_with_clk_config(uart_clk_config), + let mut uart = uart::Uart::new_with_mio( + periphs.uart_1, + uart::Config::new_with_clk_config(uart_clk_config), (gpio_pins.mio.mio48, gpio_pins.mio.mio49), ) .unwrap(); @@ -84,16 +67,16 @@ async fn main(_spawner: Spawner) -> ! { let mut ticker = Ticker::every(Duration::from_millis(200)); - let mut mio_led = Output::new_for_mio(gpio_pins.mio.mio7, PinState::Low); - let mut emio_leds: [Output; 8] = [ - Output::new_for_emio(gpio_pins.emio.take(0).unwrap(), PinState::Low), - Output::new_for_emio(gpio_pins.emio.take(1).unwrap(), PinState::Low), - Output::new_for_emio(gpio_pins.emio.take(2).unwrap(), PinState::Low), - Output::new_for_emio(gpio_pins.emio.take(3).unwrap(), PinState::Low), - Output::new_for_emio(gpio_pins.emio.take(4).unwrap(), PinState::Low), - Output::new_for_emio(gpio_pins.emio.take(5).unwrap(), PinState::Low), - Output::new_for_emio(gpio_pins.emio.take(6).unwrap(), PinState::Low), - Output::new_for_emio(gpio_pins.emio.take(7).unwrap(), PinState::Low), + let mut mio_led = gpio::Output::new_for_mio(gpio_pins.mio.mio7, gpio::PinState::Low); + let mut emio_leds: [gpio::Output; 8] = [ + gpio::Output::new_for_emio(gpio_pins.emio.take(0).unwrap(), gpio::PinState::Low), + gpio::Output::new_for_emio(gpio_pins.emio.take(1).unwrap(), gpio::PinState::Low), + gpio::Output::new_for_emio(gpio_pins.emio.take(2).unwrap(), gpio::PinState::Low), + gpio::Output::new_for_emio(gpio_pins.emio.take(3).unwrap(), gpio::PinState::Low), + gpio::Output::new_for_emio(gpio_pins.emio.take(4).unwrap(), gpio::PinState::Low), + gpio::Output::new_for_emio(gpio_pins.emio.take(5).unwrap(), gpio::PinState::Low), + gpio::Output::new_for_emio(gpio_pins.emio.take(6).unwrap(), gpio::PinState::Low), + gpio::Output::new_for_emio(gpio_pins.emio.take(7).unwrap(), gpio::PinState::Low), ]; loop { mio_led.toggle().unwrap(); @@ -108,42 +91,42 @@ async fn main(_spawner: Spawner) -> ! { } } -#[unsafe(no_mangle)] -pub extern "C" fn _irq_handler() { - let mut gic_helper = GicInterruptHelper::new(); +#[zynq7000_rt::irq] +fn irq_handler() { + let mut gic_helper = gic::GicInterruptHelper::new(); let irq_info = gic_helper.acknowledge_interrupt(); match irq_info.interrupt() { - Interrupt::Sgi(_) => (), - Interrupt::Ppi(ppi_interrupt) => { - if ppi_interrupt == zynq7000_hal::gic::PpiInterrupt::GlobalTimer { + gic::Interrupt::Sgi(_) => (), + gic::Interrupt::Ppi(ppi_interrupt) => { + if ppi_interrupt == gic::PpiInterrupt::GlobalTimer { unsafe { zynq7000_embassy::on_interrupt(); } } } - Interrupt::Spi(_spi_interrupt) => (), - Interrupt::Invalid(_) => (), - Interrupt::Spurious => (), + gic::Interrupt::Spi(_spi_interrupt) => (), + gic::Interrupt::Invalid(_) => (), + gic::Interrupt::Spurious => (), } gic_helper.end_of_interrupt(irq_info); } -#[unsafe(no_mangle)] -pub extern "C" fn _abort_handler() { +#[zynq7000_rt::exception(DataAbort)] +fn data_abort_handler(_faulting_addr: usize) -> ! { loop { nop(); } } -#[unsafe(no_mangle)] -pub extern "C" fn _undefined_handler() { +#[zynq7000_rt::exception(Undefined)] +fn undefined_handler(_faulting_addr: usize) -> ! { loop { nop(); } } -#[unsafe(no_mangle)] -pub extern "C" fn _prefetch_handler() { +#[zynq7000_rt::exception(PrefetchAbort)] +fn prefetch_handler(_faulting_addr: usize) -> ! { loop { nop(); } diff --git a/zedboard-fsbl/src/main.rs b/zedboard-fsbl/src/main.rs index 3078c7d..a7e1d68 100644 --- a/zedboard-fsbl/src/main.rs +++ b/zedboard-fsbl/src/main.rs @@ -8,21 +8,21 @@ use cortex_ar::asm::nop; use embedded_io::Write as _; use log::{error, info}; use zedboard_bsp::qspi_spansion::{self, QspiSpansionS25Fl256SLinearMode}; +use zynq_boot_image::DestinationDevice; use zynq7000_hal::{ + BootMode, clocks::{ - pll::{configure_arm_pll, configure_io_pll, PllConfig}, Clocks, + pll::{PllConfig, configure_arm_pll, configure_io_pll}, }, - ddr::{configure_ddr_for_ddr3, memtest, DdrClockSetupConfig}, + ddr::{DdrClockSetupConfig, configure_ddr_for_ddr3, memtest}, gic, gpio, l2_cache, prelude::*, qspi, time::Hertz, - uart::{ClockConfigRaw, Uart, UartConfig}, - BootMode, + uart::{ClockConfig, Config, Uart}, }; use zynq7000_rt as _; -use zynq_boot_image::DestinationDevice; use crate::ddr_cfg::{DDRC_CONFIG_ZEDBOARD_FULL_BUILDERS, DDRIOB_CONFIG_SET_ZEDBOARD}; @@ -80,7 +80,7 @@ pub fn main() -> ! { PllConfig::new_from_target_clock(PS_CLK, IO_CLK).unwrap(), ); - let mut dp = zynq7000::PsPeripherals::take().unwrap(); + let mut dp = zynq7000::Peripherals::take().unwrap(); // Clock was already initialized by PS7 Init TCL script or FSBL, we just read it. let clocks = Clocks::new_from_regs(PS_CLK).unwrap(); @@ -88,12 +88,12 @@ pub fn main() -> ! { let gpio_pins = gpio::GpioPins::new(dp.gpio); let mio_pins = gpio_pins.mio; // Set up the UART, we are logging with it. - let uart_clk_config = ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200) + let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) .unwrap() .0; let mut uart = Uart::new_with_mio( dp.uart_1, - UartConfig::new_with_clk_config(uart_clk_config), + Config::new_with_clk_config(uart_clk_config), (mio_pins.mio48, mio_pins.mio49), ) .unwrap(); diff --git a/zedboard-qspi-flasher/Cargo.toml b/zedboard-qspi-flasher/Cargo.toml new file mode 100644 index 0000000..77d7669 --- /dev/null +++ b/zedboard-qspi-flasher/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "zedboard-qspi-flasher" +version = "0.1.0" +edition = "2024" + +[dependencies] +cortex-ar = { version = "0.2", git = "https://github.com/rust-embedded/cortex-ar.git", branch = "main" } +zynq7000-rt = { path = "../zynq7000-rt" } +zynq7000 = { path = "../zynq7000" } +zynq7000-hal = { path = "../zynq7000-hal" } +zedboard-bsp = { path = "../zedboard-bsp" } +embedded-io = "0.6" +embedded-hal = "1" +log = "0.4" diff --git a/zedboard-qspi-flasher/src/main.rs b/zedboard-qspi-flasher/src/main.rs new file mode 100644 index 0000000..e43c3f7 --- /dev/null +++ b/zedboard-qspi-flasher/src/main.rs @@ -0,0 +1,139 @@ +//! QSPI flasher for the Zedboard. Assumes that external scripting took care of transferring +//! a boot binary to RAM. +#![no_std] +#![no_main] + +use core::panic::PanicInfo; +use cortex_ar::asm::nop; +use embedded_hal::{delay::DelayNs as _, digital::StatefulOutputPin as _}; +use embedded_io::Write as _; +use log::info; +use zedboard_bsp::qspi_spansion; +use zynq7000_hal::{ + clocks, gpio, prelude::*, priv_tim, qspi, time::Hertz, uart, BootMode, LevelShifterConfig, +}; +use zynq7000_rt as _; + +// Define the clock frequency as a constant. +// +// Not required for the PAC mode, is required for clean delays in HAL mode. +const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_333); + +#[allow(dead_code)] +const QSPI_DEV_COMBINATION: qspi::QspiDeviceCombination = qspi::QspiDeviceCombination { + vendor: qspi::QspiVendor::WinbondAndSpansion, + operating_mode: qspi::OperatingMode::FastReadQuadOutput, + two_devices: false, +}; + +/// Entry point (not called like a normal main function) +#[unsafe(no_mangle)] +pub extern "C" fn boot_core(cpu_id: u32) -> ! { + if cpu_id != 0 { + panic!("unexpected CPU ID {}", cpu_id); + } + main(); +} + +const INIT_STRING: &str = "-- Zynq 7000 Zedboard QSPI flasher --\n\r"; + +#[unsafe(export_name = "main")] +pub fn main() -> ! { + let periphs = zynq7000_hal::init(zynq7000_hal::Config { + init_l2_cache: true, + level_shifter_config: Some(LevelShifterConfig::EnableAll), + interrupt_config: Some(zynq7000_hal::InteruptConfig::AllInterruptsToCpu0), + }) + .unwrap(); + let clocks = clocks::Clocks::new_from_regs(PS_CLOCK_FREQUENCY).unwrap(); + + // Unwrap okay, we only call this once on core 0 here. + let mut timer = priv_tim::CpuPrivateTimer::take(clocks.arm_clocks()).unwrap(); + + let gpio_pins = gpio::GpioPins::new(periphs.gpio); + + // Set up the UART, we are logging with it. + let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200) + .unwrap() + .0; + let mut uart = uart::Uart::new_with_mio( + periphs.uart_1, + uart::Config::new_with_clk_config(uart_clk_config), + (gpio_pins.mio.mio48, gpio_pins.mio.mio49), + ) + .unwrap(); + uart.write_all(INIT_STRING.as_bytes()).unwrap(); + // Safety: We are not multi-threaded yet. + unsafe { + zynq7000_hal::log::uart_blocking::init_unsafe_single_core( + uart, + log::LevelFilter::Trace, + false, + ) + }; + + let boot_mode = BootMode::new_from_regs(); + info!("Boot mode: {:?}", boot_mode); + + let qspi_clock_config = + qspi::ClockConfig::calculate_with_loopback(qspi::SrcSelIo::IoPll, &clocks, 100.MHz()) + .expect("QSPI clock calculation failed"); + let qspi = qspi::Qspi::new_single_qspi_with_feedback( + periphs.qspi, + qspi_clock_config, + qspi::MODE_0, + qspi::IoType::LvCmos33, + gpio_pins.mio.mio1, + ( + gpio_pins.mio.mio2, + gpio_pins.mio.mio3, + gpio_pins.mio.mio4, + gpio_pins.mio.mio5, + ), + gpio_pins.mio.mio6, + gpio_pins.mio.mio8, + ); + + let qspi_io_mode = qspi.into_io_mode(false); + + let _spansion_qspi = qspi_spansion::QspiSpansionS25Fl256SIoMode::new(qspi_io_mode, true); + + let mut mio_led = gpio::Output::new_for_mio(gpio_pins.mio.mio7, gpio::PinState::Low); + loop { + mio_led.toggle().unwrap(); + + timer.delay_ms(500); + } +} + +#[zynq7000_rt::irq] +pub fn irq_handler() {} + +#[zynq7000_rt::exception(DataAbort)] +fn data_abort_handler(_faulting_addr: usize) -> ! { + loop { + nop(); + } +} + +#[zynq7000_rt::exception(Undefined)] +fn undefined_handler(_faulting_addr: usize) -> ! { + loop { + nop(); + } +} + +#[zynq7000_rt::exception(PrefetchAbort)] +fn prefetch_handler(_faulting_addr: usize) -> ! { + loop { + nop(); + } +} + +/// Panic handler +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop { + nop(); + } +} diff --git a/zynq7000-hal/src/clocks/mod.rs b/zynq7000-hal/src/clocks/mod.rs index 0d87649..74aeeff 100644 --- a/zynq7000-hal/src/clocks/mod.rs +++ b/zynq7000-hal/src/clocks/mod.rs @@ -226,13 +226,16 @@ pub enum ClockModuleId { #[derive(Debug)] pub struct DivisorZero(pub ClockModuleId); -#[derive(Debug)] +#[derive(Debug, thiserror::Error)] pub enum ClockReadError { /// The feedback value for the PLL clock output calculation is zero. + #[error("PLL feedback divisor is zero")] PllFeedbackZero, /// Detected a divisor of zero. + #[error("divisor is zero")] DivisorZero(DivisorZero), - /// Detected a divisor that is not even. + /// Detected a divisor that is not even and should be. + #[error("divisor is not even")] DivisorNotEven, } diff --git a/zynq7000-hal/src/devcfg.rs b/zynq7000-hal/src/devcfg.rs index ad36cd7..bbee0e6 100644 --- a/zynq7000-hal/src/devcfg.rs +++ b/zynq7000-hal/src/devcfg.rs @@ -15,7 +15,7 @@ pub fn configure_bitstream_non_secure( if bitstream.is_empty() { return Ok(()); } - let devcfg = unsafe { zynq7000::devcfg::DevCfg::new_mmio_fixed() }; + let mut devcfg = unsafe { zynq7000::devcfg::DevCfg::new_mmio_fixed() }; devcfg.modify_control(|mut val| { val.set_config_access_select(zynq7000::devcfg::PlConfigAccess::ConfigAccessPort); val.set_access_port_select(zynq7000::devcfg::ConfigAccessPortSelect::Pcap); @@ -54,10 +54,11 @@ pub fn configure_bitstream_non_secure( }); devcfg.write_dma_source_addr(bitstream.as_ptr() as u32); devcfg.write_dma_dest_addr(0xFFFF_FFFF); - devcfg.write_dma_source_len(bitstream.len()); - devcfg.write_dma_dest_len(bitstream.len()); + devcfg.write_dma_source_len(bitstream.len() as u32); + devcfg.write_dma_dest_len(bitstream.len() as u32); while !devcfg.read_interrupt_status().dma_done() {} // TODO: Check for errors. while !devcfg.read_interrupt_status().pl_programming_done() {} + Ok(()) } diff --git a/zynq7000-hal/src/lib.rs b/zynq7000-hal/src/lib.rs index a5447c6..c04ea6e 100644 --- a/zynq7000-hal/src/lib.rs +++ b/zynq7000-hal/src/lib.rs @@ -14,13 +14,14 @@ extern crate alloc; use slcr::Slcr; use zynq7000::{ - SpiClockPhase, SpiClockPolarity, slcr::{BootModeRegister, BootPllConfig, LevelShifterRegister}, + SpiClockPhase, SpiClockPolarity, }; pub mod cache; pub mod clocks; pub mod ddr; +pub mod devcfg; pub mod eth; pub mod gic; pub mod gpio; @@ -30,7 +31,6 @@ pub mod l2_cache; pub mod log; pub mod prelude; pub mod priv_tim; -pub mod devcfg; pub mod qspi; pub mod slcr; pub mod spi; @@ -38,6 +38,57 @@ pub mod time; pub mod ttc; pub mod uart; +pub use zynq7000 as pac; +pub use zynq7000::slcr::LevelShifterConfig; + +#[derive(Debug, thiserror::Error)] +pub enum InitError { + #[error("peripheral singleton was already taken")] + PeripheralsAlreadyTaken, +} + +#[derive(Debug)] +pub enum InteruptConfig { + /// GIC is configured to route all interrupts to CPU0. Suitable if the software handles all + /// the interrupts and only runs on CPU0. + AllInterruptsToCpu0, +} + +#[derive(Debug)] +pub struct Config { + pub init_l2_cache: bool, + /// If this has some value, it will configure the level shifter between PS and PL. + pub level_shifter_config: Option, + /// If this has some value, it configures the GIC to pre-defined settings. + pub interrupt_config: Option, +} + +/// Utility function to perform common initialization steps. +pub fn init(config: Config) -> Result { + let mut periphs = zynq7000::Peripherals::take().ok_or(InitError::PeripheralsAlreadyTaken)?; + if config.init_l2_cache { + l2_cache::init_with_defaults(&mut periphs.l2c); + } + if let Some(config) = config.level_shifter_config { + configure_level_shifter(config); + } + if let Some(interrupt_config) = config.interrupt_config { + let mut gic = gic::GicConfigurator::new_with_init(periphs.gicc, periphs.gicd); + match interrupt_config { + InteruptConfig::AllInterruptsToCpu0 => { + gic.enable_all_interrupts(); + gic.set_all_spi_interrupt_targets_cpu0(); + } + } + gic.enable(); + unsafe { + gic.enable_interrupts(); + } + } + + Ok(unsafe { zynq7000::Peripherals::steal() }) +} + /// This enumeration encodes the various boot sources. #[derive(Debug, Copy, Clone)] pub enum BootDevice { @@ -100,7 +151,7 @@ impl BootMode { /// system (PS). /// /// The Zynq-7000 TRM p.32 specifies more information about this register and how to use it. -pub fn configure_level_shifter(config: zynq7000::slcr::LevelShifterConfig) { +pub fn configure_level_shifter(config: LevelShifterConfig) { // Safety: We only manipulate the level shift registers. unsafe { Slcr::with(|slcr_unlocked| { @@ -222,7 +273,6 @@ const fn spi_mode_const_to_cpol_cpha( } } -#[allow(dead_code)] pub(crate) mod sealed { pub trait Sealed {} } diff --git a/zynq7000-hal/src/qspi/mod.rs b/zynq7000-hal/src/qspi/mod.rs index cff4353..c7c3528 100644 --- a/zynq7000-hal/src/qspi/mod.rs +++ b/zynq7000-hal/src/qspi/mod.rs @@ -7,13 +7,11 @@ use zynq7000::{ BaudRateDivisor, Config, InstructionCode, InterruptStatus, LoopbackMasterClockDelay, SpiEnable, }, - slcr::{ - clocks::{SingleCommonPeriphIoClockControl, SrcSelIo}, - mio::Speed, - reset::QspiResetControl, - }, + slcr::{clocks::SingleCommonPeriphIoClockControl, mio::Speed, reset::QspiResetControl}, }; +pub use embedded_hal::spi::{MODE_0, MODE_1, MODE_2, MODE_3, Mode}; +pub use zynq7000::slcr::clocks::SrcSelIo; pub use zynq7000::slcr::mio::IoType; use crate::{ diff --git a/zynq7000-hal/src/uart/mod.rs b/zynq7000-hal/src/uart/mod.rs index c83ca58..2d3c6fd 100644 --- a/zynq7000-hal/src/uart/mod.rs +++ b/zynq7000-hal/src/uart/mod.rs @@ -187,7 +187,7 @@ pub enum CharLen { } #[derive(Debug, Clone, Copy)] -pub struct ClockConfigRaw { +pub struct ClockConfig { cd: u16, bdiv: u8, } @@ -197,12 +197,12 @@ pub fn calculate_viable_configs( mut uart_clk: Hertz, clk_sel: ClockSelect, target_baud: u32, -) -> alloc::vec::Vec<(ClockConfigRaw, f64)> { +) -> alloc::vec::Vec<(ClockConfig, f64)> { let mut viable_cfgs = alloc::vec::Vec::new(); if clk_sel == ClockSelect::UartRefClkDiv8 { uart_clk /= 8; } - let mut current_clk_config = ClockConfigRaw::default(); + let mut current_clk_config = ClockConfig::default(); for bdiv in 4..u8::MAX { let cd = round(uart_clk.raw() as f64 / ((bdiv as u32 + 1) as f64 * target_baud as f64)) as u64; @@ -229,15 +229,15 @@ pub fn calculate_raw_baud_cfg_smallest_error( mut uart_clk: Hertz, clk_sel: ClockSelect, target_baud: u32, -) -> Result<(ClockConfigRaw, f64), DivisorZero> { +) -> Result<(ClockConfig, f64), DivisorZero> { if target_baud == 0 { return Err(DivisorZero); } if clk_sel == ClockSelect::UartRefClkDiv8 { uart_clk /= 8; } - let mut current_clk_config = ClockConfigRaw::default(); - let mut best_clk_config = ClockConfigRaw::default(); + let mut current_clk_config = ClockConfig::default(); + let mut best_clk_config = ClockConfig::default(); let mut smallest_error: f64 = 100.0; for bdiv in 4..u8::MAX { let cd = @@ -258,13 +258,13 @@ pub fn calculate_raw_baud_cfg_smallest_error( Ok((best_clk_config, smallest_error)) } -impl ClockConfigRaw { +impl ClockConfig { #[inline] pub const fn new(cd: u16, bdiv: u8) -> Result { if cd == 0 { return Err(DivisorZero); } - Ok(ClockConfigRaw { cd, bdiv }) + Ok(ClockConfig { cd, bdiv }) } /// Auto-calculates the best clock configuration settings for the target baudrate. @@ -316,16 +316,16 @@ impl ClockConfigRaw { } } -impl Default for ClockConfigRaw { +impl Default for ClockConfig { #[inline] fn default() -> Self { - ClockConfigRaw::new(1, 0).unwrap() + ClockConfig::new(1, 0).unwrap() } } #[derive(Debug)] -pub struct UartConfig { - clk_config: ClockConfigRaw, +pub struct Config { + clk_config: ClockConfig, chmode: ChMode, parity: Parity, stopbits: Stopbits, @@ -333,8 +333,8 @@ pub struct UartConfig { clk_sel: ClockSelect, } -impl UartConfig { - pub fn new_with_clk_config(clk_config: ClockConfigRaw) -> Self { +impl Config { + pub fn new_with_clk_config(clk_config: ClockConfig) -> Self { Self::new( clk_config, ChMode::default(), @@ -347,14 +347,14 @@ impl UartConfig { #[inline] pub const fn new( - clk_config: ClockConfigRaw, + clk_config: ClockConfig, chmode: ChMode, parity: Parity, stopbits: Stopbits, chrl: CharLen, clk_sel: ClockSelect, ) -> Self { - UartConfig { + Config { clk_config, chmode, parity, @@ -365,7 +365,7 @@ impl UartConfig { } #[inline] - pub const fn raw_clk_config(&self) -> ClockConfigRaw { + pub const fn raw_clk_config(&self) -> ClockConfig { self.clk_config } @@ -399,7 +399,7 @@ impl UartConfig { pub struct Uart { rx: Rx, tx: Tx, - cfg: UartConfig, + cfg: Config, } #[derive(Debug, thiserror::Error)] @@ -422,7 +422,7 @@ impl Uart { /// /// A valid PL design which routes the UART pins through into the PL must be used for this to /// work. - pub fn new_with_emio(uart: impl PsUart, cfg: UartConfig) -> Result { + pub fn new_with_emio(uart: impl PsUart, cfg: Config) -> Result { if uart.uart_id().is_none() { return Err(InvalidPsUart); } @@ -436,7 +436,7 @@ impl Uart { /// This is the constructor to use the PS UART with MIO pins. pub fn new_with_mio( uart: impl PsUart, - cfg: UartConfig, + cfg: Config, pins: (TxPinI, RxPinI), ) -> Result where @@ -465,7 +465,7 @@ impl Uart { pub fn new_generic_unchecked( mut reg_block: MmioUart<'static>, uart_id: UartId, - cfg: UartConfig, + cfg: Config, ) -> Uart { let periph_sel = match uart_id { UartId::Uart0 => crate::PeriphSelect::Uart0, @@ -557,7 +557,7 @@ impl Uart { } #[inline] - pub const fn cfg(&self) -> &UartConfig { + pub const fn cfg(&self) -> &Config { &self.cfg } @@ -657,7 +657,7 @@ mod tests { #[test] fn test_error_calc_0() { // Baud 600 - let cfg_0 = ClockConfigRaw::new(10417, 7).unwrap(); + let cfg_0 = ClockConfig::new(10417, 7).unwrap(); let actual_baud_0 = cfg_0.actual_baud(REF_UART_CLK); assert!(abs_diff_eq!(actual_baud_0, 599.980, epsilon = 0.01)); } @@ -665,7 +665,7 @@ mod tests { #[test] fn test_error_calc_1() { // Baud 9600 - let cfg = ClockConfigRaw::new(81, 7).unwrap(); + let cfg = ClockConfig::new(81, 7).unwrap(); let actual_baud = cfg.actual_baud(REF_UART_CLK_DIV_8); assert!(abs_diff_eq!(actual_baud, 9645.061, epsilon = 0.01)); } @@ -673,7 +673,7 @@ mod tests { #[test] fn test_error_calc_2() { // Baud 9600 - let cfg = ClockConfigRaw::new(651, 7).unwrap(); + let cfg = ClockConfig::new(651, 7).unwrap(); let actual_baud = cfg.actual_baud(REF_UART_CLK); assert!(abs_diff_eq!(actual_baud, 9600.614, epsilon = 0.01)); } @@ -681,7 +681,7 @@ mod tests { #[test] fn test_error_calc_3() { // Baud 28800 - let cfg = ClockConfigRaw::new(347, 4).unwrap(); + let cfg = ClockConfig::new(347, 4).unwrap(); let actual_baud = cfg.actual_baud(REF_UART_CLK); assert!(abs_diff_eq!(actual_baud, 28818.44, epsilon = 0.01)); } @@ -689,7 +689,7 @@ mod tests { #[test] fn test_error_calc_4() { // Baud 921600 - let cfg = ClockConfigRaw::new(9, 5).unwrap(); + let cfg = ClockConfig::new(9, 5).unwrap(); let actual_baud = cfg.actual_baud(REF_UART_CLK); assert!(abs_diff_eq!(actual_baud, 925925.92, epsilon = 0.01)); } @@ -697,7 +697,7 @@ mod tests { #[test] fn test_best_calc_0() { let result = - ClockConfigRaw::new_autocalc_with_raw_clk(REF_UART_CLK, ClockSelect::UartRefClk, 600); + ClockConfig::new_autocalc_with_raw_clk(REF_UART_CLK, ClockSelect::UartRefClk, 600); assert!(result.is_ok()); let (cfg, _error) = result.unwrap(); assert_eq!(cfg.cd(), 499); diff --git a/zynq7000/src/devcfg.rs b/zynq7000/src/devcfg.rs index 7299a6e..d7d67c1 100644 --- a/zynq7000/src/devcfg.rs +++ b/zynq7000/src/devcfg.rs @@ -215,7 +215,7 @@ pub struct MiscControl { #[derive(Debug, PartialEq, Eq)] pub enum UnacknowledgedDmaTransfers { None = 0b00, - One =0b01, + One = 0b01, Two = 0b10, ThreeOrMore = 0b11, } @@ -254,8 +254,7 @@ pub struct Status { #[bit(2, rw)] efuse_sec_enable: bool, #[bit(1, rw)] - efuse_jtag_disabled: bool - + efuse_jtag_disabled: bool, } #[derive(derive_mmio::Mmio)] diff --git a/zynq7000/src/lib.rs b/zynq7000/src/lib.rs index 0db7ab8..d544bb0 100644 --- a/zynq7000/src/lib.rs +++ b/zynq7000/src/lib.rs @@ -18,6 +18,7 @@ extern crate std; pub const MPCORE_BASE_ADDR: usize = 0xF8F0_0000; pub mod ddrc; +pub mod devcfg; pub mod eth; pub mod gic; pub mod gpio; @@ -27,12 +28,11 @@ pub mod l2_cache; pub mod mpcore; pub mod priv_tim; pub mod qspi; -pub mod devcfg; -pub mod xadc; pub mod slcr; pub mod spi; pub mod ttc; pub mod uart; +pub mod xadc; static PERIPHERALS_TAKEN: AtomicBool = AtomicBool::new(false); @@ -41,7 +41,7 @@ static PERIPHERALS_TAKEN: AtomicBool = AtomicBool::new(false); /// It is a singleton which exposes all peripherals supported by this crate. /// The [`svd2rust` documentation](https://docs.rs/svd2rust/latest/svd2rust/#peripheral-api) /// provides some more information about this. -pub struct PsPeripherals { +pub struct Peripherals { pub gicc: gic::MmioGicCpuInterface<'static>, pub gicd: gic::MmioGicDistributor<'static>, pub l2c: l2_cache::MmioL2Cache<'static>, @@ -64,7 +64,7 @@ pub struct PsPeripherals { pub xadc: xadc::MmioXAdc<'static>, } -impl PsPeripherals { +impl Peripherals { /// Returns all supported processing system peripherals *once*. pub fn take() -> Option { let taken = PERIPHERALS_TAKEN.swap(true, Ordering::Relaxed); @@ -101,6 +101,7 @@ impl PsPeripherals { eth_1: eth::Ethernet::new_mmio_fixed_1(), qspi: qspi::Qspi::new_mmio_fixed(), devcfg: devcfg::DevCfg::new_mmio_fixed(), + xadc: xadc::XAdc::new_mmio_fixed(), } } }