2014-07-04 23:49:08 +08:00
|
|
|
#include <stdio.h>
|
2014-09-15 22:40:33 +08:00
|
|
|
#include <string.h>
|
2014-07-04 23:49:08 +08:00
|
|
|
#include <irq.h>
|
|
|
|
#include <uart.h>
|
2015-03-12 05:02:19 +08:00
|
|
|
#include <console.h>
|
2014-07-04 23:49:08 +08:00
|
|
|
#include <system.h>
|
2014-09-15 22:56:23 +08:00
|
|
|
#include <time.h>
|
|
|
|
#include <generated/csr.h>
|
2014-07-04 23:49:08 +08:00
|
|
|
|
2015-03-12 05:02:19 +08:00
|
|
|
#include "test_mode.h"
|
2014-10-19 23:51:49 +08:00
|
|
|
#include "comm.h"
|
2014-07-04 23:49:08 +08:00
|
|
|
#include "elf_loader.h"
|
2015-04-03 17:44:56 +08:00
|
|
|
#include "kernelcpu.h"
|
2014-09-21 23:36:10 +08:00
|
|
|
#include "exceptions.h"
|
2014-09-15 22:40:33 +08:00
|
|
|
#include "services.h"
|
2014-08-28 16:56:48 +08:00
|
|
|
#include "rtio.h"
|
|
|
|
#include "dds.h"
|
2014-07-24 07:10:49 +08:00
|
|
|
|
2014-09-15 22:40:33 +08:00
|
|
|
static struct symbol symtab[128];
|
|
|
|
static int _symtab_count;
|
|
|
|
static char _symtab_strings[128*16];
|
|
|
|
static char *_symtab_strptr;
|
|
|
|
|
|
|
|
static void symtab_init(void)
|
|
|
|
{
|
|
|
|
memset(symtab, 0, sizeof(symtab));
|
|
|
|
_symtab_count = 0;
|
|
|
|
_symtab_strptr = _symtab_strings;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int symtab_add(const char *name, void *target)
|
|
|
|
{
|
|
|
|
if(_symtab_count >= sizeof(symtab)/sizeof(symtab[0])) {
|
2014-10-19 23:51:49 +08:00
|
|
|
comm_log("Too many provided symbols in object");
|
2014-09-15 22:40:33 +08:00
|
|
|
symtab_init();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
symtab[_symtab_count].name = _symtab_strptr;
|
|
|
|
symtab[_symtab_count].target = target;
|
|
|
|
_symtab_count++;
|
|
|
|
|
|
|
|
while(1) {
|
|
|
|
if(_symtab_strptr >= &_symtab_strings[sizeof(_symtab_strings)]) {
|
2014-10-19 23:51:49 +08:00
|
|
|
comm_log("Provided symbol string table overflow");
|
2014-09-15 22:40:33 +08:00
|
|
|
symtab_init();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*_symtab_strptr = *name;
|
|
|
|
_symtab_strptr++;
|
|
|
|
if(*name == 0)
|
|
|
|
break;
|
|
|
|
name++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int load_object(void *buffer, int length)
|
|
|
|
{
|
|
|
|
symtab_init();
|
|
|
|
return load_elf(
|
|
|
|
resolve_service_symbol, symtab_add,
|
2015-04-04 22:08:32 +08:00
|
|
|
buffer, length, (void *)KERNELCPU_PAYLOAD_ADDRESS, 4*1024*1024);
|
2014-09-15 22:40:33 +08:00
|
|
|
}
|
|
|
|
|
2014-07-06 04:47:23 +08:00
|
|
|
typedef void (*kernel_function)(void);
|
2014-07-04 23:49:08 +08:00
|
|
|
|
2014-09-21 23:36:10 +08:00
|
|
|
static int run_kernel(const char *kernel_name, int *eid)
|
2014-07-04 23:49:08 +08:00
|
|
|
{
|
2014-09-07 17:29:48 +08:00
|
|
|
kernel_function k;
|
2015-04-05 17:55:05 +08:00
|
|
|
#ifndef ARTIQ_AMP
|
2014-09-22 13:18:48 +08:00
|
|
|
void *jb;
|
2015-04-04 22:08:32 +08:00
|
|
|
#endif
|
2014-07-04 23:49:08 +08:00
|
|
|
|
2014-09-15 22:40:33 +08:00
|
|
|
k = find_symbol(symtab, kernel_name);
|
|
|
|
if(k == NULL) {
|
2014-10-19 23:51:49 +08:00
|
|
|
comm_log("Failed to find kernel entry point '%s' in object", kernel_name);
|
2014-09-21 23:36:10 +08:00
|
|
|
return KERNEL_RUN_STARTUP_FAILED;
|
|
|
|
}
|
|
|
|
|
2015-04-05 17:55:05 +08:00
|
|
|
#ifdef ARTIQ_AMP
|
2015-04-04 22:08:32 +08:00
|
|
|
kernelcpu_start(k);
|
|
|
|
*eid = 0;
|
|
|
|
while(1) {
|
|
|
|
unsigned int r;
|
|
|
|
|
|
|
|
r = KERNELCPU_MAILBOX;
|
|
|
|
if(r < 0x40000000) {
|
|
|
|
kernelcpu_stop();
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
2014-09-22 13:18:48 +08:00
|
|
|
jb = exception_push();
|
2014-09-23 22:09:08 +08:00
|
|
|
if(exception_setjmp(jb)) {
|
2014-09-22 13:18:48 +08:00
|
|
|
*eid = exception_getid();
|
2014-09-21 23:36:10 +08:00
|
|
|
return KERNEL_RUN_EXCEPTION;
|
2014-09-22 13:18:48 +08:00
|
|
|
} else {
|
2015-04-04 22:08:32 +08:00
|
|
|
dds_init();
|
2014-09-21 23:36:10 +08:00
|
|
|
rtio_init();
|
|
|
|
flush_cpu_icache();
|
|
|
|
k();
|
2014-09-23 16:22:32 +08:00
|
|
|
exception_pop(1);
|
2014-09-21 23:36:10 +08:00
|
|
|
return KERNEL_RUN_FINISHED;
|
2014-09-15 22:40:33 +08:00
|
|
|
}
|
2015-04-04 22:08:32 +08:00
|
|
|
#endif
|
2014-09-15 22:40:33 +08:00
|
|
|
}
|
|
|
|
|
2014-09-15 22:56:23 +08:00
|
|
|
static void blink_led(void)
|
|
|
|
{
|
|
|
|
int i, ev, p;
|
|
|
|
|
|
|
|
p = identifier_frequency_read()/10;
|
|
|
|
time_init();
|
|
|
|
for(i=0;i<3;i++) {
|
|
|
|
leds_out_write(1);
|
|
|
|
while(!elapsed(&ev, p));
|
|
|
|
leds_out_write(0);
|
|
|
|
while(!elapsed(&ev, p));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-12 05:02:19 +08:00
|
|
|
static int check_test_mode(void)
|
|
|
|
{
|
|
|
|
char c;
|
|
|
|
|
|
|
|
timer0_en_write(0);
|
|
|
|
timer0_reload_write(0);
|
|
|
|
timer0_load_write(identifier_frequency_read() >> 2);
|
|
|
|
timer0_en_write(1);
|
|
|
|
timer0_update_value_write(1);
|
|
|
|
while(timer0_value_read()) {
|
|
|
|
if(readchar_nonblock()) {
|
|
|
|
c = readchar();
|
|
|
|
if((c == 't')||(c == 'T'))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
timer0_update_value_write(1);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-15 22:40:33 +08:00
|
|
|
int main(void)
|
|
|
|
{
|
2014-09-05 12:03:22 +08:00
|
|
|
irq_setmask(0);
|
|
|
|
irq_setie(1);
|
|
|
|
uart_init();
|
2014-09-22 13:18:48 +08:00
|
|
|
|
2015-04-05 17:55:05 +08:00
|
|
|
#ifdef ARTIQ_AMP
|
|
|
|
puts("ARTIQ runtime built "__DATE__" "__TIME__" for AMP systems\n");
|
2015-04-03 17:44:56 +08:00
|
|
|
#else
|
2015-04-05 17:55:05 +08:00
|
|
|
puts("ARTIQ runtime built "__DATE__" "__TIME__" for UP systems\n");
|
2015-04-03 17:44:56 +08:00
|
|
|
#endif
|
2014-09-15 22:56:23 +08:00
|
|
|
blink_led();
|
2015-03-12 05:02:19 +08:00
|
|
|
|
|
|
|
if(check_test_mode()) {
|
|
|
|
puts("Entering test mode.");
|
|
|
|
test_main();
|
|
|
|
} else {
|
|
|
|
puts("Entering regular mode.");
|
|
|
|
comm_serve(load_object, run_kernel);
|
|
|
|
}
|
2014-09-05 12:03:22 +08:00
|
|
|
return 0;
|
2014-07-04 23:49:08 +08:00
|
|
|
}
|