#![no_std] #![no_main] extern crate alloc; use alloc::collections::BTreeMap; use libasync::{ delay, smoltcp::{Sockets, TcpStream}, task, }; use libboard_zynq::{ self as zynq, clocks::source::{ArmPll, ClockSource, IoPll}, clocks::Clocks, print, println, sdio::sd_card::SdCard, smoltcp::{ iface::{EthernetInterfaceBuilder, NeighborCache, Routes}, time::Instant, wire::{EthernetAddress, IpAddress, IpCidr}, }, time::Milliseconds, }; #[cfg(feature = "target_zc706")] use libboard_zynq::ps7_init; use libcortex_a9::{ mutex::Mutex, sync_channel::{self, sync_channel}, }; use libregister::RegisterR; use libsupport_zynq::{ boot, ram, }; use log::{info, warn}; const HWADDR: [u8; 6] = [0, 0x23, 0xde, 0xea, 0xbe, 0xef]; #[no_mangle] pub fn main_core0() { // zynq::clocks::CpuClocks::enable_io(1_250_000_000); println!("\nzc706 main"); // ps7_init::apply(); libboard_zynq::stdio::drop_uart(); libboard_zynq::logger::init().unwrap(); log::set_max_level(log::LevelFilter::Trace); info!( "Boot mode: {:?}", zynq::slcr::RegisterBlock::new() .boot_mode .read() .boot_mode_pins() ); #[cfg(feature = "target_zc706")] const CPU_FREQ: u32 = 800_000_000; #[cfg(feature = "target_cora_z7_10")] const CPU_FREQ: u32 = 650_000_000; info!("Setup clock sources..."); ArmPll::setup(2 * CPU_FREQ); Clocks::set_cpu_freq(CPU_FREQ); #[cfg(feature = "target_zc706")] { IoPll::setup(1_000_000_000); libboard_zynq::stdio::drop_uart(); } #[cfg(feature = "target_cora_z7_10")] { IoPll::setup(1_000_000_000); libboard_zynq::stdio::drop_uart(); } info!("PLLs set up"); let clocks = zynq::clocks::Clocks::get(); info!( "CPU Clocks: {}/{}/{}/{}", clocks.cpu_6x4x(), clocks.cpu_3x2x(), clocks.cpu_2x(), clocks.cpu_1x() ); let sd = libboard_zynq::sdio::SDIO::sdio0(true); // only test SD card if it is inserted if sd.is_card_inserted() { let result = SdCard::from_sdio(sd); match &result { Ok(_) => info!("OK!"), Err(a) => info!("{}", a), }; const SIZE: usize = 512 * 2 + 1; let mut sd_card = result.unwrap(); if false { let buffer: [u8; SIZE] = [5; SIZE]; sd_card.write_block(0x0, 2, &buffer).unwrap(); } let mut buffer: [u8; SIZE] = [0; SIZE]; sd_card.read_block(0 /*0x1*/, 2, &mut buffer[1..]).unwrap(); info!("buffer = {:?}", &buffer[..]); } let mut flash = zynq::flash::Flash::new(200_000_000).linear_addressing_mode(); let flash_ram: &[u8] = unsafe { core::slice::from_raw_parts(flash.ptr(), flash.size()) }; for i in 0..=1 { print!("Flash {}:", i); for b in &flash_ram[(i * 16 * 1024 * 1024)..][..128] { print!(" {:02X}", *b); } println!(""); } let _flash = flash.stop(); let timer = libboard_zynq::timer::GlobalTimer::start(); let mut ddr = zynq::ddr::DdrRam::new(); #[cfg(not(feature = "target_zc706"))] ddr.memtest(); ram::init_alloc_ddr(&mut ddr); #[cfg(dev)] for i in 0..=1 { let mut flash_io = flash.manual_mode(i); // println!("rdcr={:02X}", flash_io.rdcr()); print!("Flash {} ID:", i); for b in flash_io.rdid() { print!(" {:02X}", b); } println!(""); print!("Flash {} I/O:", i); for o in 0..8 { const CHUNK: u32 = 8; for b in flash_io.read(CHUNK * o, CHUNK as usize) { print!(" {:02X}", b); } } println!(""); flash_io.dump("Read cr1", 0x35); flash_io.dump("Read Autoboot", 0x14); flash_io.dump("Read Bank", 0x16); flash_io.dump("DLP Bank", 0x16); flash_io.dump("Read ESig", 0xAB); flash_io.dump("OTP Read", 0x4B); flash_io.dump("DYB Read", 0xE0); flash_io.dump("PPB Read", 0xE2); flash_io.dump("ASP Read", 0x2B); flash_io.dump("Password Read", 0xE7); flash_io.write_enabled(|flash_io| { flash_io.erase(0); }); flash_io.write_enabled(|flash_io| { flash_io.program(0, [0x23054223; 0x100 >> 2].iter().cloned()); }); flash = flash_io.stop(); } let core1 = boot::Core1::start(false); let (mut core1_req, rx) = sync_channel(10); *CORE1_REQ.lock() = Some(rx); let (tx, mut core1_res) = sync_channel(10); *CORE1_RES.lock() = Some(tx); task::block_on(async { for i in 0..10 { core1_req.async_send(i).await; let j = core1_res.async_recv().await; println!("{} -> {}", i, j); } }); core1.disable(); let eth = zynq::eth::Eth::default(HWADDR.clone()); println!("Eth on"); const RX_LEN: usize = 4096; // Number of transmission buffers (minimum is two because with // one, duplicate packet transmission occurs) const TX_LEN: usize = 4096; let eth = eth.start_rx(RX_LEN); let mut eth = eth.start_tx(TX_LEN); let ethernet_addr = EthernetAddress(HWADDR); // IP stack let local_addr = IpAddress::v4(192, 168, 1, 51); let mut ip_addrs = [IpCidr::new(local_addr, 24)]; let routes = Routes::new(BTreeMap::new()); let neighbor_cache = NeighborCache::new(BTreeMap::new()); let mut iface = EthernetInterfaceBuilder::new(&mut eth) .ethernet_addr(ethernet_addr) .ip_addrs(&mut ip_addrs[..]) .routes(routes) .neighbor_cache(neighbor_cache) .finalize(); #[cfg(feature = "target_zc706")] ps7_init::report_differences(); Sockets::init(32); const TCP_PORT: u16 = 19; // (rx, tx) let stats = alloc::rc::Rc::new(core::cell::RefCell::new((0, 0))); let stats_tx = stats.clone(); task::spawn(async move { while let Ok(stream) = TcpStream::accept(TCP_PORT, 0x10_0000, 0x10_0000).await { let stats_tx = stats_tx.clone(); task::spawn(async move { let tx_data = (0..=255).take(4096).collect::>(); loop { // const CHUNK_SIZE: usize = 65536; // match stream.send((0..=255).cycle().take(CHUNK_SIZE)).await { match stream.send_slice(&tx_data[..]).await { Ok(len) => stats_tx.borrow_mut().1 += tx_data.len(), //CHUNK_SIZE, Err(e) => { warn!("tx: {:?}", e); break } } } }); } }); let stats_rx = stats.clone(); task::spawn(async move { while let Ok(stream) = TcpStream::accept(TCP_PORT+1, 0x10_0000, 0x10_0000).await { let stats_rx = stats_rx.clone(); task::spawn(async move { loop { match stream.recv(|buf| (buf.len(), buf.len())).await { Ok(len) => stats_rx.borrow_mut().0 += len, Err(e) => { warn!("rx: {:?}", e); break } } } }); } }); let mut countdown = timer.countdown(); task::spawn(async move { loop { delay(&mut countdown, Milliseconds(1000)).await; let timestamp = timer.get_us(); let seconds = timestamp / 1_000_000; let micros = timestamp % 1_000_000; let (rx, tx) = { let mut stats = stats.borrow_mut(); let result = *stats; *stats = (0, 0); result }; info!("time: {:6}.{:06}s, rx: {}k/s, tx: {}k/s", seconds, micros, rx / 1024, tx / 1024); } }); Sockets::run(&mut iface, || { Instant::from_millis(timer.get_time().0 as i64) }) } static CORE1_REQ: Mutex>> = Mutex::new(None); static CORE1_RES: Mutex>> = Mutex::new(None); static DONE: Mutex = Mutex::new(false); #[no_mangle] pub fn main_core1() { println!("Hello from core1!"); let mut req = None; while req.is_none() { req = CORE1_REQ.lock().take(); } let req = req.unwrap(); let mut res = None; while res.is_none() { res = CORE1_RES.lock().take(); } let mut res = res.unwrap(); for i in req { res.send(*i * *i); } println!("core1 done!"); *DONE.lock() = true; loop {} }