zynq7000_hal/
devcfg.rs

1//! # Device Configuration Module
2#[derive(Debug, thiserror::Error)]
3#[error("unaligned address: {0}")]
4pub struct UnalignedAddrError(usize);
5
6/// Configures the bitstream using the PCAP interface in non-secure mode.
7///
8/// Blocking function which only returns when the bitstream configuration is complete.
9pub fn configure_bitstream_non_secure(
10    init_pl: bool,
11    bitstream: &[u8],
12) -> Result<(), UnalignedAddrError> {
13    if !(bitstream.as_ptr() as usize).is_multiple_of(64) {
14        return Err(UnalignedAddrError(bitstream.as_ptr() as usize));
15    }
16    if bitstream.is_empty() {
17        return Ok(());
18    }
19    let mut devcfg = unsafe { zynq7000::devcfg::DevCfg::new_mmio_fixed() };
20    devcfg.modify_control(|mut val| {
21        val.set_config_access_select(zynq7000::devcfg::PlConfigAccess::ConfigAccessPort);
22        val.set_access_port_select(zynq7000::devcfg::ConfigAccessPortSelect::Pcap);
23        val
24    });
25    devcfg.write_interrupt_status(zynq7000::devcfg::Interrupt::new_with_raw_value(0xFFFF_FFFF));
26    if init_pl {
27        devcfg.modify_control(|mut val| {
28            val.set_prog_b_bit(true);
29            val
30        });
31        devcfg.modify_control(|mut val| {
32            val.set_prog_b_bit(false);
33            val
34        });
35        while devcfg.read_status().pcfg_init() {}
36        devcfg.modify_control(|mut val| {
37            val.set_prog_b_bit(true);
38            val
39        });
40        devcfg.write_interrupt_status(
41            zynq7000::devcfg::Interrupt::ZERO.with_pl_programming_done(true),
42        );
43    }
44    while !devcfg.read_status().pcfg_init() {}
45    if !init_pl {
46        while devcfg.read_status().dma_command_queue_full() {}
47    }
48    devcfg.modify_misc_control(|mut val| {
49        val.set_loopback(false);
50        val
51    });
52    devcfg.modify_control(|mut val| {
53        val.set_pcap_rate_enable(false);
54        val
55    });
56    devcfg.write_dma_source_addr(bitstream.as_ptr() as u32);
57    devcfg.write_dma_dest_addr(0xFFFF_FFFF);
58    devcfg.write_dma_source_len(bitstream.len() as u32);
59    devcfg.write_dma_dest_len(bitstream.len() as u32);
60
61    while !devcfg.read_interrupt_status().dma_done() {}
62    // TODO: Check for errors.
63    while !devcfg.read_interrupt_status().pl_programming_done() {}
64    Ok(())
65}