forked from M-Labs/artiq
1
0
Fork 0

runtime: the Rust runtime is now just the runtime.

This commit is contained in:
whitequark 2016-10-06 15:35:43 +00:00
parent 3e829d0d01
commit 5428a866b3
27 changed files with 33 additions and 2484 deletions

View File

@ -29,7 +29,6 @@ pub mod prelude {
} }
} }
pub mod time;
pub mod error; pub mod error;
pub mod io; pub mod io;

View File

@ -1,117 +0,0 @@
use core::ops::{Add, Sub, Mul, Div};
const MILLIS_PER_SEC: u64 = 1_000;
const NANOS_PER_MILLI: u32 = 1_000_000;
/// A duration type to represent a span of time, typically used for system
/// timeouts.
///
/// Each duration is composed of a number of seconds and nanosecond precision.
/// APIs binding a system timeout will typically round up the nanosecond
/// precision if the underlying system does not support that level of precision.
///
/// Durations implement many common traits, including `Add`, `Sub`, and other
/// ops traits. Currently a duration may only be inspected for its number of
/// seconds and its nanosecond precision.
///
/// # Examples
///
/// ```
/// use std::time::Duration;
///
/// let five_seconds = Duration::new(5, 0);
/// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5);
///
/// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5);
/// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5);
///
/// let ten_millis = Duration::from_millis(10);
/// ```
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct Duration {
millis: u64
}
impl Duration {
/// Creates a new `Duration` from the specified number of seconds and
/// additional nanosecond precision.
///
/// If the nanoseconds is greater than 1 billion (the number of nanoseconds
/// in a second), then it will carry over into the seconds provided.
pub fn new(secs: u64, nanos: u32) -> Duration {
Duration { millis: secs * MILLIS_PER_SEC + (nanos / NANOS_PER_MILLI) as u64 }
}
/// Creates a new `Duration` from the specified number of seconds.
pub fn from_secs(secs: u64) -> Duration {
Duration { millis: secs * MILLIS_PER_SEC }
}
/// Creates a new `Duration` from the specified number of milliseconds.
pub fn from_millis(millis: u64) -> Duration {
Duration { millis: millis }
}
/// Returns the number of whole milliseconds represented by this duration.
pub fn as_millis(&self) -> u64 { self.millis }
/// Returns the number of whole seconds represented by this duration.
///
/// The extra precision represented by this duration is ignored (e.g. extra
/// nanoseconds are not represented in the returned value).
pub fn as_secs(&self) -> u64 {
self.millis / MILLIS_PER_SEC
}
/// Returns the nanosecond precision represented by this duration.
///
/// This method does **not** return the length of the duration when
/// represented by nanoseconds. The returned number always represents a
/// fractional portion of a second (e.g. it is less than one billion).
pub fn subsec_nanos(&self) -> u32 {
(self.millis % MILLIS_PER_SEC) as u32 * NANOS_PER_MILLI
}
}
impl Add for Duration {
type Output = Duration;
fn add(self, rhs: Duration) -> Duration {
Duration {
millis: self.millis.checked_add(rhs.millis)
.expect("overflow when adding durations")
}
}
}
impl Sub for Duration {
type Output = Duration;
fn sub(self, rhs: Duration) -> Duration {
Duration {
millis: self.millis.checked_sub(rhs.millis)
.expect("overflow when subtracting durations")
}
}
}
impl Mul<u32> for Duration {
type Output = Duration;
fn mul(self, rhs: u32) -> Duration {
Duration {
millis: self.millis.checked_mul(rhs as u64)
.expect("overflow when multiplying duration")
}
}
}
impl Div<u32> for Duration {
type Output = Duration;
fn div(self, rhs: u32) -> Duration {
Duration {
millis: self.millis / (rhs as u64)
}
}
}

View File

@ -1,81 +0,0 @@
use core::ops::{Add, Sub};
use time::duration::Duration;
/// A measurement of a monotonically increasing clock.
///
/// Instants are always guaranteed to be greater than any previously measured
/// instant when created, and are often useful for tasks such as measuring
/// benchmarks or timing how long an operation takes.
///
/// Note, however, that instants are not guaranteed to be **steady**. In other
/// words, each tick of the underlying clock may not be the same length (e.g.
/// some seconds may be longer than others). An instant may jump forwards or
/// experience time dilation (slow down or speed up), but it will never go
/// backwards.
///
/// Instants are opaque types that can only be compared to one another. There is
/// no method to get "the number of seconds" from an instant. Instead, it only
/// allows measuring the duration between two instants (or comparing two
/// instants).
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Instant {
millis: u64
}
impl Instant {
/// Returns an instant corresponding to "now".
pub fn now() -> Instant {
extern {
fn clock_get_ms() -> i64;
}
Instant { millis: unsafe { clock_get_ms() as u64 } }
}
/// Returns the amount of time elapsed from another instant to this one.
///
/// # Panics
///
/// This function will panic if `earlier` is later than `self`, which should
/// only be possible if `earlier` was created after `self`. Because
/// `Instant` is monotonic, the only time that this should happen should be
/// a bug.
pub fn duration_from_earlier(&self, earlier: Instant) -> Duration {
let millis = self.millis.checked_sub(earlier.millis)
.expect("`earlier` is later than `self`");
Duration::from_millis(millis)
}
/// Returns the amount of time elapsed since this instant was created.
///
/// # Panics
///
/// This function may panic if the current time is earlier than this
/// instant, which is something that can happen if an `Instant` is
/// produced synthetically.
pub fn elapsed(&self) -> Duration {
Instant::now().duration_from_earlier(*self)
}
}
impl Add<Duration> for Instant {
type Output = Instant;
fn add(self, other: Duration) -> Instant {
Instant {
millis: self.millis.checked_add(other.as_millis())
.expect("overflow when adding duration to instant")
}
}
}
impl Sub<Duration> for Instant {
type Output = Instant;
fn sub(self, other: Duration) -> Instant {
Instant {
millis: self.millis.checked_sub(other.as_millis())
.expect("overflow when subtracting duration from instant")
}
}
}

View File

@ -1,5 +0,0 @@
pub use self::duration::Duration;
pub use self::instant::Instant;
mod duration;
mod instant;

View File

@ -69,3 +69,13 @@ pub unsafe extern fn rust_main() {
} }
}) })
} }
#[no_mangle]
pub fn sys_now() -> u32 {
clock::get_ms() as u32
}
#[no_mangle]
pub fn sys_jiffies() -> u32 {
clock::get_ms() as u32
}

View File

@ -2,16 +2,16 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::vec::Vec; use std::vec::Vec;
use std::time::{Instant, Duration};
use std::io::{Read, Write, Result, Error, ErrorKind}; use std::io::{Read, Write, Result, Error, ErrorKind};
use fringe::OwnedStack; use fringe::OwnedStack;
use fringe::generator::{Generator, Yielder, State as GeneratorState}; use fringe::generator::{Generator, Yielder, State as GeneratorState};
use lwip; use lwip;
use clock;
use urc::Urc; use urc::Urc;
#[derive(Debug)] #[derive(Debug)]
struct WaitRequest { struct WaitRequest {
timeout: Option<Instant>, timeout: Option<u64>,
event: Option<WaitEvent> event: Option<WaitEvent>
} }
@ -106,7 +106,7 @@ impl Scheduler {
if self.threads.len() == 0 { return } if self.threads.len() == 0 { return }
let now = Instant::now(); let now = clock::get_ms();
let start_index = self.index; let start_index = self.index;
loop { loop {
@ -214,9 +214,9 @@ unsafe impl Send for WaitEvent {}
pub struct Waiter<'a>(&'a Yielder<WaitResult, WaitRequest, OwnedStack>); pub struct Waiter<'a>(&'a Yielder<WaitResult, WaitRequest, OwnedStack>);
impl<'a> Waiter<'a> { impl<'a> Waiter<'a> {
pub fn sleep(&self, duration: Duration) -> Result<()> { pub fn sleep(&self, duration_ms: u64) -> Result<()> {
let request = WaitRequest { let request = WaitRequest {
timeout: Some(Instant::now() + duration), timeout: Some(clock::get_ms() + duration_ms),
event: None event: None
}; };

View File

@ -3,9 +3,7 @@ include $(MISOC_DIRECTORY)/software/common.mak
PYTHON ?= python3.5 PYTHON ?= python3.5
OBJECTS := isr.o clock.o rtiocrg.o flash_storage.o mailbox.o \ OBJECTS := isr.o flash_storage.o ksupport_data.o main.o
session.o log.o analyzer.o moninj.o net_server.o \
ksupport_data.o kloader.o main.o
OBJECTS_KSUPPORT := ksupport.o artiq_personality.o mailbox.o \ OBJECTS_KSUPPORT := ksupport.o artiq_personality.o mailbox.o \
rtio.o dds.o i2c.o rtio.o dds.o i2c.o

View File

@ -1,158 +0,0 @@
#include <system.h>
#include <generated/csr.h>
#include "log.h"
#include "analyzer.h"
#ifdef CSR_RTIO_ANALYZER_BASE
struct analyzer_header {
unsigned int sent_bytes;
unsigned long long int total_byte_count;
unsigned char overflow_occured;
unsigned char log_channel;
unsigned char dds_onehot_sel;
} __attribute__((packed));
#define ANALYZER_BUFFER_SIZE (512*1024)
static struct analyzer_header analyzer_header;
static char analyzer_buffer[ANALYZER_BUFFER_SIZE] __attribute__((aligned(64)));
static void arm(void)
{
rtio_analyzer_message_encoder_overflow_reset_write(1);
rtio_analyzer_dma_base_address_write((unsigned int)analyzer_buffer);
rtio_analyzer_dma_last_address_write((unsigned int)analyzer_buffer + ANALYZER_BUFFER_SIZE - 1);
rtio_analyzer_dma_reset_write(1);
rtio_analyzer_enable_write(1);
}
static void disarm(void)
{
rtio_analyzer_enable_write(0);
while(rtio_analyzer_busy_read());
flush_cpu_dcache();
flush_l2_cache();
}
void analyzer_init(void)
{
arm();
}
enum {
SEND_STATE_HEADER,
SEND_STATE_POST_POINTER, /* send from pointer to end of buffer */
SEND_STATE_PRE_POINTER, /* send from start of buffer to pointer-1 */
SEND_STATE_TERMINATE
};
static int send_state;
static int pointer;
static int wraparound;
static int offset_consumed;
static int offset_sent;
void analyzer_start(void)
{
disarm();
analyzer_header.total_byte_count = rtio_analyzer_dma_byte_count_read();
pointer = analyzer_header.total_byte_count % ANALYZER_BUFFER_SIZE;
wraparound = analyzer_header.total_byte_count >= ANALYZER_BUFFER_SIZE;
if(wraparound)
analyzer_header.sent_bytes = ANALYZER_BUFFER_SIZE;
else
analyzer_header.sent_bytes = analyzer_header.total_byte_count;
analyzer_header.overflow_occured = rtio_analyzer_message_encoder_overflow_read();
analyzer_header.log_channel = CONFIG_RTIO_LOG_CHANNEL;
#ifdef CONFIG_DDS_ONEHOT_SEL
analyzer_header.dds_onehot_sel = 1;
#else
analyzer_header.dds_onehot_sel = 0;
#endif
offset_consumed = 0;
offset_sent = 0;
send_state = SEND_STATE_HEADER;
}
void analyzer_end(void)
{
arm();
}
int analyzer_input(void *data, int length)
{
core_log("no input should be received by analyzer, dropping connection\n");
return -1;
}
void analyzer_poll(void **data, int *length, int *close_flag)
{
*close_flag = 0;
switch(send_state) {
case SEND_STATE_HEADER:
*length = sizeof(struct analyzer_header) - offset_consumed;
*data = (char *)&analyzer_header + offset_consumed;
break;
case SEND_STATE_POST_POINTER:
*length = ANALYZER_BUFFER_SIZE - pointer - offset_consumed;
*data = analyzer_buffer + pointer + offset_consumed;
break;
case SEND_STATE_PRE_POINTER:
*length = pointer - offset_consumed;
*data = analyzer_buffer + offset_consumed;
break;
case SEND_STATE_TERMINATE:
*length = -1;
break;
default:
*length = 0;
break;
}
}
void analyzer_ack_consumed(int length)
{
offset_consumed += length;
}
void analyzer_ack_sent(int length)
{
offset_sent += length;
switch(send_state) {
case SEND_STATE_HEADER:
if(offset_sent >= sizeof(struct analyzer_header)) {
offset_consumed = 0;
offset_sent = 0;
if(wraparound)
send_state = SEND_STATE_POST_POINTER;
else {
if(pointer)
send_state = SEND_STATE_PRE_POINTER;
else
send_state = SEND_STATE_TERMINATE;
}
}
break;
case SEND_STATE_POST_POINTER:
if(pointer + offset_consumed >= ANALYZER_BUFFER_SIZE) {
offset_consumed = 0;
offset_sent = 0;
send_state = SEND_STATE_PRE_POINTER;
}
break;
case SEND_STATE_PRE_POINTER:
if(offset_sent >= pointer)
send_state = SEND_STATE_TERMINATE;
break;
}
}
#endif

View File

@ -1,14 +0,0 @@
#ifndef __ANALYZER_H
#define __ANALYZER_H
void analyzer_init(void);
void analyzer_start(void);
void analyzer_end(void);
int analyzer_input(void *data, int length);
void analyzer_poll(void **data, int *length, int *close_flag);
void analyzer_ack_consumed(int length);
void analyzer_ack_sent(int length);
#endif /* __ANALYZER_H */

View File

@ -1,89 +0,0 @@
#include <generated/csr.h>
#include "log.h"
#include "clock.h"
void clock_init(void)
{
timer0_en_write(0);
timer0_load_write(0x7fffffffffffffffLL);
timer0_reload_write(0x7fffffffffffffffLL);
timer0_en_write(1);
}
long long int clock_get_ms(void)
{
long long int clock_sys;
long long int clock_ms;
timer0_update_value_write(1);
clock_sys = 0x7fffffffffffffffLL - timer0_value_read();
clock_ms = clock_sys/(CONFIG_CLOCK_FREQUENCY/1000);
return clock_ms;
}
void busywait_us(long long int us)
{
long long int threshold;
timer0_update_value_write(1);
threshold = timer0_value_read() - us*CONFIG_CLOCK_FREQUENCY/1000000LL;
while(timer0_value_read() > threshold)
timer0_update_value_write(1);
}
struct watchdog {
int active;
long long int threshold;
};
static struct watchdog watchdogs[MAX_WATCHDOGS];
void watchdog_init(void)
{
int i;
for(i=0;i<MAX_WATCHDOGS;i++)
watchdogs[i].active = 0;
}
int watchdog_set(int ms)
{
int i, id;
id = -1;
for(i=0;i<MAX_WATCHDOGS;i++)
if(!watchdogs[i].active) {
id = i;
break;
}
if(id < 0) {
core_log("WARNING: Failed to add watchdog\n");
return id;
}
watchdogs[id].active = 1;
watchdogs[id].threshold = clock_get_ms() + ms;
return id;
}
void watchdog_clear(int id)
{
if((id < 0) || (id >= MAX_WATCHDOGS))
return;
watchdogs[id].active = 0;
}
int watchdog_expired(void)
{
int i;
long long int t;
t = 0x7fffffffffffffffLL;
for(i=0;i<MAX_WATCHDOGS;i++)
if(watchdogs[i].active && (watchdogs[i].threshold < t))
t = watchdogs[i].threshold;
return clock_get_ms() > t;
}

View File

@ -1,15 +0,0 @@
#ifndef __CLOCK_H
#define __CLOCK_H
void clock_init(void);
long long int clock_get_ms(void);
void busywait_us(long long us);
#define MAX_WATCHDOGS 16
void watchdog_init(void);
int watchdog_set(int ms);
void watchdog_clear(int id);
int watchdog_expired(void);
#endif /* __CLOCK_H */

View File

@ -6,7 +6,6 @@
#include "artiq_personality.h" #include "artiq_personality.h"
#include "rtio.h" #include "rtio.h"
#include "log.h"
#include "dds.h" #include "dds.h"
#define DURATION_WRITE (5 << CONFIG_RTIO_FINE_TS_WIDTH) #define DURATION_WRITE (5 << CONFIG_RTIO_FINE_TS_WIDTH)

View File

@ -9,7 +9,6 @@
#include <generated/mem.h> #include <generated/mem.h>
#include <generated/csr.h> #include <generated/csr.h>
#include "log.h"
#include "flash_storage.h" #include "flash_storage.h"
#if (defined CSR_SPIFLASH_BASE && defined CONFIG_SPIFLASH_PAGE_SIZE) #if (defined CSR_SPIFLASH_BASE && defined CONFIG_SPIFLASH_PAGE_SIZE)
@ -63,24 +62,24 @@ static int record_iter_next(struct iter_state *is, struct record *record, int *f
return 0; return 0;
if(record->size < 6) { if(record->size < 6) {
core_log("flash_storage might be corrupted: record size is %u (<6) at address %08x\n", // core_log("flash_storage might be corrupted: record size is %u (<6) at address %08x\n",
record->size, record->raw_record); // record->size, record->raw_record);
if(fatal) if(fatal)
*fatal = 1; *fatal = 1;
return 0; return 0;
} }
if(is->seek > is->buf_len - sizeof(record->size) - 2) { /* 2 is the minimum key length */ if(is->seek > is->buf_len - sizeof(record->size) - 2) { /* 2 is the minimum key length */
core_log("flash_storage might be corrupted: END_MARKER missing at the end of " // core_log("flash_storage might be corrupted: END_MARKER missing at the end of "
"the storage sector\n"); // "the storage sector\n");
if(fatal) if(fatal)
*fatal = 1; *fatal = 1;
return 0; return 0;
} }
if(record->size > is->buf_len - is->seek) { if(record->size > is->buf_len - is->seek) {
core_log("flash_storage might be corrupted: invalid record_size %d at address %08x\n", // core_log("flash_storage might be corrupted: invalid record_size %d at address %08x\n",
record->size, record->raw_record); // record->size, record->raw_record);
if(fatal) if(fatal)
*fatal = 1; *fatal = 1;
return 0; return 0;
@ -90,8 +89,8 @@ static int record_iter_next(struct iter_state *is, struct record *record, int *f
record->key_len = strnlen(record->key, record->size - sizeof(record->size)) + 1; record->key_len = strnlen(record->key, record->size - sizeof(record->size)) + 1;
if(record->key_len == record->size - sizeof(record->size) + 1) { if(record->key_len == record->size - sizeof(record->size) + 1) {
core_log("flash_storage might be corrupted: invalid key length at address %08x\n", // core_log("flash_storage might be corrupted: invalid key length at address %08x\n",
record->raw_record); // record->raw_record);
if(fatal) if(fatal)
*fatal = 1; *fatal = 1;
return 0; return 0;
@ -265,7 +264,7 @@ int fs_write(const char *key, const void *buffer, unsigned int buf_len)
return 0; // Storage is definitely full. return 0; // Storage is definitely full.
fatal_error: fatal_error:
core_log("fatal error: flash storage might be corrupted\n"); // core_log("fatal error: flash storage might be corrupted\n");
return 0; return 0;
} }
@ -295,8 +294,8 @@ unsigned int fs_read(const char *key, void *buffer, unsigned int buf_len, unsign
} }
} }
if(fatal) // if(fatal)
core_log("fatal error: flash storage might be corrupted\n"); // core_log("fatal error: flash storage might be corrupted\n");
return read_length; return read_length;
} }

View File

@ -1,179 +0,0 @@
#include <string.h>
#include <generated/csr.h>
#include "kloader.h"
#include "log.h"
#include "clock.h"
#include "flash_storage.h"
#include "mailbox.h"
#include "messages.h"
int kloader_load_library(const void *library)
{
if(!kernel_cpu_reset_read()) {
core_log("BUG: attempted to load kernel library while kernel CPU is running\n");
return 0;
}
// Stop kernel CPU before messing with its code.
kernel_cpu_reset_write(1);
// Load kernel support code.
extern void _binary_ksupport_elf_start, _binary_ksupport_elf_end;
memcpy((void *)(KERNELCPU_EXEC_ADDRESS - KSUPPORT_HEADER_SIZE),
&_binary_ksupport_elf_start,
&_binary_ksupport_elf_end - &_binary_ksupport_elf_start);
// Start kernel CPU.
kernel_cpu_reset_write(0);
struct msg_load_request request = {
.type = MESSAGE_TYPE_LOAD_REQUEST,
.library = library,
};
mailbox_send(&request);
struct msg_load_reply *reply = mailbox_wait_and_receive();
if(reply->type != MESSAGE_TYPE_LOAD_REPLY) {
core_log("BUG: unexpected reply to load/run request\n");
return 0;
}
if(reply->error != NULL) {
core_log("cannot load kernel: %s\n", reply->error);
return 0;
}
return 1;
}
void kloader_start_kernel()
{
if(kernel_cpu_reset_read()) {
core_log("BUG: attempted to load kernel library while kernel CPU is stopped\n");
return;
}
mailbox_acknowledge();
}
static int kloader_start_flash_kernel(char *key)
{
#if (defined CSR_SPIFLASH_BASE && defined CONFIG_SPIFLASH_PAGE_SIZE)
char buffer[32*1024];
unsigned int length, remain;
length = fs_read(key, buffer, sizeof(buffer), &remain);
if(length <= 0)
return 0;
if(remain) {
core_log("ERROR: kernel %s is too large\n", key);
return 0;
}
if(!kloader_load_library(buffer))
return 0;
kloader_start_kernel();
return 1;
#else
return 0;
#endif
}
int kloader_start_startup_kernel(void)
{
return kloader_start_flash_kernel("startup_kernel");
}
int kloader_start_idle_kernel(void)
{
return kloader_start_flash_kernel("idle_kernel");
}
void kloader_stop(void)
{
kernel_cpu_reset_write(1);
mailbox_acknowledge();
}
int kloader_validate_kpointer(void *p)
{
unsigned int v = (unsigned int)p;
if((v < KERNELCPU_EXEC_ADDRESS) || (v > KERNELCPU_LAST_ADDRESS)) {
core_log("Received invalid pointer from kernel CPU: 0x%08x\n", v);
return 0;
}
return 1;
}
int kloader_is_essential_kmsg(int msgtype)
{
switch(msgtype) {
case MESSAGE_TYPE_NOW_INIT_REQUEST:
case MESSAGE_TYPE_NOW_SAVE:
case MESSAGE_TYPE_LOG:
case MESSAGE_TYPE_WATCHDOG_SET_REQUEST:
case MESSAGE_TYPE_WATCHDOG_CLEAR:
return 1;
default:
return 0;
}
}
static long long int now = 0;
void kloader_service_essential_kmsg(void)
{
struct msg_base *umsg;
umsg = mailbox_receive();
if(umsg) {
if(!kloader_validate_kpointer(umsg))
return;
switch(umsg->type) {
case MESSAGE_TYPE_NOW_INIT_REQUEST: {
struct msg_now_init_reply reply;
reply.type = MESSAGE_TYPE_NOW_INIT_REPLY;
reply.now = now;
mailbox_send_and_wait(&reply);
break;
}
case MESSAGE_TYPE_NOW_SAVE: {
struct msg_now_save *msg = (struct msg_now_save *)umsg;
now = msg->now;
mailbox_acknowledge();
break;
}
case MESSAGE_TYPE_LOG: {
struct msg_log *msg = (struct msg_log *)umsg;
core_log("%s", msg->buf);
mailbox_acknowledge();
break;
}
case MESSAGE_TYPE_WATCHDOG_SET_REQUEST: {
struct msg_watchdog_set_request *msg = (struct msg_watchdog_set_request *)umsg;
struct msg_watchdog_set_reply reply;
reply.type = MESSAGE_TYPE_WATCHDOG_SET_REPLY;
reply.id = watchdog_set(msg->ms);
mailbox_send_and_wait(&reply);
break;
}
case MESSAGE_TYPE_WATCHDOG_CLEAR: {
struct msg_watchdog_clear *msg = (struct msg_watchdog_clear *)umsg;
watchdog_clear(msg->id);
mailbox_acknowledge();
break;
}
default:
/* handled elsewhere */
break;
}
}
}

View File

@ -1,20 +0,0 @@
#ifndef __KLOADER_H
#define __KLOADER_H
#define KERNELCPU_EXEC_ADDRESS 0x42000000
#define KERNELCPU_PAYLOAD_ADDRESS 0x42020000
#define KERNELCPU_LAST_ADDRESS (0x4fffffff - 1024*1024)
#define KSUPPORT_HEADER_SIZE 0x80
int kloader_load_library(const void *code);
int kloader_start_startup_kernel(void);
int kloader_start_idle_kernel(void);
void kloader_start_kernel(void);
void kloader_stop(void);
int kloader_validate_kpointer(void *p);
int kloader_is_essential_kmsg(int msgtype);
void kloader_service_essential_kmsg(void);
#endif /* __KLOADER_H */

View File

@ -9,7 +9,6 @@
#include <unwind.h> #include <unwind.h>
#include "ksupport.h" #include "ksupport.h"
#include "kloader.h"
#include "mailbox.h" #include "mailbox.h"
#include "messages.h" #include "messages.h"
#include "artiq_personality.h" #include "artiq_personality.h"
@ -17,6 +16,11 @@
#include "dds.h" #include "dds.h"
#include "i2c.h" #include "i2c.h"
#define KERNELCPU_EXEC_ADDRESS 0x42000000
#define KERNELCPU_PAYLOAD_ADDRESS 0x42020000
#define KERNELCPU_LAST_ADDRESS (0x4fffffff - 1024*1024)
#define KSUPPORT_HEADER_SIZE 0x80
double round(double x); double round(double x);
double sqrt(double x); double sqrt(double x);

View File

@ -1,51 +0,0 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <console.h>
#include <generated/csr.h>
#include "log.h"
static int buffer_cursor;
static char buffer[LOG_BUFFER_SIZE];
void core_log(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
core_log_va(fmt, args);
va_end(args);
}
void core_log_va(const char *fmt, va_list args)
{
char outbuf[256];
int len = vscnprintf(outbuf, sizeof(outbuf), fmt, args);
for(int i = 0; i < len; i++) {
buffer[buffer_cursor] = outbuf[i];
buffer_cursor = (buffer_cursor + 1) % LOG_BUFFER_SIZE;
}
#ifdef CSR_ETHMAC_BASE
/* Since main comms are over ethernet, the serial port
* is free for us to use. */
putsnonl(outbuf);
#endif
}
void core_log_get(char *outbuf)
{
int j = buffer_cursor;
for(int i = 0; i < LOG_BUFFER_SIZE; i++) {
outbuf[i] = buffer[j];
j = (j + 1) % LOG_BUFFER_SIZE;
}
}
void core_log_clear()
{
memset(buffer, 0, sizeof(buffer));
}

View File

@ -1,13 +0,0 @@
#ifndef __LOG_H
#define __LOG_H
#include <stdarg.h>
#define LOG_BUFFER_SIZE 4096
void core_log(const char *fmt, ...);
void core_log_va(const char *fmt, va_list args);
void core_log_get(char *outbuf);
void core_log_clear(void);
#endif /* __LOG_H */

View File

@ -24,24 +24,7 @@
#include <netif/ppp/pppos.h> #include <netif/ppp/pppos.h>
#endif #endif
#include "kloader.h"
#include "flash_storage.h" #include "flash_storage.h"
#include "clock.h"
#include "rtiocrg.h"
#include "net_server.h"
#include "session.h"
#include "analyzer.h"
#include "moninj.h"
u32_t sys_now(void)
{
return clock_get_ms();
}
u32_t sys_jiffies(void)
{
return clock_get_ms();
}
static struct netif netif; static struct netif netif;
@ -182,53 +165,6 @@ void network_init(void)
#endif /* CSR_ETHMAC_BASE */ #endif /* CSR_ETHMAC_BASE */
static struct net_server_instance session_inst = {
.port = 1381,
.start = session_start,
.end = session_end,
.input = session_input,
.poll = session_poll,
.ack_consumed = session_ack_consumed,
.ack_sent = session_ack_sent
};
#ifdef CSR_RTIO_ANALYZER_BASE
static struct net_server_instance analyzer_inst = {
.port = 1382,
.start = analyzer_start,
.end = analyzer_end,
.input = analyzer_input,
.poll = analyzer_poll,
.ack_consumed = analyzer_ack_consumed,
.ack_sent = analyzer_ack_sent
};
#endif
static void regular_main(void)
{
puts("ARTIQ runtime built "__DATE__" "__TIME__"\n");
clock_init();
rtiocrg_init();
session_startup_kernel();
puts("Accepting network sessions.");
network_init();
net_server_init(&session_inst);
#ifdef CSR_RTIO_ANALYZER_BASE
analyzer_init();
net_server_init(&analyzer_inst);
#endif
moninj_init();
session_end();
while(1) {
lwip_service();
kloader_service_essential_kmsg();
net_server_service();
}
}
extern void _fheap, _eheap; extern void _fheap, _eheap;
extern void rust_main(); extern void rust_main();
@ -249,8 +185,7 @@ int main(void)
alloc_give(&_fheap, &_eheap - &_fheap); alloc_give(&_fheap, &_eheap - &_fheap);
// rust_main(); rust_main();
regular_main();
return 0; return 0;
} }

View File

@ -1,166 +0,0 @@
#include <generated/csr.h>
#include <lwip/init.h>
#include <lwip/memp.h>
#include <lwip/ip4_addr.h>
#include <lwip/ip4.h>
#include <lwip/netif.h>
#include <lwip/sys.h>
#include <lwip/udp.h>
#include <lwip/timers.h>
#include "log.h"
#include "moninj.h"
enum {
MONINJ_REQ_MONITOR = 1,
MONINJ_REQ_TTLSET = 2
};
enum {
MONINJ_TTL_MODE_EXP = 0,
MONINJ_TTL_MODE_1 = 1,
MONINJ_TTL_MODE_0 = 2,
MONINJ_TTL_MODE_IN = 3
};
enum {
MONINJ_TTL_OVERRIDE_ENABLE = 0,
MONINJ_TTL_OVERRIDE_O = 1,
MONINJ_TTL_OVERRIDE_OE = 2
};
static struct udp_pcb *listen_pcb;
struct monitor_reply {
long long int ttl_levels;
long long int ttl_oes;
long long int ttl_overrides;
unsigned short int dds_rtio_first_channel;
unsigned short int dds_channels_per_bus;
#if ((defined CONFIG_RTIO_DDS_COUNT) && (CONFIG_RTIO_DDS_COUNT > 0))
unsigned int dds_ftws[CONFIG_RTIO_DDS_COUNT*CONFIG_DDS_CHANNELS_PER_BUS];
#endif
} __attribute__((packed));
static void moninj_monitor(const ip_addr_t *addr, u16_t port)
{
struct monitor_reply reply;
int i;
struct pbuf *reply_p;
reply.ttl_levels = 0;
reply.ttl_oes = 0;
reply.ttl_overrides = 0;
for(i=0;i<CONFIG_RTIO_REGULAR_TTL_COUNT;i++) {
rtio_moninj_mon_chan_sel_write(i);
rtio_moninj_mon_probe_sel_write(0);
rtio_moninj_mon_value_update_write(1);
if(rtio_moninj_mon_value_read())
reply.ttl_levels |= 1LL << i;
rtio_moninj_mon_probe_sel_write(1);
rtio_moninj_mon_value_update_write(1);
if(rtio_moninj_mon_value_read())
reply.ttl_oes |= 1LL << i;
rtio_moninj_inj_chan_sel_write(i);
rtio_moninj_inj_override_sel_write(MONINJ_TTL_OVERRIDE_ENABLE);
if(rtio_moninj_inj_value_read())
reply.ttl_overrides |= 1LL << i;
}
#if ((defined CONFIG_RTIO_DDS_COUNT) && (CONFIG_RTIO_DDS_COUNT > 0))
int j;
reply.dds_rtio_first_channel = CONFIG_RTIO_FIRST_DDS_CHANNEL;
reply.dds_channels_per_bus = CONFIG_DDS_CHANNELS_PER_BUS;
for(j=0;j<CONFIG_RTIO_DDS_COUNT;j++) {
rtio_moninj_mon_chan_sel_write(CONFIG_RTIO_FIRST_DDS_CHANNEL+j);
for(i=0;i<CONFIG_DDS_CHANNELS_PER_BUS;i++) {
rtio_moninj_mon_probe_sel_write(i);
rtio_moninj_mon_value_update_write(1);
reply.dds_ftws[CONFIG_DDS_CHANNELS_PER_BUS*j+i] = rtio_moninj_mon_value_read();
}
}
#else
reply.dds_rtio_first_channel = 0;
reply.dds_channels_per_bus = 0;
#endif
reply_p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct monitor_reply), PBUF_RAM);
if(!reply_p) {
core_log("Failed to allocate pbuf for monitor reply\n");
return;
}
memcpy(reply_p->payload, &reply, sizeof(struct monitor_reply));
udp_sendto(listen_pcb, reply_p, addr, port);
pbuf_free(reply_p);
}
static void moninj_ttlset(int channel, int mode)
{
rtio_moninj_inj_chan_sel_write(channel);
switch(mode) {
case MONINJ_TTL_MODE_EXP:
rtio_moninj_inj_override_sel_write(MONINJ_TTL_OVERRIDE_ENABLE);
rtio_moninj_inj_value_write(0);
break;
case MONINJ_TTL_MODE_1:
rtio_moninj_inj_override_sel_write(MONINJ_TTL_OVERRIDE_O);
rtio_moninj_inj_value_write(1);
rtio_moninj_inj_override_sel_write(MONINJ_TTL_OVERRIDE_OE);
rtio_moninj_inj_value_write(1);
rtio_moninj_inj_override_sel_write(MONINJ_TTL_OVERRIDE_ENABLE);
rtio_moninj_inj_value_write(1);
break;
case MONINJ_TTL_MODE_0:
rtio_moninj_inj_override_sel_write(MONINJ_TTL_OVERRIDE_O);
rtio_moninj_inj_value_write(0);
rtio_moninj_inj_override_sel_write(MONINJ_TTL_OVERRIDE_OE);
rtio_moninj_inj_value_write(1);
rtio_moninj_inj_override_sel_write(MONINJ_TTL_OVERRIDE_ENABLE);
rtio_moninj_inj_value_write(1);
break;
case MONINJ_TTL_MODE_IN:
rtio_moninj_inj_override_sel_write(MONINJ_TTL_OVERRIDE_OE);
rtio_moninj_inj_value_write(0);
rtio_moninj_inj_override_sel_write(MONINJ_TTL_OVERRIDE_ENABLE);
rtio_moninj_inj_value_write(1);
break;
default:
core_log("unknown TTL mode %d\n", mode);
break;
}
}
static void moninj_recv(void *arg, struct udp_pcb *upcb, struct pbuf *req,
const ip_addr_t *addr, u16_t port)
{
char *p = (char *)req->payload;
if(req->len >= 1) {
switch(p[0]) {
case MONINJ_REQ_MONITOR:
moninj_monitor(addr, port);
break;
case MONINJ_REQ_TTLSET:
if(req->len < 3)
break;
moninj_ttlset(p[1], p[2]);
break;
default:
break;
}
}
pbuf_free(req); /* beware: addr may point into the req pbuf */
}
void moninj_init(void)
{
listen_pcb = udp_new();
if(!listen_pcb) {
core_log("Failed to create UDP listening PCB\n");
return;
}
udp_bind(listen_pcb, IP_ADDR_ANY, 3250);
udp_recv(listen_pcb, moninj_recv, NULL);
}

View File

@ -1,6 +0,0 @@
#ifndef __MONINJ_H
#define __MONINJ_H
void moninj_init(void);
#endif /* __MONINJ_H */

View File

@ -1,227 +0,0 @@
#include <generated/csr.h>
#include <lwip/init.h>
#include <lwip/memp.h>
#include <lwip/ip4_addr.h>
#include <lwip/ip4.h>
#include <lwip/netif.h>
#include <lwip/sys.h>
#include <lwip/tcp.h>
#include <lwip/timers.h>
#include "net_server.h"
struct net_server_connstate {
struct net_server_instance *instance;
int magic_recognized;
struct pbuf *rp;
int rp_offset;
};
static struct net_server_connstate *cs_new(struct net_server_instance *instance)
{
struct net_server_connstate *cs;
cs = (struct net_server_connstate *)mem_malloc(sizeof(struct net_server_connstate));
if(!cs)
return NULL;
cs->instance = instance;
cs->magic_recognized = 0;
cs->rp = NULL;
cs->rp_offset = 0;
return cs;
}
static void cs_free(struct net_server_connstate *cs)
{
if(cs->rp)
pbuf_free(cs->rp);
mem_free(cs);
}
static const char net_server_magic[] = "ARTIQ coredev\n";
static int magic_ok(struct net_server_connstate *cs)
{
return cs->magic_recognized >= 14;
}
static void net_server_close(struct net_server_connstate *cs, struct tcp_pcb *pcb)
{
struct net_server_instance *instance;
instance = cs->instance;
if(cs == instance->open_session_cs) {
instance->end();
instance->open_session_cs = NULL;
instance->open_session_pcb = NULL;
}
if(pcb) {
/* lwip loves to call back with broken pointers. Prevent that. */
tcp_arg(pcb, NULL);
tcp_recv(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_err(pcb, NULL);
tcp_close(pcb);
}
cs_free(cs);
}
static err_t net_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct net_server_connstate *cs;
cs = (struct net_server_connstate *)arg;
if(p) {
if(cs->rp)
pbuf_cat(cs->rp, p);
else {
cs->rp = p;
cs->rp_offset = 0;
}
} else
net_server_close(cs, pcb);
return ERR_OK;
}
static err_t net_server_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
struct net_server_connstate *cs;
cs = (struct net_server_connstate *)arg;
cs->instance->ack_sent(len);
return ERR_OK;
}
static void tcp_pcb_service(void *arg, struct tcp_pcb *pcb)
{
struct net_server_connstate *cs;
struct net_server_instance *instance;
int remaining_in_pbuf;
char *rpp;
struct pbuf *next;
int r;
cs = (struct net_server_connstate *)arg;
instance = cs->instance;
/* Reader interface */
while(cs->rp) {
remaining_in_pbuf = cs->rp->len - cs->rp_offset;
rpp = (char *)cs->rp->payload;
while(remaining_in_pbuf > 0) {
if(cs == instance->open_session_cs) {
r = instance->input(&rpp[cs->rp_offset], remaining_in_pbuf);
if(r > 0) {
tcp_recved(pcb, r);
cs->rp_offset += r;
remaining_in_pbuf -= r;
} else if(r == 0)
return;
else
net_server_close(cs, pcb);
} else {
if(rpp[cs->rp_offset] == net_server_magic[cs->magic_recognized]) {
cs->magic_recognized++;
if(magic_ok(cs)) {
if(instance->open_session_cs)
net_server_close(instance->open_session_cs,
instance->open_session_pcb);
instance->start();
instance->open_session_cs = cs;
instance->open_session_pcb = pcb;
tcp_sent(pcb, net_server_sent);
}
} else {
net_server_close(cs, pcb);
return;
}
remaining_in_pbuf--;
cs->rp_offset++;
tcp_recved(pcb, 1);
}
}
next = cs->rp->next;
if(cs->rp->tot_len != cs->rp->len) {
pbuf_ref(next);
pbuf_free(cs->rp);
cs->rp = next;
cs->rp_offset = 0;
} else {
pbuf_free(cs->rp);
cs->rp = NULL;
}
}
/* Writer interface */
if(cs == instance->open_session_cs) {
void *data;
int len, sndbuf, close_flag;
cs->instance->poll(&data, &len, &close_flag);
if(len > 0) {
sndbuf = tcp_sndbuf(pcb);
if(len > sndbuf)
len = sndbuf;
tcp_write(pcb, data, len, 0);
instance->ack_consumed(len);
}
if(close_flag)
tcp_output(pcb);
if((len < 0) || close_flag)
net_server_close(cs, pcb);
}
}
static void net_server_err(void *arg, err_t err)
{
struct net_server_connstate *cs;
cs = (struct net_server_connstate *)arg;
net_server_close(cs, NULL);
}
static err_t net_server_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
{
struct net_server_instance *instance;
struct net_server_connstate *cs;
instance = (struct net_server_instance *)arg;
cs = cs_new(instance);
if(!cs)
return ERR_MEM;
tcp_accepted(instance->listen_pcb);
tcp_arg(newpcb, cs);
tcp_recv(newpcb, net_server_recv);
tcp_err(newpcb, net_server_err);
return ERR_OK;
}
void net_server_init(struct net_server_instance *instance)
{
struct tcp_pcb *bind_pcb;
bind_pcb = tcp_new();
bind_pcb->so_options |= SOF_KEEPALIVE;
tcp_bind(bind_pcb, IP_ADDR_ANY, instance->port);
instance->listen_pcb = tcp_listen(bind_pcb);
tcp_arg(instance->listen_pcb, instance);
tcp_accept(instance->listen_pcb, net_server_accept);
}
extern struct tcp_pcb *tcp_active_pcbs;
void net_server_service(void)
{
struct tcp_pcb *pcb;
pcb = tcp_active_pcbs;
while(pcb) {
if(pcb->recv == net_server_recv) /* filter our connections */
tcp_pcb_service(pcb->callback_arg, pcb);
pcb = pcb->next;
}
}

View File

@ -1,26 +0,0 @@
#ifndef __NET_SERVER_H
#define __NET_SERVER_H
struct net_server_connstate;
struct tcp_pcb;
struct net_server_instance {
int port;
void (*start)(void);
void (*end)(void);
int (*input)(void *data, int length);
void (*poll)(void **data, int *length, int *close_flag);
void (*ack_consumed)(int length);
void (*ack_sent)(int length);
/* internal use */
struct tcp_pcb *listen_pcb;
struct net_server_connstate *open_session_cs;
struct tcp_pcb *open_session_pcb;
};
void net_server_init(struct net_server_instance *instance);
void net_server_service(void);
#endif /* __NET_SERVER_H */

View File

@ -1,71 +0,0 @@
#include <generated/csr.h>
#include "log.h"
#include "clock.h"
#include "flash_storage.h"
#include "rtiocrg.h"
void rtiocrg_init(void)
{
char b;
int clk;
#ifdef CSR_RTIO_CRG_PLL_RESET_ADDR
rtio_crg_pll_reset_write(0);
#endif
b = 'i';
clk = 0;
fs_read("startup_clock", &b, 1, NULL);
if(b == 'i')
core_log("Startup RTIO clock: internal\n");
else if(b == 'e') {
core_log("Startup RTIO clock: external\n");
clk = 1;
} else
core_log("ERROR: unrecognized startup_clock entry in flash storage\n");
if(!rtiocrg_switch_clock(clk)) {
core_log("ERROR: startup RTIO clock failed\n");
core_log("WARNING: this may cause the system initialization to fail\n");
core_log("WARNING: fix clocking and reset the device\n");
}
}
int rtiocrg_check(void)
{
#if ((defined CSR_RTIO_CRG_BASE) && (defined CSR_RTIO_CRG_PLL_RESET_ADDR))
return rtio_crg_pll_locked_read();
#else
return 1;
#endif
}
int rtiocrg_switch_clock(int clk)
{
#ifdef CSR_RTIO_CRG_BASE
int current_clk;
current_clk = rtio_crg_clock_sel_read();
if(clk == current_clk) {
#ifdef CSR_RTIO_CRG_PLL_RESET_ADDR
busywait_us(150);
if(!rtio_crg_pll_locked_read())
return 0;
#endif
return 1;
}
#ifdef CSR_RTIO_CRG_PLL_RESET_ADDR
rtio_crg_pll_reset_write(1);
#endif
rtio_crg_clock_sel_write(clk);
#ifdef CSR_RTIO_CRG_PLL_RESET_ADDR
rtio_crg_pll_reset_write(0);
busywait_us(150);
if(!rtio_crg_pll_locked_read())
return 0;
#endif
return 1;
#else /* CSR_RTIO_CRG_BASE */
return 1;
#endif
}

View File

@ -1,8 +0,0 @@
#ifndef __RTIOCRG_H
#define __RTIOCRG_H
void rtiocrg_init(void);
int rtiocrg_check(void);
int rtiocrg_switch_clock(int clk);
#endif /* __RTIOCRG_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +0,0 @@
#ifndef __SESSION_H
#define __SESSION_H
void session_startup_kernel(void);
void session_start(void);
void session_end(void);
int session_input(void *data, int length);
void session_poll(void **data, int *length, int *close_flag);
void session_ack_consumed(int length);
void session_ack_sent(int length);
#endif /* __SESSION_H */