forked from M-Labs/artiq
1
0
Fork 0

drtio: add kernel API to check for link status. Closes #941

This commit is contained in:
Sebastien Bourdeauducq 2018-03-05 00:23:55 +08:00
parent 6aaa8bf9d9
commit 432e61bbb4
7 changed files with 39 additions and 4 deletions

View File

@ -47,6 +47,10 @@ def rtio_init() -> TNone:
def rtio_get_counter() -> TInt64: def rtio_get_counter() -> TInt64:
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")
@syscall(flags={"nounwind", "nowrite"})
def drtio_get_link_status(linkno: TInt32) -> TBool:
raise NotImplementedError("syscall not simulated")
class Core: class Core:
"""Core device driver. """Core device driver.
@ -155,6 +159,14 @@ class Core:
def get_rtio_counter_mu(self): def get_rtio_counter_mu(self):
return rtio_get_counter() return rtio_get_counter()
@kernel
def get_drtio_link_status(self, linkno):
"""Returns whether the specified DRTIO link is up.
This is particularly useful in startup kernels to delay
startup until certain DRTIO links are up."""
return drtio_get_link_status(linkno)
@kernel @kernel
def reset(self): def reset(self):
"""Clear RTIO FIFOs, release RTIO PHY reset, and set the time cursor """Clear RTIO FIFOs, release RTIO PHY reset, and set the time cursor

View File

@ -108,8 +108,9 @@ 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_packet_counts = ::rtio::drtio_dbg::get_packet_counts), api!(drtio_get_link_status = ::rtio::drtio::get_link_status),
api!(drtio_get_buffer_space_req_count = ::rtio::drtio_dbg::get_buffer_space_req_count), api!(drtio_get_packet_counts = ::rtio::drtio::get_packet_counts),
api!(drtio_get_buffer_space_req_count = ::rtio::drtio::get_buffer_space_req_count),
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),

View File

@ -210,11 +210,16 @@ mod imp {
pub use self::imp::*; pub use self::imp::*;
pub mod drtio_dbg { pub mod drtio {
use ::send; use ::send;
use ::recv; use ::recv;
use kernel_proto::*; use kernel_proto::*;
pub extern fn get_link_status(linkno: i32) -> bool {
send(&DrtioLinkStatusRequest { linkno: linkno as u8 });
recv!(&DrtioLinkStatusReply { up } => up)
}
#[repr(C)] #[repr(C)]
pub struct PacketCounts(i32, i32); pub struct PacketCounts(i32, i32);

View File

@ -46,6 +46,9 @@ pub enum Message<'a> {
duration: u64 duration: u64
}, },
DrtioLinkStatusRequest { linkno: u8 },
DrtioLinkStatusReply { up: bool },
DrtioPacketCountRequest { linkno: u8 }, DrtioPacketCountRequest { linkno: u8 },
DrtioPacketCountReply { tx_cnt: u32, rx_cnt: u32 }, DrtioPacketCountReply { tx_cnt: u32, rx_cnt: u32 },
DrtioBufferSpaceReqCountRequest { linkno: u8 }, DrtioBufferSpaceReqCountRequest { linkno: u8 },

View File

@ -300,6 +300,11 @@ pub fn process_kern_hwreq(io: &Io, request: &kern::Message) -> io::Result<bool>
kern_acknowledge() kern_acknowledge()
} }
#[cfg(has_rtio_core)]
&kern::DrtioLinkStatusRequest { linkno } => {
let up = rtio_mgt::drtio::link_up(linkno);
kern_send(io, &kern::DrtioLinkStatusReply { up: up })
}
#[cfg(has_rtio_core)] #[cfg(has_rtio_core)]
&kern::DrtioPacketCountRequest { linkno } => { &kern::DrtioPacketCountRequest { linkno } => {

View File

@ -54,8 +54,14 @@ pub mod drtio {
} }
} }
fn link_up(linkno: u8) -> bool { pub fn link_up(linkno: u8) -> bool {
let linkno = linkno as usize; let linkno = linkno as usize;
/* This function may be called by kernels with arbitrary
* linkno values.
*/
if linkno >= csr::DRTIO.len() {
return false;
}
unsafe { unsafe {
(csr::DRTIO[linkno].link_up_read)() == 1 (csr::DRTIO[linkno].link_up_read)() == 1
} }
@ -195,6 +201,7 @@ mod drtio {
pub fn startup(_io: &Io) {} pub fn startup(_io: &Io) {}
pub fn init() {} pub fn init() {}
pub fn link_up(_linkno: u8) -> bool { false }
} }
fn async_error_thread(io: Io) { fn async_error_thread(io: Io) {

View File

@ -187,6 +187,8 @@ 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 ``artiq_coreconfig``. 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 ``artiq_coreconfig``.
For DRTIO systems, the startup kernel should wait until the desired links are up, using :method:`artiq.coredevice.Core.get_drtio_link_status`.
* (optional) Select the startup clock * (optional) Select the startup clock
The core device may use either an external clock signal or its internal clock. This clock can be switched dynamically after the PC is connected using the ``external_clock`` parameter of the core device driver; however, one may want to select the clock at power-up so that it is used for the startup and idle kernels. Use one of these commands: :: The core device may use either an external clock signal or its internal clock. This clock can be switched dynamically after the PC is connected using the ``external_clock`` parameter of the core device driver; however, one may want to select the clock at power-up so that it is used for the startup and idle kernels. Use one of these commands: ::