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 embedded_io::Write as _;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use zedboard_bsp::qspi_spansion::{self, QspiSpansionS25Fl256SLinearMode};
|
use zedboard_bsp::qspi_spansion::{self, QspiSpansionS25Fl256SLinearMode};
|
||||||
use zynq7000::{PsPeripherals, qspi::MmioQspi};
|
|
||||||
use zynq7000_hal::{
|
use zynq7000_hal::{
|
||||||
BootMode,
|
|
||||||
clocks::{
|
clocks::{
|
||||||
|
pll::{configure_arm_pll, configure_io_pll, PllConfig},
|
||||||
Clocks,
|
Clocks,
|
||||||
pll::{PllConfig, configure_arm_pll, configure_io_pll},
|
|
||||||
},
|
},
|
||||||
ddr::{DdrClockSetupConfig, configure_ddr_for_ddr3, memtest},
|
ddr::{configure_ddr_for_ddr3, memtest, DdrClockSetupConfig},
|
||||||
gic::GicConfigurator,
|
gic, gpio, l2_cache,
|
||||||
gpio::{GpioPins, mio},
|
|
||||||
l2_cache,
|
|
||||||
prelude::*,
|
prelude::*,
|
||||||
qspi::{self, QSPI_START_ADDRESS},
|
qspi,
|
||||||
time::Hertz,
|
time::Hertz,
|
||||||
uart::{ClockConfigRaw, Uart, UartConfig},
|
uart::{ClockConfigRaw, Uart, UartConfig},
|
||||||
|
BootMode,
|
||||||
};
|
};
|
||||||
use zynq7000_rt as _;
|
use zynq7000_rt as _;
|
||||||
|
use zynq_boot_image::DestinationDevice;
|
||||||
|
|
||||||
use crate::ddr_cfg::{DDRC_CONFIG_ZEDBOARD_FULL_BUILDERS, DDRIOB_CONFIG_SET_ZEDBOARD};
|
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.
|
// 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 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;
|
let mio_pins = gpio_pins.mio;
|
||||||
// Set up the UART, we are logging with it.
|
// Set up the UART, we are logging with it.
|
||||||
let uart_clk_config = ClockConfigRaw::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
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.
|
// 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.enable_all_interrupts();
|
||||||
gic.set_all_spi_interrupt_targets_cpu0();
|
gic.set_all_spi_interrupt_targets_cpu0();
|
||||||
gic.enable();
|
gic.enable();
|
||||||
@@ -218,6 +216,28 @@ fn qspi_boot(mut qspi: QspiSpansionS25Fl256SLinearMode) -> ! {
|
|||||||
let mut name_buf: [u8; 256] = [0; 256];
|
let mut name_buf: [u8; 256] = [0; 256];
|
||||||
for image_header in boot_header.image_header_iterator().unwrap() {
|
for image_header in boot_header.image_header_iterator().unwrap() {
|
||||||
let name = image_header.image_name(&mut name_buf).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 {
|
loop {
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ pub struct PartitionHeader<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[bitbybit::bitenum(u2, exhaustive = false)]
|
#[bitbybit::bitenum(u2, exhaustive = false)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum PartitionOwner {
|
pub enum PartitionOwner {
|
||||||
Fsbl = 0,
|
Fsbl = 0,
|
||||||
@@ -343,7 +343,7 @@ pub enum PartitionOwner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[bitbybit::bitenum(u3, exhaustive = false)]
|
#[bitbybit::bitenum(u3, exhaustive = false)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum ChecksumType {
|
pub enum ChecksumType {
|
||||||
None = 0,
|
None = 0,
|
||||||
@@ -351,7 +351,7 @@ pub enum ChecksumType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[bitbybit::bitenum(u4, exhaustive = false)]
|
#[bitbybit::bitenum(u4, exhaustive = false)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum DestinationDevice {
|
pub enum DestinationDevice {
|
||||||
None = 0,
|
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 log;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
pub mod priv_tim;
|
pub mod priv_tim;
|
||||||
|
pub mod devcfg;
|
||||||
pub mod qspi;
|
pub mod qspi;
|
||||||
pub mod slcr;
|
pub mod slcr;
|
||||||
pub mod spi;
|
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 mpcore;
|
||||||
pub mod priv_tim;
|
pub mod priv_tim;
|
||||||
pub mod qspi;
|
pub mod qspi;
|
||||||
|
pub mod devcfg;
|
||||||
|
pub mod xadc;
|
||||||
pub mod slcr;
|
pub mod slcr;
|
||||||
pub mod spi;
|
pub mod spi;
|
||||||
pub mod ttc;
|
pub mod ttc;
|
||||||
@@ -58,6 +60,8 @@ pub struct PsPeripherals {
|
|||||||
pub eth_0: eth::MmioEthernet<'static>,
|
pub eth_0: eth::MmioEthernet<'static>,
|
||||||
pub eth_1: eth::MmioEthernet<'static>,
|
pub eth_1: eth::MmioEthernet<'static>,
|
||||||
pub qspi: qspi::MmioQspi<'static>,
|
pub qspi: qspi::MmioQspi<'static>,
|
||||||
|
pub devcfg: devcfg::MmioDevCfg<'static>,
|
||||||
|
pub xadc: xadc::MmioXAdc<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PsPeripherals {
|
impl PsPeripherals {
|
||||||
@@ -96,6 +100,7 @@ impl PsPeripherals {
|
|||||||
eth_0: eth::Ethernet::new_mmio_fixed_0(),
|
eth_0: eth::Ethernet::new_mmio_fixed_0(),
|
||||||
eth_1: eth::Ethernet::new_mmio_fixed_1(),
|
eth_1: eth::Ethernet::new_mmio_fixed_1(),
|
||||||
qspi: qspi::Qspi::new_mmio_fixed(),
|
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