runtime,coredevice: Ethernet support (buggy)

This commit is contained in:
Sebastien Bourdeauducq 2015-04-23 23:22:40 +08:00
parent 1968304b4f
commit 934a6b0495
8 changed files with 295 additions and 68 deletions

View File

@ -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"):

View File

@ -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",

View File

@ -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",

View File

@ -93,7 +93,7 @@ static struct pbuf *liteeth_low_level_input(struct netif *netif)
if(rxslot) if(rxslot)
rxbuffer = rxbuffer1; rxbuffer = rxbuffer1;
else else
rxbuffer = rxbuffer0; rxbuffer = rxbuffer0;
p = pbuf_alloc(PBUF_RAW, rxlen, PBUF_POOL); p = pbuf_alloc(PBUF_RAW, rxlen, PBUF_POOL);
q = p; q = p;

View File

@ -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, ...)

View File

@ -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()) {

View File

@ -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;
} }
} }

View File

@ -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 */