Compare commits
No commits in common. "d2f91eac2576999ff076165c6ed67f65e45ddb0a" and "5b95410244d809681d6c915f8d2c8aee99eccb6d" have entirely different histories.
d2f91eac25
...
5b95410244
|
@ -15,11 +15,6 @@ name = "byteorder"
|
||||||
version = "1.3.4"
|
version = "1.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfg-if"
|
|
||||||
version = "0.1.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "compiler_builtins"
|
name = "compiler_builtins"
|
||||||
version = "0.1.26"
|
version = "0.1.26"
|
||||||
|
@ -43,7 +38,6 @@ dependencies = [
|
||||||
"libboard_zynq 0.0.0",
|
"libboard_zynq 0.0.0",
|
||||||
"libcortex_a9 0.0.0",
|
"libcortex_a9 0.0.0",
|
||||||
"pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"smoltcp 0.6.0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -53,8 +47,7 @@ dependencies = [
|
||||||
"bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libcortex_a9 0.0.0",
|
"libcortex_a9 0.0.0",
|
||||||
"libregister 0.0.0",
|
"libregister 0.0.0",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"smoltcp 0.6.0",
|
|
||||||
"volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -92,14 +85,6 @@ name = "linked_list_allocator"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "log"
|
|
||||||
version = "0.4.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "managed"
|
name = "managed"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
|
@ -118,6 +103,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smoltcp"
|
name = "smoltcp"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -141,12 +127,11 @@ dependencies = [
|
||||||
"checksum bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a165d606cf084741d4ac3a28fb6e9b1eb0bd31f6cd999098cfddb0b2ab381dc0"
|
"checksum bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a165d606cf084741d4ac3a28fb6e9b1eb0bd31f6cd999098cfddb0b2ab381dc0"
|
||||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
|
||||||
"checksum compiler_builtins 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "036b035e9ebcd705affece16319223d19f229e2358be6e3b7b094e57193312e6"
|
"checksum compiler_builtins 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "036b035e9ebcd705affece16319223d19f229e2358be6e3b7b094e57193312e6"
|
||||||
"checksum linked_list_allocator 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5825aea823c659d0fdcdbe8c9b78baf56f3a10365d783db874f6d360df72626f"
|
"checksum linked_list_allocator 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5825aea823c659d0fdcdbe8c9b78baf56f3a10365d783db874f6d360df72626f"
|
||||||
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
|
||||||
"checksum managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcec5e97041c7f0f1c5b7d93f12e57293c831c646f4cc7a5db59460c7ea8de6"
|
"checksum managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcec5e97041c7f0f1c5b7d93f12e57293c831c646f4cc7a5db59460c7ea8de6"
|
||||||
"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
|
"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
|
||||||
"checksum r0 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
"checksum r0 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
||||||
|
"checksum smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0fe46639fd2ec79eadf8fe719f237a7a0bd4dac5d957f1ca5bbdbc1c3c39e53a"
|
||||||
"checksum vcell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c"
|
"checksum vcell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c"
|
||||||
"checksum volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286"
|
"checksum volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286"
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
extern crate alloc;
|
|
||||||
|
|
||||||
use core::mem::transmute;
|
use core::mem::transmute;
|
||||||
use alloc::collections::BTreeMap;
|
|
||||||
use libcortex_a9::mutex::Mutex;
|
use libcortex_a9::mutex::Mutex;
|
||||||
use libboard_zynq::{
|
use libboard_zynq::{
|
||||||
print, println,
|
print, println,
|
||||||
self as zynq, clocks::Clocks, clocks::source::{ClockSource, ArmPll, IoPll},
|
self as zynq, clocks::Clocks, clocks::source::{ClockSource, ArmPll, IoPll},
|
||||||
smoltcp::{
|
smoltcp::{
|
||||||
wire::{EthernetAddress, IpAddress, IpCidr},
|
wire::{EthernetAddress, IpAddress, IpCidr},
|
||||||
iface::{NeighborCache, EthernetInterfaceBuilder, Routes},
|
iface::{NeighborCache, EthernetInterfaceBuilder},
|
||||||
time::Instant,
|
time::Instant,
|
||||||
socket::SocketSet,
|
socket::SocketSet,
|
||||||
socket::{TcpSocket, TcpSocketBuffer},
|
socket::{TcpSocket, TcpSocketBuffer},
|
||||||
|
@ -21,7 +18,7 @@ use libsupport_zynq::{
|
||||||
ram, alloc::{vec, vec::Vec},
|
ram, alloc::{vec, vec::Vec},
|
||||||
boot,
|
boot,
|
||||||
};
|
};
|
||||||
use libasync::{smoltcp::{Sockets, TcpStream}, task};
|
use libasync::task;
|
||||||
|
|
||||||
const HWADDR: [u8; 6] = [0, 0x23, 0xde, 0xea, 0xbe, 0xef];
|
const HWADDR: [u8; 6] = [0, 0x23, 0xde, 0xea, 0xbe, 0xef];
|
||||||
|
|
||||||
|
@ -155,14 +152,14 @@ pub fn main_core0() {
|
||||||
let mut rx_descs = (0..RX_LEN)
|
let mut rx_descs = (0..RX_LEN)
|
||||||
.map(|_| zynq::eth::rx::DescEntry::zeroed())
|
.map(|_| zynq::eth::rx::DescEntry::zeroed())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let mut rx_buffers = vec![zynq::eth::Buffer::new(); RX_LEN];
|
let mut rx_buffers = vec![[0u8; zynq::eth::MTU]; RX_LEN];
|
||||||
// Number of transmission buffers (minimum is two because with
|
// Number of transmission buffers (minimum is two because with
|
||||||
// one, duplicate packet transmission occurs)
|
// one, duplicate packet transmission occurs)
|
||||||
const TX_LEN: usize = 8;
|
const TX_LEN: usize = 8;
|
||||||
let mut tx_descs = (0..TX_LEN)
|
let mut tx_descs = (0..TX_LEN)
|
||||||
.map(|_| zynq::eth::tx::DescEntry::zeroed())
|
.map(|_| zynq::eth::tx::DescEntry::zeroed())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let mut tx_buffers = vec![zynq::eth::Buffer::new(); TX_LEN];
|
let mut tx_buffers = vec![[0u8; zynq::eth::MTU]; TX_LEN];
|
||||||
let eth = eth.start_rx(&mut rx_descs, &mut rx_buffers);
|
let eth = eth.start_rx(&mut rx_descs, &mut rx_buffers);
|
||||||
//let mut eth = eth.start_tx(&mut tx_descs, &mut tx_buffers);
|
//let mut eth = eth.start_tx(&mut tx_descs, &mut tx_buffers);
|
||||||
let mut eth = eth.start_tx(
|
let mut eth = eth.start_tx(
|
||||||
|
@ -170,79 +167,63 @@ pub fn main_core0() {
|
||||||
unsafe { transmute(tx_descs.as_mut_slice()) },
|
unsafe { transmute(tx_descs.as_mut_slice()) },
|
||||||
unsafe { transmute(tx_buffers.as_mut_slice()) },
|
unsafe { transmute(tx_buffers.as_mut_slice()) },
|
||||||
);
|
);
|
||||||
// loop {
|
|
||||||
// match eth.recv_next() {
|
|
||||||
// Ok(None) => {},
|
|
||||||
// Ok(Some(pkt)) => println!("received {} bytes", pkt.len()),
|
|
||||||
// Err(e) => println!("e: {:?}", e),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
println!("iface...");
|
|
||||||
let ethernet_addr = EthernetAddress(HWADDR);
|
let ethernet_addr = EthernetAddress(HWADDR);
|
||||||
// IP stack
|
// IP stack
|
||||||
let local_addr = IpAddress::v4(192, 168, 1, 51);
|
let local_addr = IpAddress::v4(192, 168, 1, 51);
|
||||||
let mut ip_addrs = [IpCidr::new(local_addr, 24)];
|
let mut ip_addrs = [IpCidr::new(local_addr, 24)];
|
||||||
let mut routes_storage = vec![None; 4];
|
|
||||||
let routes = Routes::new(/*BTreeMap::new()*/ &mut routes_storage[..]);
|
|
||||||
let mut neighbor_storage = vec![None; 256];
|
let mut neighbor_storage = vec![None; 256];
|
||||||
let neighbor_cache = NeighborCache::new(&mut neighbor_storage[..]);
|
let neighbor_cache = NeighborCache::new(&mut neighbor_storage[..]);
|
||||||
let mut iface = EthernetInterfaceBuilder::new(&mut eth)
|
let mut iface = EthernetInterfaceBuilder::new(&mut eth)
|
||||||
.ethernet_addr(ethernet_addr)
|
.ethernet_addr(ethernet_addr)
|
||||||
.ip_addrs(&mut ip_addrs[..])
|
.ip_addrs(&mut ip_addrs[..])
|
||||||
.routes(routes)
|
|
||||||
.neighbor_cache(neighbor_cache)
|
.neighbor_cache(neighbor_cache)
|
||||||
.finalize();
|
.finalize();
|
||||||
|
let mut sockets_storage = [
|
||||||
|
None, None, None, None,
|
||||||
|
None, None, None, None
|
||||||
|
];
|
||||||
|
let mut sockets = SocketSet::new(&mut sockets_storage[..]);
|
||||||
|
|
||||||
// TODO: compare with ps7_init
|
// taken from example code for smoltcp
|
||||||
|
let mut tcp_server_rx_data = vec![0; 512 * 1024];
|
||||||
println!("Sockets init...");
|
let mut tcp_server_tx_data = vec![0; 512 * 1024];
|
||||||
Sockets::init(32);
|
let tcp_rx_buffer = TcpSocketBuffer::new(&mut tcp_server_rx_data[..]);
|
||||||
|
let tcp_tx_buffer = TcpSocketBuffer::new(&mut tcp_server_tx_data[..]);
|
||||||
|
let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
|
||||||
|
let tcp_handle = sockets.add(tcp_socket);
|
||||||
/// `chargen`
|
/// `chargen`
|
||||||
const TCP_PORT: u16 = 19;
|
const TCP_PORT: u16 = 19;
|
||||||
task::spawn(async {
|
|
||||||
println!("listening");
|
let mut time = 0u32;
|
||||||
while let socket = TcpStream::listen(TCP_PORT, 2048, 2048).await {
|
loop {
|
||||||
println!("got connection");
|
time += 1;
|
||||||
task::spawn(async {
|
let timestamp = Instant::from_millis(time);
|
||||||
println!("spawned for connection");
|
|
||||||
// while l
|
match iface.poll(&mut sockets, timestamp) {
|
||||||
drop(socket);
|
Ok(_) => {},
|
||||||
});
|
Err(e) => {
|
||||||
|
println!("poll error: {}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
println!("done?");
|
|
||||||
});
|
|
||||||
|
|
||||||
Sockets::run(&mut iface);
|
// (mostly) taken from smoltcp example: TCP echo server
|
||||||
// let mut time = 0u32;
|
let mut socket = sockets.get::<TcpSocket>(tcp_handle);
|
||||||
// loop {
|
if !socket.is_open() {
|
||||||
// time += 1;
|
socket.listen(TCP_PORT).unwrap()
|
||||||
// let timestamp = Instant::from_millis(time);
|
}
|
||||||
|
if socket.may_recv() && socket.can_send() {
|
||||||
|
socket.recv(|buf| {
|
||||||
|
let len = buf.len().min(4096);
|
||||||
|
let buffer = buf[..len].iter().cloned().collect::<Vec<_>>();
|
||||||
|
(len, buffer)
|
||||||
|
})
|
||||||
|
.and_then(|buffer| socket.send_slice(&buffer[..]))
|
||||||
|
.map(|_| {})
|
||||||
|
.unwrap_or_else(|e| println!("tcp: {:?}", e));
|
||||||
|
|
||||||
// match iface.poll(&mut sockets, timestamp) {
|
}
|
||||||
// Ok(_) => {},
|
}
|
||||||
// Err(e) => {
|
|
||||||
// println!("poll error: {}", e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // (mostly) taken from smoltcp example: TCP echo server
|
|
||||||
// let mut socket = sockets.get::<TcpSocket>(tcp_handle);
|
|
||||||
// if !socket.is_open() {
|
|
||||||
// socket.listen(TCP_PORT).unwrap()
|
|
||||||
// }
|
|
||||||
// if socket.may_recv() && socket.can_send() {
|
|
||||||
// socket.recv(|buf| {
|
|
||||||
// let len = buf.len().min(4096);
|
|
||||||
// let buffer = buf[..len].iter().cloned().collect::<Vec<_>>();
|
|
||||||
// (len, buffer)
|
|
||||||
// })
|
|
||||||
// .and_then(|buffer| socket.send_slice(&buffer[..]))
|
|
||||||
// .map(|_| {})
|
|
||||||
// .unwrap_or_else(|e| println!("tcp: {:?}", e));
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[allow(unreachable_code)]
|
// #[allow(unreachable_code)]
|
||||||
// drop(tx_descs);
|
// drop(tx_descs);
|
||||||
|
|
|
@ -11,8 +11,3 @@ pin-utils = "0.1.0-alpha.4"
|
||||||
libcortex_a9 = { path = "../libcortex_a9" }
|
libcortex_a9 = { path = "../libcortex_a9" }
|
||||||
# TODO: delete
|
# TODO: delete
|
||||||
libboard_zynq = { path = "../libboard_zynq" }
|
libboard_zynq = { path = "../libboard_zynq" }
|
||||||
|
|
||||||
[dependencies.smoltcp]
|
|
||||||
version = "0.6"
|
|
||||||
default-features = false
|
|
||||||
features = ["alloc"]
|
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
use core::{
|
use core::{
|
||||||
cell::{RefCell, UnsafeCell},
|
cell::{Cell, UnsafeCell},
|
||||||
future::Future,
|
future::Future,
|
||||||
mem::MaybeUninit,
|
mem::MaybeUninit,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{self, AtomicBool, Ordering},
|
||||||
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
|
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
|
||||||
};
|
};
|
||||||
use alloc::{boxed::Box, collections::VecDeque as Deque};
|
use alloc::{boxed::Box, collections::VecDeque as Deque};
|
||||||
//use futures::future::FutureExt;
|
//use futures::future::FutureExt;
|
||||||
use pin_utils::pin_mut;
|
use pin_utils::pin_mut;
|
||||||
|
use libcortex_a9::mutex::Mutex;
|
||||||
// TODO: delete
|
// TODO: delete
|
||||||
//use libboard_zynq::println;
|
use libboard_zynq::println;
|
||||||
|
|
||||||
// NOTE `*const ()` is &AtomicBool
|
// NOTE `*const ()` is &AtomicBool
|
||||||
static VTABLE: RawWakerVTable = {
|
static VTABLE: RawWakerVTable = {
|
||||||
|
@ -34,21 +35,16 @@ static VTABLE: RawWakerVTable = {
|
||||||
///
|
///
|
||||||
/// This is a singleton
|
/// This is a singleton
|
||||||
pub struct Executor {
|
pub struct Executor {
|
||||||
// Entered block_on() already?
|
in_block_on: Mutex<bool>,
|
||||||
in_block_on: RefCell<bool>,
|
tasks: Mutex<Deque<Task>>,
|
||||||
|
|
||||||
/// Tasks reside on the heap, so that we just queue pointers. They
|
|
||||||
/// must also be pinned in memory because our RawWaker is a pointer
|
|
||||||
/// to their `ready` field.
|
|
||||||
tasks: RefCell<Deque<Pin<Box<Task>>>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Executor {
|
impl Executor {
|
||||||
/// Creates a new instance of the executor
|
/// Creates a new instance of the executor
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
in_block_on: RefCell::new(false),
|
in_block_on: Mutex::new(false),
|
||||||
tasks: RefCell::new(Deque::new()),
|
tasks: Mutex::new(Deque::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +54,7 @@ impl Executor {
|
||||||
// application will only call `block_on` once on an infinite task
|
// application will only call `block_on` once on an infinite task
|
||||||
// (`Future<Output = !>`)
|
// (`Future<Output = !>`)
|
||||||
{
|
{
|
||||||
let mut in_block_on = self.in_block_on.borrow_mut();
|
let mut in_block_on = self.in_block_on.lock();
|
||||||
if *in_block_on {
|
if *in_block_on {
|
||||||
panic!("nested `block_on`");
|
panic!("nested `block_on`");
|
||||||
}
|
}
|
||||||
|
@ -74,17 +70,14 @@ impl Executor {
|
||||||
if ready.load(Ordering::Relaxed) {
|
if ready.load(Ordering::Relaxed) {
|
||||||
ready.store(false, Ordering::Relaxed);
|
ready.store(false, Ordering::Relaxed);
|
||||||
|
|
||||||
// println!("run block_on");
|
|
||||||
let mut cx = Context::from_waker(&waker);
|
let mut cx = Context::from_waker(&waker);
|
||||||
if let Poll::Ready(val) = f.as_mut().poll(&mut cx) {
|
if let Poll::Ready(val) = f.as_mut().poll(&mut cx) {
|
||||||
break val;
|
break val;
|
||||||
}
|
}
|
||||||
// println!("ran block_on");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// println!("tasks: {}", self.tasks.borrow().len());
|
|
||||||
// advance other tasks
|
// advance other tasks
|
||||||
let next_task = self.tasks.borrow_mut().pop_front();
|
let next_task = self.tasks.lock().pop_front();
|
||||||
if let Some(mut task) = next_task {
|
if let Some(mut task) = next_task {
|
||||||
// NOTE we don't need a CAS operation here because `wake` invocations that come from
|
// NOTE we don't need a CAS operation here because `wake` invocations that come from
|
||||||
// interrupt handlers (the only source of 'race conditions' (!= data races)) are
|
// interrupt handlers (the only source of 'race conditions' (!= data races)) are
|
||||||
|
@ -101,41 +94,46 @@ impl Executor {
|
||||||
};
|
};
|
||||||
let mut cx = Context::from_waker(&waker);
|
let mut cx = Context::from_waker(&waker);
|
||||||
// this points into a `static` memory so it's already pinned
|
// this points into a `static` memory so it's already pinned
|
||||||
// println!("run task");
|
let r = unsafe {
|
||||||
let ready = task.f.as_mut().poll(&mut cx).is_ready();
|
Pin::new_unchecked(&mut *task.f)
|
||||||
if ready {
|
.poll(&mut cx)
|
||||||
// Task is finished, do not requeue
|
.is_ready()
|
||||||
continue;
|
};
|
||||||
|
if !r {
|
||||||
|
// Task is not finished, requeue
|
||||||
|
self.tasks.lock().push_back(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Requeue
|
|
||||||
self.tasks.borrow_mut().push_back(task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// // try to sleep; this will be a no-op if any of the previous tasks generated a SEV or an
|
// // try to sleep; this will be a no-op if any of the previous tasks generated a SEV or an
|
||||||
// // interrupt ran (regardless of whether it generated a wake-up or not)
|
// // interrupt ran (regardless of whether it generated a wake-up or not)
|
||||||
// asm::wfe();
|
// asm::wfe();
|
||||||
};
|
};
|
||||||
self.in_block_on.replace(false);
|
*self.in_block_on.lock() = false;
|
||||||
val
|
val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE CAREFUL! this method can overlap with `block_on`
|
||||||
|
// FIXME we want to use `Future<Output = !>` here but the never type (`!`) is unstable; so as a
|
||||||
|
// workaround we'll "abort" if the task / future terminates (see `Task::new`)
|
||||||
pub fn spawn(&self, f: impl Future + 'static) {
|
pub fn spawn(&self, f: impl Future + 'static) {
|
||||||
let task = Box::pin(Task::new(f));
|
// NOTE(unsafe) only safe as long as `spawn` is never re-entered and this does not overlap
|
||||||
self.tasks.borrow_mut().push_back(task);
|
// with operation `(A)` (see `Task::block_on`)
|
||||||
|
self.tasks.lock().push_back(Task::new(f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Task {
|
pub struct Task {
|
||||||
ready: AtomicBool,
|
ready: AtomicBool,
|
||||||
f: Pin<Box<dyn Future<Output = ()>>>,
|
f: Box<Future<Output = ()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Task {
|
impl Task {
|
||||||
fn new(f: impl Future + 'static) -> Self {
|
fn new(f: impl Future + 'static) -> Self {
|
||||||
Task {
|
Task {
|
||||||
ready: AtomicBool::new(true),
|
ready: AtomicBool::new(true),
|
||||||
f: Box::pin(async { f.await; }),
|
f: Box::new(async { f.await; }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,5 +4,3 @@ extern crate alloc;
|
||||||
|
|
||||||
pub mod task;
|
pub mod task;
|
||||||
pub mod executor;
|
pub mod executor;
|
||||||
|
|
||||||
pub mod smoltcp;
|
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
use core::{
|
|
||||||
cell::RefCell,
|
|
||||||
task::Waker,
|
|
||||||
};
|
|
||||||
use alloc::{vec, vec::Vec};
|
|
||||||
use smoltcp::{
|
|
||||||
iface::EthernetInterface,
|
|
||||||
phy::Device,
|
|
||||||
socket::{
|
|
||||||
SocketSet, SocketHandle,
|
|
||||||
TcpSocketBuffer, TcpSocket,
|
|
||||||
},
|
|
||||||
time::Instant,
|
|
||||||
};
|
|
||||||
use libboard_zynq::println;
|
|
||||||
use crate::task;
|
|
||||||
|
|
||||||
mod tcp_stream;
|
|
||||||
pub use tcp_stream::TcpStream;
|
|
||||||
|
|
||||||
static mut SOCKETS: Option<Sockets> = None;
|
|
||||||
|
|
||||||
pub struct Sockets {
|
|
||||||
sockets: RefCell<SocketSet<'static, 'static, 'static>>,
|
|
||||||
wakers: RefCell<Vec<Waker>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Sockets {
|
|
||||||
pub fn init(max_sockets: usize) {
|
|
||||||
println!("initializing {} sockets", max_sockets);
|
|
||||||
let mut sockets_storage = Vec::with_capacity(max_sockets);
|
|
||||||
for _ in 0..max_sockets {
|
|
||||||
sockets_storage.push(None);
|
|
||||||
}
|
|
||||||
let sockets = RefCell::new(SocketSet::new(sockets_storage));
|
|
||||||
|
|
||||||
let wakers = RefCell::new(Vec::new());
|
|
||||||
|
|
||||||
let instance = Sockets {
|
|
||||||
sockets,
|
|
||||||
wakers,
|
|
||||||
};
|
|
||||||
println!("sockets initialized");
|
|
||||||
unsafe { SOCKETS = Some(instance); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Block and run executor indefinitely while polling the smoltcp
|
|
||||||
/// iface
|
|
||||||
pub fn run<'b, 'c, 'e, D: for<'d> Device<'d>>(iface: &mut EthernetInterface<'b, 'c, 'e, D>) {
|
|
||||||
task::block_on(async {
|
|
||||||
loop {
|
|
||||||
Self::instance().poll(iface);
|
|
||||||
task::r#yield().await;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn instance() -> &'static Self {
|
|
||||||
unsafe { SOCKETS.as_ref().expect("Sockets") }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn poll<'b, 'c, 'e, D: for<'d> Device<'d>>(&self, iface: &mut EthernetInterface<'b, 'c, 'e, D>) {
|
|
||||||
// TODO:
|
|
||||||
let instant = Instant::from_millis(0);
|
|
||||||
let processed = {
|
|
||||||
let mut sockets = self.sockets.borrow_mut();
|
|
||||||
let r = iface.poll(&mut sockets, instant);
|
|
||||||
if r != Ok(false) { println!("poll: {:?}", r); }
|
|
||||||
match r {
|
|
||||||
Ok(processed) => processed,
|
|
||||||
Err(_) => true,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if processed {
|
|
||||||
let mut wakers = self.wakers.borrow_mut();
|
|
||||||
println!("wakeup of {}", wakers.len());
|
|
||||||
for waker in wakers.drain(..) {
|
|
||||||
waker.wake();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// TODO: this was called through eg. TcpStream, another poll()
|
|
||||||
/// might want to send packets before sleeping for an interrupt.
|
|
||||||
pub(crate) fn register_waker(waker: Waker) {
|
|
||||||
println!("register_waker");
|
|
||||||
Self::instance().wakers.borrow_mut()
|
|
||||||
.push(waker);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
use core::{
|
|
||||||
cell::{RefCell, UnsafeCell},
|
|
||||||
future::Future,
|
|
||||||
mem::MaybeUninit,
|
|
||||||
pin::Pin,
|
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
|
||||||
task::{Context, Poll},
|
|
||||||
};
|
|
||||||
use alloc::vec;
|
|
||||||
use smoltcp::{
|
|
||||||
iface::EthernetInterface,
|
|
||||||
phy::Device,
|
|
||||||
socket::{
|
|
||||||
SocketSet, SocketHandle, SocketRef,
|
|
||||||
TcpSocketBuffer, TcpSocket,
|
|
||||||
},
|
|
||||||
time::Instant,
|
|
||||||
};
|
|
||||||
use libboard_zynq::println;
|
|
||||||
use super::Sockets;
|
|
||||||
|
|
||||||
pub struct TcpStream {
|
|
||||||
handle: SocketHandle,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TcpStream {
|
|
||||||
fn new(rx_bufsize: usize, tx_bufsize: usize) -> Self {
|
|
||||||
let rx_buffer = TcpSocketBuffer::new(vec![0u8; rx_bufsize]);
|
|
||||||
let tx_buffer = TcpSocketBuffer::new(vec![0u8; tx_bufsize]);
|
|
||||||
let socket = TcpSocket::new(rx_buffer, tx_buffer);
|
|
||||||
let handle = Sockets::instance().sockets.borrow_mut()
|
|
||||||
.add(socket);
|
|
||||||
TcpStream { handle }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_socket<F, R>(&self, f: F) -> R
|
|
||||||
where
|
|
||||||
F: FnOnce(SocketRef<TcpSocket>) -> R,
|
|
||||||
{
|
|
||||||
println!("with_socket");
|
|
||||||
let mut sockets = Sockets::instance().sockets.borrow_mut();
|
|
||||||
let socket_ref = sockets.get::<TcpSocket>(self.handle);
|
|
||||||
f(socket_ref)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn listen(port: u16, rx_bufsize: usize, tx_bufsize: usize) -> Self {
|
|
||||||
struct Accept {
|
|
||||||
stream: Option<TcpStream>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Future for Accept {
|
|
||||||
type Output = TcpStream;
|
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
||||||
let is_active = self.stream.as_ref()
|
|
||||||
.map(|s| s.with_socket(|s| s.is_active()))
|
|
||||||
.unwrap_or(true);
|
|
||||||
println!("is_active={:?}", is_active);
|
|
||||||
if is_active {
|
|
||||||
Poll::Ready(self.stream.take().unwrap())
|
|
||||||
} else {
|
|
||||||
println!("register_waker");
|
|
||||||
Sockets::register_waker(cx.waker().clone());
|
|
||||||
|
|
||||||
//asm::sev();
|
|
||||||
Poll::Pending
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let stream = Self::new(rx_bufsize, tx_bufsize);
|
|
||||||
stream.with_socket(|mut s| s.listen(port)).expect("listen");
|
|
||||||
println!("listening on {}", port);
|
|
||||||
Accept {
|
|
||||||
stream: Some(stream),
|
|
||||||
}.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn recv(&self) {
|
|
||||||
// self.socket();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for TcpStream {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
// TODO: verify
|
|
||||||
println!("tcpstream drop");
|
|
||||||
Sockets::instance().sockets.borrow_mut()
|
|
||||||
.remove(self.handle);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,7 +17,10 @@ pub fn block_on<T>(f: impl Future<Output = T>) -> T {
|
||||||
/// Spawns a task onto the executor
|
/// Spawns a task onto the executor
|
||||||
///
|
///
|
||||||
/// The spawned task will not make any progress until `block_on` is called.
|
/// The spawned task will not make any progress until `block_on` is called.
|
||||||
pub fn spawn(f: impl Future + 'static) {
|
///
|
||||||
|
/// The future `f` must never terminate. The program will *abort* if `f` (the async code) returns.
|
||||||
|
/// The right signature here would be `f: impl Future<Output = !>` but that requires nightly
|
||||||
|
pub fn spawn<T>(f: impl Future<Output = T> + 'static) {
|
||||||
executor::current().spawn(f)
|
executor::current().spawn(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ impl DdrRam {
|
||||||
fn calibrate_iob_impedance(clocks: &Clocks) {
|
fn calibrate_iob_impedance(clocks: &Clocks) {
|
||||||
let divisor0 = ((DCI_FREQ - 1 + clocks.ddr) / DCI_FREQ)
|
let divisor0 = ((DCI_FREQ - 1 + clocks.ddr) / DCI_FREQ)
|
||||||
.max(1).min(63) as u8;
|
.max(1).min(63) as u8;
|
||||||
let divisor1 = ((DCI_FREQ - 1 + clocks.ddr) / DCI_FREQ / u32::from(divisor0))
|
let divisor1 = (clocks.ddr / DCI_FREQ / u32::from(divisor0))
|
||||||
.max(1).min(63) as u8;
|
.max(1).min(63) as u8;
|
||||||
println!("DDR DCI clock: {} Hz", clocks.ddr / u32::from(divisor0) / u32::from(divisor1));
|
println!("DDR DCI clock: {} Hz", clocks.ddr / u32::from(divisor0) / u32::from(divisor1));
|
||||||
|
|
||||||
|
@ -111,46 +111,21 @@ impl DdrRam {
|
||||||
slcr.ddriob_addr0.write(addr_config.clone());
|
slcr.ddriob_addr0.write(addr_config.clone());
|
||||||
slcr.ddriob_addr1.write(addr_config);
|
slcr.ddriob_addr1.write(addr_config);
|
||||||
|
|
||||||
#[cfg(feature = "target_zc706")]
|
let data_config = slcr::DdriobConfig::zeroed()
|
||||||
let data0_config = slcr::DdriobConfig::zeroed()
|
|
||||||
.inp_type(slcr::DdriobInputType::VrefDifferential)
|
.inp_type(slcr::DdriobInputType::VrefDifferential)
|
||||||
.term_en(true)
|
.term_en(true)
|
||||||
.dci_type(slcr::DdriobDciType::Termination)
|
.dci_type(slcr::DdriobDciType::Termination)
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||||
#[cfg(feature = "target_zc706")]
|
slcr.ddriob_data0.write(data_config.clone());
|
||||||
let data1_config = data0_config.clone();
|
slcr.ddriob_data1.write(data_config);
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
|
||||||
let data0_config = slcr::DdriobConfig::zeroed()
|
|
||||||
.inp_type(slcr::DdriobInputType::VrefDifferential)
|
|
||||||
.term_en(true)
|
|
||||||
.dci_type(slcr::DdriobDciType::Termination)
|
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
|
||||||
let data1_config = slcr::DdriobConfig::zeroed()
|
|
||||||
.pullup_en(true);
|
|
||||||
slcr.ddriob_data0.write(data0_config);
|
|
||||||
slcr.ddriob_data1.write(data1_config);
|
|
||||||
|
|
||||||
#[cfg(feature = "target_zc706")]
|
let diff_config = slcr::DdriobConfig::zeroed()
|
||||||
let diff0_config = slcr::DdriobConfig::zeroed()
|
|
||||||
.inp_type(slcr::DdriobInputType::Differential)
|
.inp_type(slcr::DdriobInputType::Differential)
|
||||||
.term_en(true)
|
.term_en(true)
|
||||||
.dci_type(slcr::DdriobDciType::Termination)
|
.dci_type(slcr::DdriobDciType::Termination)
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||||
#[cfg(feature = "target_zc706")]
|
slcr.ddriob_diff0.write(diff_config.clone());
|
||||||
let diff1_config = diff0_config.clone();
|
slcr.ddriob_diff1.write(diff_config);
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
|
||||||
let diff0_config = slcr::DdriobConfig::zeroed()
|
|
||||||
.inp_type(slcr::DdriobInputType::Differential)
|
|
||||||
.term_en(true)
|
|
||||||
.dci_type(slcr::DdriobDciType::Termination)
|
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
|
||||||
let diff1_config = slcr::DdriobConfig::zeroed()
|
|
||||||
.pullup_en(true);
|
|
||||||
|
|
||||||
slcr.ddriob_diff0.write(diff0_config);
|
|
||||||
slcr.ddriob_diff1.write(diff1_config);
|
|
||||||
|
|
||||||
slcr.ddriob_clock.write(
|
slcr.ddriob_clock.write(
|
||||||
slcr::DdriobConfig::zeroed()
|
slcr::DdriobConfig::zeroed()
|
||||||
|
@ -165,17 +140,24 @@ impl DdrRam {
|
||||||
slcr.ddriob_drive_slew_clock.write(0x00F9861C);
|
slcr.ddriob_drive_slew_clock.write(0x00F9861C);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable external V[REF]
|
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
|
||||||
slcr.ddriob_ddr_ctrl.modify(|_, w| w
|
|
||||||
.vref_int_en(false)
|
|
||||||
.vref_ext_en_lower(true)
|
|
||||||
.vref_ext_en_upper(false)
|
|
||||||
);
|
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
|
let vref_sel = slcr::DdriobVrefSel::Vref0_75V;
|
||||||
|
#[cfg(feature = "target_cora_z7_10")]
|
||||||
|
let vref_sel = slcr::DdriobVrefSel::Vref0_675V;
|
||||||
|
|
||||||
|
// // Enable internal V[REF]
|
||||||
|
// slcr.ddriob_ddr_ctrl.modify(|_, w| w
|
||||||
|
// .vref_ext_en_lower(false)
|
||||||
|
// .vref_ext_en_upper(false)
|
||||||
|
// .vref_sel(vref_sel)
|
||||||
|
// .vref_int_en(true)
|
||||||
|
// );
|
||||||
|
// Enable external V[REF]
|
||||||
slcr.ddriob_ddr_ctrl.modify(|_, w| w
|
slcr.ddriob_ddr_ctrl.modify(|_, w| w
|
||||||
.vref_ext_en_lower(true)
|
.vref_ext_en_lower(true)
|
||||||
.vref_ext_en_upper(true)
|
.vref_ext_en_upper(true)
|
||||||
|
.vref_sel(vref_sel)
|
||||||
|
.vref_int_en(false)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use core::ops::{Deref, DerefMut};
|
|
||||||
use libregister::*;
|
use libregister::*;
|
||||||
use crate::println;
|
use crate::println;
|
||||||
use super::slcr;
|
use super::slcr;
|
||||||
|
@ -19,29 +18,6 @@ const TX_100: u32 = 25_000_000;
|
||||||
/// Clock for GbE
|
/// Clock for GbE
|
||||||
const TX_1000: u32 = 125_000_000;
|
const TX_1000: u32 = 125_000_000;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
#[repr(C, align(0x08))]
|
|
||||||
pub struct Buffer(pub [u8; MTU]);
|
|
||||||
|
|
||||||
impl Buffer {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Buffer([0; MTU])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for Buffer {
|
|
||||||
type Target = [u8];
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerefMut for Buffer {
|
|
||||||
fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Eth<'r, RX, TX> {
|
pub struct Eth<'r, RX, TX> {
|
||||||
rx: RX,
|
rx: RX,
|
||||||
tx: TX,
|
tx: TX,
|
||||||
|
@ -263,7 +239,7 @@ impl<'r, RX, TX> Eth<'r, RX, TX> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_rx<'rx>(self, rx_list: &'rx mut [rx::DescEntry], rx_buffers: &'rx mut [Buffer]) -> Eth<'r, rx::DescList<'rx>, TX> {
|
pub fn start_rx<'rx>(self, rx_list: &'rx mut [rx::DescEntry], rx_buffers: &'rx mut [[u8; MTU]]) -> Eth<'r, rx::DescList<'rx>, TX> {
|
||||||
let new_self = Eth {
|
let new_self = Eth {
|
||||||
rx: rx::DescList::new(rx_list, rx_buffers),
|
rx: rx::DescList::new(rx_list, rx_buffers),
|
||||||
tx: self.tx,
|
tx: self.tx,
|
||||||
|
@ -282,7 +258,7 @@ impl<'r, RX, TX> Eth<'r, RX, TX> {
|
||||||
new_self
|
new_self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_tx<'tx>(self, tx_list: &'tx mut [tx::DescEntry], tx_buffers: &'tx mut [Buffer]) -> Eth<'r, RX, tx::DescList<'tx>> {
|
pub fn start_tx<'tx>(self, tx_list: &'tx mut [tx::DescEntry], tx_buffers: &'tx mut [[u8; MTU]]) -> Eth<'r, RX, tx::DescList<'tx>> {
|
||||||
let new_self = Eth {
|
let new_self = Eth {
|
||||||
rx: self.rx,
|
rx: self.rx,
|
||||||
tx: tx::DescList::new(tx_list, tx_buffers),
|
tx: tx::DescList::new(tx_list, tx_buffers),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use libregister::*;
|
use libregister::*;
|
||||||
use super::Buffer;
|
use super::MTU;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -55,16 +55,16 @@ register_bit!(desc_word1, global_broadcast, 31);
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct DescList<'a> {
|
pub struct DescList<'a> {
|
||||||
list: &'a mut [DescEntry],
|
list: &'a mut [DescEntry],
|
||||||
buffers: &'a mut [Buffer],
|
buffers: &'a mut [[u8; MTU]],
|
||||||
next: usize,
|
next: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DescList<'a> {
|
impl<'a> DescList<'a> {
|
||||||
pub fn new(list: &'a mut [DescEntry], buffers: &'a mut [Buffer]) -> Self {
|
pub fn new(list: &'a mut [DescEntry], buffers: &'a mut [[u8; MTU]]) -> Self {
|
||||||
let last = list.len().min(buffers.len()) - 1;
|
let last = list.len().min(buffers.len()) - 1;
|
||||||
for (i, (entry, buffer)) in list.iter_mut().zip(buffers.iter_mut()).enumerate() {
|
for (i, (entry, buffer)) in list.iter_mut().zip(buffers.iter_mut()).enumerate() {
|
||||||
let is_last = i == last;
|
let is_last = i == last;
|
||||||
let buffer_addr = &mut buffer.0[0] as *mut _ as u32;
|
let buffer_addr = &mut buffer[0] as *mut _ as u32;
|
||||||
assert!(buffer_addr & 0b11 == 0);
|
assert!(buffer_addr & 0b11 == 0);
|
||||||
entry.word0.write(
|
entry.word0.write(
|
||||||
DescWord0::zeroed()
|
DescWord0::zeroed()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use core::ops::{Deref, DerefMut};
|
use core::ops::{Deref, DerefMut};
|
||||||
use libregister::*;
|
use libregister::*;
|
||||||
use super::{Buffer, regs};
|
use super::{MTU, regs};
|
||||||
|
|
||||||
/// Descriptor entry
|
/// Descriptor entry
|
||||||
#[repr(C, align(0x08))]
|
#[repr(C, align(0x08))]
|
||||||
|
@ -42,12 +42,12 @@ pub const DESCS: usize = 8;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct DescList<'a> {
|
pub struct DescList<'a> {
|
||||||
list: &'a mut [DescEntry],
|
list: &'a mut [DescEntry],
|
||||||
buffers: &'a mut [Buffer],
|
buffers: &'a mut [[u8; MTU]],
|
||||||
next: usize,
|
next: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DescList<'a> {
|
impl<'a> DescList<'a> {
|
||||||
pub fn new(list: &'a mut [DescEntry], buffers: &'a mut [Buffer]) -> Self {
|
pub fn new(list: &'a mut [DescEntry], buffers: &'a mut [[u8; MTU]]) -> Self {
|
||||||
let last = list.len().min(buffers.len()) - 1;
|
let last = list.len().min(buffers.len()) - 1;
|
||||||
// Sending seems to not work properly with only one packet
|
// Sending seems to not work properly with only one packet
|
||||||
// buffer (two duplicates get send with every packet), so
|
// buffer (two duplicates get send with every packet), so
|
||||||
|
@ -57,7 +57,7 @@ impl<'a> DescList<'a> {
|
||||||
|
|
||||||
for (i, (entry, buffer)) in list.iter_mut().zip(buffers.iter_mut()).enumerate() {
|
for (i, (entry, buffer)) in list.iter_mut().zip(buffers.iter_mut()).enumerate() {
|
||||||
let is_last = i == last;
|
let is_last = i == last;
|
||||||
let buffer_addr = &mut buffer.0[0] as *mut _ as u32;
|
let buffer_addr = &mut buffer[0] as *mut _ as u32;
|
||||||
assert!(buffer_addr & 0b11 == 0);
|
assert!(buffer_addr & 0b11 == 0);
|
||||||
entry.word0.write(
|
entry.word0.write(
|
||||||
DescWord0::zeroed()
|
DescWord0::zeroed()
|
||||||
|
|
|
@ -137,7 +137,7 @@ impl L1Table {
|
||||||
domain: 0b1111,
|
domain: 0b1111,
|
||||||
exec: true,
|
exec: true,
|
||||||
cacheable: true,
|
cacheable: true,
|
||||||
bufferable: false,
|
bufferable: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/* (unassigned/reserved). */
|
/* (unassigned/reserved). */
|
||||||
|
|
Loading…
Reference in New Issue