continue fsbl

This commit is contained in:
2025-07-27 15:39:12 +02:00
parent 76bc8e11e1
commit 54cc78acac
22 changed files with 578 additions and 74 deletions

24
fsbl/Cargo.toml Normal file
View File

@@ -0,0 +1,24 @@
[package]
name = "fsbl"
version = "0.1.0"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
edition = "2024"
description = "Rust First Stage Bootloader for the Zynq7000 SoC"
homepage = "https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs"
repository = "https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs"
license = "MIT OR Apache-2.0"
[dependencies]
cortex-ar = { version = "0.2", git = "https://github.com/rust-embedded/cortex-ar.git", rev = "79dba7000d2090d13823bfb783d9d64be8b778d2", features = ["critical-section-single-core"] }
zynq7000-rt = { path = "../zynq7000-rt" }
zynq7000 = { path = "../zynq7000" }
zynq7000-hal = { path = "../zynq7000-hal" }
embedded-io = "0.6"
embedded-hal = "1"
fugit = "0.3"
log = "0.4"
[profile.release]
codegen-units = 1
debug = true
lto = true

24
fsbl/memory.x Normal file
View File

@@ -0,0 +1,24 @@
MEMORY
{
/* The Zynq7000 has 192 kB of OCM memory which can be used for the FSBL */
CODE(rx) : ORIGIN = 0x00000000, LENGTH = 192K
OCM_UPPER(rx): ORIGIN = 0xFFFF0000, LENGTH = 64K
/* Leave 1 MB of memory which will be configured as uncached device memory by the MMU. This can
be used for something like DMA descriptors, but the DDR needs to be set up first in addition
to configuring the page at address 0x400_0000 accordingly */
UNCACHED(rx): ORIGIN = 0x4000000, LENGTH = 1M
}
REGION_ALIAS("DATA", CODE);
SECTIONS
{
/* Uncached memory */
.uncached (NOLOAD) : ALIGN(4) {
. = ALIGN(4);
_sbss_uncached = .;
*(.uncached .uncached.*);
. = ALIGN(4);
_ebss_uncached = .;
} > UNCACHED
}

77
fsbl/src/main.rs Normal file
View File

@@ -0,0 +1,77 @@
//! Simple FSBL.
#![no_std]
#![no_main]
use core::panic::PanicInfo;
use cortex_ar::asm::nop;
use log::error;
use zynq7000_hal::{
BootMode,
clocks::pll::{
PllConfig, PllConfigCtorError, configure_arm_pll, configure_ddr_pll, configure_io_pll,
},
gpio::{Output, PinState, mio},
time::Hertz,
};
use zynq7000_rt as _;
// PS clock input frequency.
const PS_CLK: Hertz = Hertz::from_raw(33_333_333);
/// 1600 MHz.
const ARM_CLK: Hertz = Hertz::from_raw(1_600_000_000);
/// 1067 MHz.
const DDR_CLK: Hertz = Hertz::from_raw(1_067_000_000);
/// 1000 MHz.
const IO_CLK: Hertz = Hertz::from_raw(1_000_000_000);
/// 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() -> ! {
let boot_mode = BootMode::new_from_regs();
// The unwraps are okay here, the provided clock frequencies are standard values also used
// by other Xilinx tools.
configure_arm_pll(boot_mode, PllConfig::new_from_target_clock(PS_CLK, ARM_CLK).unwrap());
configure_io_pll(boot_mode, PllConfig::new_from_target_clock(PS_CLK, IO_CLK).unwrap());
configure_ddr_pll(boot_mode, PllConfig::new_from_target_clock(PS_CLK, DDR_CLK).unwrap());
loop {
cortex_ar::asm::nop();
}
}
#[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 {}
}