drtio: implement get_rtio_destination_status for kernels

This commit is contained in:
Sebastien Bourdeauducq 2018-09-15 19:11:22 +08:00
parent f7ad7a99e3
commit c8cd830118
12 changed files with 110 additions and 72 deletions

View File

@ -44,11 +44,11 @@ def rtio_init() -> TNone:
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")
@syscall(flags={"nounwind", "nowrite"}) @syscall(flags={"nounwind", "nowrite"})
def rtio_get_counter() -> TInt64: def rtio_get_destination_status(linkno: TInt32) -> TBool:
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")
@syscall(flags={"nounwind", "nowrite"}) @syscall(flags={"nounwind", "nowrite"})
def drtio_get_link_status(linkno: TInt32) -> TBool: def rtio_get_counter() -> TInt64:
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")
@ -154,12 +154,12 @@ class Core:
return rtio_get_counter() return rtio_get_counter()
@kernel @kernel
def get_drtio_link_status(self, linkno): def get_rtio_destination_status(self, destination):
"""Returns whether the specified DRTIO link is up. """Returns whether the specified RTIO destination is up.
This is particularly useful in startup kernels to delay This is particularly useful in startup kernels to delay
startup until certain DRTIO links are up.""" startup until certain DRTIO destinations are up."""
return drtio_get_link_status(linkno) return rtio_get_destination_status(destination)
@kernel @kernel
def reset(self): def reset(self):

View File

@ -10,8 +10,8 @@ class Sines2Sayma(EnvExperiment):
def run(self): def run(self):
while True: while True:
print("waiting for DRTIO ready...") print("waiting for DRTIO ready...")
while not (self.core.get_drtio_link_status(0) and while not (self.core.get_rtio_destination_status(0) and
self.core.get_drtio_link_status(1)): self.core.get_rtio_destination_status(1)):
pass pass
print("OK") print("OK")
@ -27,5 +27,5 @@ class Sines2Sayma(EnvExperiment):
# Do not use a sub-multiple of oscilloscope sample rates. # Do not use a sub-multiple of oscilloscope sample rates.
sawg.frequency0.set(9*MHz) sawg.frequency0.set(9*MHz)
while self.core.get_drtio_link_status(0) and self.core.get_drtio_link_status(1): while self.core.get_rtio_destination_status(0) and self.core.get_rtio_destination_status(1):
pass pass

View File

@ -23,7 +23,7 @@ class SinesUrukulSayma(EnvExperiment):
while True: while True:
print("waiting for DRTIO ready...") print("waiting for DRTIO ready...")
while not self.core.get_drtio_link_status(0): while not self.core.get_rtio_destination_status(0):
pass pass
print("OK") print("OK")
@ -38,5 +38,5 @@ class SinesUrukulSayma(EnvExperiment):
sawg.amplitude1.set(.4) sawg.amplitude1.set(.4)
sawg.frequency0.set(9*MHz) sawg.frequency0.set(9*MHz)
while self.core.get_drtio_link_status(0): while self.core.get_rtio_destination_status(0):
pass pass

View File

@ -10,7 +10,7 @@ class SAWGTestDRTIO(EnvExperiment):
@kernel @kernel
def run(self): def run(self):
core_log("waiting for DRTIO ready...") core_log("waiting for DRTIO ready...")
while not self.core.get_drtio_link_status(0): while not self.core.get_rtio_destination_status(0):
pass pass
core_log("OK") core_log("OK")

View File

@ -95,6 +95,7 @@ static mut API: &'static [(&'static str, *const ())] = &[
/* direct syscalls */ /* direct syscalls */
api!(rtio_init = ::rtio::init), api!(rtio_init = ::rtio::init),
api!(rtio_get_destination_status = ::rtio::get_destination_status),
api!(rtio_get_counter = ::rtio::get_counter), api!(rtio_get_counter = ::rtio::get_counter),
api!(rtio_log), api!(rtio_log),
api!(rtio_output = ::rtio::output), api!(rtio_output = ::rtio::output),
@ -108,8 +109,6 @@ static mut API: &'static [(&'static str, *const ())] = &[
api!(dma_retrieve = ::dma_retrieve), api!(dma_retrieve = ::dma_retrieve),
api!(dma_playback = ::dma_playback), api!(dma_playback = ::dma_playback),
api!(drtio_get_link_status = ::rtio::drtio::get_link_status),
api!(i2c_start = ::nrt_bus::i2c::start), api!(i2c_start = ::nrt_bus::i2c::start),
api!(i2c_restart = ::nrt_bus::i2c::restart), api!(i2c_restart = ::nrt_bus::i2c::restart),
api!(i2c_stop = ::nrt_bus::i2c::stop), api!(i2c_stop = ::nrt_bus::i2c::stop),

View File

@ -5,6 +5,7 @@ mod imp {
use board_misoc::csr; use board_misoc::csr;
use ::send; use ::send;
use ::recv;
use kernel_proto::*; use kernel_proto::*;
pub const RTIO_O_STATUS_WAIT: u8 = 1; pub const RTIO_O_STATUS_WAIT: u8 = 1;
@ -19,6 +20,15 @@ mod imp {
send(&RtioInitRequest); send(&RtioInitRequest);
} }
pub extern fn get_destination_status(destination: i32) -> bool {
if 0 <= destination && destination <= 255 {
send(&RtioDestinationStatusRequest { destination: destination as u8 });
recv!(&RtioDestinationStatusReply { up } => up)
} else {
false
}
}
pub extern fn get_counter() -> i64 { pub extern fn get_counter() -> i64 {
unsafe { unsafe {
csr::rtio::counter_update_write(1); csr::rtio::counter_update_write(1);
@ -209,14 +219,3 @@ mod imp {
} }
pub use self::imp::*; pub use self::imp::*;
pub mod drtio {
use ::send;
use ::recv;
use kernel_proto::*;
pub extern fn get_link_status(linkno: i32) -> bool {
send(&DrtioLinkStatusRequest { linkno: linkno as u8 });
recv!(&DrtioLinkStatusReply { up } => up)
}
}

View File

@ -28,6 +28,9 @@ pub enum Message<'a> {
RtioInitRequest, RtioInitRequest,
RtioDestinationStatusRequest { destination: u8 },
RtioDestinationStatusReply { up: bool },
DmaRecordStart(&'a str), DmaRecordStart(&'a str),
DmaRecordAppend(&'a [u8]), DmaRecordAppend(&'a [u8]),
DmaRecordStop { DmaRecordStop {
@ -46,9 +49,6 @@ pub enum Message<'a> {
duration: u64 duration: u64
}, },
DrtioLinkStatusRequest { linkno: u8 },
DrtioLinkStatusReply { up: bool },
RunFinished, RunFinished,
RunException { RunException {
exception: Exception<'a>, exception: Exception<'a>,

View File

@ -1,7 +1,9 @@
use core::cell::RefCell;
use kernel_proto as kern; use kernel_proto as kern;
use sched::{Io, Error as SchedError}; use sched::{Io, Error as SchedError};
use session::{kern_acknowledge, kern_send, Error}; use session::{kern_acknowledge, kern_send, Error};
use rtio_mgt; use rtio_mgt;
use urc::Urc;
use board_artiq::drtio_routing; use board_artiq::drtio_routing;
use board_artiq::i2c as local_i2c; use board_artiq::i2c as local_i2c;
use board_artiq::spi as local_spi; use board_artiq::spi as local_spi;
@ -203,7 +205,9 @@ macro_rules! dispatch {
}} }}
} }
pub fn process_kern_hwreq(io: &Io, _routing_table: &drtio_routing::RoutingTable, pub fn process_kern_hwreq(io: &Io,
_routing_table: &drtio_routing::RoutingTable,
_up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
request: &kern::Message) -> Result<bool, Error<SchedError>> { request: &kern::Message) -> Result<bool, Error<SchedError>> {
match request { match request {
&kern::RtioInitRequest => { &kern::RtioInitRequest => {
@ -212,9 +216,15 @@ pub fn process_kern_hwreq(io: &Io, _routing_table: &drtio_routing::RoutingTable,
kern_acknowledge() kern_acknowledge()
} }
&kern::DrtioLinkStatusRequest { linkno } => { &kern::RtioDestinationStatusRequest { destination: _destination } => {
let up = rtio_mgt::drtio::link_up(linkno); #[cfg(has_drtio)]
kern_send(io, &kern::DrtioLinkStatusReply { up: up }) let up = {
let up_destinations = _up_destinations.borrow();
up_destinations[_destination as usize]
};
#[cfg(not(has_drtio))]
let up = true;
kern_send(io, &kern::RtioDestinationStatusReply { up: up })
} }
&kern::I2cStartRequest { busno } => { &kern::I2cStartRequest { busno } => {

View File

@ -287,16 +287,19 @@ fn startup_ethernet() {
#[cfg(not(has_drtio))] #[cfg(not(has_drtio))]
let drtio_routing_table = urc::Urc::new(RefCell::new( let drtio_routing_table = urc::Urc::new(RefCell::new(
drtio_routing::RoutingTable::default_empty())); drtio_routing::RoutingTable::default_empty()));
let up_destinations = urc::Urc::new(RefCell::new(
[false; drtio_routing::DEST_COUNT]));
let mut scheduler = sched::Scheduler::new(); let mut scheduler = sched::Scheduler::new();
let io = scheduler.io(); let io = scheduler.io();
rtio_mgt::startup(&io, &drtio_routing_table); rtio_mgt::startup(&io, &drtio_routing_table, &up_destinations);
io.spawn(4096, mgmt::thread); io.spawn(4096, mgmt::thread);
{ {
let drtio_routing_table = drtio_routing_table.clone(); let drtio_routing_table = drtio_routing_table.clone();
io.spawn(16384, move |io| { session::thread(io, &drtio_routing_table) }); let up_destinations = up_destinations.clone();
io.spawn(16384, move |io| { session::thread(io, &drtio_routing_table, &up_destinations) });
} }
#[cfg(any(has_rtio_moninj, has_drtio))] #[cfg(any(has_rtio_moninj, has_drtio))]
{ {

View File

@ -47,14 +47,16 @@ pub mod drtio {
use super::*; use super::*;
use drtioaux; use drtioaux;
pub fn startup(io: &Io, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>) { pub fn startup(io: &Io, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {
unsafe { unsafe {
csr::drtio_transceiver::stable_clkin_write(1); csr::drtio_transceiver::stable_clkin_write(1);
} }
let routing_table = routing_table.clone(); let routing_table = routing_table.clone();
let up_destinations = up_destinations.clone();
io.spawn(4096, move |io| { io.spawn(4096, move |io| {
let routing_table = routing_table.borrow(); let routing_table = routing_table.borrow();
link_thread(io, &routing_table) link_thread(io, &routing_table, &up_destinations);
}); });
} }
@ -206,31 +208,46 @@ pub mod drtio {
} }
} }
fn destination_set_up(routing_table: &drtio_routing::RoutingTable,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
destination: u8, up: bool) {
let mut up_destinations = up_destinations.borrow_mut();
up_destinations[destination as usize] = up;
if up {
drtio_routing::interconnect_enable(routing_table, 0, destination);
info!("[DEST#{}] destination is up", destination);
} else {
drtio_routing::interconnect_disable(destination);
info!("[DEST#{}] destination is down", destination);
}
}
fn destination_up(up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, destination: u8) -> bool {
let up_destinations = up_destinations.borrow();
up_destinations[destination as usize]
}
fn destination_survey(io: &Io, routing_table: &drtio_routing::RoutingTable, fn destination_survey(io: &Io, routing_table: &drtio_routing::RoutingTable,
up_destinations: &mut [bool; drtio_routing::DEST_COUNT]) { up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {
for destination in 0..drtio_routing::DEST_COUNT { for destination in 0..drtio_routing::DEST_COUNT {
let hop = routing_table.0[destination][0]; let hop = routing_table.0[destination][0];
let destination = destination as u8;
if hop == 0 { if hop == 0 {
/* local RTIO */ /* local RTIO */
if !up_destinations[destination] { if !destination_up(up_destinations, destination) {
info!("[DEST#{}] destination is up", destination); destination_set_up(routing_table, up_destinations, destination, true);
up_destinations[destination] = true;
drtio_routing::interconnect_enable(routing_table, 0, destination as u8);
} }
} else if hop as usize <= csr::DRTIO.len() { } else if hop as usize <= csr::DRTIO.len() {
let linkno = hop - 1; let linkno = hop - 1;
if up_destinations[destination] { if destination_up(up_destinations, destination) {
if link_up(linkno) { if link_up(linkno) {
drtioaux::send(linkno, &drtioaux::Packet::DestinationStatusRequest { drtioaux::send(linkno, &drtioaux::Packet::DestinationStatusRequest {
destination: destination as u8 destination: destination
}).unwrap(); }).unwrap();
match recv_aux_timeout(io, linkno, 200) { match recv_aux_timeout(io, linkno, 200) {
Ok(drtioaux::Packet::DestinationDownReply) => { Ok(drtioaux::Packet::DestinationDownReply) =>
info!("[DEST#{}] destination is down", destination); destination_set_up(routing_table, up_destinations, destination, false),
up_destinations[destination] = false;
drtio_routing::interconnect_disable(destination as u8);
},
Ok(drtioaux::Packet::DestinationOkReply) => (), Ok(drtioaux::Packet::DestinationOkReply) => (),
Ok(drtioaux::Packet::DestinationSequenceErrorReply { channel }) => Ok(drtioaux::Packet::DestinationSequenceErrorReply { channel }) =>
error!("[DEST#{}] RTIO sequence error involving channel 0x{:04x}", destination, channel), error!("[DEST#{}] RTIO sequence error involving channel 0x{:04x}", destination, channel),
@ -242,21 +259,17 @@ pub mod drtio {
Err(e) => error!("[DEST#{}] communication failed ({})", destination, e) Err(e) => error!("[DEST#{}] communication failed ({})", destination, e)
} }
} else { } else {
info!("[DEST#{}] destination is down", destination); destination_set_up(routing_table, up_destinations, destination, false);
up_destinations[destination] = false;
drtio_routing::interconnect_disable(destination as u8);
} }
} else { } else {
if link_up(linkno) { if link_up(linkno) {
drtioaux::send(linkno, &drtioaux::Packet::DestinationStatusRequest { drtioaux::send(linkno, &drtioaux::Packet::DestinationStatusRequest {
destination: destination as u8 destination: destination
}).unwrap(); }).unwrap();
match recv_aux_timeout(io, linkno, 200) { match recv_aux_timeout(io, linkno, 200) {
Ok(drtioaux::Packet::DestinationDownReply) => (), Ok(drtioaux::Packet::DestinationDownReply) => (),
Ok(drtioaux::Packet::DestinationOkReply) => { Ok(drtioaux::Packet::DestinationOkReply) => {
info!("[DEST#{}] destination is up", destination); destination_set_up(routing_table, up_destinations, destination, true);
up_destinations[destination] = true;
drtio_routing::interconnect_enable(routing_table, 0, destination as u8);
init_buffer_space(destination as u8, linkno); init_buffer_space(destination as u8, linkno);
}, },
Ok(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet), Ok(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet),
@ -268,8 +281,8 @@ pub mod drtio {
} }
} }
pub fn link_thread(io: Io, routing_table: &drtio_routing::RoutingTable) { pub fn link_thread(io: Io, routing_table: &drtio_routing::RoutingTable,
let mut up_destinations = [false; drtio_routing::DEST_COUNT]; up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {
loop { loop {
for linkno in 0..csr::DRTIO.len() { for linkno in 0..csr::DRTIO.len() {
let linkno = linkno as u8; let linkno = linkno as u8;
@ -306,7 +319,7 @@ pub mod drtio {
} }
} }
} }
destination_survey(&io, routing_table, &mut up_destinations); destination_survey(&io, routing_table, up_destinations);
io.sleep(200).unwrap(); io.sleep(200).unwrap();
} }
} }
@ -331,7 +344,8 @@ pub mod drtio {
pub mod drtio { pub mod drtio {
use super::*; use super::*;
pub fn startup(_io: &Io, _routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>) {} pub fn startup(_io: &Io, _routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>,
_up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {}
pub fn init() {} pub fn init() {}
pub fn link_up(_linkno: u8) -> bool { false } pub fn link_up(_linkno: u8) -> bool { false }
} }
@ -358,7 +372,8 @@ fn async_error_thread(io: Io) {
} }
} }
pub fn startup(io: &Io, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>) { pub fn startup(io: &Io, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {
#[cfg(has_rtio_crg)] #[cfg(has_rtio_crg)]
{ {
#[cfg(has_rtio_clock_switch)] #[cfg(has_rtio_clock_switch)]
@ -398,7 +413,7 @@ pub fn startup(io: &Io, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>
} }
} }
drtio::startup(io, &routing_table); drtio::startup(io, routing_table, up_destinations);
init_core(true); init_core(true);
io.spawn(4096, async_error_thread); io.spawn(4096, async_error_thread);
} }

View File

@ -324,7 +324,9 @@ fn process_host_message(io: &Io,
Ok(()) Ok(())
} }
fn process_kern_message(io: &Io, routing_table: &drtio_routing::RoutingTable, fn process_kern_message(io: &Io,
routing_table: &drtio_routing::RoutingTable,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
mut stream: Option<&mut TcpStream>, mut stream: Option<&mut TcpStream>,
session: &mut Session) -> Result<bool, Error<SchedError>> { session: &mut Session) -> Result<bool, Error<SchedError>> {
kern_recv_notrace(io, |request| { kern_recv_notrace(io, |request| {
@ -343,7 +345,7 @@ fn process_kern_message(io: &Io, routing_table: &drtio_routing::RoutingTable,
kern_recv_dotrace(request); kern_recv_dotrace(request);
if kern_hwreq::process_kern_hwreq(io, routing_table, request)? { if kern_hwreq::process_kern_hwreq(io, routing_table, up_destinations, request)? {
return Ok(false) return Ok(false)
} }
@ -492,7 +494,9 @@ fn process_kern_queued_rpc(stream: &mut TcpStream,
}) })
} }
fn host_kernel_worker(io: &Io, routing_table: &drtio_routing::RoutingTable, fn host_kernel_worker(io: &Io,
routing_table: &drtio_routing::RoutingTable,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
stream: &mut TcpStream, stream: &mut TcpStream,
congress: &mut Congress) -> Result<(), Error<SchedError>> { congress: &mut Congress) -> Result<(), Error<SchedError>> {
let mut session = Session::new(congress); let mut session = Session::new(congress);
@ -509,7 +513,9 @@ fn host_kernel_worker(io: &Io, routing_table: &drtio_routing::RoutingTable,
} }
if mailbox::receive() != 0 { if mailbox::receive() != 0 {
process_kern_message(io, routing_table, Some(stream), &mut session)?; process_kern_message(io,
routing_table, up_destinations,
Some(stream), &mut session)?;
} }
if session.kernel_state == KernelState::Running { if session.kernel_state == KernelState::Running {
@ -528,7 +534,9 @@ fn host_kernel_worker(io: &Io, routing_table: &drtio_routing::RoutingTable,
} }
} }
fn flash_kernel_worker(io: &Io, routing_table: &drtio_routing::RoutingTable, fn flash_kernel_worker(io: &Io,
routing_table: &drtio_routing::RoutingTable,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
congress: &mut Congress, congress: &mut Congress,
config_key: &str) -> Result<(), Error<SchedError>> { config_key: &str) -> Result<(), Error<SchedError>> {
let mut session = Session::new(congress); let mut session = Session::new(congress);
@ -551,7 +559,7 @@ fn flash_kernel_worker(io: &Io, routing_table: &drtio_routing::RoutingTable,
} }
if mailbox::receive() != 0 { if mailbox::receive() != 0 {
if process_kern_message(io, routing_table, None, &mut session)? { if process_kern_message(io, routing_table, up_destinations, None, &mut session)? {
return Ok(()) return Ok(())
} }
} }
@ -583,7 +591,8 @@ fn respawn<F>(io: &Io, handle: &mut Option<ThreadHandle>, f: F)
*handle = Some(io.spawn(16384, f)) *handle = Some(io.spawn(16384, f))
} }
pub fn thread(io: Io, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>) { pub fn thread(io: Io, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {
let listener = TcpListener::new(&io, 65535); let listener = TcpListener::new(&io, 65535);
listener.listen(1381).expect("session: cannot listen"); listener.listen(1381).expect("session: cannot listen");
info!("accepting network sessions"); info!("accepting network sessions");
@ -593,12 +602,13 @@ pub fn thread(io: Io, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>)
let mut kernel_thread = None; let mut kernel_thread = None;
{ {
let routing_table = routing_table.clone(); let routing_table = routing_table.clone();
let up_destinations = up_destinations.clone();
let congress = congress.clone(); let congress = congress.clone();
respawn(&io, &mut kernel_thread, move |io| { respawn(&io, &mut kernel_thread, move |io| {
let routing_table = routing_table.borrow(); let routing_table = routing_table.borrow();
let mut congress = congress.borrow_mut(); let mut congress = congress.borrow_mut();
info!("running startup kernel"); info!("running startup kernel");
match flash_kernel_worker(&io, &routing_table, &mut congress, "startup_kernel") { match flash_kernel_worker(&io, &routing_table, &up_destinations, &mut congress, "startup_kernel") {
Ok(()) => Ok(()) =>
info!("startup kernel finished"), info!("startup kernel finished"),
Err(Error::KernelNotFound) => Err(Error::KernelNotFound) =>
@ -628,13 +638,14 @@ pub fn thread(io: Io, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>)
info!("new connection from {}", stream.remote_endpoint()); info!("new connection from {}", stream.remote_endpoint());
let routing_table = routing_table.clone(); let routing_table = routing_table.clone();
let up_destinations = up_destinations.clone();
let congress = congress.clone(); let congress = congress.clone();
let stream = stream.into_handle(); let stream = stream.into_handle();
respawn(&io, &mut kernel_thread, move |io| { respawn(&io, &mut kernel_thread, move |io| {
let routing_table = routing_table.borrow(); let routing_table = routing_table.borrow();
let mut congress = congress.borrow_mut(); let mut congress = congress.borrow_mut();
let mut stream = TcpStream::from_handle(&io, stream); let mut stream = TcpStream::from_handle(&io, stream);
match host_kernel_worker(&io, &routing_table, &mut stream, &mut *congress) { match host_kernel_worker(&io, &routing_table, &up_destinations, &mut stream, &mut *congress) {
Ok(()) => (), Ok(()) => (),
Err(Error::Protocol(host::Error::Io(IoError::UnexpectedEnd))) => Err(Error::Protocol(host::Error::Io(IoError::UnexpectedEnd))) =>
info!("connection closed"), info!("connection closed"),
@ -653,11 +664,12 @@ pub fn thread(io: Io, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>)
info!("no connection, starting idle kernel"); info!("no connection, starting idle kernel");
let routing_table = routing_table.clone(); let routing_table = routing_table.clone();
let up_destinations = up_destinations.clone();
let congress = congress.clone(); let congress = congress.clone();
respawn(&io, &mut kernel_thread, move |io| { respawn(&io, &mut kernel_thread, move |io| {
let routing_table = routing_table.borrow(); let routing_table = routing_table.borrow();
let mut congress = congress.borrow_mut(); let mut congress = congress.borrow_mut();
match flash_kernel_worker(&io, &routing_table, &mut *congress, "idle_kernel") { match flash_kernel_worker(&io, &routing_table, &up_destinations, &mut *congress, "idle_kernel") {
Ok(()) => Ok(()) =>
info!("idle kernel finished, standing by"), info!("idle kernel finished, standing by"),
Err(Error::Protocol(host::Error::Io( Err(Error::Protocol(host::Error::Io(

View File

@ -190,7 +190,7 @@ To flash the idle kernel:
The startup kernel is executed once when the core device powers up. It should initialize DDSes, set up TTL directions, etc. Proceed as with the idle kernel, but using the ``startup_kernel`` key in the ``artiq_coremgmt`` command. The startup kernel is executed once when the core device powers up. It should initialize DDSes, set up TTL directions, etc. Proceed as with the idle kernel, but using the ``startup_kernel`` key in the ``artiq_coremgmt`` command.
For DRTIO systems, the startup kernel should wait until the desired links are up, using :meth:`artiq.coredevice.Core.get_drtio_link_status`. For DRTIO systems, the startup kernel should wait until the desired destinations (including local RTIO) are up, using :meth:`artiq.coredevice.Core.get_rtio_destination_status`.
* (optional) Select the RTIO clock source * (optional) Select the RTIO clock source