forked from M-Labs/artiq
1
0
Fork 0

runtime: support test mode on AMP

This commit is contained in:
Sebastien Bourdeauducq 2015-04-16 21:47:05 +08:00
parent 546996f896
commit 6a5f58e5a9
7 changed files with 308 additions and 66 deletions

View File

@ -9,7 +9,7 @@ UNIPROCESSOR := $(shell printf "\#include <generated/csr.h>\nCSR_KERNEL_CPU_BASE
ifeq ($(UNIPROCESSOR),0) ifeq ($(UNIPROCESSOR),0)
OBJECTS += mailbox.o kernelcpu.o ksupport_data.o OBJECTS += mailbox.o kernelcpu.o ksupport_data.o
OBJECTS_KSUPPORT += mailbox.o ksupport.o OBJECTS_KSUPPORT += mailbox.o bridge.o ksupport.o
CFLAGS += -DARTIQ_AMP CFLAGS += -DARTIQ_AMP
SERVICE_TABLE_INPUT = ksupport.elf SERVICE_TABLE_INPUT = ksupport.elf
else else

79
soc/runtime/bridge.c Normal file
View File

@ -0,0 +1,79 @@
#include "mailbox.h"
#include "messages.h"
#include "rtio.h"
#include "dds.h"
#include "bridge.h"
static void send_ready(void)
{
struct msg_base msg;
msg.type = MESSAGE_TYPE_BRG_READY;
mailbox_send_and_wait(&msg);
}
void bridge_main(void)
{
struct msg_base *umsg;
send_ready();
while(1) {
umsg = mailbox_wait_and_receive();
switch(umsg->type) {
case MESSAGE_TYPE_BRG_TTL_OUT: {
struct msg_brg_ttl_out *msg;
msg = (struct msg_brg_ttl_out *)umsg;
rtio_init();
rtio_set_oe(rtio_get_counter() + 8000, msg->channel, 1);
rtio_set_o(rtio_get_counter() + 8000, msg->channel, msg->value);
mailbox_acknowledge();
break;
}
case MESSAGE_TYPE_BRG_DDS_SEL: {
struct msg_brg_dds_sel *msg;
msg = (struct msg_brg_dds_sel *)umsg;
DDS_WRITE(DDS_GPIO, msg->channel);
mailbox_acknowledge();
break;
}
case MESSAGE_TYPE_BRG_DDS_RESET: {
unsigned int g;
g = DDS_READ(DDS_GPIO);
DDS_WRITE(DDS_GPIO, g | (1 << 7));
DDS_WRITE(DDS_GPIO, g);
mailbox_acknowledge();
break;
}
case MESSAGE_TYPE_BRG_DDS_READ_REQUEST: {
struct msg_brg_dds_read_request *msg;
struct msg_brg_dds_read_reply rmsg;
msg = (struct msg_brg_dds_read_request *)umsg;
rmsg.type = MESSAGE_TYPE_BRG_DDS_READ_REPLY;
rmsg.data = DDS_READ(msg->address);
mailbox_send_and_wait(&rmsg);
break;
}
case MESSAGE_TYPE_BRG_DDS_WRITE: {
struct msg_brg_dds_write *msg;
msg = (struct msg_brg_dds_write *)umsg;
DDS_WRITE(msg->address, msg->data);
mailbox_acknowledge();
break;
}
case MESSAGE_TYPE_BRG_DDS_FUD:
rtio_init();
rtio_fud(rtio_get_counter() + 8000);
mailbox_acknowledge();
break;
default:
mailbox_acknowledge();
break;
}
}
}

6
soc/runtime/bridge.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef __BRIDGE_H
#define __BRIDGE_H
void bridge_main(void);
#endif /* __BRIDGE_H */

View File

@ -1,6 +1,7 @@
#include <stdarg.h> #include <stdarg.h>
#include "exceptions.h" #include "exceptions.h"
#include "bridge.h"
#include "mailbox.h" #include "mailbox.h"
#include "messages.h" #include "messages.h"
#include "rtio.h" #include "rtio.h"
@ -31,26 +32,29 @@ int main(void)
kernel_function k; kernel_function k;
void *jb; void *jb;
jb = exception_push(); k = mailbox_receive();
if(exception_setjmp(jb)) {
struct msg_exception msg;
msg.type = MESSAGE_TYPE_EXCEPTION; if(k == NULL)
msg.eid = exception_getid(msg.eparams); bridge_main();
mailbox_send_and_wait(&msg); else {
} else { jb = exception_push();
struct msg_finished msg; if(exception_setjmp(jb)) {
struct msg_exception msg;
k = mailbox_receive(); msg.type = MESSAGE_TYPE_EXCEPTION;
if(!k) msg.eid = exception_getid(msg.eparams);
exception_raise(EID_INTERNAL_ERROR); mailbox_send_and_wait(&msg);
dds_init(); } else {
rtio_init(); struct msg_base msg;
k();
exception_pop(1);
msg.type = MESSAGE_TYPE_FINISHED; dds_init();
mailbox_send_and_wait(&msg); rtio_init();
k();
exception_pop(1);
msg.type = MESSAGE_TYPE_FINISHED;
mailbox_send_and_wait(&msg);
}
} }
while(1); while(1);
} }

View File

@ -70,7 +70,7 @@ static int load_object(void *buffer, int length)
#ifdef ARTIQ_AMP #ifdef ARTIQ_AMP
static int process_msg(struct msg_unknown *umsg, int *eid, long long int *eparams) static int process_msg(struct msg_base *umsg, int *eid, long long int *eparams)
{ {
int i; int i;
@ -129,7 +129,7 @@ static int run_kernel(const char *kernel_name, int *eid, long long int *eparams)
#ifdef ARTIQ_AMP #ifdef ARTIQ_AMP
kernelcpu_start(k); kernelcpu_start(k);
while(1) { while(1) {
struct msg_unknown *umsg; struct msg_base *umsg;
umsg = mailbox_receive(); umsg = mailbox_receive();
r = KERNEL_RUN_INVALID_STATUS; r = KERNEL_RUN_INVALID_STATUS;

View File

@ -8,16 +8,23 @@ enum {
MESSAGE_TYPE_EXCEPTION, MESSAGE_TYPE_EXCEPTION,
MESSAGE_TYPE_RPC_REQUEST, MESSAGE_TYPE_RPC_REQUEST,
MESSAGE_TYPE_RPC_REPLY, MESSAGE_TYPE_RPC_REPLY,
MESSAGE_TYPE_LOG MESSAGE_TYPE_LOG,
MESSAGE_TYPE_BRG_READY,
MESSAGE_TYPE_BRG_TTL_OUT,
MESSAGE_TYPE_BRG_DDS_SEL,
MESSAGE_TYPE_BRG_DDS_RESET,
MESSAGE_TYPE_BRG_DDS_READ_REQUEST,
MESSAGE_TYPE_BRG_DDS_READ_REPLY,
MESSAGE_TYPE_BRG_DDS_WRITE,
MESSAGE_TYPE_BRG_DDS_FUD,
}; };
struct msg_unknown { struct msg_base {
int type; int type;
}; };
struct msg_finished { /* kernel messages */
int type;
};
struct msg_exception { struct msg_exception {
int type; int type;
@ -43,4 +50,33 @@ struct msg_log {
va_list args; va_list args;
}; };
/* bridge messages */
struct msg_brg_ttl_out {
int type;
int channel;
int value;
};
struct msg_brg_dds_sel {
int type;
int channel;
};
struct msg_brg_dds_read_request {
int type;
unsigned int address;
};
struct msg_brg_dds_read_reply {
int type;
unsigned int data;
};
struct msg_brg_dds_write {
int type;
unsigned int address;
unsigned int data;
};
#endif /* __MESSAGES_H */ #endif /* __MESSAGES_H */

View File

@ -13,14 +13,136 @@
#ifdef ARTIQ_AMP #ifdef ARTIQ_AMP
#warning TODO #include "kernelcpu.h"
#include "mailbox.h"
#include "messages.h"
void test_main(void) static void amp_bridge_init(void)
{ {
printf("Not implemented yet for AMP systems\n"); struct msg_base *umsg;
kernelcpu_start(NULL);
while(1) {
umsg = mailbox_wait_and_receive();
if(umsg->type == MESSAGE_TYPE_BRG_READY) {
printf("AMP bridge ready\n");
mailbox_acknowledge();
break;
} else {
printf("Warning: unexpected message %d from AMP bridge\n", umsg->type);
mailbox_acknowledge();
}
}
} }
#else static void p_ttlout(int n, int value)
{
struct msg_brg_ttl_out msg;
msg.type = MESSAGE_TYPE_BRG_TTL_OUT;
msg.channel = n;
msg.value = value;
mailbox_send_and_wait(&msg);
}
static void p_ddssel(int channel)
{
struct msg_brg_dds_sel msg;
msg.type = MESSAGE_TYPE_BRG_DDS_SEL;
msg.channel = channel;
mailbox_send_and_wait(&msg);
}
static void p_ddsreset(void)
{
struct msg_base msg;
msg.type = MESSAGE_TYPE_BRG_DDS_RESET;
mailbox_send_and_wait(&msg);
}
static unsigned int p_ddsread(unsigned int address)
{
struct msg_brg_dds_read_request msg;
struct msg_brg_dds_read_reply *rmsg;
unsigned int r;
msg.type = MESSAGE_TYPE_BRG_DDS_READ_REQUEST;
msg.address = address;
mailbox_send(&msg);
while(1) {
rmsg = mailbox_wait_and_receive();
if(rmsg->type == MESSAGE_TYPE_BRG_DDS_READ_REPLY) {
r = rmsg->data;
mailbox_acknowledge();
return r;
} else {
printf("Warning: unexpected message %d from AMP bridge\n", rmsg->type);
mailbox_acknowledge();
}
}
}
static void p_ddswrite(unsigned int address, unsigned int data)
{
struct msg_brg_dds_write msg;
msg.type = MESSAGE_TYPE_BRG_DDS_WRITE;
msg.address = address;
msg.data = data;
mailbox_send_and_wait(&msg);
}
static void p_ddsfud(void)
{
struct msg_base msg;
msg.type = MESSAGE_TYPE_BRG_DDS_FUD;
mailbox_send_and_wait(&msg);
}
#else /* ARTIQ_AMP */
static void p_ttlout(int n, int value)
{
rtio_init();
rtio_set_oe(rtio_get_counter() + 8000, n2, 1);
rtio_set_o(rtio_get_counter() + 8000, n2, value2);
}
static void p_ddssel(int channel)
{
DDS_WRITE(DDS_GPIO, n2);
}
static void p_ddsreset(void)
{
unsigned int g;
g = DDS_READ(DDS_GPIO);
DDS_WRITE(DDS_GPIO, g | (1 << 7));
DDS_WRITE(DDS_GPIO, g);
}
static unsigned int p_ddsread(unsigned int address)
{
return DDS_READ(address);
}
static void p_ddswrite(unsigned int address, unsigned int data)
{
DDS_WRITE(address, data);
}
static void p_ddsfud(void)
{
rtio_init();
rtio_fud(rtio_get_counter() + 8000);
}
#endif /* ARTIQ_AMP */
static void leds(char *value) static void leds(char *value)
{ {
@ -81,9 +203,7 @@ static void ttlout(char *n, char *value)
return; return;
} }
rtio_init(); p_ttlout(n2, value2);
rtio_set_oe(rtio_get_counter() + 8000, n2, 1);
rtio_set_o(rtio_get_counter() + 8000, n2, value2);
} }
static void ddssel(char *n) static void ddssel(char *n)
@ -102,7 +222,7 @@ static void ddssel(char *n)
return; return;
} }
DDS_WRITE(DDS_GPIO, n2); p_ddssel(n2);
} }
static void ddsw(char *addr, char *value) static void ddsw(char *addr, char *value)
@ -126,7 +246,7 @@ static void ddsw(char *addr, char *value)
return; return;
} }
DDS_WRITE(addr2, value2); p_ddswrite(addr2, value2);
} }
static void ddsr(char *addr) static void ddsr(char *addr)
@ -145,13 +265,12 @@ static void ddsr(char *addr)
return; return;
} }
printf("0x%02x\n", DDS_READ(addr2)); printf("0x%02x\n", p_ddsread(addr2));
} }
static void ddsfud(void) static void ddsfud(void)
{ {
rtio_init(); p_ddsfud();
rtio_fud(rtio_get_counter() + 8000);
} }
static void ddsftw(char *n, char *ftw) static void ddsftw(char *n, char *ftw)
@ -175,31 +294,27 @@ static void ddsftw(char *n, char *ftw)
return; return;
} }
DDS_WRITE(DDS_GPIO, n2); p_ddssel(n2);
DDS_WRITE(DDS_FTW0, ftw2 & 0xff); p_ddswrite(DDS_FTW0, ftw2 & 0xff);
DDS_WRITE(DDS_FTW1, (ftw2 >> 8) & 0xff); p_ddswrite(DDS_FTW1, (ftw2 >> 8) & 0xff);
DDS_WRITE(DDS_FTW2, (ftw2 >> 16) & 0xff); p_ddswrite(DDS_FTW2, (ftw2 >> 16) & 0xff);
DDS_WRITE(DDS_FTW3, (ftw2 >> 24) & 0xff); p_ddswrite(DDS_FTW3, (ftw2 >> 24) & 0xff);
ddsfud(); p_ddsfud();
} }
static void ddsreset(void) static void ddsreset(void)
{ {
unsigned int g; p_ddsreset();
g = DDS_READ(DDS_GPIO);
DDS_WRITE(DDS_GPIO, g | (1 << 7));
DDS_WRITE(DDS_GPIO, g);
} }
static void ddsinit(void) static void ddsinit(void)
{ {
ddsreset(); p_ddsreset();
DDS_WRITE(0x00, 0x78); p_ddswrite(0x00, 0x78);
DDS_WRITE(0x01, 0x00); p_ddswrite(0x01, 0x00);
DDS_WRITE(0x02, 0x00); p_ddswrite(0x02, 0x00);
DDS_WRITE(0x03, 0x00); p_ddswrite(0x03, 0x00);
ddsfud(); p_ddsfud();
} }
static void ddstest_one(unsigned int i) static void ddstest_one(unsigned int i)
@ -211,20 +326,20 @@ static void ddstest_one(unsigned int i)
}; };
unsigned int f, g, j; unsigned int f, g, j;
DDS_WRITE(DDS_GPIO, i); p_ddssel(i);
ddsinit(); ddsinit();
for(j=0; j<12; j++) { for(j=0; j<12; j++) {
f = v[j]; f = v[j];
DDS_WRITE(0x0a, f & 0xff); p_ddswrite(0x0a, f & 0xff);
DDS_WRITE(0x0b, (f >> 8) & 0xff); p_ddswrite(0x0b, (f >> 8) & 0xff);
DDS_WRITE(0x0c, (f >> 16) & 0xff); p_ddswrite(0x0c, (f >> 16) & 0xff);
DDS_WRITE(0x0d, (f >> 24) & 0xff); p_ddswrite(0x0d, (f >> 24) & 0xff);
ddsfud(); p_ddsfud();
g = DDS_READ(0x0a); g = p_ddsread(0x0a);
g |= DDS_READ(0x0b) << 8; g |= p_ddsread(0x0b) << 8;
g |= DDS_READ(0x0c) << 16; g |= p_ddsread(0x0c) << 16;
g |= DDS_READ(0x0d) << 24; g |= p_ddsread(0x0d) << 24;
if(g != f) if(g != f)
printf("readback fail on DDS %d, 0x%08x != 0x%08x\n", i, g, f); printf("readback fail on DDS %d, 0x%08x != 0x%08x\n", i, g, f);
} }
@ -346,11 +461,13 @@ void test_main(void)
{ {
char buffer[64]; char buffer[64];
#ifdef ARTIQ_AMP
amp_bridge_init();
#endif
while(1) { while(1) {
putsnonl("\e[1mtest>\e[0m "); putsnonl("\e[1mtest>\e[0m ");
readstr(buffer, 64); readstr(buffer, 64);
do_command(buffer); do_command(buffer);
} }
} }
#endif /* ARTIQ_AMP */