Compare commits

...

10 Commits

20 changed files with 479 additions and 173 deletions

16
flake.lock generated
View File

@ -11,11 +11,11 @@
"src-pythonparser": "src-pythonparser" "src-pythonparser": "src-pythonparser"
}, },
"locked": { "locked": {
"lastModified": 1741925484, "lastModified": 1743144117,
"narHash": "sha256-sovpN0Ii+GOVY4Qku8eal5hWATScCc1VbYnfdwc88dQ=", "narHash": "sha256-LOh3KwjcEKcLA2vva6awAnMLUEyq4d+LPLCu7FwMAhw=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "cdacbf71c569b0968c81fb358838e9b69946af26", "rev": "4ddad5fd17bb07fc754d764d3ff157300d27e109",
"revCount": 9192, "revCount": 9204,
"type": "git", "type": "git",
"url": "https://github.com/m-labs/artiq.git" "url": "https://github.com/m-labs/artiq.git"
}, },
@ -229,11 +229,11 @@
"rust-overlay": "rust-overlay_2" "rust-overlay": "rust-overlay_2"
}, },
"locked": { "locked": {
"lastModified": 1741773807, "lastModified": 1743144882,
"narHash": "sha256-pywveAL5C0Jl+qo8XmgAL11RfrnSW/Afu3Yg1K/lAcU=", "narHash": "sha256-B1J8Ou/T8EDNcPVAu+c5bRiRUjoCiWCh6WNo60sRyDc=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "905b97431de37ccc61f8babd7def99627578a843", "rev": "c98c30c6565f0aa35a2f4ab31e5174f167714841",
"revCount": 694, "revCount": 696,
"type": "git", "type": "git",
"url": "https://git.m-labs.hk/m-labs/zynq-rs" "url": "https://git.m-labs.hk/m-labs/zynq-rs"
}, },

View File

@ -111,18 +111,23 @@ impl IoExpander {
fn write(&self, i2c: &mut i2c::I2c, addr: u8, value: u8) -> Result<(), &'static str> { fn write(&self, i2c: &mut i2c::I2c, addr: u8, value: u8) -> Result<(), &'static str> {
i2c.start()?; i2c.start()?;
i2c.write(self.address)?; let write_res = i2c
i2c.write(addr)?; .write(self.address)
i2c.write(value)?; .and_then(|_| i2c.write(addr))
i2c.stop()?; .and_then(|_| i2c.write(value));
Ok(()) let stop_res = i2c.stop();
write_res.and(stop_res).map_err(|e| e.into())
} }
fn check_ack(&self, i2c: &mut i2c::I2c) -> Result<bool, &'static str> { fn check_ack(&self, i2c: &mut i2c::I2c) -> Result<bool, &'static str> {
// Check for ack from io expander // Check for ack from io expander
self.select(i2c)?; self.select(i2c)?;
i2c.start()?; i2c.start()?;
let ack = i2c.write(self.address)?; let ack = match i2c.write(self.address) {
Ok(()) => true,
Err(i2c::Error::Nack) => false,
Err(e) => return Err(e.into()),
};
i2c.stop()?; i2c.stop()?;
Ok(ack) Ok(ack)
} }

View File

@ -1,7 +1,9 @@
use core::result; use core::result;
use embedded_hal::blocking::delay::DelayUs; use embedded_hal::blocking::delay::DelayUs;
use libboard_zynq::{i2c::I2c, time::Milliseconds, timer::GlobalTimer}; use libboard_zynq::{i2c::{Error as I2cError, I2c},
time::Milliseconds,
timer::GlobalTimer};
use log::info; use log::info;
#[cfg(not(si5324_soft_reset))] #[cfg(not(si5324_soft_reset))]
@ -97,15 +99,18 @@ fn map_frequency_settings(settings: &FrequencySettings) -> Result<FrequencySetti
fn write(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> { fn write(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> {
i2c.start().unwrap(); i2c.start().unwrap();
if !i2c.write(ADDRESS << 1).unwrap() { i2c.write(ADDRESS << 1).map_err(|err| match err {
return Err("Si5324 failed to ack write address"); I2cError::Nack => "Si5324 failed to ack write address",
} err => err.into(),
if !i2c.write(reg).unwrap() { })?;
return Err("Si5324 failed to ack register"); i2c.write(reg).map_err(|err| match err {
} I2cError::Nack => "Si5324 failed to ack register",
if !i2c.write(val).unwrap() { err => err.into(),
return Err("Si5324 failed to ack value"); })?;
} i2c.write(val).map_err(|err| match err {
I2cError::Nack => "Si5324 failed to ack value",
err => err.into(),
})?;
i2c.stop().unwrap(); i2c.stop().unwrap();
Ok(()) Ok(())
} }
@ -113,29 +118,37 @@ fn write(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> {
#[allow(dead_code)] #[allow(dead_code)]
fn write_no_ack_value(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> { fn write_no_ack_value(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> {
i2c.start().unwrap(); i2c.start().unwrap();
if !i2c.write(ADDRESS << 1).unwrap() { i2c.write(ADDRESS << 1).map_err(|err| match err {
return Err("Si5324 failed to ack write address"); I2cError::Nack => "Si5324 failed to ack write address",
err => err.into(),
})?;
i2c.write(reg).map_err(|err| match err {
I2cError::Nack => "Si5324 failed to ack register",
err => err.into(),
})?;
match i2c.write(val) {
Ok(()) | Err(I2cError::Nack) => (),
Err(e) => return Err(e.into()),
} }
if !i2c.write(reg).unwrap() {
return Err("Si5324 failed to ack register");
}
i2c.write(val).unwrap();
i2c.stop().unwrap(); i2c.stop().unwrap();
Ok(()) Ok(())
} }
fn read(i2c: &mut I2c, reg: u8) -> Result<u8> { fn read(i2c: &mut I2c, reg: u8) -> Result<u8> {
i2c.start().unwrap(); i2c.start().unwrap();
if !i2c.write(ADDRESS << 1).unwrap() { i2c.write(ADDRESS << 1).map_err(|err| match err {
return Err("Si5324 failed to ack write address"); I2cError::Nack => "Si5324 failed to ack write address",
} err => err.into(),
if !i2c.write(reg).unwrap() { })?;
return Err("Si5324 failed to ack register"); i2c.write(reg).map_err(|err| match err {
} I2cError::Nack => "Si5324 failed to ack register",
err => err.into(),
})?;
i2c.restart().unwrap(); i2c.restart().unwrap();
if !i2c.write((ADDRESS << 1) | 1).unwrap() { i2c.write((ADDRESS << 1) | 1).map_err(|err| match err {
return Err("Si5324 failed to ack read address"); I2cError::Nack => "Si5324 failed to ack read address",
} err => err.into(),
})?;
let val = i2c.read(false).unwrap(); let val = i2c.read(false).unwrap();
i2c.stop().unwrap(); i2c.stop().unwrap();
Ok(val) Ok(val)

View File

@ -46,7 +46,9 @@ impl fmt::Display for Error {
&Error::ROISizeTooBig(width, height) => { &Error::ROISizeTooBig(width, height) => {
write!( write!(
f, f,
"ROISizeTooBig - The maximum ROIViewer size is {} pixels but the ROI is set to {} ({}x{}) pixels", "ROISizeTooBig - The maximum ROIViewer height and total size are {} and {} pixels respectively \
but the ROI is set to {} ({}x{}) pixels",
ROI_MAX_SIZE / 4,
ROI_MAX_SIZE, ROI_MAX_SIZE,
width * height, width * height,
width, width,
@ -170,9 +172,9 @@ pub extern "C" fn write32(addr: i32, val: i32) {
} }
} }
pub extern "C" fn start_roi_viewer(x0: i32, x1: i32, y0: i32, y1: i32) { pub extern "C" fn start_roi_viewer(x0: i32, y0: i32, x1: i32, y1: i32) {
let (width, height) = ((x1 - x0) as usize, (y1 - y0) as usize); let (width, height) = ((x1 - x0) as usize, (y1 - y0) as usize);
if width * height > ROI_MAX_SIZE { if width * height > ROI_MAX_SIZE || height > ROI_MAX_SIZE / 4 {
artiq_raise!("CXPError", format!("{}", Error::ROISizeTooBig(width, height))); artiq_raise!("CXPError", format!("{}", Error::ROISizeTooBig(width, height)));
} else { } else {
unsafe { unsafe {

View File

@ -1,86 +0,0 @@
use core::mem::MaybeUninit;
use libboard_zynq::i2c::I2c;
use crate::artiq_raise;
static mut I2C_BUS: MaybeUninit<I2c> = MaybeUninit::uninit();
pub extern "C" fn start(busno: i32) {
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
if get_bus().start().is_err() {
artiq_raise!("I2CError", "I2C start failed");
}
}
pub extern "C" fn restart(busno: i32) {
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
if get_bus().restart().is_err() {
artiq_raise!("I2CError", "I2C restart failed");
}
}
pub extern "C" fn stop(busno: i32) {
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
if get_bus().stop().is_err() {
artiq_raise!("I2CError", "I2C stop failed");
}
}
pub extern "C" fn write(busno: i32, data: i32) -> bool {
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
match get_bus().write(data as u8) {
Ok(r) => r,
Err(_) => artiq_raise!("I2CError", "I2C write failed"),
}
}
pub extern "C" fn read(busno: i32, ack: bool) -> i32 {
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
match get_bus().read(ack) {
Ok(r) => r as i32,
Err(_) => artiq_raise!("I2CError", "I2C read failed"),
}
}
pub extern "C" fn switch_select(busno: i32, address: i32, mask: i32) {
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
let ch = match mask {
//decode from mainline, PCA9548-centric API
0x00 => None,
0x01 => Some(0),
0x02 => Some(1),
0x04 => Some(2),
0x08 => Some(3),
0x10 => Some(4),
0x20 => Some(5),
0x40 => Some(6),
0x80 => Some(7),
_ => artiq_raise!("I2CError", "switch select supports only one channel"),
};
if get_bus().pca954x_select(address as u8, ch).is_err() {
artiq_raise!("I2CError", "switch select failed");
}
}
pub fn init() {
let mut i2c = I2c::i2c0();
i2c.init().expect("I2C bus initialization failed");
unsafe { I2C_BUS.write(i2c) };
}
pub fn get_bus() -> &'static mut I2c {
unsafe { I2C_BUS.assume_init_mut() }
}

View File

@ -8,11 +8,12 @@ use log::{info, warn};
use super::subkernel; use super::subkernel;
use super::{cache, use super::{cache,
core1::rtio_get_destination_status, core1::rtio_get_destination_status,
dma, linalg, dma, i2c, linalg,
rpc::{rpc_recv, rpc_send, rpc_send_async}}; rpc::{rpc_recv, rpc_send, rpc_send_async},
rtio};
#[cfg(has_cxp_grabber)] #[cfg(has_cxp_grabber)]
use crate::cxp; use crate::cxp;
use crate::{eh_artiq, i2c, rtio}; use crate::eh_artiq;
extern "C" { extern "C" {
fn vsnprintf_(buffer: *mut c_char, count: size_t, format: *const c_char, va: VaList) -> c_int; fn vsnprintf_(buffer: *mut c_char, count: size_t, format: *const c_char, va: VaList) -> c_int;
@ -229,6 +230,12 @@ pub fn resolve(required: &[u8]) -> Option<u32> {
api!(__aeabi_memclr), api!(__aeabi_memclr),
// libc // libc
api!(
bcmp,
extern "C" {
fn bcmp(s1: *const u8, s2: *const u8, n: usize) -> i32;
}
),
api!( api!(
memcpy, memcpy,
extern "C" { extern "C" {

View File

@ -12,9 +12,9 @@ use libcortex_a9::{asm::{dsb, isb},
use libsupport_zynq::ram; use libsupport_zynq::ram;
use log::{debug, error, info}; use log::{debug, error, info};
use super::{api::resolve, dma, rpc::rpc_send_async, Message, CHANNEL_0TO1, CHANNEL_1TO0, CHANNEL_SEM, INIT_LOCK, use super::{api::resolve, dma, rpc::rpc_send_async, rtio, Message, CHANNEL_0TO1, CHANNEL_1TO0, CHANNEL_SEM, INIT_LOCK,
KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0, KERNEL_IMAGE}; KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0, KERNEL_IMAGE};
use crate::{eh_artiq, get_async_errors, rtio}; use crate::{eh_artiq, get_async_errors};
// linker symbols // linker symbols
extern "C" { extern "C" {

View File

@ -3,8 +3,8 @@ use core::{mem, ptr};
use cslice::CSlice; use cslice::CSlice;
use super::{Message, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0, KERNEL_IMAGE}; use super::{rtio, Message, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0, KERNEL_IMAGE};
use crate::{artiq_raise, pl::csr, rtio}; use crate::{artiq_raise, pl::csr};
#[repr(C)] #[repr(C)]
pub struct DmaTrace { pub struct DmaTrace {

View File

@ -0,0 +1,192 @@
use core::mem::MaybeUninit;
use libboard_zynq::i2c::{Error, I2c};
#[cfg(has_drtio)]
use super::{Message, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0};
use crate::artiq_raise;
static mut I2C_BUS: MaybeUninit<I2c> = MaybeUninit::uninit();
pub extern "C" fn start(busno: i32) {
let _destination = (busno >> 16) as u8;
#[cfg(has_drtio)]
if _destination != 0 {
let reply = unsafe {
KERNEL_CHANNEL_1TO0
.as_mut()
.unwrap()
.send(Message::I2cStartRequest(busno as u32));
KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv()
};
match reply {
Message::I2cBasicReply(true) => return,
Message::I2cBasicReply(false) => artiq_raise!("I2CError", "I2C remote start fail"),
msg => panic!("Expected I2cBasicReply for I2cStartRequest, got: {:?}", msg),
}
}
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
if get_bus().start().is_err() {
artiq_raise!("I2CError", "I2C start failed");
}
}
pub extern "C" fn restart(busno: i32) {
let _destination = (busno >> 16) as u8;
#[cfg(has_drtio)]
if _destination != 0 {
let reply = unsafe {
KERNEL_CHANNEL_1TO0
.as_mut()
.unwrap()
.send(Message::I2cRestartRequest(busno as u32));
KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv()
};
match reply {
Message::I2cBasicReply(true) => return,
Message::I2cBasicReply(false) => artiq_raise!("I2CError", "I2C remote restart fail"),
msg => panic!("Expected I2cBasicReply for I2cRetartRequest, got: {:?}", msg),
}
}
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
if get_bus().restart().is_err() {
artiq_raise!("I2CError", "I2C restart failed");
}
}
pub extern "C" fn stop(busno: i32) {
let _destination = (busno >> 16) as u8;
#[cfg(has_drtio)]
if _destination != 0 {
// remote
let reply = unsafe {
KERNEL_CHANNEL_1TO0
.as_mut()
.unwrap()
.send(Message::I2cStopRequest(busno as u32));
KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv()
};
match reply {
Message::I2cBasicReply(true) => return,
Message::I2cBasicReply(false) => artiq_raise!("I2CError", "I2C remote stop fail"),
msg => panic!("Expected I2cBasicReply for I2cStopRequest, got: {:?}", msg),
}
}
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
if get_bus().stop().is_err() {
artiq_raise!("I2CError", "I2C stop failed");
}
}
pub extern "C" fn write(busno: i32, data: i32) -> bool {
let _destination = (busno >> 16) as u8;
#[cfg(has_drtio)]
if _destination != 0 {
// remote
let reply = unsafe {
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send(Message::I2cWriteRequest {
busno: busno as u32,
data: data as u8,
});
KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv()
};
match reply {
Message::I2cWriteReply { succeeded: true, ack } => return ack,
Message::I2cWriteReply { succeeded: false, .. } => artiq_raise!("I2CError", "I2C remote write fail"),
msg => panic!("Expected I2cWriteReply for I2cWriteRequest, got: {:?}", msg),
}
}
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
match get_bus().write(data as u8) {
Ok(()) => true,
Err(Error::Nack) => false,
Err(_) => artiq_raise!("I2CError", "I2C write failed"),
}
}
pub extern "C" fn read(busno: i32, ack: bool) -> i32 {
let _destination = (busno >> 16) as u8;
#[cfg(has_drtio)]
if _destination != 0 {
let reply = unsafe {
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send(Message::I2cReadRequest {
busno: busno as u32,
ack,
});
KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv()
};
match reply {
Message::I2cReadReply { succeeded: true, data } => return data as i32,
Message::I2cReadReply { succeeded: false, .. } => artiq_raise!("I2CError", "I2C remote read fail"),
msg => panic!("Expected I2cReadReply for I2cReadRequest, got: {:?}", msg),
}
}
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
match get_bus().read(ack) {
Ok(r) => r as i32,
Err(_) => artiq_raise!("I2CError", "I2C read failed"),
}
}
pub extern "C" fn switch_select(busno: i32, address: i32, mask: i32) {
let _destination = (busno >> 16) as u8;
#[cfg(has_drtio)]
if _destination != 0 {
// remote
let reply = unsafe {
KERNEL_CHANNEL_1TO0
.as_mut()
.unwrap()
.send(Message::I2cSwitchSelectRequest {
busno: busno as u32,
address: address as u8,
mask: mask as u8,
});
KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv()
};
match reply {
Message::I2cBasicReply(true) => return,
Message::I2cBasicReply(false) => artiq_raise!("I2CError", "I2C remote start fail"),
msg => panic!("Expected I2cBasicReply for I2cSwitchSelectRequest, got: {:?}", msg),
}
}
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
let ch = match mask {
//decode from mainline, PCA9548-centric API
0x00 => None,
0x01 => Some(0),
0x02 => Some(1),
0x04 => Some(2),
0x08 => Some(3),
0x10 => Some(4),
0x20 => Some(5),
0x40 => Some(6),
0x80 => Some(7),
_ => artiq_raise!("I2CError", "switch select supports only one channel"),
};
if get_bus().pca954x_select(address as u8, ch).is_err() {
artiq_raise!("I2CError", "switch select failed");
}
}
pub fn init() {
let mut i2c = I2c::i2c0();
i2c.init().expect("I2C bus initialization failed");
unsafe { I2C_BUS.write(i2c) };
}
pub fn get_bus() -> &'static mut I2c {
unsafe { I2C_BUS.assume_init_mut() }
}

View File

@ -10,7 +10,14 @@ pub use control::Control;
mod api; mod api;
pub mod core1; pub mod core1;
mod dma; mod dma;
pub mod i2c;
mod rpc; mod rpc;
#[cfg(ki_impl = "csr")]
#[path = "rtio_csr.rs"]
pub mod rtio;
#[cfg(ki_impl = "acp")]
#[path = "rtio_acp.rs"]
pub mod rtio;
pub use dma::DmaRecorder; pub use dma::DmaRecorder;
mod cache; mod cache;
mod linalg; mod linalg;
@ -41,6 +48,10 @@ pub enum Message {
&'static [(usize, usize)], &'static [(usize, usize)],
u8, u8,
), ),
#[cfg(has_drtio)]
RtioInitRequest,
RpcSend { RpcSend {
is_async: bool, is_async: bool,
data: Vec<u8>, data: Vec<u8>,
@ -76,6 +87,41 @@ pub enum Message {
#[cfg(has_drtio)] #[cfg(has_drtio)]
UpDestinationsReply(bool), UpDestinationsReply(bool),
#[cfg(has_drtio)]
I2cStartRequest(u32),
#[cfg(has_drtio)]
I2cRestartRequest(u32),
#[cfg(has_drtio)]
I2cStopRequest(u32),
#[cfg(has_drtio)]
I2cWriteRequest {
busno: u32,
data: u8,
},
#[cfg(has_drtio)]
I2cWriteReply {
succeeded: bool,
ack: bool,
},
#[cfg(has_drtio)]
I2cReadRequest {
busno: u32,
ack: bool,
},
#[cfg(has_drtio)]
I2cReadReply {
succeeded: bool,
data: u8,
},
#[cfg(has_drtio)]
I2cBasicReply(bool),
#[cfg(has_drtio)]
I2cSwitchSelectRequest {
busno: u32,
address: u8,
mask: u8,
},
#[cfg(has_drtio)] #[cfg(has_drtio)]
SubkernelLoadRunRequest { SubkernelLoadRunRequest {
id: u32, id: u32,

View File

@ -4,6 +4,8 @@ use cslice::CSlice;
use libcortex_a9::asm; use libcortex_a9::asm;
use vcell::VolatileCell; use vcell::VolatileCell;
#[cfg(has_drtio)]
use super::{Message, KERNEL_CHANNEL_1TO0};
use crate::{artiq_raise, pl::csr, resolve_channel_name, rtio_core}; use crate::{artiq_raise, pl::csr, resolve_channel_name, rtio_core};
pub const RTIO_O_STATUS_WAIT: i32 = 1; pub const RTIO_O_STATUS_WAIT: i32 = 1;
@ -56,6 +58,10 @@ pub extern "C" fn init() {
csr::rtio::engine_addr_base_write(&TRANSACTION_BUFFER as *const Transaction as u32); csr::rtio::engine_addr_base_write(&TRANSACTION_BUFFER as *const Transaction as u32);
csr::rtio::enable_write(1); csr::rtio::enable_write(1);
} }
#[cfg(has_drtio)]
unsafe {
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send(Message::RtioInitRequest);
}
} }
pub extern "C" fn get_counter() -> i64 { pub extern "C" fn get_counter() -> i64 {

View File

@ -2,6 +2,8 @@ use core::ptr::{read_volatile, write_volatile};
use cslice::CSlice; use cslice::CSlice;
#[cfg(has_drtio)]
use super::{Message, KERNEL_CHANNEL_1TO0};
use crate::{artiq_raise, pl::csr, resolve_channel_name, rtio_core}; use crate::{artiq_raise, pl::csr, resolve_channel_name, rtio_core};
pub const RTIO_O_STATUS_WAIT: u8 = 1; pub const RTIO_O_STATUS_WAIT: u8 = 1;
@ -22,6 +24,10 @@ pub extern "C" fn init() {
unsafe { unsafe {
rtio_core::reset_write(1); rtio_core::reset_write(1);
} }
#[cfg(has_drtio)]
unsafe {
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send(Message::RtioInitRequest);
}
} }
pub extern "C" fn get_counter() -> i64 { pub extern "C" fn get_counter() -> i64 {

View File

@ -2,8 +2,8 @@ use alloc::vec::Vec;
use cslice::CSlice; use cslice::CSlice;
use super::{Message, SubkernelStatus, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0}; use super::{rtio::now_mu, Message, SubkernelStatus, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0};
use crate::{artiq_raise, eh_artiq, rpc::send_args, rtio::now_mu}; use crate::{artiq_raise, eh_artiq, rpc::send_args};
pub extern "C" fn load_run(id: u32, destination: u8, run: bool) { pub extern "C" fn load_run(id: u32, destination: u8, run: bool) {
unsafe { unsafe {

View File

@ -22,16 +22,9 @@ pub use pl::csr::rtio_core;
use void::Void; use void::Void;
pub mod eh_artiq; pub mod eh_artiq;
pub mod i2c;
pub mod irq; pub mod irq;
pub mod kernel; pub mod kernel;
pub mod rpc; pub mod rpc;
#[cfg(ki_impl = "csr")]
#[path = "rtio_csr.rs"]
pub mod rtio;
#[cfg(ki_impl = "acp")]
#[path = "rtio_acp.rs"]
pub mod rtio;
#[rustfmt::skip] #[rustfmt::skip]
#[path = "../../../build/pl.rs"] #[path = "../../../build/pl.rs"]
pub mod pl; pub mod pl;

View File

@ -397,6 +397,42 @@ async fn handle_run_kernel(
control.borrow_mut().tx.async_send(reply).await; control.borrow_mut().tx.async_send(reply).await;
} }
#[cfg(has_drtio)] #[cfg(has_drtio)]
kernel::Message::I2cStartRequest(busno)
| kernel::Message::I2cRestartRequest(busno)
| kernel::Message::I2cStopRequest(busno)
| kernel::Message::I2cSwitchSelectRequest { busno, .. } => {
let result = rtio_mgt::drtio::i2c_send_basic(aux_mutex, routing_table, timer, &reply, busno).await;
let reply = match result {
Ok(succeeded) => kernel::Message::I2cBasicReply(succeeded),
Err(_) => kernel::Message::I2cBasicReply(false),
};
control.borrow_mut().tx.async_send(reply).await;
}
#[cfg(has_drtio)]
kernel::Message::I2cWriteRequest { busno, data } => {
let result = rtio_mgt::drtio::i2c_send_write(aux_mutex, routing_table, timer, busno, data).await;
let reply = match result {
Ok((succeeded, ack)) => kernel::Message::I2cWriteReply { succeeded, ack },
Err(_) => kernel::Message::I2cWriteReply {
succeeded: false,
ack: false,
},
};
control.borrow_mut().tx.async_send(reply).await;
}
#[cfg(has_drtio)]
kernel::Message::I2cReadRequest { busno, ack } => {
let result = rtio_mgt::drtio::i2c_send_read(aux_mutex, routing_table, timer, busno, ack).await;
let reply = match result {
Ok((succeeded, data)) => kernel::Message::I2cReadReply { succeeded, data },
Err(_) => kernel::Message::I2cReadReply {
succeeded: false,
data: 0xFF,
},
};
control.borrow_mut().tx.async_send(reply).await;
}
#[cfg(has_drtio)]
kernel::Message::SubkernelLoadRunRequest { kernel::Message::SubkernelLoadRunRequest {
id, id,
destination: _, destination: _,
@ -521,6 +557,10 @@ async fn handle_run_kernel(
.async_send(kernel::Message::UpDestinationsReply(result)) .async_send(kernel::Message::UpDestinationsReply(result))
.await; .await;
} }
#[cfg(has_drtio)]
kernel::Message::RtioInitRequest => {
rtio_mgt::drtio::reset(aux_mutex, routing_table, timer).await;
}
_ => { _ => {
panic!("unexpected message from core1 while kernel was running: {:?}", reply); panic!("unexpected message from core1 while kernel was running: {:?}", reply);
} }

View File

@ -120,10 +120,10 @@ pub fn main_core0() {
info!("gateware ident: {}", identifier_read(&mut [0; 64])); info!("gateware ident: {}", identifier_read(&mut [0; 64]));
ksupport::i2c::init(); ksupport::kernel::i2c::init();
#[cfg(feature = "target_kasli_soc")] #[cfg(feature = "target_kasli_soc")]
{ {
let i2c_bus = ksupport::i2c::get_bus(); let i2c_bus = ksupport::kernel::i2c::get_bus();
let mut io_expander0 = io_expander::IoExpander::new(i2c_bus, 0).unwrap(); let mut io_expander0 = io_expander::IoExpander::new(i2c_bus, 0).unwrap();
let mut io_expander1 = io_expander::IoExpander::new(i2c_bus, 1).unwrap(); let mut io_expander1 = io_expander::IoExpander::new(i2c_bus, 1).unwrap();
io_expander0 io_expander0

View File

@ -1,7 +1,7 @@
#[cfg(not(feature = "target_ebaz4205"))] #[cfg(not(feature = "target_ebaz4205"))]
use embedded_hal::blocking::delay::DelayMs; use embedded_hal::blocking::delay::DelayMs;
#[cfg(has_si5324)] #[cfg(has_si5324)]
use ksupport::i2c; use ksupport::kernel::i2c;
#[cfg(not(feature = "target_ebaz4205"))] #[cfg(not(feature = "target_ebaz4205"))]
use libboard_artiq::pl; use libboard_artiq::pl;
#[cfg(has_si5324)] #[cfg(has_si5324)]

View File

@ -15,8 +15,8 @@ pub mod drtio {
use embedded_hal::blocking::delay::DelayMs; use embedded_hal::blocking::delay::DelayMs;
#[cfg(has_drtio_eem)] #[cfg(has_drtio_eem)]
use embedded_hal::blocking::delay::DelayUs; use embedded_hal::blocking::delay::DelayUs;
use ksupport::{resolve_channel_name, ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR, use ksupport::{kernel::Message as KernelMessage, resolve_channel_name, ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION,
SEEN_ASYNC_ERRORS}; ASYNC_ERROR_SEQUENCE_ERROR, SEEN_ASYNC_ERRORS};
use libasync::{delay, task}; use libasync::{delay, task};
#[cfg(has_drtio_eem)] #[cfg(has_drtio_eem)]
use libboard_artiq::drtio_eem; use libboard_artiq::drtio_eem;
@ -547,8 +547,7 @@ pub mod drtio {
} }
} }
#[allow(dead_code)] pub async fn reset(aux_mutex: &Rc<Mutex<bool>>, routing_table: &RoutingTable, mut timer: GlobalTimer) {
pub fn reset(aux_mutex: Rc<Mutex<bool>>, routing_table: &RoutingTable, mut timer: GlobalTimer) {
for linkno in 0..csr::DRTIO.len() { for linkno in 0..csr::DRTIO.len() {
unsafe { unsafe {
(csr::DRTIO[linkno].reset_write)(1); (csr::DRTIO[linkno].reset_write)(1);
@ -563,14 +562,8 @@ pub mod drtio {
for linkno in 0..csr::DRTIO.len() { for linkno in 0..csr::DRTIO.len() {
let linkno = linkno as u8; let linkno = linkno as u8;
if task::block_on(link_rx_up(linkno, &mut timer)) { if link_rx_up(linkno, &mut timer).await {
let reply = task::block_on(aux_transact( let reply = aux_transact(&aux_mutex, linkno, routing_table, &Packet::ResetRequest, timer).await;
&aux_mutex,
linkno,
routing_table,
&Packet::ResetRequest,
timer,
));
match reply { match reply {
Ok(Packet::ResetAck) => (), Ok(Packet::ResetAck) => (),
Ok(_) => error!("[LINK#{}] reset failed, received unexpected aux packet", linkno), Ok(_) => error!("[LINK#{}] reset failed, received unexpected aux packet", linkno),
@ -929,6 +922,91 @@ pub mod drtio {
) )
.await .await
} }
pub async fn i2c_send_basic(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable,
timer: GlobalTimer,
request: &KernelMessage,
busno: u32,
) -> Result<bool, Error> {
let destination = (busno >> 16) as u8;
let busno = busno as u8;
let packet = match request {
KernelMessage::I2cStartRequest(_) => Packet::I2cStartRequest { destination, busno },
KernelMessage::I2cRestartRequest(_) => Packet::I2cRestartRequest { destination, busno },
KernelMessage::I2cStopRequest(_) => Packet::I2cStopRequest { destination, busno },
KernelMessage::I2cSwitchSelectRequest { address, mask, .. } => Packet::I2cSwitchSelectRequest {
destination,
busno,
address: *address,
mask: *mask,
},
_ => unreachable!(),
};
let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(aux_mutex, linkno, routing_table, &packet, timer).await?;
match reply {
Packet::I2cBasicReply { succeeded } => Ok(succeeded),
_ => Err(Error::UnexpectedReply),
}
}
pub async fn i2c_send_write(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable,
timer: GlobalTimer,
busno: u32,
data: u8,
) -> Result<(bool, bool), Error> {
let destination = (busno >> 16) as u8;
let busno = busno as u8;
let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::I2cWriteRequest {
destination,
busno,
data,
},
timer,
)
.await?;
match reply {
Packet::I2cWriteReply { succeeded, ack } => Ok((succeeded, ack)),
_ => Err(Error::UnexpectedReply),
}
}
pub async fn i2c_send_read(
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable,
timer: GlobalTimer,
busno: u32,
ack: bool,
) -> Result<(bool, u8), Error> {
let destination = (busno >> 16) as u8;
let busno = busno as u8;
let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::I2cReadRequest {
destination,
busno,
ack,
},
timer,
)
.await?;
match reply {
Packet::I2cReadReply { succeeded, data } => Ok((succeeded, data)),
_ => Err(Error::UnexpectedReply),
}
}
} }
#[cfg(not(has_drtio))] #[cfg(not(has_drtio))]
@ -982,11 +1060,3 @@ pub fn startup(
csr::rtio_core::reset_phy_write(1); csr::rtio_core::reset_phy_write(1);
} }
} }
#[allow(dead_code)]
pub fn reset(aux_mutex: Rc<Mutex<bool>>, routing_table: &RoutingTable, timer: GlobalTimer) {
unsafe {
csr::rtio_core::reset_write(1);
}
drtio::reset(aux_mutex, routing_table, timer)
}

View File

@ -44,7 +44,10 @@ use libboard_artiq::{drtio_routing, drtioaux,
pl::csr}; pl::csr};
#[cfg(feature = "target_kasli_soc")] #[cfg(feature = "target_kasli_soc")]
use libboard_zynq::error_led::ErrorLED; use libboard_zynq::error_led::ErrorLED;
use libboard_zynq::{i2c::I2c, print, println, slcr, time::Milliseconds, timer::GlobalTimer}; use libboard_zynq::{i2c::{Error as I2cError, I2c},
print, println, slcr,
time::Milliseconds,
timer::GlobalTimer};
use libconfig::Config; use libconfig::Config;
use libcortex_a9::{l2c::enable_l2_cache, regs::MPIDR}; use libcortex_a9::{l2c::enable_l2_cache, regs::MPIDR};
use libregister::RegisterR; use libregister::RegisterR;
@ -435,11 +438,18 @@ fn process_aux_packet(
timer timer
); );
match i2c.write(data) { match i2c.write(data) {
Ok(ack) => drtioaux::send( Ok(()) => drtioaux::send(
0, 0,
&drtioaux::Packet::I2cWriteReply { &drtioaux::Packet::I2cWriteReply {
succeeded: true, succeeded: true,
ack: ack, ack: true,
},
),
Err(I2cError::Nack) => drtioaux::send(
0,
&drtioaux::Packet::I2cWriteReply {
succeeded: true,
ack: false,
}, },
), ),
Err(_) => drtioaux::send( Err(_) => drtioaux::send(
@ -1528,8 +1538,8 @@ pub extern "C" fn main_core0() -> i32 {
ram::init_alloc_core0(); ram::init_alloc_core0();
ksupport::i2c::init(); ksupport::kernel::i2c::init();
let i2c = ksupport::i2c::get_bus(); let i2c = ksupport::kernel::i2c::get_bus();
#[cfg(feature = "target_kasli_soc")] #[cfg(feature = "target_kasli_soc")]
let (mut io_expander0, mut io_expander1); let (mut io_expander0, mut io_expander1);

View File

@ -9,7 +9,7 @@ use core_io::Error as IoError;
use cslice::AsCSlice; use cslice::AsCSlice;
use dma::{Error as DmaError, Manager as DmaManager}; use dma::{Error as DmaError, Manager as DmaManager};
use io::{Cursor, ProtoWrite}; use io::{Cursor, ProtoWrite};
use ksupport::{eh_artiq, kernel, rpc, rtio}; use ksupport::{eh_artiq, kernel, kernel::rtio, rpc};
use libboard_artiq::{drtio_routing::RoutingTable, use libboard_artiq::{drtio_routing::RoutingTable,
drtioaux, drtioaux,
drtioaux_proto::{PayloadStatus, MASTER_PAYLOAD_MAX_SIZE}, drtioaux_proto::{PayloadStatus, MASTER_PAYLOAD_MAX_SIZE},
@ -846,6 +846,8 @@ impl<'a> Manager<'_> {
destination == (self_destination as i32), destination == (self_destination as i32),
)); ));
} }
/* core.reset() on satellites only affects the satellite, ignore the request */
kernel::Message::RtioInitRequest => {}
_ => { _ => {
unexpected!("unexpected message from core1 while kernel was running: {:?}", reply); unexpected!("unexpected message from core1 while kernel was running: {:?}", reply);
} }