forked from M-Labs/artiq
129 lines
2.1 KiB
C
129 lines
2.1 KiB
C
|
#include <stdarg.h>
|
||
|
#include <crc.h>
|
||
|
#include <uart.h>
|
||
|
#include <generated/csr.h>
|
||
|
|
||
|
#include "corecom.h"
|
||
|
|
||
|
enum {
|
||
|
MSGTYPE_REQUEST_IDENT = 0x01,
|
||
|
MSGTYPE_LOAD_KERNEL = 0x02,
|
||
|
MSGTYPE_KERNEL_FINISHED = 0x03,
|
||
|
MSGTYPE_RPC_REQUEST = 0x04,
|
||
|
};
|
||
|
|
||
|
static int receive_int(void)
|
||
|
{
|
||
|
unsigned int r;
|
||
|
int i;
|
||
|
|
||
|
r = 0;
|
||
|
for(i=0;i<4;i++) {
|
||
|
r <<= 8;
|
||
|
r |= (unsigned char)uart_read();
|
||
|
}
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
static char receive_char(void)
|
||
|
{
|
||
|
return uart_read();
|
||
|
}
|
||
|
|
||
|
static void send_int(int x)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for(i=0;i<4;i++) {
|
||
|
uart_write((x & 0xff000000) >> 24);
|
||
|
x <<= 8;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void send_sint(short int i)
|
||
|
{
|
||
|
uart_write((i >> 8) & 0xff);
|
||
|
uart_write(i & 0xff);
|
||
|
}
|
||
|
|
||
|
static void send_char(char c)
|
||
|
{
|
||
|
uart_write(c);
|
||
|
}
|
||
|
|
||
|
static void receive_sync(void)
|
||
|
{
|
||
|
char c;
|
||
|
int recognized;
|
||
|
|
||
|
recognized = 0;
|
||
|
while(recognized < 4) {
|
||
|
c = uart_read();
|
||
|
if(c == 0x5a)
|
||
|
recognized++;
|
||
|
else
|
||
|
recognized = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void send_sync(void)
|
||
|
{
|
||
|
send_int(0x5a5a5a5a);
|
||
|
}
|
||
|
|
||
|
int ident_and_download_kernel(void *buffer, int maxlength)
|
||
|
{
|
||
|
int length;
|
||
|
unsigned int crc;
|
||
|
int i;
|
||
|
char msgtype;
|
||
|
unsigned char *_buffer = buffer;
|
||
|
|
||
|
while(1) {
|
||
|
receive_sync();
|
||
|
msgtype = receive_char();
|
||
|
if(msgtype == MSGTYPE_REQUEST_IDENT) {
|
||
|
send_int(0x41524f52); /* "AROR" - ARTIQ runtime on OpenRISC */
|
||
|
send_int(1000000000000LL/identifier_frequency_read()); /* RTIO clock period in picoseconds */
|
||
|
} else if(msgtype == MSGTYPE_LOAD_KERNEL) {
|
||
|
length = receive_int();
|
||
|
if(length > maxlength) {
|
||
|
send_char(0x4c); /* Incorrect length */
|
||
|
return -1;
|
||
|
}
|
||
|
crc = receive_int();
|
||
|
for(i=0;i<length;i++)
|
||
|
_buffer[i] = receive_char();
|
||
|
if(crc32(buffer, length) != crc) {
|
||
|
send_char(0x43); /* CRC failed */
|
||
|
return -1;
|
||
|
}
|
||
|
send_char(0x4f); /* kernel reception OK */
|
||
|
return length;
|
||
|
} else
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int rpc(int rpc_num, int n_args, ...)
|
||
|
{
|
||
|
send_sync();
|
||
|
send_char(MSGTYPE_RPC_REQUEST);
|
||
|
send_sint(rpc_num);
|
||
|
send_char(n_args);
|
||
|
|
||
|
va_list args;
|
||
|
va_start(args, n_args);
|
||
|
while(n_args--)
|
||
|
send_int(va_arg(args, int));
|
||
|
va_end(args);
|
||
|
|
||
|
return receive_int();
|
||
|
}
|
||
|
|
||
|
void kernel_finished(void)
|
||
|
{
|
||
|
send_sync();
|
||
|
send_char(MSGTYPE_KERNEL_FINISHED);
|
||
|
}
|