add bitstream prog function
Some checks failed
ci / Check build (pull_request) Has been cancelled
ci / Check formatting (pull_request) Has been cancelled
ci / Check Documentation Build (pull_request) Has been cancelled
ci / Clippy (pull_request) Has been cancelled
ci / Check build (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
Some checks failed
ci / Check build (pull_request) Has been cancelled
ci / Check formatting (pull_request) Has been cancelled
ci / Check Documentation Build (pull_request) Has been cancelled
ci / Clippy (pull_request) Has been cancelled
ci / Check build (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
This commit is contained in:
@@ -8,23 +8,21 @@ use cortex_ar::asm::nop;
|
||||
use embedded_io::Write as _;
|
||||
use log::{error, info};
|
||||
use zedboard_bsp::qspi_spansion::{self, QspiSpansionS25Fl256SLinearMode};
|
||||
use zynq7000::{PsPeripherals, qspi::MmioQspi};
|
||||
use zynq7000_hal::{
|
||||
BootMode,
|
||||
clocks::{
|
||||
pll::{configure_arm_pll, configure_io_pll, PllConfig},
|
||||
Clocks,
|
||||
pll::{PllConfig, configure_arm_pll, configure_io_pll},
|
||||
},
|
||||
ddr::{DdrClockSetupConfig, configure_ddr_for_ddr3, memtest},
|
||||
gic::GicConfigurator,
|
||||
gpio::{GpioPins, mio},
|
||||
l2_cache,
|
||||
ddr::{configure_ddr_for_ddr3, memtest, DdrClockSetupConfig},
|
||||
gic, gpio, l2_cache,
|
||||
prelude::*,
|
||||
qspi::{self, QSPI_START_ADDRESS},
|
||||
qspi,
|
||||
time::Hertz,
|
||||
uart::{ClockConfigRaw, Uart, UartConfig},
|
||||
BootMode,
|
||||
};
|
||||
use zynq7000_rt as _;
|
||||
use zynq_boot_image::DestinationDevice;
|
||||
|
||||
use crate::ddr_cfg::{DDRC_CONFIG_ZEDBOARD_FULL_BUILDERS, DDRIOB_CONFIG_SET_ZEDBOARD};
|
||||
|
||||
@@ -87,7 +85,7 @@ pub fn main() -> ! {
|
||||
// Clock was already initialized by PS7 Init TCL script or FSBL, we just read it.
|
||||
let clocks = Clocks::new_from_regs(PS_CLK).unwrap();
|
||||
|
||||
let gpio_pins = GpioPins::new(dp.gpio);
|
||||
let gpio_pins = gpio::GpioPins::new(dp.gpio);
|
||||
let mio_pins = gpio_pins.mio;
|
||||
// Set up the UART, we are logging with it.
|
||||
let uart_clk_config = ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||
@@ -110,7 +108,7 @@ pub fn main() -> ! {
|
||||
};
|
||||
|
||||
// Set up the global interrupt controller.
|
||||
let mut gic = GicConfigurator::new_with_init(dp.gicc, dp.gicd);
|
||||
let mut gic = gic::GicConfigurator::new_with_init(dp.gicc, dp.gicd);
|
||||
gic.enable_all_interrupts();
|
||||
gic.set_all_spi_interrupt_targets_cpu0();
|
||||
gic.enable();
|
||||
@@ -218,6 +216,28 @@ fn qspi_boot(mut qspi: QspiSpansionS25Fl256SLinearMode) -> ! {
|
||||
let mut name_buf: [u8; 256] = [0; 256];
|
||||
for image_header in boot_header.image_header_iterator().unwrap() {
|
||||
let name = image_header.image_name(&mut name_buf).unwrap();
|
||||
for partition in image_header
|
||||
.partition_header_iterator(boot_header_slice)
|
||||
.unwrap()
|
||||
{
|
||||
let section_attrs = partition.section_attributes();
|
||||
if let Ok(dest_dev) = section_attrs.destination_device() {
|
||||
match dest_dev {
|
||||
DestinationDevice::Pl => {
|
||||
info!("Loading image '{name}' to PL (FPGA)..");
|
||||
// TODO: Load the bitstream.
|
||||
}
|
||||
DestinationDevice::Ps => {
|
||||
// TODO: Load the binary into DDR. Jump at lowest load address after all
|
||||
// partitions were parsed.
|
||||
}
|
||||
_ => {
|
||||
error!("Unsupported destination device {dest_dev:?}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
|
||||
@@ -335,7 +335,7 @@ pub struct PartitionHeader<'a> {
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u2, exhaustive = false)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum PartitionOwner {
|
||||
Fsbl = 0,
|
||||
@@ -343,7 +343,7 @@ pub enum PartitionOwner {
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u3, exhaustive = false)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum ChecksumType {
|
||||
None = 0,
|
||||
@@ -351,7 +351,7 @@ pub enum ChecksumType {
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u4, exhaustive = false)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum DestinationDevice {
|
||||
None = 0,
|
||||
|
||||
63
zynq7000-hal/src/devcfg.rs
Normal file
63
zynq7000-hal/src/devcfg.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("unaligned address: {0}")]
|
||||
pub struct UnalignedAddrError(usize);
|
||||
|
||||
/// Configures the bitstream using the PCAP interface in non-secure mode.
|
||||
///
|
||||
/// Blocking function which only returns when the bitstream configuration is complete.
|
||||
pub fn configure_bitstream_non_secure(
|
||||
init_pl: bool,
|
||||
bitstream: &[u8],
|
||||
) -> Result<(), UnalignedAddrError> {
|
||||
if !(bitstream.as_ptr() as usize).is_multiple_of(64) {
|
||||
return Err(UnalignedAddrError(bitstream.as_ptr() as usize));
|
||||
}
|
||||
if bitstream.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let devcfg = unsafe { zynq7000::devcfg::DevCfg::new_mmio_fixed() };
|
||||
devcfg.modify_control(|mut val| {
|
||||
val.set_config_access_select(zynq7000::devcfg::PlConfigAccess::ConfigAccessPort);
|
||||
val.set_access_port_select(zynq7000::devcfg::ConfigAccessPortSelect::Pcap);
|
||||
val
|
||||
});
|
||||
devcfg.write_interrupt_status(zynq7000::devcfg::Interrupt::new_with_raw_value(0xFFFF_FFFF));
|
||||
if init_pl {
|
||||
devcfg.modify_control(|mut val| {
|
||||
val.set_prog_b_bit(true);
|
||||
val
|
||||
});
|
||||
devcfg.modify_control(|mut val| {
|
||||
val.set_prog_b_bit(false);
|
||||
val
|
||||
});
|
||||
while devcfg.read_status().pcfg_init() {}
|
||||
devcfg.modify_control(|mut val| {
|
||||
val.set_prog_b_bit(true);
|
||||
val
|
||||
});
|
||||
devcfg.write_interrupt_status(
|
||||
zynq7000::devcfg::Interrupt::ZERO.with_pl_programming_done(true),
|
||||
);
|
||||
}
|
||||
while !devcfg.read_status().pcfg_init() {}
|
||||
if !init_pl {
|
||||
while devcfg.read_status().dma_command_queue_full() {}
|
||||
}
|
||||
devcfg.modify_misc_control(|mut val| {
|
||||
val.set_loopback(false);
|
||||
val
|
||||
});
|
||||
devcfg.modify_control(|mut val| {
|
||||
val.set_pcap_rate_enable(false);
|
||||
val
|
||||
});
|
||||
devcfg.write_dma_source_addr(bitstream.as_ptr() as u32);
|
||||
devcfg.write_dma_dest_addr(0xFFFF_FFFF);
|
||||
devcfg.write_dma_source_len(bitstream.len());
|
||||
devcfg.write_dma_dest_len(bitstream.len());
|
||||
|
||||
while !devcfg.read_interrupt_status().dma_done() {}
|
||||
// TODO: Check for errors.
|
||||
while !devcfg.read_interrupt_status().pl_programming_done() {}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ pub mod l2_cache;
|
||||
pub mod log;
|
||||
pub mod prelude;
|
||||
pub mod priv_tim;
|
||||
pub mod devcfg;
|
||||
pub mod qspi;
|
||||
pub mod slcr;
|
||||
pub mod spi;
|
||||
|
||||
304
zynq7000/src/devcfg.rs
Normal file
304
zynq7000/src/devcfg.rs
Normal file
@@ -0,0 +1,304 @@
|
||||
use arbitrary_int::{u4, u5, u7};
|
||||
|
||||
pub const DEVCFG_BASE_ADDR: usize = 0xF8007000;
|
||||
|
||||
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum PlConfigAccess {
|
||||
/// Used for JTAG access
|
||||
TapController = 0,
|
||||
/// Used for PCAP or ICAP access.
|
||||
ConfigAccessPort = 1,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ConfigAccessPortSelect {
|
||||
/// Internal Configuration Access Port (ICAP), using PL or PS-based software.
|
||||
Icap = 0,
|
||||
/// Processor Configuration Access Port (PCAP), using PS-based software.
|
||||
Pcap = 1,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum TimerSelect {
|
||||
_64kTimer = 0,
|
||||
_4kTimer = 1,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u3, exhaustive = false)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum AesEnable {
|
||||
Disable = 0b000,
|
||||
Enable = 0b111,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum PsBootMode {
|
||||
NonSecure = 0,
|
||||
Secure = 1,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u3, exhaustive = false)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ArmDapEnable {
|
||||
Enabled = 0b111,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32, debug)]
|
||||
pub struct Control {
|
||||
#[bit(31, rw)]
|
||||
force_reset: bool,
|
||||
/// Program singal used to reset the PL. It acts at the PROG_B signal in the PL.
|
||||
#[bit(30, rw)]
|
||||
prog_b_bit: bool,
|
||||
/// Called PCFG_POR_CNT_4K by Xilinx.
|
||||
#[bit(29, rw)]
|
||||
timer_select: TimerSelect,
|
||||
/// Called XDCFG_CTRL_PCAP_PR_MASK by Xilinx.
|
||||
#[bit(27, rw)]
|
||||
access_port_select: ConfigAccessPortSelect,
|
||||
#[bit(26, rw)]
|
||||
config_access_select: PlConfigAccess,
|
||||
#[bit(25, rw)]
|
||||
pcap_rate_enable: bool,
|
||||
#[bit(24, rw)]
|
||||
multiboot_enable: bool,
|
||||
#[bit(23, rw)]
|
||||
jtag_chain_disable: bool,
|
||||
#[bit(12, rw)]
|
||||
pcfg_aes_fuse: bool,
|
||||
#[bits(9..=11, rw)]
|
||||
pcfg_aes_enable: Option<AesEnable>,
|
||||
#[bit(8, rw)]
|
||||
seu_enable: bool,
|
||||
/// Read-only because this is set and locked by BootROM.
|
||||
#[bit(7, r)]
|
||||
ps_boot_mode: PsBootMode,
|
||||
/// SPNIDEN
|
||||
#[bit(6, rw)]
|
||||
secure_non_invasive_debug_enable: bool,
|
||||
/// SPIDEN
|
||||
#[bit(5, rw)]
|
||||
secure_invasive_debug_enable: bool,
|
||||
/// NIDEN
|
||||
#[bit(4, rw)]
|
||||
non_invasive_debug_enable: bool,
|
||||
/// DBGEN
|
||||
#[bit(3, rw)]
|
||||
invasive_debug_enable: bool,
|
||||
#[bits(0..=2, rw)]
|
||||
dap_enable: Option<ArmDapEnable>,
|
||||
}
|
||||
|
||||
/// The bits in this register and read/write, set-only, which means that only a PS_POR_B reset
|
||||
/// can clear the bits.
|
||||
#[bitbybit::bitfield(u32, debug)]
|
||||
pub struct Lock {
|
||||
#[bit(4, rw)]
|
||||
aes_fuse: bool,
|
||||
#[bit(3, rw)]
|
||||
aes: bool,
|
||||
#[bit(2, rw)]
|
||||
seu: bool,
|
||||
/// Locks the SEC_EN bit. BootROM will set this bit.
|
||||
#[bit(1, rw)]
|
||||
sec: bool,
|
||||
/// Locks SPNIDEN, SPIDEN, NIDEN, DBGEN and DAP_EN
|
||||
#[bit(0, rw)]
|
||||
debug: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum EdgeConfig {
|
||||
Falling = 0,
|
||||
Rising = 1,
|
||||
}
|
||||
|
||||
/// Related to the full level for reads, and the empty level for writes.
|
||||
#[bitbybit::bitenum(u2, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum FifoThresholdConfig {
|
||||
OneFourth = 0b00,
|
||||
HalfEmpty = 0b01,
|
||||
ThreeFourth = 0b10,
|
||||
EmptyOrFull = 0b11,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32, debug)]
|
||||
pub struct Config {
|
||||
#[bits(10..=11, rw)]
|
||||
read_fifo_threshhold: FifoThresholdConfig,
|
||||
#[bits(8..=9, rw)]
|
||||
write_fifo_threshold: FifoThresholdConfig,
|
||||
#[bit(7, rw)]
|
||||
read_data_active_clock_edge: EdgeConfig,
|
||||
#[bit(6, rw)]
|
||||
write_data_active_clock_edge: EdgeConfig,
|
||||
#[bit(5, rw)]
|
||||
disable_src_increment: bool,
|
||||
#[bit(4, rw)]
|
||||
disable_dst_incremenet: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32, debug)]
|
||||
pub struct Interrupt {
|
||||
/// Tri-state PL IO during HIZ.
|
||||
#[bit(31, rw)]
|
||||
gts_usr_b: bool,
|
||||
#[bit(30, rw)]
|
||||
first_config_done: bool,
|
||||
#[bit(29, rw)]
|
||||
global_powerdown: bool,
|
||||
/// Tri-state PL IO during configuration.
|
||||
#[bit(28, rw)]
|
||||
gts_cfg_b: bool,
|
||||
/// PSS_CFG_RESET_B_INT
|
||||
#[bit(27, rw)]
|
||||
pl_config_reset: bool,
|
||||
#[bit(23, rw)]
|
||||
axi_write_timeout: bool,
|
||||
#[bit(22, rw)]
|
||||
axi_write_response_error: bool,
|
||||
#[bit(21, rw)]
|
||||
axi_read_timeout: bool,
|
||||
#[bit(20, rw)]
|
||||
axi_read_response_error: bool,
|
||||
#[bit(18, rw)]
|
||||
rx_overflow: bool,
|
||||
#[bit(17, rw)]
|
||||
tx_fifo_below_threshold: bool,
|
||||
#[bit(16, rw)]
|
||||
rx_fifo_above_threshold: bool,
|
||||
#[bit(15, rw)]
|
||||
dma_illegal_command: bool,
|
||||
#[bit(14, rw)]
|
||||
dma_queue_overflow: bool,
|
||||
#[bit(13, rw)]
|
||||
dma_done: bool,
|
||||
#[bit(12, rw)]
|
||||
dma_pcap_done: bool,
|
||||
#[bit(11, rw)]
|
||||
inconsistent_pcap_to_dma_transfer_len: bool,
|
||||
#[bit(6, rw)]
|
||||
hamc_error: bool,
|
||||
#[bit(5, rw)]
|
||||
seu_error: bool,
|
||||
#[bit(4, rw)]
|
||||
pl_power_loss_por_b_low: bool,
|
||||
#[bit(3, rw)]
|
||||
pl_config_controller_under_reset: bool,
|
||||
#[bit(2, rw)]
|
||||
pl_programming_done: bool,
|
||||
#[bit(1, rw)]
|
||||
positive_edge_pl_init: bool,
|
||||
#[bit(0, rw)]
|
||||
negative_edge_pl_init: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32, debug)]
|
||||
pub struct MiscControl {
|
||||
#[bits(28..=31, r)]
|
||||
ps_version: u4,
|
||||
|
||||
#[bit(8, r)]
|
||||
por_b_signal: bool,
|
||||
|
||||
#[bit(4, rw)]
|
||||
loopback: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u2, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum UnacknowledgedDmaTransfers {
|
||||
None = 0b00,
|
||||
One =0b01,
|
||||
Two = 0b10,
|
||||
ThreeOrMore = 0b11,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32, debug)]
|
||||
pub struct Status {
|
||||
#[bit(31, rw)]
|
||||
dma_command_queue_full: bool,
|
||||
#[bit(30, rw)]
|
||||
dma_command_queue_empty: bool,
|
||||
#[bits(28..=29, rw)]
|
||||
unacknowledged_dma_transfers: UnacknowledgedDmaTransfers,
|
||||
#[bits(20..=24, rw)]
|
||||
rx_fifo_level: u5,
|
||||
#[bits(12..=18, rw)]
|
||||
tx_fifo_level: u7,
|
||||
#[bit(11, rw)]
|
||||
gts_usr_b: bool,
|
||||
#[bit(10, rw)]
|
||||
first_config_done: bool,
|
||||
#[bit(9, rw)]
|
||||
global_powerdown: bool,
|
||||
#[bit(8, rw)]
|
||||
gts_cfg_b: bool,
|
||||
#[bit(7, rw)]
|
||||
secure_lockdown: bool,
|
||||
#[bit(6, rw)]
|
||||
illegal_apb_access: bool,
|
||||
/// Active low reset bit.
|
||||
#[bit(5, rw)]
|
||||
pl_reset_n: bool,
|
||||
#[bit(4, rw)]
|
||||
pcfg_init: bool,
|
||||
#[bit(3, rw)]
|
||||
efuse_bbram_aes_key_disabled: bool,
|
||||
#[bit(2, rw)]
|
||||
efuse_sec_enable: bool,
|
||||
#[bit(1, rw)]
|
||||
efuse_jtag_disabled: bool
|
||||
|
||||
}
|
||||
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct DevCfg {
|
||||
control: Control,
|
||||
lock: Lock,
|
||||
config: Config,
|
||||
/// Interrupt is cleared by writing to this register.
|
||||
interrupt_status: Interrupt,
|
||||
/// Bits can be set to one to mask the interrupts.
|
||||
interrupt_mask: Interrupt,
|
||||
status: Status,
|
||||
dma_source_addr: u32,
|
||||
dma_dest_addr: u32,
|
||||
dma_source_len: u32,
|
||||
dma_dest_len: u32,
|
||||
_reserved0: u32,
|
||||
multiboot_addr: u32,
|
||||
_reserved1: u32,
|
||||
unlock_control: u32,
|
||||
_reserved2: [u32; 0x12],
|
||||
misc_control: MiscControl,
|
||||
|
||||
_reserved3: [u32; 0x1F],
|
||||
|
||||
// Included here but not exposed to avoid providing multiple references to the same peripheral.
|
||||
// Exposed in [crate::xadc].
|
||||
_xadc: crate::xadc::XAdc,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<DevCfg>(), 0x11C);
|
||||
|
||||
impl DevCfg {
|
||||
/// Create a new DevCfg MMIO instance for for device configuration peripheral at address
|
||||
/// [DEVCFG_BASE_ADDR].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub unsafe fn new_mmio_fixed() -> MmioDevCfg<'static> {
|
||||
unsafe { Self::new_mmio_at(DEVCFG_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,8 @@ pub mod l2_cache;
|
||||
pub mod mpcore;
|
||||
pub mod priv_tim;
|
||||
pub mod qspi;
|
||||
pub mod devcfg;
|
||||
pub mod xadc;
|
||||
pub mod slcr;
|
||||
pub mod spi;
|
||||
pub mod ttc;
|
||||
@@ -58,6 +60,8 @@ pub struct PsPeripherals {
|
||||
pub eth_0: eth::MmioEthernet<'static>,
|
||||
pub eth_1: eth::MmioEthernet<'static>,
|
||||
pub qspi: qspi::MmioQspi<'static>,
|
||||
pub devcfg: devcfg::MmioDevCfg<'static>,
|
||||
pub xadc: xadc::MmioXAdc<'static>,
|
||||
}
|
||||
|
||||
impl PsPeripherals {
|
||||
@@ -96,6 +100,7 @@ impl PsPeripherals {
|
||||
eth_0: eth::Ethernet::new_mmio_fixed_0(),
|
||||
eth_1: eth::Ethernet::new_mmio_fixed_1(),
|
||||
qspi: qspi::Qspi::new_mmio_fixed(),
|
||||
devcfg: devcfg::DevCfg::new_mmio_fixed(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
29
zynq7000/src/xadc.rs
Normal file
29
zynq7000/src/xadc.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
pub const XADC_BASE_ADDR: usize = 0xF8007100;
|
||||
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct XAdc {
|
||||
config: u32,
|
||||
interrupt_status: u32,
|
||||
interrupt_mask: u32,
|
||||
misc_status: u32,
|
||||
command_fifo: u32,
|
||||
data_fifo: u32,
|
||||
misc_control: u32,
|
||||
}
|
||||
|
||||
impl XAdc {
|
||||
/// Create a new XADC MMIO instance for for device configuration peripheral at address
|
||||
/// [XADC_BASE_ADDR].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub unsafe fn new_mmio_fixed() -> MmioXAdc<'static> {
|
||||
unsafe { XAdc::new_mmio_at(XADC_BASE_ADDR) }
|
||||
}
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<XAdc>(), 0x1C);
|
||||
Reference in New Issue
Block a user