forked from M-Labs/artiq-zynq
Compare commits
10 Commits
267a1222ed
...
246b8d383b
Author | SHA1 | Date | |
---|---|---|---|
246b8d383b | |||
afd0389bf3 | |||
f5139ee140 | |||
761b7c99cd | |||
5982937ee6 | |||
32889c11f1 | |||
bc7925989b | |||
b2256800fe | |||
637163bbca | |||
50ead76c09 |
16
flake.lock
generated
16
flake.lock
generated
@ -11,11 +11,11 @@
|
||||
"src-pythonparser": "src-pythonparser"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1741925484,
|
||||
"narHash": "sha256-sovpN0Ii+GOVY4Qku8eal5hWATScCc1VbYnfdwc88dQ=",
|
||||
"lastModified": 1743144117,
|
||||
"narHash": "sha256-LOh3KwjcEKcLA2vva6awAnMLUEyq4d+LPLCu7FwMAhw=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "cdacbf71c569b0968c81fb358838e9b69946af26",
|
||||
"revCount": 9192,
|
||||
"rev": "4ddad5fd17bb07fc754d764d3ff157300d27e109",
|
||||
"revCount": 9204,
|
||||
"type": "git",
|
||||
"url": "https://github.com/m-labs/artiq.git"
|
||||
},
|
||||
@ -229,11 +229,11 @@
|
||||
"rust-overlay": "rust-overlay_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1741773807,
|
||||
"narHash": "sha256-pywveAL5C0Jl+qo8XmgAL11RfrnSW/Afu3Yg1K/lAcU=",
|
||||
"lastModified": 1743144882,
|
||||
"narHash": "sha256-B1J8Ou/T8EDNcPVAu+c5bRiRUjoCiWCh6WNo60sRyDc=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "905b97431de37ccc61f8babd7def99627578a843",
|
||||
"revCount": 694,
|
||||
"rev": "c98c30c6565f0aa35a2f4ab31e5174f167714841",
|
||||
"revCount": 696,
|
||||
"type": "git",
|
||||
"url": "https://git.m-labs.hk/m-labs/zynq-rs"
|
||||
},
|
||||
|
@ -111,18 +111,23 @@ impl IoExpander {
|
||||
|
||||
fn write(&self, i2c: &mut i2c::I2c, addr: u8, value: u8) -> Result<(), &'static str> {
|
||||
i2c.start()?;
|
||||
i2c.write(self.address)?;
|
||||
i2c.write(addr)?;
|
||||
i2c.write(value)?;
|
||||
i2c.stop()?;
|
||||
Ok(())
|
||||
let write_res = i2c
|
||||
.write(self.address)
|
||||
.and_then(|_| i2c.write(addr))
|
||||
.and_then(|_| i2c.write(value));
|
||||
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> {
|
||||
// Check for ack from io expander
|
||||
self.select(i2c)?;
|
||||
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()?;
|
||||
Ok(ack)
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
use core::result;
|
||||
|
||||
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;
|
||||
|
||||
#[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<()> {
|
||||
i2c.start().unwrap();
|
||||
if !i2c.write(ADDRESS << 1).unwrap() {
|
||||
return Err("Si5324 failed to ack write address");
|
||||
}
|
||||
if !i2c.write(reg).unwrap() {
|
||||
return Err("Si5324 failed to ack register");
|
||||
}
|
||||
if !i2c.write(val).unwrap() {
|
||||
return Err("Si5324 failed to ack value");
|
||||
}
|
||||
i2c.write(ADDRESS << 1).map_err(|err| match err {
|
||||
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(),
|
||||
})?;
|
||||
i2c.write(val).map_err(|err| match err {
|
||||
I2cError::Nack => "Si5324 failed to ack value",
|
||||
err => err.into(),
|
||||
})?;
|
||||
i2c.stop().unwrap();
|
||||
Ok(())
|
||||
}
|
||||
@ -113,29 +118,37 @@ fn write(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
fn write_no_ack_value(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> {
|
||||
i2c.start().unwrap();
|
||||
if !i2c.write(ADDRESS << 1).unwrap() {
|
||||
return Err("Si5324 failed to ack write address");
|
||||
i2c.write(ADDRESS << 1).map_err(|err| match err {
|
||||
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();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read(i2c: &mut I2c, reg: u8) -> Result<u8> {
|
||||
i2c.start().unwrap();
|
||||
if !i2c.write(ADDRESS << 1).unwrap() {
|
||||
return Err("Si5324 failed to ack write address");
|
||||
}
|
||||
if !i2c.write(reg).unwrap() {
|
||||
return Err("Si5324 failed to ack register");
|
||||
}
|
||||
i2c.write(ADDRESS << 1).map_err(|err| match err {
|
||||
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(),
|
||||
})?;
|
||||
i2c.restart().unwrap();
|
||||
if !i2c.write((ADDRESS << 1) | 1).unwrap() {
|
||||
return Err("Si5324 failed to ack read address");
|
||||
}
|
||||
i2c.write((ADDRESS << 1) | 1).map_err(|err| match err {
|
||||
I2cError::Nack => "Si5324 failed to ack read address",
|
||||
err => err.into(),
|
||||
})?;
|
||||
let val = i2c.read(false).unwrap();
|
||||
i2c.stop().unwrap();
|
||||
Ok(val)
|
||||
|
@ -46,7 +46,9 @@ impl fmt::Display for Error {
|
||||
&Error::ROISizeTooBig(width, height) => {
|
||||
write!(
|
||||
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,
|
||||
width * height,
|
||||
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);
|
||||
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)));
|
||||
} else {
|
||||
unsafe {
|
||||
|
@ -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() }
|
||||
}
|
@ -8,11 +8,12 @@ use log::{info, warn};
|
||||
use super::subkernel;
|
||||
use super::{cache,
|
||||
core1::rtio_get_destination_status,
|
||||
dma, linalg,
|
||||
rpc::{rpc_recv, rpc_send, rpc_send_async}};
|
||||
dma, i2c, linalg,
|
||||
rpc::{rpc_recv, rpc_send, rpc_send_async},
|
||||
rtio};
|
||||
#[cfg(has_cxp_grabber)]
|
||||
use crate::cxp;
|
||||
use crate::{eh_artiq, i2c, rtio};
|
||||
use crate::eh_artiq;
|
||||
|
||||
extern "C" {
|
||||
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),
|
||||
|
||||
// libc
|
||||
api!(
|
||||
bcmp,
|
||||
extern "C" {
|
||||
fn bcmp(s1: *const u8, s2: *const u8, n: usize) -> i32;
|
||||
}
|
||||
),
|
||||
api!(
|
||||
memcpy,
|
||||
extern "C" {
|
||||
|
@ -12,9 +12,9 @@ use libcortex_a9::{asm::{dsb, isb},
|
||||
use libsupport_zynq::ram;
|
||||
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};
|
||||
use crate::{eh_artiq, get_async_errors, rtio};
|
||||
use crate::{eh_artiq, get_async_errors};
|
||||
|
||||
// linker symbols
|
||||
extern "C" {
|
||||
|
@ -3,8 +3,8 @@ use core::{mem, ptr};
|
||||
|
||||
use cslice::CSlice;
|
||||
|
||||
use super::{Message, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0, KERNEL_IMAGE};
|
||||
use crate::{artiq_raise, pl::csr, rtio};
|
||||
use super::{rtio, Message, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0, KERNEL_IMAGE};
|
||||
use crate::{artiq_raise, pl::csr};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DmaTrace {
|
||||
|
192
src/libksupport/src/kernel/i2c.rs
Normal file
192
src/libksupport/src/kernel/i2c.rs
Normal 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() }
|
||||
}
|
@ -10,7 +10,14 @@ pub use control::Control;
|
||||
mod api;
|
||||
pub mod core1;
|
||||
mod dma;
|
||||
pub mod i2c;
|
||||
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;
|
||||
mod cache;
|
||||
mod linalg;
|
||||
@ -41,6 +48,10 @@ pub enum Message {
|
||||
&'static [(usize, usize)],
|
||||
u8,
|
||||
),
|
||||
|
||||
#[cfg(has_drtio)]
|
||||
RtioInitRequest,
|
||||
|
||||
RpcSend {
|
||||
is_async: bool,
|
||||
data: Vec<u8>,
|
||||
@ -76,6 +87,41 @@ pub enum Message {
|
||||
#[cfg(has_drtio)]
|
||||
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)]
|
||||
SubkernelLoadRunRequest {
|
||||
id: u32,
|
||||
|
@ -4,6 +4,8 @@ use cslice::CSlice;
|
||||
use libcortex_a9::asm;
|
||||
use vcell::VolatileCell;
|
||||
|
||||
#[cfg(has_drtio)]
|
||||
use super::{Message, KERNEL_CHANNEL_1TO0};
|
||||
use crate::{artiq_raise, pl::csr, resolve_channel_name, rtio_core};
|
||||
|
||||
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::enable_write(1);
|
||||
}
|
||||
#[cfg(has_drtio)]
|
||||
unsafe {
|
||||
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send(Message::RtioInitRequest);
|
||||
}
|
||||
}
|
||||
|
||||
pub extern "C" fn get_counter() -> i64 {
|
@ -2,6 +2,8 @@ use core::ptr::{read_volatile, write_volatile};
|
||||
|
||||
use cslice::CSlice;
|
||||
|
||||
#[cfg(has_drtio)]
|
||||
use super::{Message, KERNEL_CHANNEL_1TO0};
|
||||
use crate::{artiq_raise, pl::csr, resolve_channel_name, rtio_core};
|
||||
|
||||
pub const RTIO_O_STATUS_WAIT: u8 = 1;
|
||||
@ -22,6 +24,10 @@ pub extern "C" fn init() {
|
||||
unsafe {
|
||||
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 {
|
@ -2,8 +2,8 @@ use alloc::vec::Vec;
|
||||
|
||||
use cslice::CSlice;
|
||||
|
||||
use super::{Message, SubkernelStatus, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0};
|
||||
use crate::{artiq_raise, eh_artiq, rpc::send_args, rtio::now_mu};
|
||||
use super::{rtio::now_mu, Message, SubkernelStatus, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0};
|
||||
use crate::{artiq_raise, eh_artiq, rpc::send_args};
|
||||
|
||||
pub extern "C" fn load_run(id: u32, destination: u8, run: bool) {
|
||||
unsafe {
|
||||
|
@ -22,16 +22,9 @@ pub use pl::csr::rtio_core;
|
||||
use void::Void;
|
||||
|
||||
pub mod eh_artiq;
|
||||
pub mod i2c;
|
||||
pub mod irq;
|
||||
pub mod kernel;
|
||||
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]
|
||||
#[path = "../../../build/pl.rs"]
|
||||
pub mod pl;
|
||||
|
@ -397,6 +397,42 @@ async fn handle_run_kernel(
|
||||
control.borrow_mut().tx.async_send(reply).await;
|
||||
}
|
||||
#[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 {
|
||||
id,
|
||||
destination: _,
|
||||
@ -521,6 +557,10 @@ async fn handle_run_kernel(
|
||||
.async_send(kernel::Message::UpDestinationsReply(result))
|
||||
.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);
|
||||
}
|
||||
|
@ -120,10 +120,10 @@ pub fn main_core0() {
|
||||
|
||||
info!("gateware ident: {}", identifier_read(&mut [0; 64]));
|
||||
|
||||
ksupport::i2c::init();
|
||||
ksupport::kernel::i2c::init();
|
||||
#[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_expander1 = io_expander::IoExpander::new(i2c_bus, 1).unwrap();
|
||||
io_expander0
|
||||
|
@ -1,7 +1,7 @@
|
||||
#[cfg(not(feature = "target_ebaz4205"))]
|
||||
use embedded_hal::blocking::delay::DelayMs;
|
||||
#[cfg(has_si5324)]
|
||||
use ksupport::i2c;
|
||||
use ksupport::kernel::i2c;
|
||||
#[cfg(not(feature = "target_ebaz4205"))]
|
||||
use libboard_artiq::pl;
|
||||
#[cfg(has_si5324)]
|
||||
|
@ -15,8 +15,8 @@ pub mod drtio {
|
||||
use embedded_hal::blocking::delay::DelayMs;
|
||||
#[cfg(has_drtio_eem)]
|
||||
use embedded_hal::blocking::delay::DelayUs;
|
||||
use ksupport::{resolve_channel_name, ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR,
|
||||
SEEN_ASYNC_ERRORS};
|
||||
use ksupport::{kernel::Message as KernelMessage, resolve_channel_name, ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION,
|
||||
ASYNC_ERROR_SEQUENCE_ERROR, SEEN_ASYNC_ERRORS};
|
||||
use libasync::{delay, task};
|
||||
#[cfg(has_drtio_eem)]
|
||||
use libboard_artiq::drtio_eem;
|
||||
@ -547,8 +547,7 @@ pub mod drtio {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn reset(aux_mutex: Rc<Mutex<bool>>, routing_table: &RoutingTable, mut timer: GlobalTimer) {
|
||||
pub async fn reset(aux_mutex: &Rc<Mutex<bool>>, routing_table: &RoutingTable, mut timer: GlobalTimer) {
|
||||
for linkno in 0..csr::DRTIO.len() {
|
||||
unsafe {
|
||||
(csr::DRTIO[linkno].reset_write)(1);
|
||||
@ -563,14 +562,8 @@ pub mod drtio {
|
||||
|
||||
for linkno in 0..csr::DRTIO.len() {
|
||||
let linkno = linkno as u8;
|
||||
if task::block_on(link_rx_up(linkno, &mut timer)) {
|
||||
let reply = task::block_on(aux_transact(
|
||||
&aux_mutex,
|
||||
linkno,
|
||||
routing_table,
|
||||
&Packet::ResetRequest,
|
||||
timer,
|
||||
));
|
||||
if link_rx_up(linkno, &mut timer).await {
|
||||
let reply = aux_transact(&aux_mutex, linkno, routing_table, &Packet::ResetRequest, timer).await;
|
||||
match reply {
|
||||
Ok(Packet::ResetAck) => (),
|
||||
Ok(_) => error!("[LINK#{}] reset failed, received unexpected aux packet", linkno),
|
||||
@ -929,6 +922,91 @@ pub mod drtio {
|
||||
)
|
||||
.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))]
|
||||
@ -982,11 +1060,3 @@ pub fn startup(
|
||||
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)
|
||||
}
|
||||
|
@ -44,7 +44,10 @@ use libboard_artiq::{drtio_routing, drtioaux,
|
||||
pl::csr};
|
||||
#[cfg(feature = "target_kasli_soc")]
|
||||
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 libcortex_a9::{l2c::enable_l2_cache, regs::MPIDR};
|
||||
use libregister::RegisterR;
|
||||
@ -435,11 +438,18 @@ fn process_aux_packet(
|
||||
timer
|
||||
);
|
||||
match i2c.write(data) {
|
||||
Ok(ack) => drtioaux::send(
|
||||
Ok(()) => drtioaux::send(
|
||||
0,
|
||||
&drtioaux::Packet::I2cWriteReply {
|
||||
succeeded: true,
|
||||
ack: ack,
|
||||
ack: true,
|
||||
},
|
||||
),
|
||||
Err(I2cError::Nack) => drtioaux::send(
|
||||
0,
|
||||
&drtioaux::Packet::I2cWriteReply {
|
||||
succeeded: true,
|
||||
ack: false,
|
||||
},
|
||||
),
|
||||
Err(_) => drtioaux::send(
|
||||
@ -1528,8 +1538,8 @@ pub extern "C" fn main_core0() -> i32 {
|
||||
|
||||
ram::init_alloc_core0();
|
||||
|
||||
ksupport::i2c::init();
|
||||
let i2c = ksupport::i2c::get_bus();
|
||||
ksupport::kernel::i2c::init();
|
||||
let i2c = ksupport::kernel::i2c::get_bus();
|
||||
|
||||
#[cfg(feature = "target_kasli_soc")]
|
||||
let (mut io_expander0, mut io_expander1);
|
||||
|
@ -9,7 +9,7 @@ use core_io::Error as IoError;
|
||||
use cslice::AsCSlice;
|
||||
use dma::{Error as DmaError, Manager as DmaManager};
|
||||
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,
|
||||
drtioaux,
|
||||
drtioaux_proto::{PayloadStatus, MASTER_PAYLOAD_MAX_SIZE},
|
||||
@ -846,6 +846,8 @@ impl<'a> Manager<'_> {
|
||||
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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user