diff --git a/zynq/examples/embassy/src/bin/dht22-open-drain-pins.rs b/zynq/examples/embassy/src/bin/dht22-open-drain-pins.rs index fa6862c..05bf73e 100644 --- a/zynq/examples/embassy/src/bin/dht22-open-drain-pins.rs +++ b/zynq/examples/embassy/src/bin/dht22-open-drain-pins.rs @@ -21,28 +21,23 @@ use zynq7000_hal::{ }; use zynq7000::Peripherals; -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(); -} - /// Try to talk to a DHT22 sensor connected at MIO0. const DHT22_AT_MIO0: bool = true; /// Open drain pin testing. MIO9 needs to be tied to MIO14. const OPEN_DRAIN_PINS_MIO9_TO_MIO14: bool = false; +/// Entry point which calls the embassy main method. +#[zynq7000_rt::entry] +fn entry_point() -> ! { + main(); +} + #[embassy_executor::main] -#[unsafe(export_name = "main")] async fn main(_spawner: Spawner) -> ! { let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); diff --git a/zynq/examples/embassy/src/bin/embassy-hello.rs b/zynq/examples/embassy/src/bin/embassy-hello.rs index d52d64b..dac242f 100644 --- a/zynq/examples/embassy/src/bin/embassy-hello.rs +++ b/zynq/examples/embassy/src/bin/embassy-hello.rs @@ -15,17 +15,13 @@ 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); - } +/// Entry point which calls the embassy main method. +#[zynq7000_rt::entry] +fn entry_point() -> ! { 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, diff --git a/zynq/examples/embassy/src/bin/logger-non-blocking.rs b/zynq/examples/embassy/src/bin/logger-non-blocking.rs index 5cbc8c8..6a03a06 100644 --- a/zynq/examples/embassy/src/bin/logger-non-blocking.rs +++ b/zynq/examples/embassy/src/bin/logger-non-blocking.rs @@ -26,16 +26,12 @@ 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); - } +/// Entry point which calls the embassy main method. +#[zynq7000_rt::entry] +fn entry_point() -> ! { main(); } -#[unsafe(export_name = "main")] #[embassy_executor::main] async fn main(spawner: Spawner) -> ! { let mut dp = Peripherals::take().unwrap(); diff --git a/zynq/examples/embassy/src/bin/pwm.rs b/zynq/examples/embassy/src/bin/pwm.rs index 6bc15ce..1a736f6 100644 --- a/zynq/examples/embassy/src/bin/pwm.rs +++ b/zynq/examples/embassy/src/bin/pwm.rs @@ -32,17 +32,13 @@ 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); - } +/// Entry point which calls the embassy main method. +#[zynq7000_rt::entry] +fn entry_point() -> ! { main(); } #[embassy_executor::main] -#[unsafe(export_name = "main")] async fn main(_spawner: Spawner) -> ! { let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); diff --git a/zynq/examples/embassy/src/main.rs b/zynq/examples/embassy/src/main.rs index 5150062..d7be0c3 100644 --- a/zynq/examples/embassy/src/main.rs +++ b/zynq/examples/embassy/src/main.rs @@ -9,22 +9,16 @@ use embedded_hal::digital::StatefulOutputPin; use log::error; use zynq7000_hal::{InteruptConfig, clocks, gic, gpio, gtc, time::Hertz}; -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); - } +/// Entry point which calls the embassy main method. +#[zynq7000_rt::entry] +fn entry_point() -> ! { 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, diff --git a/zynq/examples/simple/src/bin/blinky.rs b/zynq/examples/simple/src/bin/blinky.rs index 95688f6..b1d788a 100644 --- a/zynq/examples/simple/src/bin/blinky.rs +++ b/zynq/examples/simple/src/bin/blinky.rs @@ -13,7 +13,6 @@ use zynq7000_hal::{ priv_tim::CpuPrivateTimer, time::Hertz, }; -use zynq7000_rt as _; pub const LIB: Lib = Lib::Hal; @@ -31,17 +30,8 @@ pub enum Lib { 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() -> ! { +#[zynq7000_rt::entry] +fn main() -> ! { l2_cache::init_with_defaults(&mut unsafe { zynq7000::l2_cache::Registers::new_mmio_fixed() }); match LIB { Lib::Pac => { diff --git a/zynq/examples/simple/src/bin/gtc-ticks.rs b/zynq/examples/simple/src/bin/gtc-ticks.rs index d0d7fe2..48fc703 100644 --- a/zynq/examples/simple/src/bin/gtc-ticks.rs +++ b/zynq/examples/simple/src/bin/gtc-ticks.rs @@ -18,24 +18,13 @@ use zynq7000_hal::{ uart::{ClockConfig, Config, Uart}, }; -use zynq7000_rt as _; - // Define the clock frequency as a constant const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_333); static MS_TICKS: AtomicU64 = AtomicU64::new(0); -/// 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() -> ! { +#[zynq7000_rt::entry] +fn main() -> ! { let mut dp = zynq7000::Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); diff --git a/zynq/examples/simple/src/bin/logger.rs b/zynq/examples/simple/src/bin/logger.rs index 31e5096..7a0b5f9 100644 --- a/zynq/examples/simple/src/bin/logger.rs +++ b/zynq/examples/simple/src/bin/logger.rs @@ -19,24 +19,13 @@ use zynq7000_hal::{ uart::{ClockConfig, Config, Uart}, }; -use zynq7000_rt as _; - // Define the clock frequency as a constant const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300); static MS_TICKS: AtomicU64 = AtomicU64::new(0); -/// 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() -> ! { +#[zynq7000_rt::entry] +fn main() -> ! { let mut dp = zynq7000::Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); diff --git a/zynq/examples/simple/src/main.rs b/zynq/examples/simple/src/main.rs index f6bb554..19afa60 100644 --- a/zynq/examples/simple/src/main.rs +++ b/zynq/examples/simple/src/main.rs @@ -4,19 +4,9 @@ use aarch32_cpu::asm::nop; use core::panic::PanicInfo; -use zynq7000_rt as _; -/// 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() -> ! { +#[zynq7000_rt::entry] +fn main() -> ! { loop { nop(); } diff --git a/zynq/examples/zedboard/src/bin/ethernet.rs b/zynq/examples/zedboard/src/bin/ethernet.rs index 65eb859..a9e066f 100644 --- a/zynq/examples/zedboard/src/bin/ethernet.rs +++ b/zynq/examples/zedboard/src/bin/ethernet.rs @@ -104,12 +104,9 @@ pub enum IpMode { StackReady, } -/// 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); - } +/// Entry point which calls the embassy main method. +#[zynq7000_rt::entry] +fn entry_point() -> ! { main(); } @@ -204,7 +201,6 @@ async fn tcp_task(mut tcp: TcpSocket<'static>) -> ! { } #[embassy_executor::main] -#[unsafe(export_name = "main")] async fn main(spawner: Spawner) -> ! { let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); diff --git a/zynq/examples/zedboard/src/bin/l3gd20h-i2c-mio.rs b/zynq/examples/zedboard/src/bin/l3gd20h-i2c-mio.rs index 24db741..3649679 100644 --- a/zynq/examples/zedboard/src/bin/l3gd20h-i2c-mio.rs +++ b/zynq/examples/zedboard/src/bin/l3gd20h-i2c-mio.rs @@ -36,17 +36,13 @@ use zynq7000_rt as _; const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300); const I2C_ADDR_SEL: I2cAddr = I2cAddr::Sa0Low; -/// 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); - } +/// Entry point which calls the embassy main method. +#[zynq7000_rt::entry] +fn entry_point() -> ! { main(); } #[embassy_executor::main] -#[unsafe(export_name = "main")] async fn main(_spawner: Spawner) -> ! { let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); diff --git a/zynq/examples/zedboard/src/bin/l3gd20h-spi-mio.rs b/zynq/examples/zedboard/src/bin/l3gd20h-spi-mio.rs index 7c887d2..60d4435 100644 --- a/zynq/examples/zedboard/src/bin/l3gd20h-spi-mio.rs +++ b/zynq/examples/zedboard/src/bin/l3gd20h-spi-mio.rs @@ -39,17 +39,13 @@ const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300); const DEBUG_SPI_CLK_CONFIG: bool = false; const BLOCKING: bool = 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); - } +/// Entry point which calls the embassy main method. +#[zynq7000_rt::entry] +fn entry_point() -> ! { main(); } #[embassy_executor::main] -#[unsafe(export_name = "main")] async fn main(spawner: Spawner) -> ! { let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); diff --git a/zynq/examples/zedboard/src/bin/qspi.rs b/zynq/examples/zedboard/src/bin/qspi.rs index 4162ca1..a595019 100644 --- a/zynq/examples/zedboard/src/bin/qspi.rs +++ b/zynq/examples/zedboard/src/bin/qspi.rs @@ -21,19 +21,15 @@ const QSPI_DEV_COMBINATION: qspi::QspiDeviceCombination = qspi::QspiDeviceCombin 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); - } +/// Entry point which calls the embassy main method. +#[zynq7000_rt::entry] +fn entry_point() -> ! { main(); } const ERASE_PROGRAM_READ_TEST: bool = false; #[embassy_executor::main] -#[unsafe(export_name = "main")] async fn main(_spawner: Spawner) -> ! { let periphs = zynq7000_hal::init(zynq7000_hal::Config { init_l2_cache: true, diff --git a/zynq/examples/zedboard/src/bin/uart-blocking.rs b/zynq/examples/zedboard/src/bin/uart-blocking.rs index 25dace2..04689af 100644 --- a/zynq/examples/zedboard/src/bin/uart-blocking.rs +++ b/zynq/examples/zedboard/src/bin/uart-blocking.rs @@ -31,12 +31,9 @@ const INIT_STRING: &str = "-- Zynq 7000 Zedboard blocking UART example --\n\r"; const AXI_UARTLITE_BASE_ADDR: u32 = 0x42C0_0000; const AXI_UAR16550_BASE_ADDR: u32 = 0x43C0_0000; -/// 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); - } +/// Entry point which calls the embassy main method. +#[zynq7000_rt::entry] +fn entry_point() -> ! { main(); } @@ -99,7 +96,6 @@ impl UartMultiplexer { } } #[embassy_executor::main] -#[unsafe(export_name = "main")] async fn main(_spawner: Spawner) -> ! { let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); diff --git a/zynq/examples/zedboard/src/bin/uart-non-blocking.rs b/zynq/examples/zedboard/src/bin/uart-non-blocking.rs index 8965a7d..767ba9a 100644 --- a/zynq/examples/zedboard/src/bin/uart-non-blocking.rs +++ b/zynq/examples/zedboard/src/bin/uart-non-blocking.rs @@ -95,12 +95,9 @@ static UARTLITE_PROD: Mutex>>> = Mutex::new(RefCell::new(None)); -/// 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); - } +/// Entry point which calls the embassy main method. +#[zynq7000_rt::entry] +fn entry_point() -> ! { main(); } @@ -164,7 +161,6 @@ impl UartMultiplexer { } #[embassy_executor::main] -#[unsafe(export_name = "main")] async fn main(spawner: Spawner) -> ! { let mut dp = Peripherals::take().unwrap(); l2_cache::init_with_defaults(&mut dp.l2c); diff --git a/zynq/examples/zedboard/src/main.rs b/zynq/examples/zedboard/src/main.rs index bd51ff1..7ba30c6 100644 --- a/zynq/examples/zedboard/src/main.rs +++ b/zynq/examples/zedboard/src/main.rs @@ -15,17 +15,13 @@ use zynq7000_rt as _; const INIT_STRING: &str = "-- Zynq 7000 Zedboard GPIO blinky example --\n\r"; -/// 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); - } +/// Entry point which calls the embassy main method. +#[zynq7000_rt::entry] +fn entry_point() -> ! { 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, diff --git a/zynq/zedboard-fsbl/src/main.rs b/zynq/zedboard-fsbl/src/main.rs index 1e3a1f6..de00366 100644 --- a/zynq/zedboard-fsbl/src/main.rs +++ b/zynq/zedboard-fsbl/src/main.rs @@ -29,7 +29,6 @@ use zynq7000_hal::{ time::Hertz, uart::{ClockConfig, Config, Uart}, }; -use zynq7000_rt as _; // PS clock input frequency. const PS_CLK: Hertz = Hertz::from_raw(33_333_333); @@ -60,17 +59,8 @@ pub const ELF_BASE_ADDR: usize = 0x100000; /// 8 MB reserved for application ELF. pub const BOOT_BIN_STAGING_OFFSET: usize = 8 * 1024 * 1024; -/// 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() -> ! { +#[zynq7000_rt::entry] +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. diff --git a/zynq/zedboard-qspi-flasher/src/main.rs b/zynq/zedboard-qspi-flasher/src/main.rs index 6c5dcf9..9b744dc 100644 --- a/zynq/zedboard-qspi-flasher/src/main.rs +++ b/zynq/zedboard-qspi-flasher/src/main.rs @@ -36,19 +36,10 @@ const QSPI_DEV_COMBINATION: qspi::QspiDeviceCombination = qspi::QspiDeviceCombin 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() -> ! { +#[zynq7000_rt::entry] +fn main() -> ! { let periphs = zynq7000_hal::init(zynq7000_hal::Config { init_l2_cache: true, level_shifter_config: Some(LevelShifterConfig::EnableAll), diff --git a/zynq/zynq7000-rt/CHANGELOG.md b/zynq/zynq7000-rt/CHANGELOG.md index 0c6c123..0489968 100644 --- a/zynq/zynq7000-rt/CHANGELOG.md +++ b/zynq/zynq7000-rt/CHANGELOG.md @@ -14,6 +14,9 @@ Bugfixes in startup assembler code. - `.data` initialization is skipped if it is already in place, which is usually the default case because it is flashed to RAM. +- Runtime now calls a `kmain` method similar to the re-export `aarch32-rt` crate. + Former `boot_core` method must be renamed to `kmain`, but it is recommended to use + the `zynq7000-rt::entry` proc macro to annotate the main method. ## Fixed diff --git a/zynq/zynq7000-rt/README.md b/zynq/zynq7000-rt/README.md index dfaaf8d..14b930f 100644 --- a/zynq/zynq7000-rt/README.md +++ b/zynq/zynq7000-rt/README.md @@ -9,15 +9,18 @@ Startup code and minimal runtime for the AMD Zynq7000 SoC to write bare metal Ru This run-time crate is strongly based on the [startup code provided by AMD](https://github.com/Xilinx/embeddedsw/blob/master/lib/bsp/standalone/src/arm/cortexa9/gcc/boot.S). -Some major differences: +It mostly builds on [aarch32-rt](https://github.com/rust-embedded/aarch32/tree/main/aarch32-rt). +It activates the `fpu-d32` feature on that crate and overrides the `_default_start` method +to add necessary setup code for the Zynq7000. It re-exports the `aarch32-rt` crate, including +the attributes macros. The [documentation](https://docs.rs/aarch32-rt/latest/aarch32_rt/) specifies +these in detail. + +Some major differences to the startup code provided by AMD: - No L2 cache initialization is performed. - MMU table is specified as Rust code. - Modification to the stack setup code, because a different linker script is used. -This crate pulls in the [aarch32-rt](https://github.com/rust-embedded/aarch32/tree/main/aarch32-rt) -crate to provide ARM vectors and the linker script. - ## Features - `rt` is a default feature which activates the run-time. diff --git a/zynq/zynq7000-rt/src/lib.rs b/zynq/zynq7000-rt/src/lib.rs index 09da463..9715bd7 100644 --- a/zynq/zynq7000-rt/src/lib.rs +++ b/zynq/zynq7000-rt/src/lib.rs @@ -1,8 +1,16 @@ //! # Rust bare metal run-time support for the AMD Zynq 7000 SoCs //! -//! This includes basic low-level startup code similar to the bare-metal boot routines -//! [provided by Xilinx](https://github.com/Xilinx/embeddedsw/tree/master/lib/bsp/standalone/src/arm/cortexa9/gcc). -//! Some major differences: +//! Startup code and minimal runtime for the AMD Zynq7000 SoC to write bare metal Rust code. +//! This run-time crate is strongly based on the +//! [startup code provided by AMD](https://github.com/Xilinx/embeddedsw/blob/master/lib/bsp/standalone/src/arm/cortexa9/gcc/boot.S). +//! +//! It mostly builds on [aarch32-rt](https://github.com/rust-embedded/aarch32/tree/main/aarch32-rt). +//! It activates the `fpu-d32` feature on that crate and overrides the `_default_start` method +//! to add necessary setup code for the Zynq7000. It re-exports the `aarch32-rt` crate, including +//! the attributes macros. The [documentation](https://docs.rs/aarch32-rt/latest/aarch32_rt/) specifies +//! these in detail. +//! +//! Some major differences to the startup code provided by AMD: //! //! - No L2 cache initialization is performed. //! - MMU table is specified as Rust code. diff --git a/zynq/zynq7000-rt/src/rt.rs b/zynq/zynq7000-rt/src/rt.rs index 27b8813..d41fcdc 100644 --- a/zynq/zynq7000-rt/src/rt.rs +++ b/zynq/zynq7000-rt/src/rt.rs @@ -213,7 +213,7 @@ data_init_done: // Jump to application // Load CPU ID 0, which will be used as a function argument to the boot_core function. mov r0, #0x0 - bl boot_core + bl kmain // In case the application returns, loop forever b . .size _start, . - _start