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}