more cleanup
Some checks failed
ci / Check build (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
ci / Check build (pull_request) Has been cancelled
ci / Check formatting (pull_request) Has been cancelled
ci / Check Documentation Build (pull_request) Has been cancelled
ci / Clippy (pull_request) Has been cancelled

This commit is contained in:
Robin Mueller
2025-10-08 19:47:32 +02:00
parent 79042a68dd
commit 10caa6ccb5
10 changed files with 240 additions and 92 deletions

View File

@@ -8,25 +8,25 @@ family of SoCs.
This project contains the following crates:
## Zynq Workspace
## [Zynq Workspace](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq)
This workspace contains libraries and application which can only be run on the target system.
- The [`zynq7000-rt`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq7000-rt)
- The [`zynq7000-rt`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/zynq7000-rt)
run-time crate containing basic low-level startup code necessary to boot a Rust app on the
Zynq7000.
- The [`zynq7000`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq7000) PAC
- The [`zynq7000`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/zynq7000) PAC
crate containing basic low-level register definitions.
- The [`zynq7000-mmu`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq7000-hal)
- The [`zynq7000-mmu`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/zynq7000-hal)
crate containing common MMU abstractions used by both the HAL and the run-time crate.
- The [`zynq7000-hal`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq7000-hal)
- The [`zynq7000-hal`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/zynq7000-hal)
HAL crate containing higher-level abstractions on top of the PAC register crate.
- The [`zynq7000-embassy`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq7000-embassy)
- The [`zynq7000-embassy`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/zynq7000-embassy)
crate containing support for running the embassy-rs asynchronous run-time.
It also contains the following helper crates:
- The [`examples`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/examples)
- The [`examples`](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples)
folder contains various example applications crates using the HAL and the PAC.
This folder also contains dedicated example applications using the
[`embassy`](https://github.com/embassy-rs/embassy) native Rust RTOS.

View File

@@ -149,7 +149,7 @@ fn generate_ddrc_config(
let ctrl_reg6 = reg_to_values.val_as_token("CTRL Reg 6", 0xF800_607C);
let che_t_zq = reg_to_values.val_as_token("CHE T ZQ", 0xF800_60A4);
let che_t_zq_short_interval_reg =
reg_to_values.val_as_token("CHE T ZQ Short Interval", 0xF800_60A4);
reg_to_values.val_as_token("CHE T ZQ Short Interval", 0xF800_60A8);
let deep_powerdown = reg_to_values.val_as_token("Deep Powerdown", 0xF800_60AC);
let reg_2c = reg_to_values.val_as_token("Reg 2C", 0xF800_60B0);
let reg_2d = reg_to_values.val_as_token("Reg 2D", 0xF800_60B4);

View File

@@ -0,0 +1,123 @@
#![no_std]
#![no_main]
use core::panic::PanicInfo;
use cortex_ar::asm::nop;
use embassy_executor::Spawner;
use embassy_time::{Duration, Ticker};
use embedded_hal::digital::StatefulOutputPin;
use embedded_io::Write;
use log::{error, info};
use zynq7000_hal::{BootMode, InteruptConfig, clocks, gic, gpio, gtc, time::Hertz, uart};
use zynq7000_rt as _;
// Define the clock frequency as a constant
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
/// 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();
}
#[embassy_executor::main]
#[unsafe(export_name = "main")]
async fn main(_spawner: Spawner) -> ! {
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 = 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 = 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),
(mio_pins.mio48, mio_pins.mio49),
)
.unwrap();
uart.write_all(b"-- Zynq 7000 Embassy Hello World --\n\r")
.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 mut ticker = Ticker::every(Duration::from_millis(1000));
let mut led = gpio::Output::new_for_mio(mio_pins.mio7, gpio::PinState::Low);
loop {
info!("Hello, world!");
led.toggle().unwrap();
ticker.next().await;
}
}
#[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() {
gic::Interrupt::Sgi(_) => (),
gic::Interrupt::Ppi(ppi_interrupt) => {
if ppi_interrupt == zynq7000_hal::gic::PpiInterrupt::GlobalTimer {
unsafe {
zynq7000_embassy::on_interrupt();
}
}
}
gic::Interrupt::Spi(_spi_interrupt) => (),
gic::Interrupt::Invalid(_) => (),
gic::Interrupt::Spurious => (),
}
gic_helper.end_of_interrupt(irq_info);
}
#[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) -> ! {
error!("Panic: {info:?}");
loop {}
}

View File

@@ -6,9 +6,8 @@ use cortex_ar::asm::nop;
use embassy_executor::Spawner;
use embassy_time::{Duration, Ticker};
use embedded_hal::digital::StatefulOutputPin;
use embedded_io::Write;
use log::{error, info};
use zynq7000_hal::{BootMode, InteruptConfig, clocks, gic, gpio, gtc, time::Hertz, uart};
use log::error;
use zynq7000_hal::{InteruptConfig, clocks, gic, gpio, gtc, time::Hertz};
use zynq7000_rt as _;
@@ -38,37 +37,10 @@ async fn main(_spawner: Spawner) -> ! {
// Set up global timer counter and embassy time driver.
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 = 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),
(mio_pins.mio48, mio_pins.mio49),
)
.unwrap();
uart.write_all(b"-- Zynq 7000 Embassy Hello World --\n\r")
.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 mut ticker = Ticker::every(Duration::from_millis(1000));
let mut led = gpio::Output::new_for_mio(mio_pins.mio7, gpio::PinState::Low);
loop {
info!("Hello, world!");
led.toggle().unwrap();
ticker.next().await;
}

View File

@@ -1,5 +1,5 @@
[package]
name = "blinky"
name = "simple"
version = "0.1.0"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
edition = "2024"

View File

@@ -0,0 +1,103 @@
//! Simple blinky app, showing a PAC variant and a HAL variant.
#![no_std]
#![no_main]
use core::panic::PanicInfo;
use cortex_ar::asm::nop;
use embedded_hal::{delay::DelayNs, digital::StatefulOutputPin};
use zynq7000::Peripherals;
use zynq7000_hal::{
clocks::Clocks,
gpio::{Output, PinState, mio},
l2_cache,
priv_tim::CpuPrivateTimer,
time::Hertz,
};
use zynq7000_rt as _;
pub const LIB: Lib = Lib::Hal;
/// One user LED is MIO7
const ZEDBOARD_LED_MASK: u32 = 1 << 7;
// 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);
#[derive(Debug)]
pub enum Lib {
Pac,
Hal,
}
/// 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();
}
#[unsafe(export_name = "main")]
pub fn main() -> ! {
l2_cache::init_with_defaults(&mut unsafe { zynq7000::l2_cache::L2Cache::new_mmio_fixed() });
match LIB {
Lib::Pac => {
let mut gpio = unsafe { zynq7000::gpio::Gpio::new_mmio_fixed() };
gpio.bank_0().modify_dirm(|v| v | ZEDBOARD_LED_MASK);
gpio.bank_0().modify_out_en(|v| v | ZEDBOARD_LED_MASK);
loop {
gpio.modify_out_0(|v| v ^ ZEDBOARD_LED_MASK);
for _ in 0..5_000_000 {
nop();
}
}
}
Lib::Hal => {
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();
let mio_pins = mio::Pins::new(dp.gpio);
let mut led = Output::new_for_mio(mio_pins.mio7, PinState::High);
loop {
led.toggle().unwrap();
cpu_tim.delay_ms(1000);
}
}
}
}
#[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();
}
}

View File

@@ -4,33 +4,8 @@
use core::panic::PanicInfo;
use cortex_ar::asm::nop;
use embedded_hal::{delay::DelayNs, digital::StatefulOutputPin};
use zynq7000::Peripherals;
use zynq7000_hal::{
clocks::Clocks,
gpio::{Output, PinState, mio},
l2_cache,
priv_tim::CpuPrivateTimer,
time::Hertz,
};
use zynq7000_rt as _;
pub const LIB: Lib = Lib::Hal;
/// One user LED is MIO7
const ZEDBOARD_LED_MASK: u32 = 1 << 7;
// 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);
#[derive(Debug)]
pub enum Lib {
Pac,
Hal,
}
/// Entry point (not called like a normal main function)
#[unsafe(no_mangle)]
pub extern "C" fn boot_core(cpu_id: u32) -> ! {
@@ -42,31 +17,8 @@ pub extern "C" fn boot_core(cpu_id: u32) -> ! {
#[unsafe(export_name = "main")]
pub fn main() -> ! {
l2_cache::init_with_defaults(&mut unsafe { zynq7000::l2_cache::L2Cache::new_mmio_fixed() });
match LIB {
Lib::Pac => {
let mut gpio = unsafe { zynq7000::gpio::Gpio::new_mmio_fixed() };
gpio.bank_0().modify_dirm(|v| v | ZEDBOARD_LED_MASK);
gpio.bank_0().modify_out_en(|v| v | ZEDBOARD_LED_MASK);
loop {
gpio.modify_out_0(|v| v ^ ZEDBOARD_LED_MASK);
for _ in 0..5_000_000 {
nop();
}
}
}
Lib::Hal => {
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();
let mio_pins = mio::Pins::new(dp.gpio);
let mut led = Output::new_for_mio(mio_pins.mio7, PinState::High);
loop {
led.toggle().unwrap();
cpu_tim.delay_ms(1000);
}
}
loop {
cortex_ar::asm::nop();
}
}

View File

@@ -98,4 +98,3 @@ pub const DDRC_CONFIG_ZEDBOARD: DdrcConfigSet = DdrcConfigSet {
lpddr_ctrl_2: regs::LpddrControl2::new_with_raw_value(0x00005125),
lpddr_ctrl_3: regs::LpddrControl3::new_with_raw_value(0x000012a8),
};

View File

@@ -13,4 +13,3 @@ pub const DDRIOB_CONFIG_SET_ZEDBOARD: DdriobConfigSet = DdriobConfigSet {
diff1: regs::DdriobConfig::new_with_raw_value(0x00000674),
clock: regs::DdriobConfig::new_with_raw_value(0x00000600),
};

View File

@@ -1,8 +1,8 @@
pub const DDRC_BASE_ADDR: usize = 0xF800_6000;
pub mod regs {
use arbitrary_int::{u2, u3, u4, u5, u6, u7, u9, u10, u11, u12, u20};
pub use crate::slcr::ddriob::DdriobConfig;
use arbitrary_int::{u2, u3, u4, u5, u6, u7, u9, u10, u11, u12, u20};
#[bitbybit::bitenum(u2)]
#[derive(Debug, PartialEq, Eq)]