forked from M-Labs/artiq
runtime: the Rust runtime is now just the runtime.
This commit is contained in:
parent
3e829d0d01
commit
5428a866b3
|
@ -29,7 +29,6 @@ pub mod prelude {
|
|||
}
|
||||
}
|
||||
|
||||
pub mod time;
|
||||
pub mod error;
|
||||
pub mod io;
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
pub use self::duration::Duration;
|
||||
pub use self::instant::Instant;
|
||||
|
||||
mod duration;
|
||||
mod instant;
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
use std::cell::RefCell;
|
||||
use std::vec::Vec;
|
||||
use std::time::{Instant, Duration};
|
||||
use std::io::{Read, Write, Result, Error, ErrorKind};
|
||||
use fringe::OwnedStack;
|
||||
use fringe::generator::{Generator, Yielder, State as GeneratorState};
|
||||
use lwip;
|
||||
use clock;
|
||||
use urc::Urc;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct WaitRequest {
|
||||
timeout: Option<Instant>,
|
||||
timeout: Option<u64>,
|
||||
event: Option<WaitEvent>
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ impl Scheduler {
|
|||
|
||||
if self.threads.len() == 0 { return }
|
||||
|
||||
let now = Instant::now();
|
||||
let now = clock::get_ms();
|
||||
|
||||
let start_index = self.index;
|
||||
loop {
|
||||
|
@ -214,9 +214,9 @@ unsafe impl Send for WaitEvent {}
|
|||
pub struct Waiter<'a>(&'a Yielder<WaitResult, WaitRequest, OwnedStack>);
|
||||
|
||||
impl<'a> Waiter<'a> {
|
||||
pub fn sleep(&self, duration: Duration) -> Result<()> {
|
||||
pub fn sleep(&self, duration_ms: u64) -> Result<()> {
|
||||
let request = WaitRequest {
|
||||
timeout: Some(Instant::now() + duration),
|
||||
timeout: Some(clock::get_ms() + duration_ms),
|
||||
event: None
|
||||
};
|
||||
|
||||
|
|
|
@ -3,9 +3,7 @@ include $(MISOC_DIRECTORY)/software/common.mak
|
|||
|
||||
PYTHON ?= python3.5
|
||||
|
||||
OBJECTS := isr.o clock.o rtiocrg.o flash_storage.o mailbox.o \
|
||||
session.o log.o analyzer.o moninj.o net_server.o \
|
||||
ksupport_data.o kloader.o main.o
|
||||
OBJECTS := isr.o flash_storage.o ksupport_data.o main.o
|
||||
OBJECTS_KSUPPORT := ksupport.o artiq_personality.o mailbox.o \
|
||||
rtio.o dds.o i2c.o
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include "artiq_personality.h"
|
||||
#include "rtio.h"
|
||||
#include "log.h"
|
||||
#include "dds.h"
|
||||
|
||||
#define DURATION_WRITE (5 << CONFIG_RTIO_FINE_TS_WIDTH)
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include <generated/mem.h>
|
||||
#include <generated/csr.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "flash_storage.h"
|
||||
|
||||
#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;
|
||||
|
||||
if(record->size < 6) {
|
||||
core_log("flash_storage might be corrupted: record size is %u (<6) at address %08x\n",
|
||||
record->size, record->raw_record);
|
||||
// core_log("flash_storage might be corrupted: record size is %u (<6) at address %08x\n",
|
||||
// record->size, record->raw_record);
|
||||
if(fatal)
|
||||
*fatal = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 "
|
||||
"the storage sector\n");
|
||||
// core_log("flash_storage might be corrupted: END_MARKER missing at the end of "
|
||||
// "the storage sector\n");
|
||||
if(fatal)
|
||||
*fatal = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(record->size > is->buf_len - is->seek) {
|
||||
core_log("flash_storage might be corrupted: invalid record_size %d at address %08x\n",
|
||||
record->size, record->raw_record);
|
||||
// core_log("flash_storage might be corrupted: invalid record_size %d at address %08x\n",
|
||||
// record->size, record->raw_record);
|
||||
if(fatal)
|
||||
*fatal = 1;
|
||||
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;
|
||||
|
||||
if(record->key_len == record->size - sizeof(record->size) + 1) {
|
||||
core_log("flash_storage might be corrupted: invalid key length at address %08x\n",
|
||||
record->raw_record);
|
||||
// core_log("flash_storage might be corrupted: invalid key length at address %08x\n",
|
||||
// record->raw_record);
|
||||
if(fatal)
|
||||
*fatal = 1;
|
||||
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.
|
||||
|
||||
fatal_error:
|
||||
core_log("fatal error: flash storage might be corrupted\n");
|
||||
// core_log("fatal error: flash storage might be corrupted\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -295,8 +294,8 @@ unsigned int fs_read(const char *key, void *buffer, unsigned int buf_len, unsign
|
|||
}
|
||||
}
|
||||
|
||||
if(fatal)
|
||||
core_log("fatal error: flash storage might be corrupted\n");
|
||||
// if(fatal)
|
||||
// core_log("fatal error: flash storage might be corrupted\n");
|
||||
|
||||
return read_length;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 */
|
|
@ -9,7 +9,6 @@
|
|||
#include <unwind.h>
|
||||
|
||||
#include "ksupport.h"
|
||||
#include "kloader.h"
|
||||
#include "mailbox.h"
|
||||
#include "messages.h"
|
||||
#include "artiq_personality.h"
|
||||
|
@ -17,6 +16,11 @@
|
|||
#include "dds.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 sqrt(double x);
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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 */
|
|
@ -24,24 +24,7 @@
|
|||
#include <netif/ppp/pppos.h>
|
||||
#endif
|
||||
|
||||
#include "kloader.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;
|
||||
|
||||
|
@ -182,53 +165,6 @@ void network_init(void)
|
|||
#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 rust_main();
|
||||
|
@ -249,8 +185,7 @@ int main(void)
|
|||
|
||||
alloc_give(&_fheap, &_eheap - &_fheap);
|
||||
|
||||
// rust_main();
|
||||
regular_main();
|
||||
rust_main();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef __MONINJ_H
|
||||
#define __MONINJ_H
|
||||
|
||||
void moninj_init(void);
|
||||
|
||||
#endif /* __MONINJ_H */
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 */
|
|
@ -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
|
||||
}
|
|
@ -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
|
@ -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 */
|
Loading…
Reference in New Issue