Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: ef971ef8ba3d
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 18b7ccea4e0e
Choose a head ref
  • 2 commits
  • 13 files changed
  • 1 contributor

Commits on Nov 21, 2016

  1. runtime: rewrite rtio support code in Rust.

    whitequark committed Nov 21, 2016
    Copy the full SHA
    a825584 View commit details
  2. runtime: rewrite i2c support code in Rust.

    whitequark committed Nov 21, 2016
    Copy the full SHA
    18b7cce View commit details
3 changes: 1 addition & 2 deletions artiq/coredevice/rtio.py
Original file line number Diff line number Diff line change
@@ -3,8 +3,7 @@


@syscall(flags={"nowrite"})
def rtio_output(time_mu: TInt64, channel: TInt32, addr: TInt32, data: TInt32
) -> TNone:
def rtio_output(time_mu: TInt64, channel: TInt32, addr: TInt32, data: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")


20 changes: 10 additions & 10 deletions artiq/runtime.rs/libksupport/api.rs
Original file line number Diff line number Diff line change
@@ -98,16 +98,16 @@ static mut API: &'static [(&'static str, *const ())] = &[
api!(cache_put = ::cache_put),

/* direct syscalls */
api!(rtio_init),
api!(rtio_get_counter),
api!(rtio_init = ::rtio::init),
api!(rtio_get_counter = ::rtio::get_counter),
api!(rtio_log),
api!(rtio_output),
api!(rtio_input_timestamp),
api!(rtio_input_data),
api!(rtio_output = ::rtio::output),
api!(rtio_input_timestamp = ::rtio::input_timestamp),
api!(rtio_input_data = ::rtio::input_data),

api!(i2c_init),
api!(i2c_start),
api!(i2c_stop),
api!(i2c_write),
api!(i2c_read),
api!(i2c_init = ::i2c::init),
api!(i2c_start = ::i2c::start),
api!(i2c_stop = ::i2c::stop),
api!(i2c_write = ::i2c::write),
api!(i2c_read = ::i2c::read),
];
166 changes: 166 additions & 0 deletions artiq/runtime.rs/libksupport/i2c.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
use board::csr;

fn half_period() {
unsafe {
csr::timer_kernel::en_write(0);
csr::timer_kernel::load_write(csr::CONFIG_CLOCK_FREQUENCY/10000);
csr::timer_kernel::reload_write(0);
csr::timer_kernel::en_write(1);

csr::timer_kernel::update_value_write(1);
while csr::timer_kernel::value_read() != 0 {
csr::timer_kernel::update_value_write(1)
}
}
}

#[cfg(has_i2c)]
mod imp {
use board::csr;

fn sda_bit(busno: u32) -> u32 { 1 << (2 * busno + 1) }
fn scl_bit(busno: u32) -> u32 { 1 << (2 * busno) }

pub fn sda_i(busno: u32) -> bool {
unsafe {
if busno >= csr::CONFIG_I2C_BUS_COUNT {
true
} else {
csr::i2c::in_read() & sda_bit(busno) != 0
}
}
}

pub fn sda_oe(busno: u32, oe: bool) {
unsafe {
let reg = csr::i2c::oe_read();
let reg = if oe { reg | sda_bit(busno) } else { reg & !sda_bit(busno) };
csr::i2c::oe_write(reg);
}
}

pub fn sda_o(busno: u32, o: bool) {
unsafe {
let reg = csr::i2c::out_read();
let reg = if o { reg | sda_bit(busno) } else { reg & !sda_bit(busno) };
csr::i2c::out_write(reg)
}
}

pub fn scl_oe(busno: u32, oe: bool) {
unsafe {
let reg = csr::i2c::oe_read();
let reg = if oe { reg | scl_bit(busno) } else { reg & !scl_bit(busno) };
csr::i2c::oe_write(reg)
}
}

pub fn scl_o(busno: u32, o: bool) {
unsafe {
let reg = csr::i2c::out_read();
let reg = if o { reg | scl_bit(busno) } else { reg & !scl_bit(busno) };
csr::i2c::out_write(reg)
}
}
}

// #[cfg(not(has_i2c))]
// mod imp {
// pub fn sda_i(busno: u32) -> bool { true }
// pub fn sda_oe(busno: u32, oe: bool) {}
// pub fn sda_o(busno: u32, o: bool) {}
// pub fn scl_oe(busno: u32, oe: bool) {}
// pub fn scl_o(busno: u32, o: bool) {}
// }

use self::imp::*;

pub extern fn init(busno: u32) {
// Set SCL as output, and high level
scl_o(busno, true);
scl_oe(busno, true);
// Prepare a zero level on SDA so that sda_oe pulls it down
sda_o(busno, false);
// Release SDA
sda_oe(busno, false);

// Check the I2C bus is ready
half_period();
half_period();
if !sda_i(busno) {
artiq_raise!("I2CError", "SDA is stuck low")
}
}

pub extern fn start(busno: u32) {
// Set SCL high then SDA low
scl_o(busno, true);
half_period();
sda_oe(busno, true);
half_period();
}

pub extern fn stop(busno: u32) {
// First, make sure SCL is low, so that the target releases the SDA line
scl_o(busno, false);
half_period();
// Set SCL high then SDA high
sda_oe(busno, true);
scl_o(busno, true);
half_period();
sda_oe(busno, false);
half_period();
}

pub extern fn write(busno: u32, data: u8) -> bool {
// MSB first
for bit in (0..8).rev() {
// Set SCL low and set our bit on SDA
scl_o(busno, false);
sda_oe(busno, data & (1 << bit) == 0);
half_period();
// Set SCL high ; data is shifted on the rising edge of SCL
scl_o(busno, true);
half_period();
}
// Check ack
// Set SCL low, then release SDA so that the I2C target can respond
scl_o(busno, false);
half_period();
sda_oe(busno, false);
// Set SCL high and check for ack
scl_o(busno, true);
half_period();
// returns true if acked (I2C target pulled SDA low)
!sda_i(busno)
}

pub extern fn read(busno: u32, ack: bool) -> u8 {
// Set SCL low first, otherwise setting SDA as input may cause a transition
// on SDA with SCL high which will be interpreted as START/STOP condition.
scl_o(busno, false);
half_period(); // make sure SCL has settled low
sda_oe(busno, false);

let mut data: u8 = 0;

// MSB first
for bit in (0..8).rev() {
scl_o(busno, false);
half_period();
// Set SCL high and shift data
scl_o(busno, true);
half_period();
if sda_i(busno) { data |= 1 << bit }
}
// Send ack
// Set SCL low and pull SDA low when acking
scl_o(busno, false);
if ack { sda_oe(busno, true) }
half_period();
// then set SCL high
scl_o(busno, true);
half_period();

data
}
58 changes: 35 additions & 23 deletions artiq/runtime.rs/libksupport/lib.rs
Original file line number Diff line number Diff line change
@@ -23,6 +23,35 @@ mod rpc_proto;
mod dyld;
mod api;

#[allow(improper_ctypes)]
extern {
fn __artiq_raise(exn: *const ::kernel_proto::Exception) -> !;
}

macro_rules! artiq_raise {
($name:expr, $message:expr, $param0:expr, $param1:expr, $param2:expr) => ({
let exn = $crate::kernel_proto::Exception {
name: concat!("0:artiq.coredevice.exceptions.", $name, "\0").as_bytes().as_ptr(),
file: concat!(file!(), "\0").as_bytes().as_ptr(),
line: line!(),
column: column!(),
// https://github.com/rust-lang/rfcs/pull/1719
function: "(Rust function)\0".as_bytes().as_ptr(),
message: concat!($message, "\0").as_bytes().as_ptr(),
param: [$param0, $param1, $param2],
phantom: ::core::marker::PhantomData
};
#[allow(unused_unsafe)]
unsafe { $crate::__artiq_raise(&exn as *const _) }
});
($name:expr, $message:expr) => ({
artiq_raise!($name, $message, 0, 0, 0)
});
}

mod rtio;
mod i2c;

use core::{mem, ptr, slice, str};
use std::io::Cursor;
use libc::{c_char, size_t};
@@ -91,12 +120,17 @@ extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u32) -
static mut NOW: u64 = 0;

#[no_mangle]
pub extern fn send_to_log(ptr: *const u8, len: usize) {
pub extern fn send_to_core_log(ptr: *const u8, len: usize) {
send(&LogSlice(unsafe {
str::from_utf8_unchecked(slice::from_raw_parts(ptr, len))
}))
}

#[no_mangle]
pub extern fn send_to_rtio_log(timestamp: i64, ptr: *const u8, len: usize) {
rtio::log(timestamp, unsafe { slice::from_raw_parts(ptr, len) })
}

extern fn abort() -> ! {
println!("kernel called abort()");
send(&RunAborted);
@@ -151,28 +185,6 @@ extern fn recv_rpc(slot: *mut ()) -> usize {
})
}

#[allow(improper_ctypes)]
extern {
fn __artiq_raise(exn: *const ::kernel_proto::Exception) -> !;
}

macro_rules! artiq_raise {
($name:expr, $message:expr) => ({
let exn = Exception {
name: concat!("0:artiq.coredevice.exceptions.", $name, "\0").as_bytes().as_ptr(),
file: concat!(file!(), "\0").as_bytes().as_ptr(),
line: line!(),
column: column!(),
// https://github.com/rust-lang/rfcs/pull/1719
function: "(Rust function)\0".as_bytes().as_ptr(),
message: concat!($message, "\0").as_bytes().as_ptr(),
param: [0; 3],
phantom: ::core::marker::PhantomData
};
unsafe { __artiq_raise(&exn as *const _) }
})
}

#[no_mangle]
pub extern fn __artiq_terminate(exception: *const kernel_proto::Exception,
backtrace_data: *mut usize,
Loading