mirror of https://github.com/m-labs/artiq.git
runtime,coredevice: Ethernet support (buggy)
This commit is contained in:
parent
1968304b4f
commit
934a6b0495
|
@ -18,6 +18,7 @@ class Comm(CommGeneric, AutoDB):
|
||||||
return
|
return
|
||||||
self.socket = socket.create_connection((self.host, self.port))
|
self.socket = socket.create_connection((self.host, self.port))
|
||||||
logger.debug("connected to host %s on port %d", self.host, self.port)
|
logger.debug("connected to host %s on port %d", self.host, self.port)
|
||||||
|
self.write(b"ARTIQ coredev\n")
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if not hasattr(self, "socket"):
|
if not hasattr(self, "socket"):
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"comm": {
|
"comm": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.comm_serial",
|
"module": "artiq.coredevice.comm_tcp",
|
||||||
"class": "Comm",
|
"class": "Comm",
|
||||||
"arguments": {"serial_dev": "/dev/ttyUSB1"}
|
"arguments": {"host": "192.168.0.42"}
|
||||||
},
|
},
|
||||||
"core": {
|
"core": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"comm": {
|
"comm": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.comm_serial",
|
"module": "artiq.coredevice.comm_tcp",
|
||||||
"class": "Comm",
|
"class": "Comm",
|
||||||
"arguments": {"serial_dev": "/dev/ttyUSB1"}
|
"arguments": {"host": "192.168.0.42"}
|
||||||
},
|
},
|
||||||
"core": {
|
"core": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <generated/csr.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
static int buffer_index;
|
static int buffer_index;
|
||||||
|
@ -18,6 +20,12 @@ void log_va(const char *fmt, va_list args)
|
||||||
}
|
}
|
||||||
buffer[buffer_index] = '\n';
|
buffer[buffer_index] = '\n';
|
||||||
buffer_index = (buffer_index + 1) % LOG_BUFFER_SIZE;
|
buffer_index = (buffer_index + 1) % LOG_BUFFER_SIZE;
|
||||||
|
|
||||||
|
#ifdef CSR_ETHMAC_BASE
|
||||||
|
/* Since main comms are over ethernet, the serial port
|
||||||
|
* is free for us to use. */
|
||||||
|
puts(outbuf);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void log(const char *fmt, ...)
|
void log(const char *fmt, ...)
|
||||||
|
|
|
@ -29,22 +29,13 @@ unsigned char macadr[6] = {0x10, 0xe2, 0xd5, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
u32_t clock_ms;
|
u32_t clock_ms;
|
||||||
|
|
||||||
static void clock_init(void)
|
|
||||||
{
|
|
||||||
timer0_en_write(0);
|
|
||||||
timer0_load_write(0xffffffff);
|
|
||||||
timer0_reload_write(0xffffffff);
|
|
||||||
timer0_en_write(1);
|
|
||||||
clock_ms = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32_t sys_now(void)
|
u32_t sys_now(void)
|
||||||
{
|
{
|
||||||
unsigned int freq;
|
unsigned int freq;
|
||||||
unsigned int prescaler;
|
unsigned int prescaler;
|
||||||
|
|
||||||
freq = identifier_frequency_read();
|
freq = identifier_frequency_read();
|
||||||
prescaler = freq/1000; /* sys_now expect time in ms */
|
prescaler = freq/1000; /* sys_now expects time in ms */
|
||||||
timer0_update_value_write(1);
|
timer0_update_value_write(1);
|
||||||
clock_ms += (0xffffffff - timer0_value_read())/prescaler;
|
clock_ms += (0xffffffff - timer0_value_read())/prescaler;
|
||||||
/* Reset timer to avoid rollover, this will increase clock_ms
|
/* Reset timer to avoid rollover, this will increase clock_ms
|
||||||
|
@ -64,47 +55,18 @@ static void lwip_service(void)
|
||||||
ethmac_sram_writer_ev_pending_write(ETHMAC_EV_SRAM_WRITER);
|
ethmac_sram_writer_ev_pending_write(ETHMAC_EV_SRAM_WRITER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void comm_service(void)
|
static void network_init(void)
|
||||||
{
|
{
|
||||||
char *txdata;
|
|
||||||
int txlen;
|
|
||||||
static char rxdata;
|
|
||||||
static int rxpending;
|
|
||||||
int r, i;
|
|
||||||
|
|
||||||
#ifdef CSR_ETHMAC_BASE
|
|
||||||
lwip_service();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(!rxpending && uart_read_nonblock()) {
|
|
||||||
rxdata = uart_read();
|
|
||||||
rxpending = 1;
|
|
||||||
}
|
|
||||||
if(rxpending) {
|
|
||||||
r = session_input(&rxdata, 1);
|
|
||||||
if(r > 0)
|
|
||||||
rxpending = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
session_poll((void **)&txdata, &txlen);
|
|
||||||
if(txlen > 0) {
|
|
||||||
for(i=0;i<txlen;i++)
|
|
||||||
uart_write(txdata[i]);
|
|
||||||
session_ack(txlen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void regular_main(void)
|
|
||||||
{
|
|
||||||
#ifdef CSR_ETHMAC_BASE
|
|
||||||
struct ip4_addr local_ip;
|
struct ip4_addr local_ip;
|
||||||
struct ip4_addr netmask;
|
struct ip4_addr netmask;
|
||||||
struct ip4_addr gateway_ip;
|
struct ip4_addr gateway_ip;
|
||||||
|
|
||||||
time_init();
|
timer0_en_write(0);
|
||||||
clock_init();
|
timer0_load_write(0xffffffff);
|
||||||
|
timer0_reload_write(0xffffffff);
|
||||||
|
timer0_en_write(1);
|
||||||
|
clock_ms = 0;
|
||||||
|
|
||||||
IP4_ADDR(&local_ip, 192, 168, 0, 42);
|
IP4_ADDR(&local_ip, 192, 168, 0, 42);
|
||||||
IP4_ADDR(&netmask, 255, 255, 255, 0);
|
IP4_ADDR(&netmask, 255, 255, 255, 0);
|
||||||
|
@ -116,13 +78,255 @@ static void regular_main(void)
|
||||||
netif_set_default(&netif);
|
netif_set_default(&netif);
|
||||||
netif_set_up(&netif);
|
netif_set_up(&netif);
|
||||||
netif_set_link_up(&netif);
|
netif_set_link_up(&netif);
|
||||||
#endif
|
|
||||||
|
|
||||||
session_start();
|
|
||||||
while(1)
|
|
||||||
comm_service();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct kserver_connstate {
|
||||||
|
int magic_recognized;
|
||||||
|
struct pbuf *rp;
|
||||||
|
int rp_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct kserver_connstate *cs_new(void)
|
||||||
|
{
|
||||||
|
struct kserver_connstate *cs;
|
||||||
|
|
||||||
|
cs = (struct kserver_connstate *)mem_malloc(sizeof(struct kserver_connstate));
|
||||||
|
if(!cs)
|
||||||
|
return NULL;
|
||||||
|
cs->magic_recognized = 0;
|
||||||
|
cs->rp = NULL;
|
||||||
|
cs->rp_offset = 0;
|
||||||
|
return cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cs_free(struct kserver_connstate *cs)
|
||||||
|
{
|
||||||
|
if(cs->rp)
|
||||||
|
pbuf_free(cs->rp);
|
||||||
|
mem_free(cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char kserver_magic[] = "ARTIQ coredev\n";
|
||||||
|
|
||||||
|
static int magic_ok(struct kserver_connstate *cs)
|
||||||
|
{
|
||||||
|
return cs->magic_recognized >= 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kserver_connstate *active_cs;
|
||||||
|
static struct tcp_pcb *active_pcb;
|
||||||
|
|
||||||
|
static void kserver_close(struct kserver_connstate *cs, struct tcp_pcb *pcb)
|
||||||
|
{
|
||||||
|
if(cs == active_cs) {
|
||||||
|
session_end();
|
||||||
|
active_cs = NULL;
|
||||||
|
active_pcb = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
cs_free(cs);
|
||||||
|
tcp_close(pcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static err_t kserver_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
||||||
|
{
|
||||||
|
struct kserver_connstate *cs;
|
||||||
|
|
||||||
|
cs = (struct kserver_connstate *)arg;
|
||||||
|
if(p) {
|
||||||
|
if(cs->rp)
|
||||||
|
pbuf_cat(cs->rp, p);
|
||||||
|
else {
|
||||||
|
cs->rp = p;
|
||||||
|
cs->rp_offset = 0;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
kserver_close(cs, pcb);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static err_t kserver_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
|
||||||
|
{
|
||||||
|
session_ack_mem(len);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcp_pcb_service(void *arg, struct tcp_pcb *pcb)
|
||||||
|
{
|
||||||
|
struct kserver_connstate *cs;
|
||||||
|
int remaining_in_pbuf;
|
||||||
|
char *rpp;
|
||||||
|
struct pbuf *next;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
cs = (struct kserver_connstate *)arg;
|
||||||
|
|
||||||
|
while(cs->rp) {
|
||||||
|
remaining_in_pbuf = cs->rp->len - cs->rp_offset;
|
||||||
|
rpp = (char *)cs->rp->payload;
|
||||||
|
while(remaining_in_pbuf > 0) {
|
||||||
|
if(cs == active_cs) {
|
||||||
|
r = session_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
|
||||||
|
kserver_close(cs, pcb);
|
||||||
|
} else {
|
||||||
|
if(rpp[cs->rp_offset] == kserver_magic[cs->magic_recognized]) {
|
||||||
|
cs->magic_recognized++;
|
||||||
|
if(magic_ok(cs)) {
|
||||||
|
if(active_cs)
|
||||||
|
kserver_close(active_cs, active_pcb);
|
||||||
|
session_start();
|
||||||
|
active_cs = cs;
|
||||||
|
active_pcb = pcb;
|
||||||
|
tcp_sent(pcb, kserver_sent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
kserver_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kserver_err(void *arg, err_t err)
|
||||||
|
{
|
||||||
|
struct kserver_connstate *cs;
|
||||||
|
|
||||||
|
cs = (struct kserver_connstate *)arg;
|
||||||
|
cs_free(cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct tcp_pcb *listen_pcb;
|
||||||
|
|
||||||
|
static err_t kserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||||
|
{
|
||||||
|
struct kserver_connstate *cs;
|
||||||
|
|
||||||
|
cs = cs_new();
|
||||||
|
if(!cs)
|
||||||
|
return ERR_MEM;
|
||||||
|
tcp_accepted(listen_pcb);
|
||||||
|
tcp_arg(newpcb, cs);
|
||||||
|
tcp_recv(newpcb, kserver_recv);
|
||||||
|
tcp_err(newpcb, kserver_err);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kserver_init(void)
|
||||||
|
{
|
||||||
|
listen_pcb = tcp_new();
|
||||||
|
tcp_bind(listen_pcb, IP_ADDR_ANY, 1381);
|
||||||
|
listen_pcb = tcp_listen(listen_pcb);
|
||||||
|
tcp_accept(listen_pcb, kserver_accept);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern struct tcp_pcb *tcp_active_pcbs;
|
||||||
|
|
||||||
|
static void kserver_service(void)
|
||||||
|
{
|
||||||
|
struct tcp_pcb *pcb;
|
||||||
|
void *data;
|
||||||
|
int len, sndbuf;
|
||||||
|
|
||||||
|
/* Assume all active TCP PCBs with a non-NULL arg are our connections. */
|
||||||
|
pcb = tcp_active_pcbs;
|
||||||
|
while(pcb) {
|
||||||
|
if(pcb->callback_arg)
|
||||||
|
tcp_pcb_service(pcb->callback_arg, pcb);
|
||||||
|
pcb = pcb->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(active_cs) {
|
||||||
|
session_poll(&data, &len);
|
||||||
|
if(len > 0) {
|
||||||
|
sndbuf = tcp_sndbuf(active_pcb);
|
||||||
|
if(len > sndbuf)
|
||||||
|
len = sndbuf;
|
||||||
|
tcp_write(active_pcb, data, len, 0);
|
||||||
|
session_ack_data(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void regular_main(void)
|
||||||
|
{
|
||||||
|
network_init();
|
||||||
|
kserver_init();
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
lwip_service();
|
||||||
|
kserver_service();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* CSR_ETHMAC_BASE */
|
||||||
|
|
||||||
|
static void serial_service(void)
|
||||||
|
{
|
||||||
|
char *txdata;
|
||||||
|
int txlen;
|
||||||
|
static char rxdata;
|
||||||
|
static int rxpending;
|
||||||
|
int r, i;
|
||||||
|
|
||||||
|
if(!rxpending && uart_read_nonblock()) {
|
||||||
|
rxdata = uart_read();
|
||||||
|
rxpending = 1;
|
||||||
|
}
|
||||||
|
if(rxpending) {
|
||||||
|
r = session_input(&rxdata, 1);
|
||||||
|
if(r > 0)
|
||||||
|
rxpending = 0;
|
||||||
|
if(r < 0) {
|
||||||
|
session_end();
|
||||||
|
session_start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
session_poll((void **)&txdata, &txlen);
|
||||||
|
if(txlen > 0) {
|
||||||
|
for(i=0;i<txlen;i++)
|
||||||
|
uart_write(txdata[i]);
|
||||||
|
session_ack_data(txlen);
|
||||||
|
session_ack_mem(txlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void regular_main(void)
|
||||||
|
{
|
||||||
|
/* Open the session for the serial control. */
|
||||||
|
session_start();
|
||||||
|
while(1)
|
||||||
|
serial_service();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static void blink_led(void)
|
static void blink_led(void)
|
||||||
{
|
{
|
||||||
|
@ -169,6 +373,12 @@ int main(void)
|
||||||
#else
|
#else
|
||||||
puts("ARTIQ runtime built "__DATE__" "__TIME__" for UP systems\n");
|
puts("ARTIQ runtime built "__DATE__" "__TIME__" for UP systems\n");
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CSR_ETHMAC_BASE
|
||||||
|
puts("Accepting sessions on Ethernet");
|
||||||
|
#else
|
||||||
|
puts("Accepting sessions on serial link");
|
||||||
|
#endif
|
||||||
|
puts("Press 't' to enter test mode...");
|
||||||
blink_led();
|
blink_led();
|
||||||
|
|
||||||
if(check_test_mode()) {
|
if(check_test_mode()) {
|
||||||
|
|
|
@ -30,7 +30,8 @@ static struct {
|
||||||
char data[BUFFER_IN_SIZE];
|
char data[BUFFER_IN_SIZE];
|
||||||
} __attribute__((packed)) _buffer_in __attribute__((aligned(4)));
|
} __attribute__((packed)) _buffer_in __attribute__((aligned(4)));
|
||||||
#define buffer_in _buffer_in.data
|
#define buffer_in _buffer_in.data
|
||||||
static int buffer_out_index;
|
static int buffer_out_index_data;
|
||||||
|
static int buffer_out_index_mem;
|
||||||
static char buffer_out[BUFFER_OUT_SIZE];
|
static char buffer_out[BUFFER_OUT_SIZE];
|
||||||
|
|
||||||
static int get_in_packet_len(void)
|
static int get_in_packet_len(void)
|
||||||
|
@ -53,7 +54,8 @@ static void submit_output(int len)
|
||||||
{
|
{
|
||||||
memset(&buffer_out[0], 0x5a, 4);
|
memset(&buffer_out[0], 0x5a, 4);
|
||||||
memcpy(&buffer_out[4], &len, 4);
|
memcpy(&buffer_out[4], &len, 4);
|
||||||
buffer_out_index = 0;
|
buffer_out_index_data = 0;
|
||||||
|
buffer_out_index_mem = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int user_kernel_state;
|
static int user_kernel_state;
|
||||||
|
@ -68,7 +70,8 @@ enum {
|
||||||
void session_start(void)
|
void session_start(void)
|
||||||
{
|
{
|
||||||
buffer_in_index = 0;
|
buffer_in_index = 0;
|
||||||
buffer_out_index = 0;
|
buffer_out_index_data = 0;
|
||||||
|
buffer_out_index_mem = 0;
|
||||||
memset(&buffer_out[4], 0, 4);
|
memset(&buffer_out[4], 0, 4);
|
||||||
#ifdef ARTIQ_AMP
|
#ifdef ARTIQ_AMP
|
||||||
kloader_stop_kernel();
|
kloader_stop_kernel();
|
||||||
|
@ -214,8 +217,8 @@ int rpc(int rpc_num, ...)
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
user_kernel_state = USER_KERNEL_WAIT_RPC;
|
user_kernel_state = USER_KERNEL_WAIT_RPC;
|
||||||
while(user_kernel_state == USER_KERNEL_WAIT_RPC)
|
/*while(user_kernel_state == USER_KERNEL_WAIT_RPC)
|
||||||
comm_service();
|
comm_service();*/
|
||||||
|
|
||||||
if(rpc_reply_eid != EID_NONE)
|
if(rpc_reply_eid != EID_NONE)
|
||||||
exception_raise(rpc_reply_eid);
|
exception_raise(rpc_reply_eid);
|
||||||
|
@ -491,15 +494,20 @@ void session_poll(void **data, int *len)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*len = l - buffer_out_index;
|
*len = l - buffer_out_index_data;
|
||||||
*data = &buffer_out[buffer_out_index];
|
*data = &buffer_out[buffer_out_index_data];
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_ack(int len)
|
void session_ack_data(int len)
|
||||||
{
|
{
|
||||||
buffer_out_index += len;
|
buffer_out_index_data += len;
|
||||||
if(buffer_out_index >= get_out_packet_len()) {
|
}
|
||||||
|
|
||||||
|
void session_ack_mem(int len)
|
||||||
|
{
|
||||||
|
buffer_out_index_mem += len;
|
||||||
|
if(buffer_out_index_mem >= get_out_packet_len()) {
|
||||||
memset(&buffer_out[4], 0, 4);
|
memset(&buffer_out[4], 0, 4);
|
||||||
buffer_out_index = 0;
|
buffer_out_index_mem = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@ void session_end(void);
|
||||||
|
|
||||||
int session_input(void *data, int len);
|
int session_input(void *data, int len);
|
||||||
void session_poll(void **data, int *len);
|
void session_poll(void **data, int *len);
|
||||||
void session_ack(int len);
|
void session_ack_data(int len);
|
||||||
|
void session_ack_mem(int len);
|
||||||
|
|
||||||
int rpc(int rpc_num, ...);
|
int rpc(int rpc_num, ...);
|
||||||
void comm_service(void);
|
|
||||||
|
|
||||||
#endif /* __SESSION_H */
|
#endif /* __SESSION_H */
|
||||||
|
|
Loading…
Reference in New Issue