Compare commits
4 Commits
prep-rt-pa
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| e43cab0312 | |||
| b5f5ccb52c | |||
| 25c326c3f1 | |||
| 116cb496d9 |
2
tools/Cargo.lock
generated
2
tools/Cargo.lock
generated
@@ -725,7 +725,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zynq7000-rt"
|
name = "zynq7000-rt"
|
||||||
version = "0.1.2"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aarch32-cpu",
|
"aarch32-cpu",
|
||||||
"arbitrary-int 2.0.0",
|
"arbitrary-int 2.0.0",
|
||||||
|
|||||||
@@ -21,28 +21,23 @@ use zynq7000_hal::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use zynq7000::Peripherals;
|
use zynq7000::Peripherals;
|
||||||
use zynq7000_rt as _;
|
|
||||||
|
|
||||||
// Define the clock frequency as a constant
|
// Define the clock frequency as a constant
|
||||||
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
|
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.
|
/// Try to talk to a DHT22 sensor connected at MIO0.
|
||||||
const DHT22_AT_MIO0: bool = true;
|
const DHT22_AT_MIO0: bool = true;
|
||||||
|
|
||||||
/// Open drain pin testing. MIO9 needs to be tied to MIO14.
|
/// Open drain pin testing. MIO9 needs to be tied to MIO14.
|
||||||
const OPEN_DRAIN_PINS_MIO9_TO_MIO14: bool = false;
|
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]
|
#[embassy_executor::main]
|
||||||
#[unsafe(export_name = "main")]
|
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
let mut dp = Peripherals::take().unwrap();
|
let mut dp = Peripherals::take().unwrap();
|
||||||
l2_cache::init_with_defaults(&mut dp.l2c);
|
l2_cache::init_with_defaults(&mut dp.l2c);
|
||||||
|
|||||||
@@ -15,17 +15,13 @@ use zynq7000_rt as _;
|
|||||||
// Define the clock frequency as a constant
|
// Define the clock frequency as a constant
|
||||||
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
|
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
/// Entry point which calls the embassy main method.
|
||||||
#[unsafe(no_mangle)]
|
#[zynq7000_rt::entry]
|
||||||
pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
fn entry_point() -> ! {
|
||||||
if cpu_id != 0 {
|
|
||||||
panic!("unexpected CPU ID {}", cpu_id);
|
|
||||||
}
|
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
#[unsafe(export_name = "main")]
|
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
let periphs = zynq7000_hal::init(zynq7000_hal::Config {
|
let periphs = zynq7000_hal::init(zynq7000_hal::Config {
|
||||||
init_l2_cache: true,
|
init_l2_cache: true,
|
||||||
|
|||||||
@@ -26,16 +26,12 @@ use zynq7000_rt as _;
|
|||||||
// Define the clock frequency as a constant
|
// Define the clock frequency as a constant
|
||||||
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
|
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
/// Entry point which calls the embassy main method.
|
||||||
#[unsafe(no_mangle)]
|
#[zynq7000_rt::entry]
|
||||||
pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
fn entry_point() -> ! {
|
||||||
if cpu_id != 0 {
|
|
||||||
panic!("unexpected CPU ID {}", cpu_id);
|
|
||||||
}
|
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(export_name = "main")]
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(spawner: Spawner) -> ! {
|
async fn main(spawner: Spawner) -> ! {
|
||||||
let mut dp = Peripherals::take().unwrap();
|
let mut dp = Peripherals::take().unwrap();
|
||||||
|
|||||||
@@ -32,17 +32,13 @@ use zynq7000_rt as _;
|
|||||||
// Define the clock frequency as a constant
|
// Define the clock frequency as a constant
|
||||||
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
|
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
/// Entry point which calls the embassy main method.
|
||||||
#[unsafe(no_mangle)]
|
#[zynq7000_rt::entry]
|
||||||
pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
fn entry_point() -> ! {
|
||||||
if cpu_id != 0 {
|
|
||||||
panic!("unexpected CPU ID {}", cpu_id);
|
|
||||||
}
|
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
#[unsafe(export_name = "main")]
|
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
let mut dp = Peripherals::take().unwrap();
|
let mut dp = Peripherals::take().unwrap();
|
||||||
l2_cache::init_with_defaults(&mut dp.l2c);
|
l2_cache::init_with_defaults(&mut dp.l2c);
|
||||||
|
|||||||
@@ -9,22 +9,16 @@ use embedded_hal::digital::StatefulOutputPin;
|
|||||||
use log::error;
|
use log::error;
|
||||||
use zynq7000_hal::{InteruptConfig, clocks, gic, gpio, gtc, time::Hertz};
|
use zynq7000_hal::{InteruptConfig, clocks, gic, gpio, gtc, time::Hertz};
|
||||||
|
|
||||||
use zynq7000_rt as _;
|
|
||||||
|
|
||||||
// Define the clock frequency as a constant
|
// Define the clock frequency as a constant
|
||||||
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
|
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
/// Entry point which calls the embassy main method.
|
||||||
#[unsafe(no_mangle)]
|
#[zynq7000_rt::entry]
|
||||||
pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
fn entry_point() -> ! {
|
||||||
if cpu_id != 0 {
|
|
||||||
panic!("unexpected CPU ID {}", cpu_id);
|
|
||||||
}
|
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
#[unsafe(export_name = "main")]
|
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
let periphs = zynq7000_hal::init(zynq7000_hal::Config {
|
let periphs = zynq7000_hal::init(zynq7000_hal::Config {
|
||||||
init_l2_cache: true,
|
init_l2_cache: true,
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ use zynq7000_hal::{
|
|||||||
priv_tim::CpuPrivateTimer,
|
priv_tim::CpuPrivateTimer,
|
||||||
time::Hertz,
|
time::Hertz,
|
||||||
};
|
};
|
||||||
use zynq7000_rt as _;
|
|
||||||
|
|
||||||
pub const LIB: Lib = Lib::Hal;
|
pub const LIB: Lib = Lib::Hal;
|
||||||
|
|
||||||
@@ -31,17 +30,8 @@ pub enum Lib {
|
|||||||
Hal,
|
Hal,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
#[zynq7000_rt::entry]
|
||||||
#[unsafe(no_mangle)]
|
fn main() -> ! {
|
||||||
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::Registers::new_mmio_fixed() });
|
l2_cache::init_with_defaults(&mut unsafe { zynq7000::l2_cache::Registers::new_mmio_fixed() });
|
||||||
match LIB {
|
match LIB {
|
||||||
Lib::Pac => {
|
Lib::Pac => {
|
||||||
|
|||||||
@@ -18,24 +18,13 @@ use zynq7000_hal::{
|
|||||||
uart::{ClockConfig, Config, Uart},
|
uart::{ClockConfig, Config, Uart},
|
||||||
};
|
};
|
||||||
|
|
||||||
use zynq7000_rt as _;
|
|
||||||
|
|
||||||
// Define the clock frequency as a constant
|
// Define the clock frequency as a constant
|
||||||
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_333);
|
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_333);
|
||||||
|
|
||||||
static MS_TICKS: AtomicU64 = AtomicU64::new(0);
|
static MS_TICKS: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
#[zynq7000_rt::entry]
|
||||||
#[unsafe(no_mangle)]
|
fn main() -> ! {
|
||||||
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 mut dp = zynq7000::Peripherals::take().unwrap();
|
let mut dp = zynq7000::Peripherals::take().unwrap();
|
||||||
l2_cache::init_with_defaults(&mut dp.l2c);
|
l2_cache::init_with_defaults(&mut dp.l2c);
|
||||||
|
|
||||||
|
|||||||
@@ -19,24 +19,13 @@ use zynq7000_hal::{
|
|||||||
uart::{ClockConfig, Config, Uart},
|
uart::{ClockConfig, Config, Uart},
|
||||||
};
|
};
|
||||||
|
|
||||||
use zynq7000_rt as _;
|
|
||||||
|
|
||||||
// Define the clock frequency as a constant
|
// Define the clock frequency as a constant
|
||||||
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
|
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
|
||||||
|
|
||||||
static MS_TICKS: AtomicU64 = AtomicU64::new(0);
|
static MS_TICKS: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
#[zynq7000_rt::entry]
|
||||||
#[unsafe(no_mangle)]
|
fn main() -> ! {
|
||||||
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 mut dp = zynq7000::Peripherals::take().unwrap();
|
let mut dp = zynq7000::Peripherals::take().unwrap();
|
||||||
l2_cache::init_with_defaults(&mut dp.l2c);
|
l2_cache::init_with_defaults(&mut dp.l2c);
|
||||||
|
|
||||||
|
|||||||
@@ -4,19 +4,9 @@
|
|||||||
|
|
||||||
use aarch32_cpu::asm::nop;
|
use aarch32_cpu::asm::nop;
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
use zynq7000_rt as _;
|
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
#[zynq7000_rt::entry]
|
||||||
#[unsafe(no_mangle)]
|
fn main() -> ! {
|
||||||
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() -> ! {
|
|
||||||
loop {
|
loop {
|
||||||
nop();
|
nop();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,12 +104,9 @@ pub enum IpMode {
|
|||||||
StackReady,
|
StackReady,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
/// Entry point which calls the embassy main method.
|
||||||
#[unsafe(no_mangle)]
|
#[zynq7000_rt::entry]
|
||||||
pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
fn entry_point() -> ! {
|
||||||
if cpu_id != 0 {
|
|
||||||
panic!("unexpected CPU ID {}", cpu_id);
|
|
||||||
}
|
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +201,6 @@ async fn tcp_task(mut tcp: TcpSocket<'static>) -> ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
#[unsafe(export_name = "main")]
|
|
||||||
async fn main(spawner: Spawner) -> ! {
|
async fn main(spawner: Spawner) -> ! {
|
||||||
let mut dp = Peripherals::take().unwrap();
|
let mut dp = Peripherals::take().unwrap();
|
||||||
l2_cache::init_with_defaults(&mut dp.l2c);
|
l2_cache::init_with_defaults(&mut dp.l2c);
|
||||||
|
|||||||
@@ -36,17 +36,13 @@ use zynq7000_rt as _;
|
|||||||
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
|
const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
|
||||||
const I2C_ADDR_SEL: I2cAddr = I2cAddr::Sa0Low;
|
const I2C_ADDR_SEL: I2cAddr = I2cAddr::Sa0Low;
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
/// Entry point which calls the embassy main method.
|
||||||
#[unsafe(no_mangle)]
|
#[zynq7000_rt::entry]
|
||||||
pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
fn entry_point() -> ! {
|
||||||
if cpu_id != 0 {
|
|
||||||
panic!("unexpected CPU ID {}", cpu_id);
|
|
||||||
}
|
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
#[unsafe(export_name = "main")]
|
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
let mut dp = Peripherals::take().unwrap();
|
let mut dp = Peripherals::take().unwrap();
|
||||||
l2_cache::init_with_defaults(&mut dp.l2c);
|
l2_cache::init_with_defaults(&mut dp.l2c);
|
||||||
|
|||||||
@@ -39,17 +39,13 @@ const PS_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(33_333_300);
|
|||||||
const DEBUG_SPI_CLK_CONFIG: bool = false;
|
const DEBUG_SPI_CLK_CONFIG: bool = false;
|
||||||
const BLOCKING: bool = false;
|
const BLOCKING: bool = false;
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
/// Entry point which calls the embassy main method.
|
||||||
#[unsafe(no_mangle)]
|
#[zynq7000_rt::entry]
|
||||||
pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
fn entry_point() -> ! {
|
||||||
if cpu_id != 0 {
|
|
||||||
panic!("unexpected CPU ID {}", cpu_id);
|
|
||||||
}
|
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
#[unsafe(export_name = "main")]
|
|
||||||
async fn main(spawner: Spawner) -> ! {
|
async fn main(spawner: Spawner) -> ! {
|
||||||
let mut dp = Peripherals::take().unwrap();
|
let mut dp = Peripherals::take().unwrap();
|
||||||
l2_cache::init_with_defaults(&mut dp.l2c);
|
l2_cache::init_with_defaults(&mut dp.l2c);
|
||||||
|
|||||||
@@ -21,19 +21,15 @@ const QSPI_DEV_COMBINATION: qspi::QspiDeviceCombination = qspi::QspiDeviceCombin
|
|||||||
two_devices: false,
|
two_devices: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
/// Entry point which calls the embassy main method.
|
||||||
#[unsafe(no_mangle)]
|
#[zynq7000_rt::entry]
|
||||||
pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
fn entry_point() -> ! {
|
||||||
if cpu_id != 0 {
|
|
||||||
panic!("unexpected CPU ID {}", cpu_id);
|
|
||||||
}
|
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ERASE_PROGRAM_READ_TEST: bool = false;
|
const ERASE_PROGRAM_READ_TEST: bool = false;
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
#[unsafe(export_name = "main")]
|
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
let periphs = zynq7000_hal::init(zynq7000_hal::Config {
|
let periphs = zynq7000_hal::init(zynq7000_hal::Config {
|
||||||
init_l2_cache: true,
|
init_l2_cache: true,
|
||||||
|
|||||||
@@ -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_UARTLITE_BASE_ADDR: u32 = 0x42C0_0000;
|
||||||
const AXI_UAR16550_BASE_ADDR: u32 = 0x43C0_0000;
|
const AXI_UAR16550_BASE_ADDR: u32 = 0x43C0_0000;
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
/// Entry point which calls the embassy main method.
|
||||||
#[unsafe(no_mangle)]
|
#[zynq7000_rt::entry]
|
||||||
pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
fn entry_point() -> ! {
|
||||||
if cpu_id != 0 {
|
|
||||||
panic!("unexpected CPU ID {}", cpu_id);
|
|
||||||
}
|
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +96,6 @@ impl UartMultiplexer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
#[unsafe(export_name = "main")]
|
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
let mut dp = Peripherals::take().unwrap();
|
let mut dp = Peripherals::take().unwrap();
|
||||||
l2_cache::init_with_defaults(&mut dp.l2c);
|
l2_cache::init_with_defaults(&mut dp.l2c);
|
||||||
|
|||||||
@@ -95,12 +95,9 @@ static UARTLITE_PROD: Mutex<RefCell<Option<heapless::spsc::Producer<'static, u8,
|
|||||||
static UART16550_PROD: Mutex<RefCell<Option<heapless::spsc::Producer<'static, u8, RB_SIZE>>>> =
|
static UART16550_PROD: Mutex<RefCell<Option<heapless::spsc::Producer<'static, u8, RB_SIZE>>>> =
|
||||||
Mutex::new(RefCell::new(None));
|
Mutex::new(RefCell::new(None));
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
/// Entry point which calls the embassy main method.
|
||||||
#[unsafe(no_mangle)]
|
#[zynq7000_rt::entry]
|
||||||
pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
fn entry_point() -> ! {
|
||||||
if cpu_id != 0 {
|
|
||||||
panic!("unexpected CPU ID {}", cpu_id);
|
|
||||||
}
|
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +161,6 @@ impl UartMultiplexer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
#[unsafe(export_name = "main")]
|
|
||||||
async fn main(spawner: Spawner) -> ! {
|
async fn main(spawner: Spawner) -> ! {
|
||||||
let mut dp = Peripherals::take().unwrap();
|
let mut dp = Peripherals::take().unwrap();
|
||||||
l2_cache::init_with_defaults(&mut dp.l2c);
|
l2_cache::init_with_defaults(&mut dp.l2c);
|
||||||
|
|||||||
@@ -15,17 +15,13 @@ use zynq7000_rt as _;
|
|||||||
|
|
||||||
const INIT_STRING: &str = "-- Zynq 7000 Zedboard GPIO blinky example --\n\r";
|
const INIT_STRING: &str = "-- Zynq 7000 Zedboard GPIO blinky example --\n\r";
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
/// Entry point which calls the embassy main method.
|
||||||
#[unsafe(no_mangle)]
|
#[zynq7000_rt::entry]
|
||||||
pub extern "C" fn boot_core(cpu_id: u32) -> ! {
|
fn entry_point() -> ! {
|
||||||
if cpu_id != 0 {
|
|
||||||
panic!("unexpected CPU ID {}", cpu_id);
|
|
||||||
}
|
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
#[unsafe(export_name = "main")]
|
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
let periphs = zynq7000_hal::init(zynq7000_hal::Config {
|
let periphs = zynq7000_hal::init(zynq7000_hal::Config {
|
||||||
init_l2_cache: true,
|
init_l2_cache: true,
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ use zynq7000_hal::{
|
|||||||
time::Hertz,
|
time::Hertz,
|
||||||
uart::{ClockConfig, Config, Uart},
|
uart::{ClockConfig, Config, Uart},
|
||||||
};
|
};
|
||||||
use zynq7000_rt as _;
|
|
||||||
|
|
||||||
// PS clock input frequency.
|
// PS clock input frequency.
|
||||||
const PS_CLK: Hertz = Hertz::from_raw(33_333_333);
|
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.
|
/// 8 MB reserved for application ELF.
|
||||||
pub const BOOT_BIN_STAGING_OFFSET: usize = 8 * 1024 * 1024;
|
pub const BOOT_BIN_STAGING_OFFSET: usize = 8 * 1024 * 1024;
|
||||||
|
|
||||||
/// Entry point (not called like a normal main function)
|
#[zynq7000_rt::entry]
|
||||||
#[unsafe(no_mangle)]
|
fn main() -> ! {
|
||||||
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();
|
let boot_mode = BootMode::new_from_regs();
|
||||||
// The unwraps are okay here, the provided clock frequencies are standard values also used
|
// The unwraps are okay here, the provided clock frequencies are standard values also used
|
||||||
// by other Xilinx tools.
|
// by other Xilinx tools.
|
||||||
|
|||||||
@@ -36,19 +36,10 @@ const QSPI_DEV_COMBINATION: qspi::QspiDeviceCombination = qspi::QspiDeviceCombin
|
|||||||
two_devices: false,
|
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";
|
const INIT_STRING: &str = "-- Zynq 7000 Zedboard QSPI flasher --\n\r";
|
||||||
|
|
||||||
#[unsafe(export_name = "main")]
|
#[zynq7000_rt::entry]
|
||||||
pub fn main() -> ! {
|
fn main() -> ! {
|
||||||
let periphs = zynq7000_hal::init(zynq7000_hal::Config {
|
let periphs = zynq7000_hal::init(zynq7000_hal::Config {
|
||||||
init_l2_cache: true,
|
init_l2_cache: true,
|
||||||
level_shifter_config: Some(LevelShifterConfig::EnableAll),
|
level_shifter_config: Some(LevelShifterConfig::EnableAll),
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
- Increased UART type safety by providing dedicated MIO constructors for UART 0 and UART 1
|
- Increased UART type safety by providing dedicated MIO constructors for UART 0 and UART 1
|
||||||
respectively.
|
respectively.
|
||||||
|
- Several bugfixes and improvements for GIC module. Some of the registers previously were
|
||||||
|
completely overwritten instead of only modifying their own bit portions. Also allow targeting
|
||||||
|
interrupts without clearing other CPU target.
|
||||||
|
|
||||||
# [v0.1.1] 2025-10-10
|
# [v0.1.1] 2025-10-10
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ bitbybit = "1.4"
|
|||||||
arbitrary-int = "2"
|
arbitrary-int = "2"
|
||||||
thiserror = { version = "2", default-features = false }
|
thiserror = { version = "2", default-features = false }
|
||||||
num_enum = { version = "0.7", default-features = false }
|
num_enum = { version = "0.7", default-features = false }
|
||||||
|
bitflags = "2"
|
||||||
ringbuf = { version = "0.4.8", default-features = false }
|
ringbuf = { version = "0.4.8", default-features = false }
|
||||||
embedded-hal-nb = "1"
|
embedded-hal-nb = "1"
|
||||||
embedded-io = "0.7"
|
embedded-io = "0.7"
|
||||||
@@ -40,6 +41,7 @@ smoltcp = { version = "0.12", default-features = false, features = ["proto-ipv4"
|
|||||||
vcell = "0.1"
|
vcell = "0.1"
|
||||||
raw-slicee = "0.1"
|
raw-slicee = "0.1"
|
||||||
embedded-io-async = "0.7"
|
embedded-io-async = "0.7"
|
||||||
|
serde = { version = "1", optional = true, features = ["derive"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
std = ["thiserror/std", "alloc"]
|
std = ["thiserror/std", "alloc"]
|
||||||
|
|||||||
@@ -6,17 +6,22 @@
|
|||||||
//! # Examples
|
//! # Examples
|
||||||
//!
|
//!
|
||||||
//! - [GTC ticks](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/examples/simple/src/bin/gtc-ticks.rs)
|
//! - [GTC ticks](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/examples/simple/src/bin/gtc-ticks.rs)
|
||||||
|
#![deny(missing_docs)]
|
||||||
use arbitrary_int::prelude::*;
|
use arbitrary_int::prelude::*;
|
||||||
|
|
||||||
use aarch32_cpu::interrupt;
|
use aarch32_cpu::interrupt;
|
||||||
use zynq7000::gic::{
|
use zynq7000::gic::{
|
||||||
CpuInterfaceRegisters, DistributorControlRegister, DistributorRegisters, InterfaceControl,
|
CpuInterfaceRegisters, DistributorControlRegister, DistributorRegisters, InterfaceControl,
|
||||||
InterruptSignalRegister, MmioCpuInterfaceRegisters, MmioDistributorRegisters, PriorityRegister,
|
InterruptProcessorTargetRegister, InterruptSignalRegister, MmioCpuInterfaceRegisters,
|
||||||
|
MmioDistributorRegisters, PriorityRegister,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SPURIOUS_INTERRUPT_ID: u32 = 1023;
|
/// Spurious interrupt ID.
|
||||||
|
pub const SPURIOUS_INTERRUPT_ID: u32 = 1023;
|
||||||
|
|
||||||
|
/// Highest interrupt priority (smallest number).
|
||||||
pub const HIGHEST_PRIORITY: u8 = 0;
|
pub const HIGHEST_PRIORITY: u8 = 0;
|
||||||
|
/// Lowest interrupt priority (largest number).
|
||||||
pub const LOWEST_PRIORITY: u8 = 31;
|
pub const LOWEST_PRIORITY: u8 = 31;
|
||||||
|
|
||||||
/// These fixed values must be programmed according to the Zynq7000 TRM p.236.
|
/// These fixed values must be programmed according to the Zynq7000 TRM p.236.
|
||||||
@@ -36,119 +41,218 @@ pub const ICFR_4_FIXED_VALUE: u32 = 0b01110101010101010101010101010101;
|
|||||||
pub const ICFR_5_FIXED_VALUE: u32 = 0b00000011010101010101010101010101;
|
pub const ICFR_5_FIXED_VALUE: u32 = 0b00000011010101010101010101010101;
|
||||||
|
|
||||||
/// Helper value to target all interrupts which can be targetted to CPU 0
|
/// Helper value to target all interrupts which can be targetted to CPU 0
|
||||||
pub const TARGETS_ALL_CPU_0_IPTR_VAL: u32 = 0x01010101;
|
pub const TARGETS_ALL_CPU_0_IPTR_VAL: InterruptProcessorTargetRegister =
|
||||||
|
InterruptProcessorTargetRegister::new_with_raw_value(0x01010101);
|
||||||
/// Helper value to target all interrupts which can be targetted to CPU 1
|
/// Helper value to target all interrupts which can be targetted to CPU 1
|
||||||
pub const TARGETS_ALL_CPU_1_IPTR_VAL: u32 = 0x02020202;
|
pub const TARGETS_ALL_CPU_1_IPTR_VAL: InterruptProcessorTargetRegister =
|
||||||
|
InterruptProcessorTargetRegister::new_with_raw_value(0x02020202);
|
||||||
|
|
||||||
|
/// Mask for activating all softare generated interrupts.
|
||||||
pub const ACTIVATE_ALL_SGIS_MASK_ISER: u32 = 0x0000_FFFF;
|
pub const ACTIVATE_ALL_SGIS_MASK_ISER: u32 = 0x0000_FFFF;
|
||||||
|
/// Mask for activating all private peripheral interrupts.
|
||||||
pub const ACTIVATE_ALL_PPIS_MASK_ISER: u32 = 0xF800_0000;
|
pub const ACTIVATE_ALL_PPIS_MASK_ISER: u32 = 0xF800_0000;
|
||||||
|
|
||||||
|
/// Shared peripheral interrupt sensitivity.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub enum SpiSensitivity {
|
pub enum SpiSensitivity {
|
||||||
|
/// Level triggered interrupt.
|
||||||
Level = 0b01,
|
Level = 0b01,
|
||||||
|
/// Edge triggered interrupt.
|
||||||
Edge = 0b11,
|
Edge = 0b11,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum TargetCpu {
|
/// CPU enumeration.
|
||||||
None = 0b00,
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
Cpu0 = 0b01,
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
Cpu1 = 0b10,
|
pub enum Cpu {
|
||||||
Both = 0b11,
|
/// CPU 0.
|
||||||
|
Cpu0,
|
||||||
|
/// CPU 1.
|
||||||
|
Cpu1,
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags::bitflags! {
|
||||||
|
/// Target CPU bitflags.
|
||||||
|
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
pub struct TargetCpus: u8 {
|
||||||
|
/// No CPU.
|
||||||
|
const NONE = 0b00;
|
||||||
|
/// CPU 0.
|
||||||
|
const CPU_0 = 0b01;
|
||||||
|
/// CPU 1.
|
||||||
|
const CPU_1 = 0b10;
|
||||||
|
/// Both CPUs.
|
||||||
|
const BOTH_CPUS = 0b11;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Private Peripheral Interrupt (PPI) which are private to the CPU.
|
/// Private Peripheral Interrupt (PPI) which are private to the CPU.
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, num_enum::TryFromPrimitive)]
|
#[derive(Debug, Eq, PartialEq, Clone, Copy, num_enum::TryFromPrimitive)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum PpiInterrupt {
|
pub enum PpiInterrupt {
|
||||||
|
/// Global timer.
|
||||||
GlobalTimer = 27,
|
GlobalTimer = 27,
|
||||||
// Interrupt signal from the PL. CPU0: `IRQF2P[18]` and CPU1: `IRQF2P[19]`
|
/// Interrupt signal from the PL. CPU0: `IRQF2P[18]` and CPU1: `IRQF2P[19]`
|
||||||
NFiq = 28,
|
NFiq = 28,
|
||||||
|
/// CPU private timer.
|
||||||
CpuPrivateTimer = 29,
|
CpuPrivateTimer = 29,
|
||||||
/// AWDT0 and AWDT1 for each CPU.
|
/// AWDT0 and AWDT1 for each CPU.
|
||||||
Awdt = 30,
|
Awdt = 30,
|
||||||
// Interrupt signal from the PL. CPU0: `IRQF2P[16]` and CPU1: `IRQF2P[17]`
|
/// Interrupt signal from the PL. CPU0: `IRQF2P[16]` and CPU1: `IRQF2P[17]`
|
||||||
NIrq = 31,
|
NIrq = 31,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shared Peripheral Interrupt IDs.
|
/// Shared Peripheral Interrupt IDs.
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, num_enum::TryFromPrimitive)]
|
#[derive(Debug, Eq, PartialEq, Clone, Copy, num_enum::TryFromPrimitive)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum SpiInterrupt {
|
pub enum SpiInterrupt {
|
||||||
|
/// CPU 0.
|
||||||
Cpu0 = 32,
|
Cpu0 = 32,
|
||||||
|
/// CPU 1.
|
||||||
Cpu1 = 33,
|
Cpu1 = 33,
|
||||||
|
/// L2 cache.
|
||||||
L2Cache = 34,
|
L2Cache = 34,
|
||||||
|
/// On-chip memory.
|
||||||
Ocm = 35,
|
Ocm = 35,
|
||||||
|
/// Reserved.
|
||||||
_Reserved0 = 36,
|
_Reserved0 = 36,
|
||||||
|
/// Performance monitor unit 0.
|
||||||
Pmu0 = 37,
|
Pmu0 = 37,
|
||||||
|
/// Performance monitor unit 1.
|
||||||
Pmu1 = 38,
|
Pmu1 = 38,
|
||||||
|
/// XADC.
|
||||||
Xadc = 39,
|
Xadc = 39,
|
||||||
|
/// Device configuration.
|
||||||
DevC = 40,
|
DevC = 40,
|
||||||
|
/// System watchdog timer.
|
||||||
Swdt = 41,
|
Swdt = 41,
|
||||||
|
/// Triple timer counter 00.
|
||||||
Ttc00 = 42,
|
Ttc00 = 42,
|
||||||
|
/// Triple timer counter 01.
|
||||||
Ttc01 = 43,
|
Ttc01 = 43,
|
||||||
|
/// Triple timer counter 02.
|
||||||
Ttc02 = 44,
|
Ttc02 = 44,
|
||||||
|
/// DMAC abort.
|
||||||
DmacAbort = 45,
|
DmacAbort = 45,
|
||||||
|
/// DMAC 0.
|
||||||
Dmac0 = 46,
|
Dmac0 = 46,
|
||||||
|
/// DMAC 1.
|
||||||
Dmac1 = 47,
|
Dmac1 = 47,
|
||||||
|
/// DMAC 2.
|
||||||
Dmac2 = 48,
|
Dmac2 = 48,
|
||||||
|
/// DMAC 3.
|
||||||
Dmac3 = 49,
|
Dmac3 = 49,
|
||||||
|
/// Shared memory controller.
|
||||||
Smc = 50,
|
Smc = 50,
|
||||||
|
/// Quad SPI.
|
||||||
Qspi = 51,
|
Qspi = 51,
|
||||||
|
/// GPIO.
|
||||||
Gpio = 52,
|
Gpio = 52,
|
||||||
|
/// USB 0.
|
||||||
Usb0 = 53,
|
Usb0 = 53,
|
||||||
|
/// Ethernet 0.
|
||||||
Eth0 = 54,
|
Eth0 = 54,
|
||||||
|
/// Ethernet 0 wakeup.
|
||||||
Eth0Wakeup = 55,
|
Eth0Wakeup = 55,
|
||||||
|
/// SDIO 0.
|
||||||
Sdio0 = 56,
|
Sdio0 = 56,
|
||||||
|
/// I2C 0.
|
||||||
I2c0 = 57,
|
I2c0 = 57,
|
||||||
|
/// SPI 0.
|
||||||
Spi0 = 58,
|
Spi0 = 58,
|
||||||
|
/// UART 0.
|
||||||
Uart0 = 59,
|
Uart0 = 59,
|
||||||
|
/// CAN 0.
|
||||||
Can0 = 60,
|
Can0 = 60,
|
||||||
|
/// Programmable Logic 0.
|
||||||
Pl0 = 61,
|
Pl0 = 61,
|
||||||
|
/// Programmable Logic 1.
|
||||||
Pl1 = 62,
|
Pl1 = 62,
|
||||||
|
/// Programmable Logic 2.
|
||||||
Pl2 = 63,
|
Pl2 = 63,
|
||||||
|
/// Programmable Logic 3.
|
||||||
Pl3 = 64,
|
Pl3 = 64,
|
||||||
|
/// Programmable Logic 4.
|
||||||
Pl4 = 65,
|
Pl4 = 65,
|
||||||
|
/// Programmable Logic 5.
|
||||||
Pl5 = 66,
|
Pl5 = 66,
|
||||||
|
/// Programmable Logic 6.
|
||||||
Pl6 = 67,
|
Pl6 = 67,
|
||||||
|
/// Programmable Logic 7.
|
||||||
Pl7 = 68,
|
Pl7 = 68,
|
||||||
|
/// Triple timer counter 10.
|
||||||
Ttc10 = 69,
|
Ttc10 = 69,
|
||||||
|
/// Triple timer counter 11.
|
||||||
Ttc11 = 70,
|
Ttc11 = 70,
|
||||||
|
/// Triple timer counter 12.
|
||||||
Ttc12 = 71,
|
Ttc12 = 71,
|
||||||
|
/// DMAC 4.
|
||||||
Dmac4 = 72,
|
Dmac4 = 72,
|
||||||
|
/// DMAC 5.
|
||||||
Dmac5 = 73,
|
Dmac5 = 73,
|
||||||
|
/// DMAC 6.
|
||||||
Dmac6 = 74,
|
Dmac6 = 74,
|
||||||
|
/// DMAC 7.
|
||||||
Dmac7 = 75,
|
Dmac7 = 75,
|
||||||
|
/// USB 1.
|
||||||
Usb1 = 76,
|
Usb1 = 76,
|
||||||
|
/// Ethernet 1.
|
||||||
Eth1 = 77,
|
Eth1 = 77,
|
||||||
|
/// Ethernet 1 wakeup.
|
||||||
Eth1Wakeup = 78,
|
Eth1Wakeup = 78,
|
||||||
|
/// SDIO 1.
|
||||||
Sdio1 = 79,
|
Sdio1 = 79,
|
||||||
|
/// I2C 1.
|
||||||
I2c1 = 80,
|
I2c1 = 80,
|
||||||
|
/// SPI 1.
|
||||||
Spi1 = 81,
|
Spi1 = 81,
|
||||||
|
/// UART 1.
|
||||||
Uart1 = 82,
|
Uart1 = 82,
|
||||||
|
/// CAN 1.
|
||||||
Can1 = 83,
|
Can1 = 83,
|
||||||
|
/// Programmable Logic 8.
|
||||||
Pl8 = 84,
|
Pl8 = 84,
|
||||||
|
/// Programmable Logic 9.
|
||||||
Pl9 = 85,
|
Pl9 = 85,
|
||||||
|
/// Programmable Logic 10.
|
||||||
Pl10 = 86,
|
Pl10 = 86,
|
||||||
|
/// Programmable Logic 11.
|
||||||
Pl11 = 87,
|
Pl11 = 87,
|
||||||
|
/// Programmable Logic 12.
|
||||||
Pl12 = 88,
|
Pl12 = 88,
|
||||||
|
/// Programmable Logic 13.
|
||||||
Pl13 = 89,
|
Pl13 = 89,
|
||||||
|
/// Programmable Logic 14.
|
||||||
Pl14 = 90,
|
Pl14 = 90,
|
||||||
|
/// Programmable Logic 15.
|
||||||
Pl15 = 91,
|
Pl15 = 91,
|
||||||
|
/// Snoop control unit parity.
|
||||||
ScuParity = 92,
|
ScuParity = 92,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interrupt ID wrapper.
|
/// Interrupt ID wrapper.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub enum Interrupt {
|
pub enum Interrupt {
|
||||||
|
/// Software-generated interrupt (SGI).
|
||||||
Sgi(usize),
|
Sgi(usize),
|
||||||
|
/// Private peripheral interrupt (PPI).
|
||||||
Ppi(PpiInterrupt),
|
Ppi(PpiInterrupt),
|
||||||
|
/// Shared peripheral interrupt (SPI).
|
||||||
Spi(SpiInterrupt),
|
Spi(SpiInterrupt),
|
||||||
/// Detects an invalid interrupt ID.
|
/// Detects an invalid interrupt ID.
|
||||||
Invalid(usize),
|
Invalid(usize),
|
||||||
/// Spurious interrupt (ID# 1023).
|
/// Spurious interrupt (ID# 1023, [SPURIOUS_INTERRUPT_ID]).
|
||||||
Spurious,
|
Spurious,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Interrupt information structure.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub struct InterruptInfo {
|
pub struct InterruptInfo {
|
||||||
raw_reg: InterruptSignalRegister,
|
raw_reg: InterruptSignalRegister,
|
||||||
interrupt: Interrupt,
|
interrupt: Interrupt,
|
||||||
@@ -156,34 +260,46 @@ pub struct InterruptInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl InterruptInfo {
|
impl InterruptInfo {
|
||||||
pub fn raw_reg(&self) -> InterruptSignalRegister {
|
/// Raw interrupt signal register value.
|
||||||
|
#[inline]
|
||||||
|
pub const fn raw_reg(&self) -> InterruptSignalRegister {
|
||||||
self.raw_reg
|
self.raw_reg
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cpu_id(&self) -> u8 {
|
/// CPU ID.
|
||||||
|
#[inline]
|
||||||
|
pub const fn cpu_id(&self) -> u8 {
|
||||||
self.cpu_id
|
self.cpu_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interrupt(&self) -> Interrupt {
|
/// Interrupt ID.
|
||||||
|
#[inline]
|
||||||
|
pub const fn interrupt(&self) -> Interrupt {
|
||||||
self.interrupt
|
self.interrupt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Invalid priority value error.
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[error("Invalid priority value {0}, range is [0, 31]")]
|
#[error("Invalid priority value {0}, range is [0, 31]")]
|
||||||
pub struct InvalidPriorityValue(pub u8);
|
pub struct InvalidPriorityValue(pub u8);
|
||||||
|
|
||||||
|
/// Invalid programmable logic interrupt ID.
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[error("Invalid PL interrupt ID {0}")]
|
#[error("Invalid PL interrupt ID {0}")]
|
||||||
pub struct InvalidPlInterruptId(pub usize);
|
pub struct InvalidPlInterruptId(pub usize);
|
||||||
|
|
||||||
/// Invalid Shared Peripheral Interrupt (SPI) ID.
|
/// Invalid Shared Peripheral Interrupt (SPI) ID.
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[error("Invalid SPI interrupt ID {0}")]
|
#[error("Invalid SPI interrupt ID {0}")]
|
||||||
pub struct InvalidSpiInterruptId(pub usize);
|
pub struct InvalidSpiInterruptId(pub usize);
|
||||||
|
|
||||||
/// Invalid Software Generated Interrupt (SGI) ID.
|
/// Invalid Software Generated Interrupt (SGI) ID.
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[error("Invalid SGI interrupt ID {0}")]
|
#[error("Invalid SGI interrupt ID {0}")]
|
||||||
pub struct InvalidSgiInterruptId(pub usize);
|
pub struct InvalidSgiInterruptId(pub usize);
|
||||||
|
|
||||||
@@ -202,7 +318,8 @@ pub struct InvalidSgiInterruptId(pub usize);
|
|||||||
/// the [SpiSensitivity] enum. You can use the following (helper) API to configure the
|
/// the [SpiSensitivity] enum. You can use the following (helper) API to configure the
|
||||||
/// interrupts:
|
/// interrupts:
|
||||||
///
|
///
|
||||||
/// - [Self::set_spi_interrupt_cpu_target]
|
/// - [Self::set_spi_interrupt_target_for_cpu]
|
||||||
|
/// - [Self::set_spi_interrupt_cpu_target_flags]
|
||||||
/// - [Self::set_all_spi_interrupt_targets_cpu0]
|
/// - [Self::set_all_spi_interrupt_targets_cpu0]
|
||||||
/// - [Self::set_pl_interrupt_sensitivity]
|
/// - [Self::set_pl_interrupt_sensitivity]
|
||||||
///
|
///
|
||||||
@@ -219,12 +336,14 @@ pub struct InvalidSgiInterruptId(pub usize);
|
|||||||
/// You might also chose to enable these interrupts at run-time after the GIC was started.
|
/// You might also chose to enable these interrupts at run-time after the GIC was started.
|
||||||
/// 4. Start the GIC by calling [Self::update_ctrl_regs] with the required settings or
|
/// 4. Start the GIC by calling [Self::update_ctrl_regs] with the required settings or
|
||||||
/// with [Self::enable] which assumes a certain configuration.
|
/// with [Self::enable] which assumes a certain configuration.
|
||||||
/// 5. Enable interrupts for the Cortex-AR core by calling [Self::enable_interrupts].
|
/// 5. Enable interrupts for the Cortex-A core by calling [Self::enable_interrupts].
|
||||||
///
|
///
|
||||||
/// For the handling of the interrupts, you can use the [GicInterruptHelper] which assumes a
|
/// For the handling of the interrupts, you can use the [GicInterruptHelper] which assumes a
|
||||||
/// properly configured GIC.
|
/// properly configured GIC.
|
||||||
pub struct GicConfigurator {
|
pub struct GicConfigurator {
|
||||||
|
/// GIC CPU interface registers.
|
||||||
pub gicc: MmioCpuInterfaceRegisters<'static>,
|
pub gicc: MmioCpuInterfaceRegisters<'static>,
|
||||||
|
/// GIC Distributor interface registers.
|
||||||
pub gicd: MmioDistributorRegisters<'static>,
|
pub gicd: MmioDistributorRegisters<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,45 +444,90 @@ impl GicConfigurator {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the CPU target for a SPI interrupt.
|
/// Set the CPU target(s) for a SPI interrupt.
|
||||||
///
|
///
|
||||||
/// See [Self::set_all_spi_interrupt_targets_cpu0] for a utility method to handle all
|
/// See [Self::set_all_spi_interrupt_targets_cpu0] for a utility method to handle all
|
||||||
/// interrupts with one core.
|
/// interrupts with one core.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_spi_interrupt_cpu_target(&mut self, spi_int: SpiInterrupt, target: TargetCpu) {
|
pub fn set_spi_interrupt_cpu_target_flags(
|
||||||
|
&mut self,
|
||||||
|
spi_int: SpiInterrupt,
|
||||||
|
target: TargetCpus,
|
||||||
|
) {
|
||||||
let spi_int_raw = spi_int as u32;
|
let spi_int_raw = spi_int as u32;
|
||||||
let spi_offset_to_0 = spi_int_raw as usize - 32;
|
let spi_offset_to_0 = spi_int_raw as usize - 32;
|
||||||
// Unwrap okay, calculated index is always valid.
|
// Unwrap okay, calculated index is always valid.
|
||||||
self.gicd
|
self.gicd
|
||||||
.write_iptr_spi(
|
.modify_iptr_spi(spi_offset_to_0 / 4, |mut v| {
|
||||||
spi_offset_to_0 / 4,
|
// Every register contains 4 target flags, the modulo extracts the index because
|
||||||
(target as u32) << ((spi_offset_to_0 % 4) * 8),
|
// counting starts at 32 (32 -> index 0, 33 -> index 1 etc.).
|
||||||
)
|
v.set_targets(spi_offset_to_0 % 4, u2::new(target.bits()));
|
||||||
|
v
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enable SPI interrupt target for a specific CPU without clearing the other CPU bit if it is
|
||||||
|
/// set.
|
||||||
|
#[inline]
|
||||||
|
pub fn set_spi_interrupt_target_for_cpu(&mut self, spi_int: SpiInterrupt, cpu: Cpu) {
|
||||||
|
let bitflag = match cpu {
|
||||||
|
Cpu::Cpu0 => TargetCpus::CPU_0,
|
||||||
|
Cpu::Cpu1 => TargetCpus::CPU_1,
|
||||||
|
};
|
||||||
|
let spi_int_raw = spi_int as u32;
|
||||||
|
let spi_offset_to_0 = spi_int_raw as usize - 32;
|
||||||
|
// Unwrap okay, calculated index is always valid.
|
||||||
|
self.gicd
|
||||||
|
.modify_iptr_spi(spi_offset_to_0 / 4, |mut v| {
|
||||||
|
v.set_targets(
|
||||||
|
spi_offset_to_0 % 4,
|
||||||
|
// Extract the target bits, bitwise OR them with [TargetCpus::CPU_0], and set
|
||||||
|
// them back.
|
||||||
|
u2::new(
|
||||||
|
(TargetCpus::from_bits(v.targets(spi_offset_to_0 % 4).as_u8()).unwrap()
|
||||||
|
| bitflag)
|
||||||
|
.bits(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
v
|
||||||
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Utility function to set all SGI interrupt targets to CPU0.
|
/// Utility function to set all SGI interrupt targets to CPU0.
|
||||||
///
|
///
|
||||||
|
/// This does not clear interrupt target bits for CPU1, it only activates the interrupts for
|
||||||
|
/// CPU 0 as well.
|
||||||
/// This is useful if only CPU0 is active in a system, or if CPU0 handles most interrupts in
|
/// This is useful if only CPU0 is active in a system, or if CPU0 handles most interrupts in
|
||||||
/// the system.
|
/// the system.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_all_spi_interrupt_targets_cpu0(&mut self) {
|
pub fn set_all_spi_interrupt_targets_cpu0(&mut self) {
|
||||||
for i in 0..0x10 {
|
for i in 0..0x10 {
|
||||||
self.gicd
|
self.gicd
|
||||||
.write_iptr_spi(i, TARGETS_ALL_CPU_0_IPTR_VAL)
|
.modify_iptr_spi(i, |v| {
|
||||||
|
InterruptProcessorTargetRegister::new_with_raw_value(
|
||||||
|
v.raw_value() | TARGETS_ALL_CPU_0_IPTR_VAL.raw_value(),
|
||||||
|
)
|
||||||
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable a specific SGI interrupt.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn enable_sgi_interrupt(&mut self, int_id: usize) -> Result<(), InvalidSpiInterruptId> {
|
pub fn enable_sgi_interrupt(&mut self, int_id: usize) -> Result<(), InvalidSpiInterruptId> {
|
||||||
if int_id >= 16 {
|
if int_id >= 16 {
|
||||||
return Err(InvalidSpiInterruptId(int_id));
|
return Err(InvalidSpiInterruptId(int_id));
|
||||||
}
|
}
|
||||||
unsafe { self.gicd.write_iser_unchecked(0, 1 << int_id) };
|
unsafe {
|
||||||
|
self.gicd
|
||||||
|
.modify_iser_unchecked(0, |val| val | (1 << int_id))
|
||||||
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable all SGI interrupts.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn enable_all_sgi_interrupts(&mut self) {
|
pub fn enable_all_sgi_interrupts(&mut self) {
|
||||||
// Unwrap okay, index is valid.
|
// Unwrap okay, index is valid.
|
||||||
@@ -375,17 +539,16 @@ impl GicConfigurator {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable specific PPI interrupt.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn enable_ppi_interrupt(&mut self, ppi_int: PpiInterrupt) {
|
pub fn enable_ppi_interrupt(&mut self, ppi_int: PpiInterrupt) {
|
||||||
// Unwrap okay, index is valid.
|
// Unwrap okay, index is valid.
|
||||||
self.gicd
|
self.gicd
|
||||||
.modify_iser(0, |mut v| {
|
.modify_iser(0, |v| v | 1 << (ppi_int as u32))
|
||||||
v |= 1 << (ppi_int as u32);
|
|
||||||
v
|
|
||||||
})
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable all PPI interrupts.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn enable_all_ppi_interrupts(&mut self) {
|
pub fn enable_all_ppi_interrupts(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
@@ -396,6 +559,7 @@ impl GicConfigurator {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable specific SPI interrupt.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn enable_spi_interrupt(&mut self, spi_int: SpiInterrupt) {
|
pub fn enable_spi_interrupt(&mut self, spi_int: SpiInterrupt) {
|
||||||
let spi_int_raw = spi_int as u32;
|
let spi_int_raw = spi_int as u32;
|
||||||
@@ -403,17 +567,18 @@ impl GicConfigurator {
|
|||||||
32..=63 => {
|
32..=63 => {
|
||||||
let bit_pos = spi_int_raw - 32;
|
let bit_pos = spi_int_raw - 32;
|
||||||
// Unwrap okay, valid index.
|
// Unwrap okay, valid index.
|
||||||
self.gicd.write_iser(1, 1 << bit_pos).unwrap();
|
self.gicd.modify_iser(1, |v| v | (1 << bit_pos)).unwrap();
|
||||||
}
|
}
|
||||||
64..=92 => {
|
64..=92 => {
|
||||||
let bit_pos = spi_int_raw - 64;
|
let bit_pos = spi_int_raw - 64;
|
||||||
// Unwrap okay, valid index.
|
// Unwrap okay, valid index.
|
||||||
self.gicd.write_iser(2, 1 << bit_pos).unwrap();
|
self.gicd.modify_iser(2, |v| v | (1 << bit_pos)).unwrap();
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable all SPI interrupts.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn enable_all_spi_interrupts(&mut self) {
|
pub fn enable_all_spi_interrupts(&mut self) {
|
||||||
self.gicd.write_iser(1, 0xFFFF_FFFF).unwrap();
|
self.gicd.write_iser(1, 0xFFFF_FFFF).unwrap();
|
||||||
|
|||||||
@@ -8,14 +8,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
# [v0.1.2] 2025-11-28
|
|
||||||
|
|
||||||
Bugfixes in startup assembler code.
|
Bugfixes in startup assembler code.
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
- `.data` initialization is skipped if it is already in place, which is usually the default
|
- `.data` initialization is skipped if it is already in place, which is usually the default
|
||||||
case because it is flashed to RAM.
|
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
|
## Fixed
|
||||||
|
|
||||||
@@ -31,7 +32,6 @@ Documentation fixes.
|
|||||||
|
|
||||||
Initial release
|
Initial release
|
||||||
|
|
||||||
[unreleased]: https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/compare/zynq7000-rt-v0.1.2...HEAD
|
[unreleased]: https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/compare/zynq7000-rt-v0.1.0...HEAD
|
||||||
[v0.1.2]: https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/compare/zynq7000-rt-v0.1.1...zynq7000-rt-v0.1.2
|
|
||||||
[v0.1.1]: https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/compare/zynq7000-rt-v0.1.0...zynq7000-rt-v0.1.1
|
[v0.1.1]: https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/compare/zynq7000-rt-v0.1.0...zynq7000-rt-v0.1.1
|
||||||
[v0.1.0]: https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/tag/zynq7000-rt-v0.1.0
|
[v0.1.0]: https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/tag/zynq7000-rt-v0.1.0
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "zynq7000-rt"
|
name = "zynq7000-rt"
|
||||||
version = "0.1.2"
|
version = "0.1.1"
|
||||||
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
|
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
description = "Run-time support for the Zynq7000 family of SoCs for running bare-metal applications"
|
description = "Run-time support for the Zynq7000 family of SoCs for running bare-metal applications"
|
||||||
|
|||||||
@@ -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
|
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).
|
[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.
|
- No L2 cache initialization is performed.
|
||||||
- MMU table is specified as Rust code.
|
- MMU table is specified as Rust code.
|
||||||
- Modification to the stack setup code, because a different linker script is used.
|
- 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
|
## Features
|
||||||
|
|
||||||
- `rt` is a default feature which activates the run-time.
|
- `rt` is a default feature which activates the run-time.
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
//! # Rust bare metal run-time support for the AMD Zynq 7000 SoCs
|
//! # 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
|
//! Startup code and minimal runtime for the AMD Zynq7000 SoC to write bare metal Rust code.
|
||||||
//! [provided by Xilinx](https://github.com/Xilinx/embeddedsw/tree/master/lib/bsp/standalone/src/arm/cortexa9/gcc).
|
//! This run-time crate is strongly based on the
|
||||||
//! Some major differences:
|
//! [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.
|
//! - No L2 cache initialization is performed.
|
||||||
//! - MMU table is specified as Rust code.
|
//! - MMU table is specified as Rust code.
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ data_init_done:
|
|||||||
// Jump to application
|
// Jump to application
|
||||||
// Load CPU ID 0, which will be used as a function argument to the boot_core function.
|
// Load CPU ID 0, which will be used as a function argument to the boot_core function.
|
||||||
mov r0, #0x0
|
mov r0, #0x0
|
||||||
bl boot_core
|
bl kmain
|
||||||
// In case the application returns, loop forever
|
// In case the application returns, loop forever
|
||||||
b .
|
b .
|
||||||
.size _start, . - _start
|
.size _start, . - _start
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
- Renamed all register blocks to `Registers` to subblocks to `<Subblock>Registers`
|
- Renamed all register blocks to `Registers` to subblocks to `<Subblock>Registers`.
|
||||||
- Added SDIO registers
|
- Updated IPTR registers in the GIC module to use a custom register type instead of a raw u32.
|
||||||
|
- Added SDIO registers.
|
||||||
|
|
||||||
# [v0.1.1] 2025-10-09
|
# [v0.1.1] 2025-10-09
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//! # GIC (Generic Interrupt Controller) register module.
|
//! # GIC (Generic Interrupt Controller) register module.
|
||||||
pub use crate::mpcore::{GICC_BASE_ADDR, GICD_BASE_ADDR};
|
pub use crate::mpcore::{GICC_BASE_ADDR, GICD_BASE_ADDR};
|
||||||
use arbitrary_int::{u3, u5, u10};
|
use arbitrary_int::{u2, u3, u5, u10};
|
||||||
use static_assertions::const_assert_eq;
|
use static_assertions::const_assert_eq;
|
||||||
|
|
||||||
/// Distributor Control Register
|
/// Distributor Control Register
|
||||||
@@ -40,6 +40,16 @@ impl TypeRegister {
|
|||||||
|
|
||||||
pub type Typer = TypeRegister;
|
pub type Typer = TypeRegister;
|
||||||
|
|
||||||
|
// TODO: Use bitbybit debug derive if new release was released.
|
||||||
|
/// Interrupt processor target register (IPTR).
|
||||||
|
#[bitbybit::bitfield(u32)]
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct InterruptProcessorTargetRegister {
|
||||||
|
/// Target array. Every register holds the information for 4 interrupts.
|
||||||
|
#[bits(0..=1, rw, stride = 8)]
|
||||||
|
targets: [u2; 4],
|
||||||
|
}
|
||||||
|
|
||||||
#[deprecated(note = "Use DistributorRegisters instead")]
|
#[deprecated(note = "Use DistributorRegisters instead")]
|
||||||
pub type GicDistributorTyper = DistributorRegisters;
|
pub type GicDistributorTyper = DistributorRegisters;
|
||||||
|
|
||||||
@@ -78,10 +88,11 @@ pub struct DistributorRegisters {
|
|||||||
pub ipr: [u32; 0x18],
|
pub ipr: [u32; 0x18],
|
||||||
_reserved_11: [u32; 0xE8],
|
_reserved_11: [u32; 0xE8],
|
||||||
/// Interrupt Processor Targes Registers
|
/// Interrupt Processor Targes Registers
|
||||||
pub iptr_sgi: [u32; 0x4],
|
pub iptr_sgi: [InterruptProcessorTargetRegister; 0x4],
|
||||||
// TODO: Mark those read-only as soon as that works for arrays.
|
/// These are read-only because they always target their private CPU.
|
||||||
pub iptr_ppi: [u32; 0x4],
|
#[mmio(PureRead)]
|
||||||
pub iptr_spi: [u32; 0x10],
|
pub iptr_ppi: [InterruptProcessorTargetRegister; 0x4],
|
||||||
|
pub iptr_spi: [InterruptProcessorTargetRegister; 0x10],
|
||||||
// Those are split in the ARM documentation for some reason..
|
// Those are split in the ARM documentation for some reason..
|
||||||
_reserved_12: [u32; 0xE8],
|
_reserved_12: [u32; 0xE8],
|
||||||
/// Interrupt Configuration Registers
|
/// Interrupt Configuration Registers
|
||||||
|
|||||||
Reference in New Issue
Block a user