2019-05-05 20:56:23 +08:00
|
|
|
#![no_std]
|
|
|
|
#![no_main]
|
|
|
|
|
2020-03-31 07:16:58 +08:00
|
|
|
extern crate alloc;
|
|
|
|
|
2020-04-01 04:34:32 +08:00
|
|
|
use alloc::{borrow::ToOwned, collections::BTreeMap, format};
|
2020-06-11 05:20:43 +08:00
|
|
|
use core::task::Poll;
|
2020-06-05 11:48:41 +08:00
|
|
|
use libasync::{
|
|
|
|
delay,
|
|
|
|
smoltcp::{Sockets, TcpStream},
|
|
|
|
task,
|
|
|
|
};
|
2020-03-26 05:23:30 +08:00
|
|
|
use libboard_zynq::{
|
2020-06-05 11:48:41 +08:00
|
|
|
self as zynq,
|
|
|
|
clocks::source::{ArmPll, ClockSource, IoPll},
|
|
|
|
clocks::Clocks,
|
2020-03-26 05:23:30 +08:00
|
|
|
print, println,
|
2020-06-25 07:40:42 +08:00
|
|
|
ps7_init,
|
2020-06-05 11:48:41 +08:00
|
|
|
sdio::sd_card::SdCard,
|
2020-03-26 05:23:30 +08:00
|
|
|
smoltcp::{
|
2020-04-01 04:34:32 +08:00
|
|
|
self,
|
2020-06-05 11:48:41 +08:00
|
|
|
iface::{EthernetInterfaceBuilder, NeighborCache, Routes},
|
2020-03-26 05:23:30 +08:00
|
|
|
time::Instant,
|
2020-06-05 11:48:41 +08:00
|
|
|
wire::{EthernetAddress, IpAddress, IpCidr},
|
2020-03-26 05:23:30 +08:00
|
|
|
},
|
2020-04-25 07:18:49 +08:00
|
|
|
time::Milliseconds,
|
2020-03-26 05:23:30 +08:00
|
|
|
};
|
2020-06-05 11:48:41 +08:00
|
|
|
use libcortex_a9::{
|
|
|
|
mutex::Mutex,
|
|
|
|
sync_channel::{self, sync_channel},
|
|
|
|
};
|
|
|
|
use libregister::RegisterR;
|
2020-01-31 05:54:48 +08:00
|
|
|
use libsupport_zynq::{
|
2020-06-05 11:48:41 +08:00
|
|
|
boot, ram,
|
2019-12-18 07:06:10 +08:00
|
|
|
};
|
2020-06-22 08:06:11 +08:00
|
|
|
use log::{info, warn};
|
2019-05-05 20:56:23 +08:00
|
|
|
|
2019-07-05 06:44:53 +08:00
|
|
|
const HWADDR: [u8; 6] = [0, 0x23, 0xde, 0xea, 0xbe, 0xef];
|
|
|
|
|
2019-12-18 07:06:10 +08:00
|
|
|
#[no_mangle]
|
|
|
|
pub fn main_core0() {
|
2019-12-17 08:07:46 +08:00
|
|
|
// zynq::clocks::CpuClocks::enable_io(1_250_000_000);
|
2019-12-10 09:50:44 +08:00
|
|
|
println!("\nzc706 main");
|
2020-06-27 05:27:28 +08:00
|
|
|
// ps7_init::apply();
|
2020-06-25 07:27:02 +08:00
|
|
|
libboard_zynq::stdio::drop_uart();
|
2020-04-21 05:40:01 +08:00
|
|
|
|
2020-05-01 07:33:00 +08:00
|
|
|
libboard_zynq::logger::init().unwrap();
|
2020-04-21 05:40:01 +08:00
|
|
|
log::set_max_level(log::LevelFilter::Trace);
|
|
|
|
|
2020-06-05 11:48:41 +08:00
|
|
|
info!(
|
|
|
|
"Boot mode: {:?}",
|
|
|
|
zynq::slcr::RegisterBlock::new()
|
|
|
|
.boot_mode
|
|
|
|
.read()
|
|
|
|
.boot_mode_pins()
|
|
|
|
);
|
2019-12-10 09:50:44 +08:00
|
|
|
|
2020-01-24 05:44:10 +08:00
|
|
|
#[cfg(feature = "target_zc706")]
|
|
|
|
const CPU_FREQ: u32 = 800_000_000;
|
|
|
|
#[cfg(feature = "target_cora_z7_10")]
|
|
|
|
const CPU_FREQ: u32 = 650_000_000;
|
|
|
|
|
2020-05-01 07:45:52 +08:00
|
|
|
info!("Setup clock sources...");
|
2020-01-24 05:44:10 +08:00
|
|
|
ArmPll::setup(2 * CPU_FREQ);
|
|
|
|
Clocks::set_cpu_freq(CPU_FREQ);
|
2020-04-01 00:47:36 +08:00
|
|
|
#[cfg(feature = "target_zc706")]
|
|
|
|
{
|
|
|
|
IoPll::setup(1_000_000_000);
|
|
|
|
libboard_zynq::stdio::drop_uart();
|
|
|
|
}
|
2020-06-05 11:47:06 +08:00
|
|
|
#[cfg(feature = "target_cora_z7_10")]
|
|
|
|
{
|
|
|
|
IoPll::setup(1_000_000_000);
|
|
|
|
libboard_zynq::stdio::drop_uart();
|
|
|
|
}
|
2020-05-01 07:45:52 +08:00
|
|
|
info!("PLLs set up");
|
2020-01-24 05:44:10 +08:00
|
|
|
let clocks = zynq::clocks::Clocks::get();
|
2020-06-05 11:48:41 +08:00
|
|
|
info!(
|
|
|
|
"CPU Clocks: {}/{}/{}/{}",
|
|
|
|
clocks.cpu_6x4x(),
|
|
|
|
clocks.cpu_3x2x(),
|
|
|
|
clocks.cpu_2x(),
|
|
|
|
clocks.cpu_1x()
|
|
|
|
);
|
2020-01-24 05:44:10 +08:00
|
|
|
|
2020-06-10 12:55:22 +08:00
|
|
|
let sd = libboard_zynq::sdio::SDIO::sdio0(true);
|
2020-06-05 11:47:06 +08:00
|
|
|
// only test SD card if it is inserted
|
|
|
|
if sd.is_card_inserted() {
|
|
|
|
let result = SdCard::from_sdio(sd);
|
|
|
|
match &result {
|
|
|
|
Ok(_) => info!("OK!"),
|
2020-06-15 15:00:54 +08:00
|
|
|
Err(a) => info!("{}", a),
|
2020-06-05 11:47:06 +08:00
|
|
|
};
|
2020-06-09 17:03:17 +08:00
|
|
|
const SIZE: usize = 512 * 2 + 1;
|
2020-06-05 11:47:06 +08:00
|
|
|
let mut sd_card = result.unwrap();
|
2020-06-27 05:27:28 +08:00
|
|
|
if false {
|
2020-06-10 12:54:50 +08:00
|
|
|
let buffer: [u8; SIZE] = [5; SIZE];
|
|
|
|
sd_card.write_block(0x0, 2, &buffer).unwrap();
|
2020-06-05 11:47:06 +08:00
|
|
|
}
|
2020-06-10 12:54:50 +08:00
|
|
|
let mut buffer: [u8; SIZE] = [0; SIZE];
|
2020-06-27 05:27:28 +08:00
|
|
|
sd_card.read_block(0 /*0x1*/, 2, &mut buffer[1..]).unwrap();
|
|
|
|
info!("buffer = {:?}", &buffer[..]);
|
2020-06-05 11:47:06 +08:00
|
|
|
}
|
|
|
|
|
2019-12-10 09:50:44 +08:00
|
|
|
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 mut flash = flash.stop();
|
2019-10-22 04:19:03 +08:00
|
|
|
|
2020-04-25 08:59:48 +08:00
|
|
|
let timer = libboard_zynq::timer::GlobalTimer::start();
|
2020-04-25 07:18:49 +08:00
|
|
|
|
2019-10-26 05:19:34 +08:00
|
|
|
let mut ddr = zynq::ddr::DdrRam::new();
|
2019-12-17 08:07:46 +08:00
|
|
|
#[cfg(not(feature = "target_zc706"))]
|
2019-10-26 05:19:34 +08:00
|
|
|
ddr.memtest();
|
2020-04-27 10:06:55 +08:00
|
|
|
ram::init_alloc_ddr(&mut ddr);
|
2019-10-31 08:41:10 +08:00
|
|
|
|
2020-05-01 07:25:52 +08:00
|
|
|
#[cfg(dev)]
|
2019-12-10 09:50:44 +08:00
|
|
|
for i in 0..=1 {
|
|
|
|
let mut flash_io = flash.manual_mode(i);
|
2019-12-17 08:07:46 +08:00
|
|
|
// println!("rdcr={:02X}", flash_io.rdcr());
|
2019-12-10 09:50:44 +08:00
|
|
|
print!("Flash {} ID:", i);
|
|
|
|
for b in flash_io.rdid() {
|
|
|
|
print!(" {:02X}", b);
|
|
|
|
}
|
|
|
|
println!("");
|
|
|
|
print!("Flash {} I/O:", i);
|
2019-12-17 08:07:46 +08:00
|
|
|
for o in 0..8 {
|
|
|
|
const CHUNK: u32 = 8;
|
|
|
|
for b in flash_io.read(CHUNK * o, CHUNK as usize) {
|
2019-12-10 09:50:44 +08:00
|
|
|
print!(" {:02X}", b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
println!("");
|
2019-12-17 08:07:46 +08:00
|
|
|
|
|
|
|
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| {
|
2020-05-01 07:17:53 +08:00
|
|
|
flash_io.program(0, [0x23054223; 0x100 >> 2].iter().cloned());
|
2019-12-17 08:07:46 +08:00
|
|
|
});
|
|
|
|
|
2019-12-10 09:50:44 +08:00
|
|
|
flash = flash_io.stop();
|
|
|
|
}
|
2019-12-17 08:07:46 +08:00
|
|
|
|
2020-05-06 22:05:34 +08:00
|
|
|
let core1 = boot::Core1::start(false);
|
2019-12-17 08:07:46 +08:00
|
|
|
|
2020-04-13 07:24:37 +08:00
|
|
|
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);
|
2020-04-09 08:49:24 +08:00
|
|
|
}
|
2020-04-13 07:24:37 +08:00
|
|
|
});
|
2020-04-17 14:05:45 +08:00
|
|
|
core1.disable();
|
2019-12-17 08:07:46 +08:00
|
|
|
|
2019-10-22 04:19:03 +08:00
|
|
|
let eth = zynq::eth::Eth::default(HWADDR.clone());
|
2019-06-20 06:30:18 +08:00
|
|
|
println!("Eth on");
|
2019-05-08 01:28:33 +08:00
|
|
|
|
2020-06-22 08:06:11 +08:00
|
|
|
const RX_LEN: usize = 4096;
|
2019-09-29 07:39:57 +08:00
|
|
|
// Number of transmission buffers (minimum is two because with
|
|
|
|
// one, duplicate packet transmission occurs)
|
2020-06-22 08:06:11 +08:00
|
|
|
const TX_LEN: usize = 4096;
|
2020-06-11 05:20:43 +08:00
|
|
|
let eth = eth.start_rx(RX_LEN);
|
|
|
|
let mut eth = eth.start_tx(TX_LEN);
|
2020-05-01 07:17:53 +08:00
|
|
|
|
2019-07-05 06:44:53 +08:00
|
|
|
let ethernet_addr = EthernetAddress(HWADDR);
|
|
|
|
// IP stack
|
2019-11-13 23:02:56 +08:00
|
|
|
let local_addr = IpAddress::v4(192, 168, 1, 51);
|
2019-07-05 06:44:53 +08:00
|
|
|
let mut ip_addrs = [IpCidr::new(local_addr, 24)];
|
2020-05-01 07:17:53 +08:00
|
|
|
let routes = Routes::new(BTreeMap::new());
|
|
|
|
let neighbor_cache = NeighborCache::new(BTreeMap::new());
|
2019-07-05 06:44:53 +08:00
|
|
|
let mut iface = EthernetInterfaceBuilder::new(&mut eth)
|
|
|
|
.ethernet_addr(ethernet_addr)
|
|
|
|
.ip_addrs(&mut ip_addrs[..])
|
2020-03-31 07:16:58 +08:00
|
|
|
.routes(routes)
|
2019-07-05 06:44:53 +08:00
|
|
|
.neighbor_cache(neighbor_cache)
|
|
|
|
.finalize();
|
2020-03-31 07:16:58 +08:00
|
|
|
|
2020-06-05 12:23:43 +08:00
|
|
|
#[cfg(feature = "target_zc706")]
|
2020-05-01 07:17:53 +08:00
|
|
|
ps7_init::report_differences();
|
|
|
|
|
2020-03-31 07:16:58 +08:00
|
|
|
Sockets::init(32);
|
2019-12-17 08:07:46 +08:00
|
|
|
/// `chargen`
|
|
|
|
const TCP_PORT: u16 = 19;
|
2020-04-02 04:55:25 +08:00
|
|
|
async fn handle_connection(stream: TcpStream) -> smoltcp::Result<()> {
|
|
|
|
stream.send("Enter your name: ".bytes()).await?;
|
2020-06-05 11:48:41 +08:00
|
|
|
let name = stream
|
|
|
|
.recv(|buf| {
|
|
|
|
for (i, b) in buf.iter().enumerate() {
|
|
|
|
if *b == '\n' as u8 {
|
|
|
|
return match core::str::from_utf8(&buf[0..i]) {
|
|
|
|
Ok(name) => Poll::Ready((i + 1, Some(name.to_owned()))),
|
|
|
|
Err(_) => Poll::Ready((i + 1, None)),
|
|
|
|
};
|
|
|
|
}
|
2020-04-02 04:55:25 +08:00
|
|
|
}
|
2020-06-05 11:48:41 +08:00
|
|
|
if buf.len() > 100 {
|
|
|
|
// Too much input, consume all
|
|
|
|
Poll::Ready((buf.len(), None))
|
|
|
|
} else {
|
|
|
|
Poll::Pending
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.await?;
|
2020-04-01 04:34:32 +08:00
|
|
|
match name {
|
2020-06-05 11:48:41 +08:00
|
|
|
Some(name) => stream.send(format!("Hello {}!\n", name).bytes()).await?,
|
|
|
|
None => {
|
|
|
|
stream
|
|
|
|
.send("I had trouble reading your name.\n".bytes())
|
|
|
|
.await?
|
|
|
|
}
|
2020-04-01 04:34:32 +08:00
|
|
|
}
|
2020-06-11 02:21:01 +08:00
|
|
|
let _ = stream.close().await;
|
2020-04-01 04:34:32 +08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-06-22 08:06:11 +08:00
|
|
|
// (rx, tx)
|
|
|
|
let stats = alloc::rc::Rc::new(core::cell::RefCell::new((0, 0)));
|
|
|
|
let stats_tx = stats.clone();
|
2020-04-17 02:28:40 +08:00
|
|
|
task::spawn(async move {
|
2020-06-22 08:06:11 +08:00
|
|
|
while let Ok(stream) = TcpStream::accept(TCP_PORT, 0x10_0000, 0x10_0000).await {
|
|
|
|
let stats_tx = stats_tx.clone();
|
2020-04-17 02:28:40 +08:00
|
|
|
task::spawn(async move {
|
2020-06-22 08:06:11 +08:00
|
|
|
let tx_data = (0..=255).take(4096).collect::<alloc::vec::Vec<u8>>();
|
|
|
|
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| Poll::Ready((buf.len(), buf.len()))).await {
|
|
|
|
Ok(len) => stats_rx.borrow_mut().0 += len,
|
|
|
|
Err(e) => {
|
|
|
|
warn!("rx: {:?}", e);
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-04-17 02:28:40 +08:00
|
|
|
});
|
|
|
|
}
|
2020-03-31 07:16:58 +08:00
|
|
|
});
|
2019-12-17 08:07:46 +08:00
|
|
|
|
2020-04-25 07:18:49 +08:00
|
|
|
let mut countdown = timer.countdown();
|
|
|
|
task::spawn(async move {
|
|
|
|
loop {
|
|
|
|
delay(&mut countdown, Milliseconds(1000)).await;
|
2020-04-25 09:01:19 +08:00
|
|
|
|
|
|
|
let timestamp = timer.get_us();
|
2020-06-05 11:48:41 +08:00
|
|
|
let seconds = timestamp / 1_000_000;
|
|
|
|
let micros = timestamp % 1_000_000;
|
2020-06-22 08:06:11 +08:00
|
|
|
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);
|
2020-04-25 07:18:49 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-04-03 06:18:04 +08:00
|
|
|
Sockets::run(&mut iface, || {
|
2020-04-25 07:18:49 +08:00
|
|
|
Instant::from_millis(timer.get_time().0 as i64)
|
2020-04-17 02:42:21 +08:00
|
|
|
})
|
2019-05-28 06:28:35 +08:00
|
|
|
}
|
2019-05-31 02:30:19 +08:00
|
|
|
|
2020-04-13 07:24:37 +08:00
|
|
|
static CORE1_REQ: Mutex<Option<sync_channel::Receiver<usize>>> = Mutex::new(None);
|
|
|
|
static CORE1_RES: Mutex<Option<sync_channel::Sender<usize>>> = Mutex::new(None);
|
2019-12-17 08:07:46 +08:00
|
|
|
static DONE: Mutex<bool> = Mutex::new(false);
|
|
|
|
|
2019-12-18 07:06:10 +08:00
|
|
|
#[no_mangle]
|
2019-11-16 07:21:57 +08:00
|
|
|
pub fn main_core1() {
|
2019-11-21 00:00:57 +08:00
|
|
|
println!("Hello from core1!");
|
2020-04-09 08:49:24 +08:00
|
|
|
|
2020-04-13 07:24:37 +08:00
|
|
|
let mut req = None;
|
|
|
|
while req.is_none() {
|
|
|
|
req = CORE1_REQ.lock().take();
|
|
|
|
}
|
2020-05-01 07:17:53 +08:00
|
|
|
let req = req.unwrap();
|
2020-04-13 07:24:37 +08:00
|
|
|
let mut res = None;
|
|
|
|
while res.is_none() {
|
|
|
|
res = CORE1_RES.lock().take();
|
2020-04-09 08:49:24 +08:00
|
|
|
}
|
2020-04-13 07:24:37 +08:00
|
|
|
let mut res = res.unwrap();
|
2020-04-09 08:49:24 +08:00
|
|
|
|
2020-04-13 07:24:37 +08:00
|
|
|
for i in req {
|
|
|
|
res.send(*i * *i);
|
2019-12-17 08:07:46 +08:00
|
|
|
}
|
2020-04-09 08:49:24 +08:00
|
|
|
|
2019-12-17 08:07:46 +08:00
|
|
|
println!("core1 done!");
|
|
|
|
*DONE.lock() = true;
|
|
|
|
|
2019-11-16 07:21:57 +08:00
|
|
|
loop {}
|
|
|
|
}
|