diff --git a/soc/runtime/Makefile b/soc/runtime/Makefile index 43238912f..e8b1bb820 100644 --- a/soc/runtime/Makefile +++ b/soc/runtime/Makefile @@ -3,7 +3,7 @@ include $(MSCDIR)/software/common.mak BOARD=papilio_pro SERIAL=/dev/ttyUSB1 -OBJECTS=isr.o elf_loader.o main.o +OBJECTS=isr.o elf_loader.o symbols.o corecom_serial.o gpio.o rtio.o dds.o main.o all: runtime.bin diff --git a/soc/runtime/corecom.h b/soc/runtime/corecom.h new file mode 100644 index 000000000..c0ac37e9b --- /dev/null +++ b/soc/runtime/corecom.h @@ -0,0 +1,8 @@ +#ifndef __CORECOM_H +#define __CORECOM_H + +int ident_and_download_kernel(void *buffer, int maxlength); +int rpc(int rpc_num, int n_args, ...); +void kernel_finished(void); + +#endif /* __CORECOM_H */ diff --git a/soc/runtime/corecom_serial.c b/soc/runtime/corecom_serial.c new file mode 100644 index 000000000..bb39b0ba9 --- /dev/null +++ b/soc/runtime/corecom_serial.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include + +#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 + +#include "dds.h" + +#define DDS_FTW0 0x0a +#define DDS_FTW1 0x0b +#define DDS_FTW2 0x0c +#define DDS_FTW3 0x0d +#define DDS_FUD 0x40 +#define DDS_GPIO 0x41 + +#define DDS_READ(addr) \ + MMPTR(0xb0000000 + (addr)*4) + +#define DDS_WRITE(addr, data) \ + MMPTR(0xb0000000 + (addr)*4) = data + +void dds_init(void) +{ + int i; + + DDS_WRITE(DDS_GPIO, 1 << 7); + + for(i=0;i<8;i++) { + DDS_WRITE(DDS_GPIO, i); + DDS_WRITE(0x00, 0x78); + DDS_WRITE(0x01, 0x00); + DDS_WRITE(0x02, 0x00); + DDS_WRITE(0x03, 0x00); + DDS_WRITE(DDS_FUD, 0); + } +} + +void dds_program(int channel, int ftw) +{ + DDS_WRITE(DDS_GPIO, channel); + DDS_WRITE(DDS_FTW0, ftw & 0xff); + DDS_WRITE(DDS_FTW1, (ftw >> 8) & 0xff); + DDS_WRITE(DDS_FTW2, (ftw >> 16) & 0xff); + DDS_WRITE(DDS_FTW3, (ftw >> 24) & 0xff); + DDS_WRITE(DDS_FUD, 0); +} diff --git a/soc/runtime/dds.h b/soc/runtime/dds.h new file mode 100644 index 000000000..91093b03b --- /dev/null +++ b/soc/runtime/dds.h @@ -0,0 +1,7 @@ +#ifndef __DDS_H +#define __DDS_H + +void dds_init(void); +void dds_program(int channel, int ftw); + +#endif /* __DDS_H */ diff --git a/soc/runtime/elf_loader.c b/soc/runtime/elf_loader.c index f2518de83..718bec49a 100644 --- a/soc/runtime/elf_loader.c +++ b/soc/runtime/elf_loader.c @@ -89,7 +89,7 @@ struct elf32_sym { SANITIZE_OFFSET_SIZE(offset, sizeof(target_type)); \ target = (target_type *)((char *)elf_data + offset) -static void *find_symbol(const struct symbol *symbols, const char *name) +void *find_symbol(const struct symbol *symbols, const char *name) { int i; @@ -117,7 +117,7 @@ static int fixup(void *dest, int dest_length, struct elf32_rela *rela, void *tar return 1; } -int load_elf(const struct symbol *symbols, void *elf_data, int elf_length, void *dest, int dest_length) +int load_elf(symbol_resolver resolver, void *elf_data, int elf_length, void *dest, int dest_length) { struct elf32_ehdr *ehdr; struct elf32_shdr *strtable; @@ -199,7 +199,7 @@ int load_elf(const struct symbol *symbols, void *elf_data, int elf_length, void void *target; name = (char *)elf_data + strtaboff + sym->name; - target = find_symbol(symbols, name); + target = resolver(name); if(target == NULL) { printf("Undefined symbol: %s\n", name); return 0; diff --git a/soc/runtime/elf_loader.h b/soc/runtime/elf_loader.h index 7c8fae33d..5b8431ff8 100644 --- a/soc/runtime/elf_loader.h +++ b/soc/runtime/elf_loader.h @@ -6,6 +6,9 @@ struct symbol { void *target; }; -int load_elf(const struct symbol *symbols, void *elf_data, int elf_length, void *dest, int dest_length); +void *find_symbol(const struct symbol *symbols, const char *name); + +typedef void * (*symbol_resolver)(const char *name); +int load_elf(symbol_resolver resolver, void *elf_data, int elf_length, void *dest, int dest_length); #endif /* __ELF_LOADER_H */ diff --git a/soc/runtime/gpio.c b/soc/runtime/gpio.c new file mode 100644 index 000000000..3d7948ac4 --- /dev/null +++ b/soc/runtime/gpio.c @@ -0,0 +1,14 @@ +#include + +#include "gpio.h" + +void gpio_set(int channel, int value) +{ + static int csr_value; + + if(value) + csr_value |= 1 << channel; + else + csr_value &= ~(1 << channel); + leds_out_write(csr_value); +} diff --git a/soc/runtime/gpio.h b/soc/runtime/gpio.h new file mode 100644 index 000000000..63301cca5 --- /dev/null +++ b/soc/runtime/gpio.h @@ -0,0 +1,6 @@ +#ifndef __GPIO_H +#define __GPIO_H + +void gpio_set(int channel, int value); + +#endif /* __GPIO_H */ diff --git a/soc/runtime/main.c b/soc/runtime/main.c index cf907c132..6aca21f55 100644 --- a/soc/runtime/main.c +++ b/soc/runtime/main.c @@ -1,208 +1,13 @@ #include -#include -#include -#include -#include - #include #include -#include #include -#include -#include +#include "corecom.h" #include "elf_loader.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); -} - -static 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> 8) & 0xff); - DDS_WRITE(DDS_FTW2, (ftw >> 16) & 0xff); - DDS_WRITE(DDS_FTW3, (ftw >> 24) & 0xff); - DDS_WRITE(DDS_FUD, 0); -} - -static const struct symbol syscalls[] = { - {"__syscall_rpc", rpc}, - {"__syscall_gpio_set", gpio_set}, - {"__syscall_rtio_set", rtio_set}, - {"__syscall_rtio_sync", rtio_sync}, - {"__syscall_dds_program", dds_program}, - {NULL, NULL} -}; - -static void dds_init(void) -{ - int i; - - DDS_WRITE(DDS_GPIO, 1 << 7); - - for(i=0;i<8;i++) { - DDS_WRITE(DDS_GPIO, i); - DDS_WRITE(0x00, 0x78); - DDS_WRITE(0x01, 0x00); - DDS_WRITE(0x02, 0x00); - DDS_WRITE(0x03, 0x00); - DDS_WRITE(DDS_FUD, 0); - } -} +#include "symbols.h" +#include "rtio.h" +#include "dds.h" typedef void (*kernel_function)(void); @@ -222,16 +27,15 @@ int main(void) while(1) { length = ident_and_download_kernel(kbuf, sizeof(kbuf)); if(length > 0) { - if(load_elf(syscalls, kbuf, length, kcode, sizeof(kcode))) { - flush_cpu_icache(); + if(load_elf(resolve_symbol, kbuf, length, kcode, sizeof(kcode))) { + rtio_init(); dds_init(); + flush_cpu_icache(); k(); - rtio_reset_write(1); - send_sync(); - send_char(MSGTYPE_KERNEL_FINISHED); + kernel_finished(); } } } - + return 0; } diff --git a/soc/runtime/rtio.c b/soc/runtime/rtio.c new file mode 100644 index 000000000..f75aa2413 --- /dev/null +++ b/soc/runtime/rtio.c @@ -0,0 +1,24 @@ +#include + +#include "rtio.h" + +void rtio_init(void) +{ + rtio_reset_write(1); +} + +void rtio_set(long long int timestamp, int channel, int value) +{ + rtio_reset_write(0); + rtio_chan_sel_write(channel); + rtio_o_timestamp_write(timestamp); + rtio_o_value_write(value); + while(!rtio_o_writable_read()); + rtio_o_we_write(1); +} + +void rtio_sync(int channel) +{ + rtio_chan_sel_write(channel); + while(rtio_o_level_read() != 0); +} diff --git a/soc/runtime/rtio.h b/soc/runtime/rtio.h new file mode 100644 index 000000000..2ed47058e --- /dev/null +++ b/soc/runtime/rtio.h @@ -0,0 +1,8 @@ +#ifndef __RTIO_H +#define __RTIO_H + +void rtio_init(void); +void rtio_set(long long int timestamp, int channel, int value); +void rtio_sync(int channel); + +#endif /* __RTIO_H */ diff --git a/soc/runtime/symbols.c b/soc/runtime/symbols.c new file mode 100644 index 000000000..a00fe0d5c --- /dev/null +++ b/soc/runtime/symbols.c @@ -0,0 +1,41 @@ +#include + +#include "elf_loader.h" +#include "corecom.h" +#include "gpio.h" +#include "rtio.h" +#include "dds.h" +#include "symbols.h" + +static const struct symbol syscalls[] = { + {"rpc", rpc}, + {"gpio_set", gpio_set}, + {"rtio_set", rtio_set}, + {"rtio_sync", rtio_sync}, + {"dds_program", dds_program}, + {NULL, NULL} +}; + +static long long int gcd64(long long int a, long long int b) +{ + long long int c; + + while(a) { + c = a; + a = b % a; + b = c; + } + return b; +} + +static const struct symbol arithmetic[] = { + {"__gcd64", gcd64}, + {NULL, NULL} +}; + +void *resolve_symbol(const char *name) +{ + if(strncmp(name, "__syscall_", 10) == 0) + return find_symbol(syscalls, name + 10); + return find_symbol(arithmetic, name); +} diff --git a/soc/runtime/symbols.h b/soc/runtime/symbols.h new file mode 100644 index 000000000..c963a1e7d --- /dev/null +++ b/soc/runtime/symbols.h @@ -0,0 +1,6 @@ +#ifndef __SYMBOLS_H +#define __SYMBOLS_H + +void *resolve_symbol(const char *name); + +#endif /* __SYMBOLS_H */