forked from M-Labs/artiq
runtime,coredevice: Ethernet support (buggy)
This commit is contained in:
parent
1968304b4f
commit
934a6b0495
@ -18,6 +18,7 @@ class Comm(CommGeneric, AutoDB):
|
||||
return
|
||||
self.socket = socket.create_connection((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):
|
||||
if not hasattr(self, "socket"):
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"comm": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.comm_serial",
|
||||
"module": "artiq.coredevice.comm_tcp",
|
||||
"class": "Comm",
|
||||
"arguments": {"serial_dev": "/dev/ttyUSB1"}
|
||||
"arguments": {"host": "192.168.0.42"}
|
||||
},
|
||||
"core": {
|
||||
"type": "local",
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"comm": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.comm_serial",
|
||||
"module": "artiq.coredevice.comm_tcp",
|
||||
"class": "Comm",
|
||||
"arguments": {"serial_dev": "/dev/ttyUSB1"}
|
||||
"arguments": {"host": "192.168.0.42"}
|
||||
},
|
||||
"core": {
|
||||
"type": "local",
|
||||
|
@ -93,7 +93,7 @@ static struct pbuf *liteeth_low_level_input(struct netif *netif)
|
||||
if(rxslot)
|
||||
rxbuffer = rxbuffer1;
|
||||
else
|
||||
rxbuffer = rxbuffer0;
|
||||
rxbuffer = rxbuffer0;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, rxlen, PBUF_POOL);
|
||||
q = p;
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <generated/csr.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
static int buffer_index;
|
||||
@ -18,6 +20,12 @@ void log_va(const char *fmt, va_list args)
|
||||
}
|
||||
buffer[buffer_index] = '\n';
|
||||
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, ...)
|
||||
|
@ -29,22 +29,13 @@ unsigned char macadr[6] = {0x10, 0xe2, 0xd5, 0x00, 0x00, 0x00};
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned int freq;
|
||||
unsigned int prescaler;
|
||||
|
||||
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);
|
||||
clock_ms += (0xffffffff - timer0_value_read())/prescaler;
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
#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 netmask;
|
||||
struct ip4_addr gateway_ip;
|
||||
|
||||
time_init();
|
||||
clock_init();
|
||||
timer0_en_write(0);
|
||||
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(&netmask, 255, 255, 255, 0);
|
||||
@ -116,13 +78,255 @@ static void regular_main(void)
|
||||
netif_set_default(&netif);
|
||||
netif_set_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)
|
||||
{
|
||||
@ -169,6 +373,12 @@ int main(void)
|
||||
#else
|
||||
puts("ARTIQ runtime built "__DATE__" "__TIME__" for UP systems\n");
|
||||
#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();
|
||||
|
||||
if(check_test_mode()) {
|
||||
|
@ -30,7 +30,8 @@ static struct {
|
||||
char data[BUFFER_IN_SIZE];
|
||||
} __attribute__((packed)) _buffer_in __attribute__((aligned(4)));
|
||||
#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 int get_in_packet_len(void)
|
||||
@ -53,7 +54,8 @@ static void submit_output(int len)
|
||||
{
|
||||
memset(&buffer_out[0], 0x5a, 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;
|
||||
@ -68,7 +70,8 @@ enum {
|
||||
void session_start(void)
|
||||
{
|
||||
buffer_in_index = 0;
|
||||
buffer_out_index = 0;
|
||||
buffer_out_index_data = 0;
|
||||
buffer_out_index_mem = 0;
|
||||
memset(&buffer_out[4], 0, 4);
|
||||
#ifdef ARTIQ_AMP
|
||||
kloader_stop_kernel();
|
||||
@ -214,8 +217,8 @@ int rpc(int rpc_num, ...)
|
||||
va_end(args);
|
||||
|
||||
user_kernel_state = USER_KERNEL_WAIT_RPC;
|
||||
while(user_kernel_state == USER_KERNEL_WAIT_RPC)
|
||||
comm_service();
|
||||
/*while(user_kernel_state == USER_KERNEL_WAIT_RPC)
|
||||
comm_service();*/
|
||||
|
||||
if(rpc_reply_eid != EID_NONE)
|
||||
exception_raise(rpc_reply_eid);
|
||||
@ -491,15 +494,20 @@ void session_poll(void **data, int *len)
|
||||
}
|
||||
#endif
|
||||
|
||||
*len = l - buffer_out_index;
|
||||
*data = &buffer_out[buffer_out_index];
|
||||
*len = l - buffer_out_index_data;
|
||||
*data = &buffer_out[buffer_out_index_data];
|
||||
}
|
||||
|
||||
void session_ack(int len)
|
||||
void session_ack_data(int len)
|
||||
{
|
||||
buffer_out_index += len;
|
||||
if(buffer_out_index >= get_out_packet_len()) {
|
||||
buffer_out_index_data += 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);
|
||||
buffer_out_index = 0;
|
||||
buffer_out_index_mem = 0;
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,9 @@ void session_end(void);
|
||||
|
||||
int session_input(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, ...);
|
||||
void comm_service(void);
|
||||
|
||||
#endif /* __SESSION_H */
|
||||
|
Loading…
Reference in New Issue
Block a user