UART and docs update
Some checks are pending
ci / Check build (push) Waiting to run
ci / Check formatting (push) Waiting to run
ci / Check Documentation Build (push) Waiting to run
ci / Clippy (push) Waiting to run
ci / Check build (pull_request) Waiting to run
ci / Check formatting (pull_request) Waiting to run
ci / Check Documentation Build (pull_request) Waiting to run
ci / Clippy (pull_request) Waiting to run

This commit is contained in:
Robin Mueller
2025-11-28 13:06:39 +01:00
parent 13dd737666
commit 893d2e870e
35 changed files with 330 additions and 124 deletions

View File

@@ -19,3 +19,23 @@ exclude = [
# Exclude, can not be built with debug optimization level, too large.
"zedboard-fsbl",
]
# cargo build/run
[profile.dev]
# default is opt-level = '0', but that makes very
# verbose machine code
opt-level = 's'
# trade compile speed for slightly better optimisations
codegen-units = 1
# cargo build/run --release
[profile.release]
# Optimize for maximum speed.
opt-level = 3
# trade compile speed for slightly better optimisations
codegen-units = 1
# Use Link Time Optimisations to further inline things across
# crates
lto = 'fat'
# Leave the debug symbols in (default is no debug info)
debug = 2

View File

@@ -31,24 +31,3 @@ embassy-executor = { version = "0.9", features = [
]}
# TODO: Remove generic-queue-16 feature as soon as upstream executor is used again.
embassy-time = { version = "0.5", features = ["tick-hz-1_000_000", "generic-queue-16"] }
# cargo build/run
[profile.dev]
# default is opt-level = '0', but that makes very
# verbose machine code
opt-level = 's'
# trade compile speed for slightly better optimisations
codegen-units = 1
# cargo build/run --release
[profile.release]
# default is opt-level = '3', but that makes quite
# verbose machine code
opt-level = 's'
# trade compile speed for slightly better optimisations
codegen-units = 1
# Use Link Time Optimisations to further inline things across
# crates
lto = 'fat'
# Leave the debug symbols in (default is no debug info)
debug = 2

View File

@@ -67,7 +67,7 @@ async fn main(_spawner: Spawner) -> ! {
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
.unwrap()
.0;
let mut uart = Uart::new_with_mio(
let mut uart = Uart::new_with_mio_for_uart_1(
dp.uart_1,
Config::new_with_clk_config(uart_clk_config),
(mio_pins.mio48, mio_pins.mio49),

View File

@@ -45,7 +45,7 @@ async fn main(_spawner: Spawner) -> ! {
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
.unwrap()
.0;
let mut uart = uart::Uart::new_with_mio(
let mut uart = uart::Uart::new_with_mio_for_uart_1(
periphs.uart_1,
uart::Config::new_with_clk_config(uart_clk_config),
(mio_pins.mio48, mio_pins.mio49),

View File

@@ -61,7 +61,7 @@ async fn main(spawner: Spawner) -> ! {
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
.unwrap()
.0;
let mut uart = Uart::new_with_mio(
let mut uart = Uart::new_with_mio_for_uart_1(
dp.uart_1,
Config::new_with_clk_config(uart_clk_config),
(mio_pins.mio48, mio_pins.mio49),

View File

@@ -74,7 +74,7 @@ async fn main(_spawner: Spawner) -> ! {
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
.unwrap()
.0;
let mut uart = Uart::new_with_mio(
let mut uart = Uart::new_with_mio_for_uart_1(
dp.uart_1,
Config::new_with_clk_config(uart_clk_config),
(mio_pins.mio48, mio_pins.mio49),

View File

@@ -17,8 +17,3 @@ embedded-io = "0.7"
embedded-hal = "1"
fugit = "0.3"
log = "0.4"
[profile.release]
codegen-units = 1
debug = true
lto = true

View File

@@ -62,7 +62,7 @@ pub fn main() -> ! {
// This structure holds all MIO pins.
let mio_pins = mio::Pins::new(dp.gpio);
let mut uart = Uart::new_with_mio(
let mut uart = Uart::new_with_mio_for_uart_1(
dp.uart_1,
Config::new_with_clk_config(uart_clk_config),
(mio_pins.mio48, mio_pins.mio49),

View File

@@ -62,7 +62,7 @@ pub fn main() -> ! {
gtc.enable();
let mio_pins = mio::Pins::new(dp.gpio);
let mut uart = Uart::new_with_mio(
let mut uart = Uart::new_with_mio_for_uart_1(
dp.uart_1,
Config::new_with_clk_config(uart_clk_config),
(mio_pins.mio48, mio_pins.mio49),

View File

@@ -42,10 +42,5 @@ embassy-net = { version = "0.7", features = ["dhcpv4", "packet-trace", "medium-e
embassy-sync = { version = "0.7" }
# TODO: Bump as soon as new compatible smoltcp/embassy-net version is released.
heapless = "0.8"
axi-uartlite = { git = "https://egit.irs.uni-stuttgart.de/rust/axi-uartlite.git" }
axi-uart16550 = { git = "https://egit.irs.uni-stuttgart.de/rust/axi-uart16550.git" }
[profile.release]
codegen-units = 1
debug = true
lto = true
axi-uartlite = { version = "0.1" }
axi-uart16550 = { version = "0.1" }

View File

@@ -237,7 +237,7 @@ async fn main(spawner: Spawner) -> ! {
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
.unwrap()
.0;
let mut uart = Uart::new_with_mio(
let mut uart = Uart::new_with_mio_for_uart_1(
dp.uart_1,
Config::new_with_clk_config(uart_clk_config),
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),

View File

@@ -76,7 +76,7 @@ async fn main(_spawner: Spawner) -> ! {
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
.unwrap()
.0;
let mut uart = uart::Uart::new_with_mio(
let mut uart = uart::Uart::new_with_mio_for_uart_1(
dp.uart_1,
uart::Config::new_with_clk_config(uart_clk_config),
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),

View File

@@ -86,7 +86,7 @@ async fn main(spawner: Spawner) -> ! {
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
.unwrap()
.0;
let mut uart = uart::Uart::new_with_mio(
let mut uart = uart::Uart::new_with_mio_for_uart_1(
dp.uart_1,
uart::Config::new_with_clk_config(uart_clk_config),
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),

View File

@@ -54,7 +54,7 @@ async fn main(_spawner: Spawner) -> ! {
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
.unwrap()
.0;
let mut uart = uart::Uart::new_with_mio(
let mut uart = uart::Uart::new_with_mio_for_uart_1(
periphs.uart_1,
uart::Config::new_with_clk_config(uart_clk_config),
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),

View File

@@ -126,7 +126,7 @@ async fn main(_spawner: Spawner) -> ! {
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
.unwrap()
.0;
let mut log_uart = Uart::new_with_mio(
let mut log_uart = Uart::new_with_mio_for_uart_1(
dp.uart_1,
Config::new_with_clk_config(uart_clk_config),
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
@@ -151,7 +151,7 @@ async fn main(_spawner: Spawner) -> ! {
// TODO: Can we determine/read the clock frequency to the FPGAs as well?
let (clk_config, error) =
axi_uart16550::ClkConfig::new_autocalc_with_error(100.MHz(), 115200).unwrap();
axi_uart16550::ClockConfig::new_autocalc_with_error(100.MHz(), 115200).unwrap();
assert!(error < 0.02);
let mut uart_16550 = unsafe {
AxiUart16550::new(

View File

@@ -197,7 +197,7 @@ async fn main(spawner: Spawner) -> ! {
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
.unwrap()
.0;
let mut log_uart = Uart::new_with_mio(
let mut log_uart = Uart::new_with_mio_for_uart_1(
dp.uart_1,
Config::new_with_clk_config(uart_clk_config),
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
@@ -245,7 +245,7 @@ async fn main(spawner: Spawner) -> ! {
uartlite.enable_interrupt();
let (clk_config, error) =
axi_uart16550::ClkConfig::new_autocalc_with_error(clocks.pl_clocks()[0], 115200).unwrap();
axi_uart16550::ClockConfig::new_autocalc_with_error(clocks.pl_clocks()[0], 115200).unwrap();
assert!(error < 0.02);
let _uart_16550 = unsafe {
AxiUart16550::new(
@@ -492,19 +492,19 @@ fn on_interrupt_axi_16550() {
let iir = rx.read_iir();
if let Ok(int_id) = iir.int_id() {
match int_id {
axi_uart16550::registers::IntId2::ReceiverLineStatus => {
axi_uart16550::registers::InterruptId2::ReceiverLineStatus => {
let errors = rx.on_interrupt_receiver_line_status(iir);
warn!("Receiver line status error: {errors:?}");
}
axi_uart16550::registers::IntId2::RxDataAvailable
| axi_uart16550::registers::IntId2::CharTimeout => {
axi_uart16550::registers::InterruptId2::RxDataAvailable
| axi_uart16550::registers::InterruptId2::CharTimeout => {
read_bytes = rx.on_interrupt_data_available_or_char_timeout(int_id, &mut buf);
}
axi_uart16550::registers::IntId2::ThrEmpty => {
axi_uart16550::registers::InterruptId2::ThrEmpty => {
let mut tx = unsafe { axi_uart16550::Tx::steal(AXI_UAR16550_BASE_ADDR as usize) };
axi_uart16550::tx_async::on_interrupt_tx(&mut tx, 0);
}
axi_uart16550::registers::IntId2::ModemStatus => (),
axi_uart16550::registers::InterruptId2::ModemStatus => (),
}
}
// Send received RX data to main task.

View File

@@ -46,7 +46,7 @@ async fn main(_spawner: Spawner) -> ! {
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
.unwrap()
.0;
let mut uart = uart::Uart::new_with_mio(
let mut uart = uart::Uart::new_with_mio_for_uart_1(
periphs.uart_1,
uart::Config::new_with_clk_config(uart_clk_config),
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),

View File

@@ -20,3 +20,23 @@ embedded-hal = "1"
fugit = "0.3"
log = "0.4"
arbitrary-int = "2"
# cargo build/run
[profile.dev]
# default is opt-level = '0', but that makes very
# verbose machine code
opt-level = 's'
# trade compile speed for slightly better optimisations
codegen-units = 1
# cargo build/run --release
[profile.release]
# Optimize for size.
opt-level = 's'
# trade compile speed for slightly better optimisations
codegen-units = 1
# Use Link Time Optimisations to further inline things across
# crates
lto = 'fat'
# Leave the debug symbols in (default is no debug info)
debug = 2

View File

@@ -94,7 +94,7 @@ pub fn main() -> ! {
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
.unwrap()
.0;
let mut logger_uart = Uart::new_with_mio(
let mut logger_uart = Uart::new_with_mio_for_uart_1(
periphs.uart_1,
Config::new_with_clk_config(uart_clk_config),
(mio_pins.mio48, mio_pins.mio49),

View File

@@ -66,7 +66,7 @@ pub fn main() -> ! {
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
.unwrap()
.0;
let mut uart = uart::Uart::new_with_mio(
let mut uart = uart::Uart::new_with_mio_for_uart_1(
periphs.uart_1,
uart::Config::new_with_clk_config(uart_clk_config),
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),

View File

@@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased]
## Changed
- Increased UART type safety by providing dedicated MIO constructors for UART 0 and UART 1
respectively.
# [v0.1.1] 2025-10-10
Documentation fixes.

View File

@@ -10,9 +10,8 @@ use arbitrary_int::prelude::*;
use aarch32_cpu::interrupt;
use zynq7000::gic::{
DistributorControlRegister, GicCpuInterfaceRegisters, GicDistributorRegisters,
InterfaceControl, InterruptSignalRegister, MmioGicCpuInterfaceRegisters,
MmioGicDistributorRegisters, PriorityRegister,
CpuInterfaceRegisters, DistributorControlRegister, DistributorRegisters, InterfaceControl,
InterruptSignalRegister, MmioCpuInterfaceRegisters, MmioDistributorRegisters, PriorityRegister,
};
const SPURIOUS_INTERRUPT_ID: u32 = 1023;
@@ -193,7 +192,7 @@ pub struct InvalidSgiInterruptId(pub usize);
/// The flow of using this controller is as follows:
///
/// 1. Create the controller using [Self::new_with_init]. You can use the [zynq7000::Peripherals]
/// structure or the [zynq7000::gic::GicCpuInterface::new_mmio] and [zynq7000::gic::GicDistributor::new_mmio]
/// structure or the [zynq7000::gic::CpuInterfaceRegisters::new_mmio] and [zynq7000::gic::DistributorRegisters::new_mmio]
/// functions to retrieve the MMIO instances. The constructor configures all PL interrupts
/// sensivities to high-level sensitivity and configures all sensitivities which are expected
/// to have a certain value. It also sets the priority mask to 0xff by calling
@@ -225,8 +224,8 @@ pub struct InvalidSgiInterruptId(pub usize);
/// For the handling of the interrupts, you can use the [GicInterruptHelper] which assumes a
/// properly configured GIC.
pub struct GicConfigurator {
pub gicc: MmioGicCpuInterfaceRegisters<'static>,
pub gicd: MmioGicDistributorRegisters<'static>,
pub gicc: MmioCpuInterfaceRegisters<'static>,
pub gicd: MmioDistributorRegisters<'static>,
}
impl GicConfigurator {
@@ -234,8 +233,8 @@ impl GicConfigurator {
/// strongly recommended initialization routines for the GIC.
#[inline]
pub fn new_with_init(
gicc: MmioGicCpuInterfaceRegisters<'static>,
gicd: MmioGicDistributorRegisters<'static>,
gicc: MmioCpuInterfaceRegisters<'static>,
gicd: MmioDistributorRegisters<'static>,
) -> Self {
let mut gic = GicConfigurator { gicc, gicd };
gic.initialize();
@@ -252,8 +251,8 @@ impl GicConfigurator {
#[inline]
pub unsafe fn steal() -> Self {
GicConfigurator {
gicc: unsafe { GicCpuInterfaceRegisters::new_mmio_fixed() },
gicd: unsafe { GicDistributorRegisters::new_mmio_fixed() },
gicc: unsafe { CpuInterfaceRegisters::new_mmio_fixed() },
gicd: unsafe { DistributorRegisters::new_mmio_fixed() },
}
}
@@ -489,12 +488,12 @@ impl GicConfigurator {
/// Helper structure which should only be used inside the interrupt handler once the GIC has
/// been configured with the [GicConfigurator].
pub struct GicInterruptHelper(MmioGicCpuInterfaceRegisters<'static>);
pub struct GicInterruptHelper(MmioCpuInterfaceRegisters<'static>);
impl GicInterruptHelper {
/// Create the interrupt helper with the fixed GICC MMIO instance.
pub const fn new() -> Self {
GicInterruptHelper(unsafe { GicCpuInterfaceRegisters::new_mmio_fixed() })
GicInterruptHelper(unsafe { CpuInterfaceRegisters::new_mmio_fixed() })
}
/// Acknowledges an interrupt by reading the IAR register and returning the interrupt context

View File

@@ -4,6 +4,7 @@
//!
//! - [GTC ticks example](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/simple/src/bin/gtc-ticks.rs)
//! - [Embassy Timer Driver](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/zynq7000-embassy/src/lib.rs)
#![deny(missing_docs)]
use zynq7000::gtc::MmioRegisters;
use crate::{clocks::ArmClocks, time::Hertz};
@@ -20,6 +21,7 @@ pub struct GlobalTimerCounter {
unsafe impl Send for GlobalTimerCounter {}
/// Convert a frequency to GTC ticks given a clock frequency.
pub const fn frequency_to_ticks(clock: Hertz, frequency: Hertz) -> u32 {
clock.raw().div_ceil(frequency.raw())
}
@@ -38,7 +40,7 @@ impl GlobalTimerCounter {
/// # Safety
///
/// This function allows creating an arbitrary amount of memory-mapped peripheral drivers.
/// See the [zynq7000::gtc::GlobalTimerCounter::new_mmio] docs for more safety information.
/// See the [zynq7000::gtc::Registers::new_mmio] docs for more safety information.
#[inline]
pub const unsafe fn steal_fixed(cpu_3x2x_clk: Option<Hertz>) -> Self {
Self {
@@ -47,6 +49,7 @@ impl GlobalTimerCounter {
}
}
/// Set the CPU 3x2x clock frequency.
#[inline]
pub fn set_cpu_3x2x_clock(&mut self, clock: Hertz) {
self.cpu_3x2x_clock = Some(clock);
@@ -85,6 +88,7 @@ impl GlobalTimerCounter {
});
}
/// Convert a frequency to GTC ticks.
pub fn frequency_to_ticks(&self, frequency: Hertz) -> u32 {
if self.cpu_3x2x_clock.is_none() {
return 0;
@@ -99,12 +103,14 @@ impl GlobalTimerCounter {
self.regs.write_auto_increment(value);
}
/// Set auto-increment value for a given frequency.
#[inline]
pub fn set_auto_increment_value_for_frequency(&mut self, frequency: Hertz) {
self.regs
.write_auto_increment(self.frequency_to_ticks(frequency));
}
/// Enable the GTC.
#[inline]
pub fn enable(&mut self) {
self.regs.modify_ctrl(|mut ctrl| {
@@ -113,6 +119,7 @@ impl GlobalTimerCounter {
});
}
/// Enable auto-increment.
#[inline]
pub fn enable_auto_increment(&mut self) {
self.regs.modify_ctrl(|mut ctrl| {
@@ -121,6 +128,7 @@ impl GlobalTimerCounter {
});
}
/// Set a pre-scaler.
#[inline]
pub fn set_prescaler(&mut self, prescaler: u8) {
self.regs.modify_ctrl(|mut ctrl| {
@@ -129,6 +137,7 @@ impl GlobalTimerCounter {
});
}
/// Disable the GTC.
#[inline]
pub fn disable(&mut self) {
self.regs.modify_ctrl(|mut ctrl| {

View File

@@ -1,4 +1,5 @@
//! # L2 cache module
#![deny(missing_docs)]
use core::sync::atomic::compiler_fence;
use arbitrary_int::{u2, u3};
@@ -44,7 +45,7 @@ pub const DEFAULT_DATA_RAM_LATENCY: LatencyConfig = LatencyConfig::builder()
.with_setup_latency(u3::new(0b001))
.build();
// SLCR L2C ram configuration.
/// SLCR L2C RAM configuration magic value.
pub const SLCR_L2C_CONFIG_MAGIC_VALUE: u32 = 0x00020202;
/// Similar to [init], but uses Xilinx/AMD defaults for the latency configurations.

View File

@@ -3,6 +3,7 @@
//! ## Examples
//!
//! - Private timer as delay provider in [blinky](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/simple/src/bin/blinky.rs)
#![deny(missing_docs)]
use core::{marker::PhantomData, sync::atomic::AtomicBool};
use zynq7000::priv_tim::InterruptStatus;
@@ -62,11 +63,13 @@ impl CpuPrivateTimer {
self.regs.write_reload(value);
}
/// Write the current counter value.
#[inline]
pub fn write_counter(&mut self, value: u32) {
self.regs.write_counter(value);
}
/// Read the current counter value.
#[inline]
pub fn counter(&self) -> u32 {
self.regs.read_counter()

View File

@@ -1,9 +1,13 @@
//! # System Level Control Register (SLCR) module
#![deny(missing_docs)]
use zynq7000::slcr::MmioRegisters;
/// Lock key for the SLCR registers.
pub const LOCK_KEY: u32 = 0x767B;
/// Unlock key for the SLCR registers.
pub const UNLOCK_KEY: u32 = 0xDF0D;
/// SLCR helper structure.
pub struct Slcr(zynq7000::slcr::MmioRegisters<'static>);
impl Slcr {
@@ -12,7 +16,7 @@ impl Slcr {
/// # Safety
///
/// This method unsafely steals the SLCR MMIO block and then calls a user provided function
/// with the [SLCR MMIO][MmioSlcr] block as an input argument. It is the user's responsibility
/// with the [SLCR MMIO][MmioRegisters] block as an input argument. It is the user's responsibility
/// that the SLCR is not used concurrently in a way which leads to data races.
pub unsafe fn with<F: FnOnce(&mut MmioRegisters<'static>)>(f: F) {
let mut slcr = unsafe { zynq7000::slcr::Registers::new_mmio_fixed() };
@@ -47,7 +51,7 @@ impl Slcr {
/// Modify the SLCR register.
///
/// This method unlocks the SLCR registers and then calls a user provided function
/// with the [SLCR MMIO][MmioSlcr] block as an input argument. This allows the user
/// with the [SLCR MMIO][MmioRegisters] block as an input argument. This allows the user
/// to safely modify the SLCR registers. The SLCR will be locked afte the operation.
pub fn modify<F: FnMut(&mut MmioRegisters)>(&mut self, mut f: F) {
self.0.write_unlock(UNLOCK_KEY);

View File

@@ -1,17 +1,21 @@
//! # Time units
#![deny(missing_docs)]
// Frequency based
/// Hertz
pub type Hertz = fugit::HertzU32;
/// Type alias for Hertz.
pub type Hz = Hertz;
/// KiloHertz
pub type KiloHertz = fugit::KilohertzU32;
/// Type alias for Kilo Hertz.
pub type KHz = KiloHertz;
/// MegaHertz
pub type MegaHertz = fugit::MegahertzU32;
/// Type alias for Mega Hertz.
pub type MHz = MegaHertz;
// Period based

View File

@@ -5,7 +5,7 @@
//! ## Examples
//!
//! - [PWM](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/embassy/src/bin/pwm.rs)
#![deny(missing_docs)]
use core::convert::Infallible;
use arbitrary_int::{prelude::*, u3, u4};
@@ -25,19 +25,28 @@ use crate::{
/// Each TTC consists of three independent timers/counters.
#[derive(Debug, Copy, Clone)]
pub enum TtcId {
/// TTC 0.
Ttc0 = 0,
/// TTC 1.
Ttc1 = 1,
}
/// Each TTC has 3 channels.
#[derive(Debug, Copy, Clone)]
pub enum ChannelId {
/// Channel 0.
Ch0 = 0,
/// Channel 1.
Ch1 = 1,
/// Channel 2.
Ch2 = 2,
}
/// Common trait for TTC register blocks.
pub trait PsTtc {
/// Register block.
fn reg_block(&self) -> MmioRegisters<'static>;
/// ID.
fn id(&self) -> Option<TtcId>;
}
@@ -59,13 +68,18 @@ impl PsTtc for MmioRegisters<'static> {
}
}
/// TTC pin configuration
pub const TTC_MUX_CONF: MuxConfig = MuxConfig::new_with_l3(u3::new(0b110));
/// Input clock pin trait.
pub trait ClockInPin: MioPin {
/// TTC ID.
const ID: TtcId;
}
/// Output wave pin trait.
pub trait WaveOutPin: MioPin {
/// TTC ID.
const ID: TtcId;
}
@@ -121,9 +135,13 @@ impl WaveOutPin for Pin<Mio40> {
const ID: TtcId = TtcId::Ttc1;
}
/// Triple-timer counter (TTC) peripheral.
pub struct Ttc {
/// TTC channel 0.
pub ch0: TtcChannel,
/// TTC channel 1.
pub ch1: TtcChannel,
/// TTC channel 2.
pub ch2: TtcChannel,
}
@@ -151,16 +169,20 @@ impl Ttc {
}
}
/// Single TTC channel.
pub struct TtcChannel {
regs: MmioRegisters<'static>,
id: ChannelId,
}
impl TtcChannel {
/// Raw access to the TTC MMIO registers.
#[inline]
pub fn regs_mut(&mut self) -> &mut MmioRegisters<'static> {
&mut self.regs
}
/// Read the current counter value.
#[inline]
pub fn read_counter(&self) -> u16 {
self.regs
@@ -169,27 +191,36 @@ impl TtcChannel {
.count()
}
/// Channel ID.
#[inline]
pub fn id(&self) -> ChannelId {
self.id
}
}
/// Invalid TTC pin configuration error.
#[derive(Debug, thiserror::Error)]
#[error("invalid TTC pin configuration")]
pub struct InvalidTtcPinConfigError(pub MuxConfig);
/// Frequency is zero error.
#[derive(Debug, thiserror::Error)]
#[error("frequency is zero")]
pub struct FrequencyIsZeroError;
/// TTC construction error.
#[derive(Debug, thiserror::Error)]
pub enum TtcConstructionError {
/// Invalid TTC pin configuration.
#[error("invalid TTC pin configuration")]
InvalidTtcPinConfig(#[from] InvalidTtcPinConfigError),
/// Frequency is zero.
#[error("frequency is zero")]
FrequencyIsZero(#[from] FrequencyIsZeroError),
}
/// Calculate prescaler register value and interval ticks for a given reference clock and
/// frequency.
pub fn calc_prescaler_reg_and_interval_ticks(mut ref_clk: Hertz, freq: Hertz) -> (Option<u4>, u16) {
// TODO: Can this be optimized?
let mut prescaler: Option<u32> = None;
@@ -210,6 +241,7 @@ pub fn calc_prescaler_reg_and_interval_ticks(mut ref_clk: Hertz, freq: Hertz) ->
(prescaler.map(|v| u4::new(v as u8)), tick_val as u16)
}
/// PWM driver using a TTC channel.
pub struct Pwm {
channel: TtcChannel,
ref_clk: Hertz,
@@ -266,11 +298,13 @@ impl Pwm {
Ok(())
}
/// Mutable access to the underlying TTC channel.
#[inline]
pub fn ttc_channel_mut(&mut self) -> &mut TtcChannel {
&mut self.channel
}
/// Maximum duty cycle value.
#[inline]
pub fn max_duty_cycle(&self) -> u16 {
self.channel
@@ -280,6 +314,7 @@ impl Pwm {
.value()
}
/// Set duty cycle value.
#[inline]
pub fn set_duty_cycle(&mut self, duty: u16) {
let id = self.channel.id() as usize;

View File

@@ -7,6 +7,7 @@
//! - [Logger through UART](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/simple/src/bin/logger.rs)
//! - [Zedboard Blocking UART](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/zedboard/src/bin/uart-blocking.rs)
//! - [Zedboard Non-Blocking UART](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/zedboard/src/bin/uart-non-blocking.rs)
#![deny(missing_docs)]
use core::convert::Infallible;
use arbitrary_int::u3;
@@ -49,18 +50,27 @@ pub use tx_async::*;
pub mod rx;
pub use rx::*;
/// FIFO depth of the UART peripheral.
pub const FIFO_DEPTH: usize = 64;
/// Default RX trigger level.
pub const DEFAULT_RX_TRIGGER_LEVEL: u8 = 32;
/// UART pin configuration.
pub const UART_MUX_CONF: MuxConfig = MuxConfig::new_with_l3(u3::new(0b111));
/// UART ID.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum UartId {
/// UART 0.
Uart0 = 0,
/// UART 1.
Uart1 = 1,
}
/// Common trait for PS UART peripherals.
pub trait PsUart {
/// UART register block.
fn reg_block(&self) -> MmioRegisters<'static>;
/// UART ID.
fn uart_id(&self) -> Option<UartId>;
}
@@ -95,38 +105,57 @@ impl UartId {
}
}
pub trait RxPin: MioPin {
const UART_IDX: UartId;
/// Receiver (RX) pin for UART 0.
pub trait RxPin0: MioPin {
/// UART index.
const UART_IDX: UartId = UartId::Uart0;
}
pub trait TxPin: MioPin {
const UART_IDX: UartId;
/// Transmitter (TX) pin for UART 0.
pub trait TxPin0: MioPin {
/// UART index.
const UART_IDX: UartId = UartId::Uart0;
}
pub trait UartPins {}
/// Receiver (RX) pin for UART 1.
pub trait RxPin1: MioPin {
/// UART index.
const UART_IDX: UartId = UartId::Uart0;
}
/// Transmitter (TX) pin for UART 1.
pub trait TxPin1: MioPin {
/// UART index.
const UART_IDX: UartId = UartId::Uart0;
}
/// UART pin pair trait for UART 0.
pub trait UartPins0 {}
/// UART pin pair trait for UART 1.
pub trait UartPins1 {}
/// Divisor zero error.
#[derive(Debug, thiserror::Error)]
#[error("divisor is zero")]
pub struct DivisorZero;
macro_rules! pin_pairs {
($UartPeriph:path, ($( [$(#[$meta:meta], )? $TxMio:ident, $RxMio:ident] ),+ $(,)? )) => {
($index:literal, $UartPeriph:path, ($( [$(#[$meta:meta], )? $TxMio:ident, $RxMio:ident] ),+ $(,)? )) => {
$(
paste::paste! {
$( #[$meta] )?
impl TxPin for Pin<$TxMio> {
const UART_IDX: UartId = $UartPeriph;
}
impl [<TxPin $index>] for Pin<$TxMio> {}
$( #[$meta] )?
impl RxPin for Pin<$RxMio> {
const UART_IDX: UartId = $UartPeriph;
}
impl [<RxPin $index>] for Pin<$RxMio> {}
impl UartPins for (Pin<$TxMio>, Pin<$RxMio>) {}
impl [<UartPins $index>] for (Pin<$TxMio>, Pin<$RxMio>) {}
}
)+
};
}
pin_pairs!(
0,
UartId::Uart0,
(
[Mio11, Mio10],
@@ -144,7 +173,7 @@ pin_pairs!(
);
pin_pairs!(
UartId::Uart1,
1, UartId::Uart1,
(
[Mio8, Mio9],
[Mio12, Mio13],
@@ -166,38 +195,53 @@ pub const MAX_BAUD_RATE: u32 = 6240000;
/// Based on values provided by the vendor library.
pub const MIN_BAUD_RATE: u32 = 110;
/// Maximum acceptable baud rate error rate (0.5 %).
pub const MAX_BAUDERROR_RATE: f32 = 0.005;
/// Parity configuration.
#[derive(Debug, Default, Clone, Copy)]
pub enum Parity {
/// Even parity.
Even,
/// Odd parity.
Odd,
/// No parity (default).
#[default]
None,
}
/// Stopbit configuration.
#[derive(Debug, Default, Clone, Copy)]
pub enum Stopbits {
/// One stop bit (default).
#[default]
One,
/// 1.5 stopbits.
OnePointFive,
/// 2 stopbits.
Two,
}
/// Character length configuration.
#[derive(Debug, Default, Clone, Copy)]
pub enum CharLen {
/// 6 bits.
SixBits,
/// 7 bits.
SevenBits,
/// 8 bits (default).
#[default]
EightBits,
}
/// Clock configuration for baud rate generation.
#[derive(Debug, Clone, Copy)]
pub struct ClockConfig {
cd: u16,
bdiv: u8,
}
/// Calculate all viable clock configurations.
#[cfg(feature = "alloc")]
pub fn calculate_viable_configs(
mut uart_clk: Hertz,
@@ -265,6 +309,7 @@ pub fn calculate_raw_baud_cfg_smallest_error(
}
impl ClockConfig {
/// Constructor.
#[inline]
pub const fn new(cd: u16, bdiv: u8) -> Result<Self, DivisorZero> {
if cd == 0 {
@@ -285,6 +330,7 @@ impl ClockConfig {
Self::new_autocalc_generic(io_clks, ClockSelect::UartRefClk, target_baud)
}
/// New generic autocalculating constructor.
pub fn new_autocalc_generic(
io_clks: &IoClocks,
clk_sel: ClockSelect,
@@ -293,6 +339,7 @@ impl ClockConfig {
Self::new_autocalc_with_raw_clk(io_clks.uart_clk(), clk_sel, target_baud)
}
/// New generic autocalculating constructor using a raw UART Input clock.
pub fn new_autocalc_with_raw_clk(
uart_clk: Hertz,
clk_sel: ClockSelect,
@@ -301,21 +348,25 @@ impl ClockConfig {
calculate_raw_baud_cfg_smallest_error(uart_clk, clk_sel, target_baud)
}
/// CD value.
#[inline]
pub const fn cd(&self) -> u16 {
self.cd
}
/// Baud divisor value.
#[inline]
pub const fn bdiv(&self) -> u8 {
self.bdiv
}
/// Rounded baudrate.
#[inline]
pub fn rounded_baud(&self, sel_clk: Hertz) -> u32 {
round(self.actual_baud(sel_clk)) as u32
}
/// Actual baudrate.
#[inline]
pub fn actual_baud(&self, sel_clk: Hertz) -> f64 {
sel_clk.raw() as f64 / (self.cd as f64 * (self.bdiv + 1) as f64)
@@ -329,6 +380,7 @@ impl Default for ClockConfig {
}
}
/// UART configuration.
#[derive(Debug)]
pub struct Config {
clk_config: ClockConfig,
@@ -340,6 +392,7 @@ pub struct Config {
}
impl Config {
/// Create a new configuration from a given clock configuartion.
pub fn new_with_clk_config(clk_config: ClockConfig) -> Self {
Self::new(
clk_config,
@@ -351,6 +404,7 @@ impl Config {
)
}
/// Constructor.
#[inline]
pub const fn new(
clk_config: ClockConfig,
@@ -370,54 +424,63 @@ impl Config {
}
}
/// Raw clock configuration.
#[inline]
pub const fn raw_clk_config(&self) -> ClockConfig {
self.clk_config
}
/// Character mode.
#[inline]
pub const fn chmode(&self) -> ChMode {
self.chmode
}
/// Parity configuration.
#[inline]
pub const fn parity(&self) -> Parity {
self.parity
}
/// Stopbits configuration.
#[inline]
pub const fn stopbits(&self) -> Stopbits {
self.stopbits
}
/// Character length configuration.
#[inline]
pub const fn chrl(&self) -> CharLen {
pub const fn charlen(&self) -> CharLen {
self.chrl
}
/// Clock select configuration.
#[inline]
pub const fn clksel(&self) -> ClockSelect {
self.clk_sel
}
}
// TODO: Impl Debug
/// UART peripheral driver.
#[derive(Debug)]
pub struct Uart {
rx: Rx,
tx: Tx,
cfg: Config,
}
/// Invalid PS UART error.
#[derive(Debug, thiserror::Error)]
#[error("invalid UART ID")]
pub struct InvalidPsUart;
/// UART construction error.
#[derive(Debug, thiserror::Error)]
pub enum UartConstructionError {
/// Invalid PS UART error.
#[error("invalid UART ID")]
InvalidPsUart(#[from] InvalidPsUart),
#[error("missmatch between pins index and passed index")]
IdxMissmatch,
/// Invalid pin configuration.
#[error("invalid pin mux conf for UART")]
InvalidMuxConf(MuxConfig),
}
@@ -439,21 +502,46 @@ impl Uart {
))
}
/// This is the constructor to use the PS UART with MIO pins.
pub fn new_with_mio<TxPinI: TxPin, RxPinI: RxPin>(
/// This is the constructor to use the PS UART with MIO pins for UART 0.
pub fn new_with_mio_for_uart_0<TxPinI: TxPin0, RxPinI: RxPin0>(
uart: impl PsUart,
cfg: Config,
pins: (TxPinI, RxPinI),
) -> Result<Self, UartConstructionError>
where
(TxPinI, RxPinI): UartPins,
(TxPinI, RxPinI): UartPins0,
{
let id = uart.uart_id();
if id.is_none() {
return Err(InvalidPsUart.into());
}
if id.unwrap() != TxPinI::UART_IDX || id.unwrap() != RxPinI::UART_IDX {
return Err(UartConstructionError::IdxMissmatch);
if id.unwrap() != UartId::Uart0 {
return Err(InvalidPsUart.into());
}
IoPeriphPin::new(pins.0, UART_MUX_CONF, None);
IoPeriphPin::new(pins.1, UART_MUX_CONF, None);
Ok(Self::new_generic_unchecked(
uart.reg_block(),
id.unwrap(),
cfg,
))
}
/// This is the constructor to use the PS UART with MIO pins for UART 1.
pub fn new_with_mio_for_uart_1<TxPinI: TxPin1, RxPinI: RxPin1>(
uart: impl PsUart,
cfg: Config,
pins: (TxPinI, RxPinI),
) -> Result<Self, UartConstructionError>
where
(TxPinI, RxPinI): UartPins1,
{
let id = uart.uart_id();
if id.is_none() {
return Err(InvalidPsUart.into());
}
if id.unwrap() != UartId::Uart1 {
return Err(InvalidPsUart.into());
}
IoPeriphPin::new(pins.0, UART_MUX_CONF, None);
IoPeriphPin::new(pins.1, UART_MUX_CONF, None);
@@ -549,6 +637,7 @@ impl Uart {
}
}
/// Set character mode.
#[inline]
pub fn set_mode(&mut self, mode: ChMode) {
self.regs().modify_mr(|mut mr| {
@@ -557,16 +646,19 @@ impl Uart {
});
}
/// Raw access to the UART registers.
#[inline]
pub const fn regs(&mut self) -> &mut MmioRegisters<'static> {
&mut self.rx.regs
}
/// Configuration.
#[inline]
pub const fn cfg(&self) -> &Config {
&self.cfg
}
/// Split into TX and RX halves.
#[inline]
pub const fn split(self) -> (Tx, Rx) {
(self.tx, self.rx)

View File

@@ -1,3 +1,4 @@
//! # Receiver (RX) support module
use core::convert::Infallible;
use arbitrary_int::prelude::*;
@@ -5,12 +6,23 @@ use zynq7000::uart::{InterruptControl, InterruptStatus, MmioRegisters};
use super::FIFO_DEPTH;
/// Receiver (RX) driver.
pub struct Rx {
pub(crate) regs: MmioRegisters<'static>,
}
// TODO: Remove once this is impelemnted for MmioUart
impl core::fmt::Debug for Rx {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Rx").finish_non_exhaustive()
}
}
/// # Safety
///
/// This is not a CPU specific register block.
unsafe impl Send for Rx {}
/// RX errors structure.
#[derive(Debug, Default, Clone, Copy)]
pub struct RxErrors {
framing: bool,
@@ -19,20 +31,26 @@ pub struct RxErrors {
}
impl RxErrors {
/// Framing error occurred.
#[inline]
pub const fn framing(&self) -> bool {
self.framing
}
/// Overrun error occurred.
#[inline]
pub const fn overrun(&self) -> bool {
self.overrun
}
/// Parity error occurred.
#[inline]
pub const fn parity(&self) -> bool {
self.parity
}
}
/// RX interrupt result structure.
#[derive(Debug, Default)]
pub struct RxInterruptResult {
read_bytes: usize,
@@ -40,16 +58,19 @@ pub struct RxInterruptResult {
}
impl RxInterruptResult {
/// Bytes read during the interrupt.
pub fn read_bytes(&self) -> usize {
self.read_bytes
}
/// Errors occurred during reception.
pub fn errors(&self) -> Option<RxErrors> {
self.errors
}
}
impl Rx {
/// Read one byte from the FIFO in a non-blocking manner.
#[inline]
pub fn read_fifo(&mut self) -> nb::Result<u8, Infallible> {
if self.regs.read_sr().rx_empty() {
@@ -58,6 +79,7 @@ impl Rx {
Ok(self.regs.read_fifo().fifo())
}
/// Read one byte from the FIFO without checking if data is available.
#[inline(always)]
pub fn read_fifo_unchecked(&mut self) -> u8 {
self.regs.read_fifo().fifo()
@@ -74,6 +96,7 @@ impl Rx {
self.regs.write_rx_tout(rto as u32);
}
/// Perform a soft-reset of the RX side of the UART.
#[inline]
pub fn soft_reset(&mut self) {
self.regs.modify_cr(|mut cr| {
@@ -121,6 +144,9 @@ impl Rx {
);
}
/// This function should be called from the UART interrupt handler.
///
/// It reads all available data from the RX FIFO into the provided buffer.
pub fn on_interrupt(
&mut self,
buf: &mut [u8; FIFO_DEPTH],
@@ -180,7 +206,7 @@ impl Rx {
result
}
// This clears all RX related interrupts.
/// This clears all RX related interrupts.
#[inline]
pub fn clear_interrupts(&mut self) {
self.regs.write_isr(

View File

@@ -1,14 +1,22 @@
//! # Transmitter (TX) support module
use core::convert::Infallible;
use zynq7000::uart::{Fifo, InterruptControl, InterruptStatus, MmioRegisters};
use super::UartId;
/// Transmitter (TX) driver.
pub struct Tx {
pub(crate) regs: MmioRegisters<'static>,
pub(crate) idx: UartId,
}
impl core::fmt::Debug for Tx {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Tx").field("idx", &self.idx).finish()
}
}
impl Tx {
/// Steal the TX side of the UART for a given UART index.
///
@@ -23,16 +31,21 @@ impl Tx {
}
}
/// UART index.
#[inline]
pub const fn uart_idx(&self) -> UartId {
self.idx
}
/// Direct access to the UART MMIO registers.
#[inline]
pub const fn regs(&mut self) -> &mut MmioRegisters<'static> {
&mut self.regs
}
/// Write a byte to the TX FIFO.
///
/// [nb] API which returns [nb::Error::WouldBlock] if the FIFO is full.
#[inline]
pub fn write_fifo(&mut self, word: u8) -> nb::Result<(), Infallible> {
if self.regs.read_sr().tx_full() {
@@ -65,6 +78,7 @@ impl Tx {
});
}
/// Performs a soft-reset of the TX side of the UART.
#[inline]
pub fn soft_reset(&mut self) {
self.regs.modify_cr(|mut val| {
@@ -78,10 +92,12 @@ impl Tx {
}
}
/// Flushes the TX FIFO by blocking until it is empty.
pub fn flush(&mut self) {
while !self.regs.read_sr().tx_empty() {}
}
/// Write a byte to the TX FIFO without checking if there is space available.
#[inline]
pub fn write_fifo_unchecked(&mut self, word: u8) {
self.regs.write_fifo(Fifo::new_with_raw_value(word as u32));

View File

@@ -1,3 +1,4 @@
//! Asynchronous UART transmitter (TX) implementation.
use core::{cell::RefCell, convert::Infallible, sync::atomic::AtomicBool};
use critical_section::Mutex;
@@ -6,14 +7,6 @@ use raw_slice::RawBufSlice;
use crate::uart::{FIFO_DEPTH, Tx, UartId};
#[derive(Debug)]
pub enum TransferType {
Read,
Write,
Transfer,
TransferInPlace,
}
static UART_TX_WAKERS: [AtomicWaker; 2] = [const { AtomicWaker::new() }; 2];
static TX_CONTEXTS: [Mutex<RefCell<TxContext>>; 2] =
[const { Mutex::new(RefCell::new(TxContext::new())) }; 2];
@@ -84,7 +77,7 @@ pub fn on_interrupt_tx(peripheral: UartId) {
}
#[derive(Debug, Copy, Clone)]
pub struct TxContext {
struct TxContext {
progress: usize,
tx_overrun: bool,
slice: RawBufSlice,
@@ -101,6 +94,7 @@ impl TxContext {
}
}
/// Transmission future for UART TX.
pub struct TxFuture {
id: UartId,
}
@@ -164,11 +158,13 @@ impl Drop for TxFuture {
}
}
/// Asynchronous UART transmitter (TX) driver.
pub struct TxAsync {
tx: Tx,
}
impl TxAsync {
/// Constructor.
pub fn new(tx: Tx) -> Self {
Self { tx }
}
@@ -185,6 +181,7 @@ impl TxAsync {
fut.await
}
/// Release the underlying blocking TX driver.
pub fn release(self) -> Tx {
self.tx
}

View File

@@ -40,10 +40,13 @@ impl TypeRegister {
pub type Typer = TypeRegister;
#[deprecated(note = "Use DistributorRegisters instead")]
pub type GicDistributorTyper = DistributorRegisters;
/// GIC Distributor registers.
#[derive(derive_mmio::Mmio)]
#[repr(C, align(8))]
pub struct GicDistributorRegisters {
pub struct DistributorRegisters {
/// Distributor Control Register
pub dcr: DistributorControlRegister,
/// Interrupt Controller Type Register
@@ -109,9 +112,9 @@ pub struct GicDistributorRegisters {
pub cidr: [u32; 4],
}
const_assert_eq!(core::mem::size_of::<GicDistributorRegisters>(), 0x1000);
const_assert_eq!(core::mem::size_of::<DistributorRegisters>(), 0x1000);
impl GicDistributorRegisters {
impl DistributorRegisters {
/// Create a new Global Interrupt Controller Distributor MMIO instance at the fixed address of
/// the processing system.
///
@@ -121,7 +124,7 @@ impl GicDistributorRegisters {
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
/// interfere with each other.
#[inline]
pub const unsafe fn new_mmio_fixed() -> MmioGicDistributorRegisters<'static> {
pub const unsafe fn new_mmio_fixed() -> MmioDistributorRegisters<'static> {
unsafe { Self::new_mmio_at(GICD_BASE_ADDR) }
}
}
@@ -157,10 +160,13 @@ pub struct InterruptSignalRegister {
ack_int_id: u10,
}
#[deprecated(note = "Use DistributorRegisters instead")]
pub type GicCpuInterfaceIar = CpuInterfaceRegisters;
/// GIC CPU interface registers.
#[derive(derive_mmio::Mmio)]
#[repr(C, align(8))]
pub struct GicCpuInterfaceRegisters {
pub struct CpuInterfaceRegisters {
/// CPU Interface Control Register (ICR).
pub icr: InterfaceControl,
/// Interrupt Priority Mask Register.
@@ -183,9 +189,9 @@ pub struct GicCpuInterfaceRegisters {
pub iidr: u32,
}
const_assert_eq!(core::mem::size_of::<GicCpuInterfaceRegisters>(), 0x100);
const_assert_eq!(core::mem::size_of::<CpuInterfaceRegisters>(), 0x100);
impl GicCpuInterfaceRegisters {
impl CpuInterfaceRegisters {
/// Create a new Global Interrupt Controller CPU MMIO instance at the fixed address of the
/// processing system.
///
@@ -195,7 +201,7 @@ impl GicCpuInterfaceRegisters {
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
/// interfere with each other.
#[inline]
pub const unsafe fn new_mmio_fixed() -> MmioGicCpuInterfaceRegisters<'static> {
pub const unsafe fn new_mmio_fixed() -> MmioCpuInterfaceRegisters<'static> {
unsafe { Self::new_mmio_at(GICC_BASE_ADDR) }
}
}

View File

@@ -43,8 +43,8 @@ static PERIPHERALS_TAKEN: AtomicBool = AtomicBool::new(false);
/// The [`svd2rust` documentation](https://docs.rs/svd2rust/latest/svd2rust/#peripheral-api)
/// provides some more information about this.
pub struct Peripherals {
pub gicc: gic::MmioGicCpuInterfaceRegisters<'static>,
pub gicd: gic::MmioGicDistributorRegisters<'static>,
pub gicc: gic::MmioCpuInterfaceRegisters<'static>,
pub gicd: gic::MmioDistributorRegisters<'static>,
pub l2c: l2_cache::MmioRegisters<'static>,
pub ddrc: ddrc::MmioRegisters<'static>,
pub uart_0: uart::MmioRegisters<'static>,
@@ -83,8 +83,8 @@ impl Peripherals {
pub unsafe fn steal() -> Self {
unsafe {
Self {
gicc: gic::GicCpuInterfaceRegisters::new_mmio_fixed(),
gicd: gic::GicDistributorRegisters::new_mmio_fixed(),
gicc: gic::CpuInterfaceRegisters::new_mmio_fixed(),
gicd: gic::DistributorRegisters::new_mmio_fixed(),
l2c: l2_cache::Registers::new_mmio_fixed(),
ddrc: ddrc::Registers::new_mmio_fixed(),
uart_0: uart::Registers::new_mmio_fixed_0(),

View File

@@ -5,8 +5,8 @@ use static_assertions::const_assert_eq;
use crate::{
gic::{
GicCpuInterfaceRegisters, GicDistributorRegisters, MmioGicCpuInterfaceRegisters,
MmioGicDistributorRegisters,
CpuInterfaceRegisters, DistributorRegisters, MmioCpuInterfaceRegisters,
MmioDistributorRegisters,
},
gtc::{MmioRegisters, Registers},
};
@@ -57,7 +57,7 @@ pub struct MpCore {
_reserved_0: [u32; 0x2A],
#[mmio(Inner)]
gicc: GicCpuInterfaceRegisters,
gicc: CpuInterfaceRegisters,
#[mmio(Inner)]
gt: Registers,
@@ -81,7 +81,7 @@ pub struct MpCore {
_reserved_3: [u32; 0x272],
#[mmio(Inner)]
gicd: GicDistributorRegisters,
gicd: DistributorRegisters,
}
const_assert_eq!(core::mem::size_of::<MpCore>(), 0x2000);