From 6a5f58e5a944c2efe59c631d454641ab0ec1118f Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 16 Apr 2015 21:47:05 +0800 Subject: [PATCH] runtime: support test mode on AMP --- soc/runtime/Makefile | 2 +- soc/runtime/bridge.c | 79 ++++++++++++++++ soc/runtime/bridge.h | 6 ++ soc/runtime/ksupport.c | 38 ++++---- soc/runtime/main.c | 4 +- soc/runtime/messages.h | 46 +++++++++- soc/runtime/test_mode.c | 199 +++++++++++++++++++++++++++++++--------- 7 files changed, 308 insertions(+), 66 deletions(-) create mode 100644 soc/runtime/bridge.c create mode 100644 soc/runtime/bridge.h diff --git a/soc/runtime/Makefile b/soc/runtime/Makefile index a77879511..be5dc48f5 100644 --- a/soc/runtime/Makefile +++ b/soc/runtime/Makefile @@ -9,7 +9,7 @@ UNIPROCESSOR := $(shell printf "\#include \nCSR_KERNEL_CPU_BASE ifeq ($(UNIPROCESSOR),0) 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 SERVICE_TABLE_INPUT = ksupport.elf else diff --git a/soc/runtime/bridge.c b/soc/runtime/bridge.c new file mode 100644 index 000000000..aa55fc94a --- /dev/null +++ b/soc/runtime/bridge.c @@ -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; + } + } +} diff --git a/soc/runtime/bridge.h b/soc/runtime/bridge.h new file mode 100644 index 000000000..d9e4f3654 --- /dev/null +++ b/soc/runtime/bridge.h @@ -0,0 +1,6 @@ +#ifndef __BRIDGE_H +#define __BRIDGE_H + +void bridge_main(void); + +#endif /* __BRIDGE_H */ diff --git a/soc/runtime/ksupport.c b/soc/runtime/ksupport.c index 935d742f2..dbeac95fa 100644 --- a/soc/runtime/ksupport.c +++ b/soc/runtime/ksupport.c @@ -1,6 +1,7 @@ #include #include "exceptions.h" +#include "bridge.h" #include "mailbox.h" #include "messages.h" #include "rtio.h" @@ -31,26 +32,29 @@ int main(void) kernel_function k; void *jb; - jb = exception_push(); - if(exception_setjmp(jb)) { - struct msg_exception msg; + k = mailbox_receive(); - msg.type = MESSAGE_TYPE_EXCEPTION; - msg.eid = exception_getid(msg.eparams); - mailbox_send_and_wait(&msg); - } else { - struct msg_finished msg; + if(k == NULL) + bridge_main(); + else { + jb = exception_push(); + if(exception_setjmp(jb)) { + struct msg_exception msg; - k = mailbox_receive(); - if(!k) - exception_raise(EID_INTERNAL_ERROR); - dds_init(); - rtio_init(); - k(); - exception_pop(1); + msg.type = MESSAGE_TYPE_EXCEPTION; + msg.eid = exception_getid(msg.eparams); + mailbox_send_and_wait(&msg); + } else { + struct msg_base msg; - msg.type = MESSAGE_TYPE_FINISHED; - mailbox_send_and_wait(&msg); + dds_init(); + rtio_init(); + k(); + exception_pop(1); + + msg.type = MESSAGE_TYPE_FINISHED; + mailbox_send_and_wait(&msg); + } } while(1); } diff --git a/soc/runtime/main.c b/soc/runtime/main.c index 4167037fe..3fa54d11c 100644 --- a/soc/runtime/main.c +++ b/soc/runtime/main.c @@ -70,7 +70,7 @@ static int load_object(void *buffer, int length) #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; @@ -129,7 +129,7 @@ static int run_kernel(const char *kernel_name, int *eid, long long int *eparams) #ifdef ARTIQ_AMP kernelcpu_start(k); while(1) { - struct msg_unknown *umsg; + struct msg_base *umsg; umsg = mailbox_receive(); r = KERNEL_RUN_INVALID_STATUS; diff --git a/soc/runtime/messages.h b/soc/runtime/messages.h index 274d40cf1..8c48a0946 100644 --- a/soc/runtime/messages.h +++ b/soc/runtime/messages.h @@ -8,16 +8,23 @@ enum { MESSAGE_TYPE_EXCEPTION, MESSAGE_TYPE_RPC_REQUEST, 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; }; -struct msg_finished { - int type; -}; +/* kernel messages */ struct msg_exception { int type; @@ -43,4 +50,33 @@ struct msg_log { 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 */ diff --git a/soc/runtime/test_mode.c b/soc/runtime/test_mode.c index 15a81d830..6ab78aa76 100644 --- a/soc/runtime/test_mode.c +++ b/soc/runtime/test_mode.c @@ -13,14 +13,136 @@ #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) { @@ -81,9 +203,7 @@ static void ttlout(char *n, char *value) return; } - rtio_init(); - rtio_set_oe(rtio_get_counter() + 8000, n2, 1); - rtio_set_o(rtio_get_counter() + 8000, n2, value2); + p_ttlout(n2, value2); } static void ddssel(char *n) @@ -102,7 +222,7 @@ static void ddssel(char *n) return; } - DDS_WRITE(DDS_GPIO, n2); + p_ddssel(n2); } static void ddsw(char *addr, char *value) @@ -126,7 +246,7 @@ static void ddsw(char *addr, char *value) return; } - DDS_WRITE(addr2, value2); + p_ddswrite(addr2, value2); } static void ddsr(char *addr) @@ -145,13 +265,12 @@ static void ddsr(char *addr) return; } - printf("0x%02x\n", DDS_READ(addr2)); + printf("0x%02x\n", p_ddsread(addr2)); } static void ddsfud(void) { - rtio_init(); - rtio_fud(rtio_get_counter() + 8000); + p_ddsfud(); } static void ddsftw(char *n, char *ftw) @@ -175,31 +294,27 @@ static void ddsftw(char *n, char *ftw) return; } - DDS_WRITE(DDS_GPIO, n2); - DDS_WRITE(DDS_FTW0, ftw2 & 0xff); - DDS_WRITE(DDS_FTW1, (ftw2 >> 8) & 0xff); - DDS_WRITE(DDS_FTW2, (ftw2 >> 16) & 0xff); - DDS_WRITE(DDS_FTW3, (ftw2 >> 24) & 0xff); - ddsfud(); + p_ddssel(n2); + p_ddswrite(DDS_FTW0, ftw2 & 0xff); + p_ddswrite(DDS_FTW1, (ftw2 >> 8) & 0xff); + p_ddswrite(DDS_FTW2, (ftw2 >> 16) & 0xff); + p_ddswrite(DDS_FTW3, (ftw2 >> 24) & 0xff); + p_ddsfud(); } static void ddsreset(void) { - unsigned int g; - - g = DDS_READ(DDS_GPIO); - DDS_WRITE(DDS_GPIO, g | (1 << 7)); - DDS_WRITE(DDS_GPIO, g); + p_ddsreset(); } static void ddsinit(void) { - ddsreset(); - DDS_WRITE(0x00, 0x78); - DDS_WRITE(0x01, 0x00); - DDS_WRITE(0x02, 0x00); - DDS_WRITE(0x03, 0x00); - ddsfud(); + p_ddsreset(); + p_ddswrite(0x00, 0x78); + p_ddswrite(0x01, 0x00); + p_ddswrite(0x02, 0x00); + p_ddswrite(0x03, 0x00); + p_ddsfud(); } static void ddstest_one(unsigned int i) @@ -211,20 +326,20 @@ static void ddstest_one(unsigned int i) }; unsigned int f, g, j; - DDS_WRITE(DDS_GPIO, i); + p_ddssel(i); ddsinit(); for(j=0; j<12; j++) { f = v[j]; - DDS_WRITE(0x0a, f & 0xff); - DDS_WRITE(0x0b, (f >> 8) & 0xff); - DDS_WRITE(0x0c, (f >> 16) & 0xff); - DDS_WRITE(0x0d, (f >> 24) & 0xff); - ddsfud(); - g = DDS_READ(0x0a); - g |= DDS_READ(0x0b) << 8; - g |= DDS_READ(0x0c) << 16; - g |= DDS_READ(0x0d) << 24; + p_ddswrite(0x0a, f & 0xff); + p_ddswrite(0x0b, (f >> 8) & 0xff); + p_ddswrite(0x0c, (f >> 16) & 0xff); + p_ddswrite(0x0d, (f >> 24) & 0xff); + p_ddsfud(); + g = p_ddsread(0x0a); + g |= p_ddsread(0x0b) << 8; + g |= p_ddsread(0x0c) << 16; + g |= p_ddsread(0x0d) << 24; if(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]; +#ifdef ARTIQ_AMP + amp_bridge_init(); +#endif + while(1) { putsnonl("\e[1mtest>\e[0m "); readstr(buffer, 64); do_command(buffer); } } - -#endif /* ARTIQ_AMP */