From 1197314093a4ce88d7fe250a377ac7ce68c619f2 Mon Sep 17 00:00:00 2001 From: Ludwig Ortmann Date: Thu, 21 Mar 2013 16:55:57 +0100 Subject: [PATCH 01/12] native cpu fixes init hwtimer with interrupts enabled more error checking for hwtimer fix signal handler init in hwtimer error checking for irq (not necessary yet afaik) --- cpu/native/hwtimer_cpu.c | 6 +++++- cpu/native/irq_cpu.c | 9 +++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/cpu/native/hwtimer_cpu.c b/cpu/native/hwtimer_cpu.c index 7082094d38..c59a4f9e98 100644 --- a/cpu/native/hwtimer_cpu.c +++ b/cpu/native/hwtimer_cpu.c @@ -67,6 +67,9 @@ void hwtimer_isr_timer() DEBUG("hwtimer_isr_timer(): calling hwtimer.int_handler(%i)\n", i); int_handler(i); } + if (timer_getoverrun(native_hwtimer_timer[i]) > 0 ) { + errx(1, "XXX: unhandled hwtimer situation"); + } } } @@ -165,10 +168,11 @@ void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu) native_hwtimer_irq[i] = 0; //sev.sigev_signo = _SIG_TIMER + i;; sev.sigev_signo = SIGALRM; - sev.sigev_value.sival_ptr = &native_hwtimer_timer[i]; + //sev.sigev_value.sival_ptr = &native_hwtimer_timer[i]; if (timer_create(CLOCK_REALTIME, &sev, &native_hwtimer_timer[i]) == -1) { err(1, "timer_create"); } } + hwtimer_arch_enable_interrupt(); return; } diff --git a/cpu/native/irq_cpu.c b/cpu/native/irq_cpu.c index 07d9adfb21..4ac6f47ea0 100644 --- a/cpu/native/irq_cpu.c +++ b/cpu/native/irq_cpu.c @@ -51,11 +51,13 @@ unsigned disableIRQ(void) err(1, "disableIRQ(): sigfillset"); } if (native_interrupts_enabled == 1) { + DEBUG("sigprocmask(..native_sig_set)\n"); if (sigprocmask(SIG_SETMASK, &mask, &native_sig_set) == -1) { err(1, "disableIRQ(): sigprocmask"); } } else { + DEBUG("sigprocmask()\n"); if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1) { err(1, "disableIRQ(): sigprocmask()"); } @@ -120,14 +122,21 @@ void eINT(void) */ void native_irq_handler() { + if (last_sig == -1) { + errx(1, "XXX: internal error"); + } if (native_irq_handlers[last_sig].func != NULL) { DEBUG("calling interrupt handler for %i\n", last_sig); native_irq_handlers[last_sig].func(); } + else if (last_sig == SIGUSR1) { + DEBUG("ignoring SIGUSR1\n"); + } else { printf("XXX: no handler for signal %i\n", last_sig); errx(1, "XXX: this should not have happened!\n"); } + last_sig = -1; native_in_irs = 0; cpu_switch_context_exit(); } From 671cb6560f4b52e35625f9dba1f59f036dd9d775 Mon Sep 17 00:00:00 2001 From: Ludwig Ortmann Date: Thu, 21 Mar 2013 17:08:41 +0100 Subject: [PATCH 02/12] native cc110x_ng placebo --- Makefile.dep | 6 ++ cpu/native/Makefile | 3 + cpu/native/cc110x_ng/Makefile | 7 ++ cpu/native/cc110x_ng/cc110x_ng_cpu.c | 151 +++++++++++++++++++++++++++ cpu/native/include/cpu-conf.h | 6 +- drivers/cc110x_ng/Makefile | 3 + 6 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 cpu/native/cc110x_ng/Makefile create mode 100644 cpu/native/cc110x_ng/cc110x_ng_cpu.c diff --git a/Makefile.dep b/Makefile.dep index e23725d442..8a32b0900c 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -33,5 +33,11 @@ ifneq (,$(findstring cc110x_ng,$(USEMODULE))) USEMODULE += hwtimer endif endif + ifneq (,$(findstring native,$(BOARD))) + USEMODULE += cc110x_spi + ifeq (,$(findstring hwtimer,$(USEMODULE))) + USEMODULE += hwtimer + endif + endif endif diff --git a/cpu/native/Makefile b/cpu/native/Makefile index bc80511fb5..b804fc8755 100644 --- a/cpu/native/Makefile +++ b/cpu/native/Makefile @@ -5,6 +5,9 @@ DIRS = ifneq (,$(findstring rtc,$(USEMODULE))) DIRS += rtc endif +ifneq (,$(findstring cc110x_ng,$(USEMODULE))) + DIRS += cc110x_ng +endif all: $(BINDIR)$(MODULE).a @for i in $(DIRS) ; do $(MAKE) -C $$i ; done ; diff --git a/cpu/native/cc110x_ng/Makefile b/cpu/native/cc110x_ng/Makefile new file mode 100644 index 0000000000..db427dad5a --- /dev/null +++ b/cpu/native/cc110x_ng/Makefile @@ -0,0 +1,7 @@ +INCLUDES = -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/core/include +INCLUDES += -I$(RIOTBASE)/drivers/cc110x_ng/include/ -I$(RIOTBASE)/sys/include + +MODULE =cc110x_ng + +include $(MAKEBASE)/Makefile.base + diff --git a/cpu/native/cc110x_ng/cc110x_ng_cpu.c b/cpu/native/cc110x_ng/cc110x_ng_cpu.c new file mode 100644 index 0000000000..bb04e2a29c --- /dev/null +++ b/cpu/native/cc110x_ng/cc110x_ng_cpu.c @@ -0,0 +1,151 @@ +#include +#include + +#include + +#include +#include +#include +#include /* CC1100_READ_BURST etc. */ + +static int native_cc110x_enabled; + +static int native_cc110x_gd0; +static int native_cc110x_gd1; +static int native_cc110x_gd2; + +static int native_cc110x_gd0_enabled; +static int native_cc110x_gd2_enabled; + +static uint8_t native_cc110x_ssp0dr; + +/* arch */ + +/** + * writes to SSP0 data register and reads from it once it is ready + */ +uint8_t cc110x_txrx(uint8_t c) +{ + native_cc110x_ssp0dr = c; + switch (c) { + case CC1100_READ_BURST: + case CC1100_WRITE_BURST: + case CC1100_READ_SINGLE: + case CC1100_NOBYTE: + default: + warnx("cc110x_txrx (%i): not implemented", c); + } + DEBUG("cc110x_txrx\n"); + return native_cc110x_ssp0dr; +} + +/** + * disables GDO0 interrupt + */ +void cc110x_gdo0_enable(void) +{ + /* this would be for rising/high edge if this was proper hardware */ + native_cc110x_gd0_enabled = 1; + DEBUG("cc110x_gdo0_enable\n"); + return; +} + + +/** + * enables GDO0 interrupt + */ +void cc110x_gdo0_disable(void) +{ + native_cc110x_gd0_enabled = 0; + DEBUG("cc110x_gdo0_disable\n"); + return; +} + +/** + * enables GDO2 interrupt + */ +void cc110x_gdo2_enable(void) +{ + /* this would be for falling/low edge if this was proper hardware */ + native_cc110x_gd2_enabled = 1; + DEBUG("cc110x_gdo2_enable\n"); + return; +} + +/** + * disables GDO2 interrupt + */ +void cc110x_gdo2_disable(void) +{ + native_cc110x_gd2_enabled = 0; + DEBUG("cc110x_gdo2_disable\n"); + return; +} + +/** + * enable interrupts for GDO0 and GDO2 + */ +void cc110x_init_interrupts(void) +{ + /* this would be for low edge in both cases if this was proper hardware */ + cc110x_gdo2_enable(); + cc110x_gdo0_enable(); + DEBUG("cc110x_init_interrupts\n"); + return; +} + +void cc110x_before_send(void) +{ + cc110x_gdo2_disable(); + DEBUG("cc110x_before_send\n"); + return; +} +void cc110x_after_send(void) +{ + cc110x_gdo2_enable(); + DEBUG("cc110x_after_send\n"); + return; +} + +/* spi */ + +int cc110x_get_gdo0(void) +{ + DEBUG("cc110x_get_gdo0\n"); + return native_cc110x_gd0; +} +int cc110x_get_gdo1(void) +{ + DEBUG("cc110x_get_gdo1\n"); + return native_cc110x_gd1; +} +int cc110x_get_gdo2(void) +{ + DEBUG("cc110x_get_gdo2\n"); + return native_cc110x_gd2; +} + +void cc110x_spi_init(void) +{ + native_cc110x_enabled = 1; /* power on */ + DEBUG("cc110x_spi_init\n"); + return; +} + +void cc110x_spi_cs(void) +{ + DEBUG("cc110x_spi_cs\n"); + return; +} +void cc110x_spi_select(void) +{ + DEBUG("cc110x_spi_select\n"); + return; +} +void cc110x_spi_unselect(void) +{ + DEBUG("cc110x_spi_unselect\n"); + return; +} + +/* ng */ diff --git a/cpu/native/include/cpu-conf.h b/cpu/native/include/cpu-conf.h index eebbe2e30b..5964de56af 100644 --- a/cpu/native/include/cpu-conf.h +++ b/cpu/native/include/cpu-conf.h @@ -21,7 +21,7 @@ #define KERNEL_CONF_STACKSIZE_DEFAULT 8192 #endif -#define KERNEL_CONF_STACKSIZE_IDLE 2048 +#define KERNEL_CONF_STACKSIZE_IDLE 4096 #define NATIVE_ISR_STACKSIZE 8192 #define _SIG_UNDEF SIGRTMIN + 0 @@ -30,4 +30,8 @@ /* TODO: check for overflow (SIGRTMAX) */ +/* for cc110x_ng */ +#define RX_BUF_SIZE (10) +#define TRANSCEIVER_BUFFER_SIZE (3) + #endif /* CPUCONF_H_ */ diff --git a/drivers/cc110x_ng/Makefile b/drivers/cc110x_ng/Makefile index 6fadf78ad4..f5f3820efc 100644 --- a/drivers/cc110x_ng/Makefile +++ b/drivers/cc110x_ng/Makefile @@ -8,6 +8,9 @@ endif ifneq (,$(findstring msba2,$(BOARD))) DIRS += spi endif +ifneq (,$(findstring native,$(BOARD))) + DIRS += spi +endif all: $(BINDIR)$(MODULE).a @for i in $(DIRS) ; do $(MAKE) -C $$i ; done ; From 2f74d35709834dec10d9e7c236fe3c45e1692ac3 Mon Sep 17 00:00:00 2001 From: Ludwig Ortmann Date: Wed, 3 Apr 2013 18:53:19 +0200 Subject: [PATCH 03/12] removed posix real-time extension timers from cpu --- cpu/native/hwtimer_cpu.c | 141 +++++++++++++++++++++++----------- cpu/native/include/cpu-conf.h | 4 +- 2 files changed, 96 insertions(+), 49 deletions(-) diff --git a/cpu/native/hwtimer_cpu.c b/cpu/native/hwtimer_cpu.c index c59a4f9e98..608304d90a 100644 --- a/cpu/native/hwtimer_cpu.c +++ b/cpu/native/hwtimer_cpu.c @@ -1,8 +1,11 @@ /** * Native CPU hwtimer_arch.h implementation * - * Uses POSIX real-time extension timers to mimic hardware timers. - * XXX: see hwtimer_isr_timer() + * Uses POSIX realtime clock and POSIX itimer to mimic hardware. + * Since there is only 1 itmer per process and RIOT needs several + * hardware timers, hwtimers are being multiplexed onto the itimer. + * + * XXX: does not scale well with number of timers (overhead: O(N)). * * Copyright (C) 2013 Ludwig Ortmann * @@ -18,6 +21,7 @@ */ #include +#include #include #include #include @@ -31,17 +35,30 @@ #include "debug.h" static unsigned long native_hwtimer_now; + static int native_hwtimer_irq[ARCH_MAXTIMERS]; -static timer_t native_hwtimer_timer[ARCH_MAXTIMERS]; +static struct itimerval native_hwtimer[ARCH_MAXTIMERS]; +static int native_hwtimer_isset[ARCH_MAXTIMERS]; + +static int next_timer; static void (*int_handler)(int); /** - * sets timespec to given ticks + * sets timeval to given ticks */ -void ticks2ts(unsigned long ticks, struct timespec *tp) +void ticks2tv(unsigned long ticks, struct timeval *tp) { tp->tv_sec = ticks / HWTIMER_SPEED; - tp->tv_nsec = (ticks % HWTIMER_SPEED)*1000 ; + tp->tv_usec = (ticks % HWTIMER_SPEED) ; +} + +/** + * returns ticks for give timeval + */ +unsigned long tv2ticks(struct timeval *tp) +{ + /* TODO: check for overflow */ + return((tp->tv_sec * HWTIMER_SPEED) + (tp->tv_usec)); } /** @@ -54,22 +71,72 @@ unsigned long ts2ticks(struct timespec *tp) } /** - * native timer signal handler, + * set next_timer to the next lowest enabled timer index + */ +void schedule_timer(void) +{ + int l = next_timer; + for ( + int i = ((next_timer +1) % ARCH_MAXTIMERS); + i != next_timer; + i = ((i+1) % ARCH_MAXTIMERS) + ) + { + + if ( native_hwtimer_isset[l] != 1 ) { + /* make sure we dont compare to garbage in the following + * if condition */ + l = i; + } + + if ( + ( native_hwtimer_isset[i] == 1 ) && + ( tv2ticks(&(native_hwtimer[i].it_value)) < tv2ticks(&(native_hwtimer[l].it_value)) ) + ) + { + /* set l to the lowest active time */ + l = i; + } + + } + next_timer = l; + /* l could still point to some unused (garbage) timer if no timers + * are set at all */ + if (native_hwtimer_isset[next_timer] == 1) { + if (setitimer(ITIMER_REAL, &native_hwtimer[next_timer], NULL) == -1) { + err(1, "schedule_timer"); + } + else { + DEBUG("schedule_timer(): set next timer.\n"); + } + } + else { + DEBUG("schedule_timer(): no next timer!? This looks suspicous.\n"); + // TODO: unset timer. + } +} + +/** + * native timer signal handler * - * XXX: Calls callback for all timers whenever any timer finishes. + * set new system timer, call timer interrupt handler */ void hwtimer_isr_timer() { + int i; + DEBUG("hwtimer_isr_timer()\n"); - for (int i = 0; i 0 ) { - errx(1, "XXX: unhandled hwtimer situation"); - } + i = next_timer; + native_hwtimer_isset[next_timer] = 0; + schedule_timer(); + + if (native_hwtimer_irq[i] == 1) { + DEBUG("hwtimer_isr_timer(): calling hwtimer.int_handler(%i)\n", i); + int_handler(i); + } + else { + DEBUG("hwtimer_isr_timer(): this should not have happened"); } } @@ -93,39 +160,27 @@ void hwtimer_arch_disable_interrupt(void) void hwtimer_arch_unset(short timer) { - struct itimerspec its; - DEBUG("hwtimer_arch_unset(%d)\n", timer); native_hwtimer_irq[timer] = 0; - - its.it_interval.tv_nsec = 0; - its.it_interval.tv_sec = 0; - its.it_value.tv_nsec = 0; - its.it_value.tv_sec = 0; - - if( (timer_settime(native_hwtimer_timer[timer], 0, &its, NULL)) == -1) { - err(1, "hwtimer_arch_unset: timer_settime"); - } + native_hwtimer_isset[timer] = 0; + schedule_timer(); return; } void hwtimer_arch_set(unsigned long offset, short timer) { - struct itimerspec its; - DEBUG("hwtimer_arch_set(%li, %i)\n", offset, timer); native_hwtimer_irq[timer] = 1; + native_hwtimer_isset[timer] = 1; - ticks2ts(offset, &its.it_value); - DEBUG("hwtimer_arch_set(): that is %lis %lins from now\n", its.it_value.tv_sec, its.it_value.tv_nsec); + ticks2tv(offset, &(native_hwtimer[timer].it_value)); + DEBUG("hwtimer_arch_set(): that is %lis %lius from now\n", + native_hwtimer[timer].it_value.tv_sec, + native_hwtimer[timer].it_value.tv_usec); - its.it_interval.tv_sec = 0; - its.it_interval.tv_nsec = 0; - if (timer_settime(native_hwtimer_timer[timer], 0, &its, NULL) == -1) { - err(1, "hwtimer_arch_unset: timer_settime"); - } + schedule_timer(); return; } @@ -155,24 +210,18 @@ unsigned long hwtimer_arch_now(void) void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu) { - struct sigevent sev; - DEBUG("hwtimer_arch_init()\n"); hwtimer_arch_disable_interrupt(); - int_handler = handler; - sev.sigev_notify = SIGEV_SIGNAL; for (int i = 0; i Date: Wed, 10 Apr 2013 12:48:35 +0200 Subject: [PATCH 04/12] move native board specific parts to corresponding Makefile --- Makefile.dep | 3 --- 1 file changed, 3 deletions(-) diff --git a/Makefile.dep b/Makefile.dep index bec0a6c2d4..00844b4933 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -20,7 +20,4 @@ ifneq (,$(findstring cc110x_ng,$(USEMODULE))) ifeq (,$(findstring hwtimer,$(USEMODULE))) USEMODULE += hwtimer endif - ifneq (,$(findstring native,$(BOARD))) - USEMODULE += cc110x_spi - endif endif From 2d29a26b64136a265385281c757939434ac9046c Mon Sep 17 00:00:00 2001 From: Ludwig Ortmann Date: Mon, 15 Apr 2013 20:08:46 +0200 Subject: [PATCH 05/12] fix stack and interrupt bugs --- cpu/native/include/cpu-conf.h | 14 ++-- cpu/native/include/cpu.h | 1 + cpu/native/irq_cpu.c | 128 ++++++++++++++++++++++++++++++++-- cpu/native/native_cpu.c | 37 ++++++++-- sys/include/transceiver.h | 2 + 5 files changed, 159 insertions(+), 23 deletions(-) diff --git a/cpu/native/include/cpu-conf.h b/cpu/native/include/cpu-conf.h index 1a6d31ba81..f83318f582 100644 --- a/cpu/native/include/cpu-conf.h +++ b/cpu/native/include/cpu-conf.h @@ -17,16 +17,10 @@ #include /* TODO: choose more sensibly? */ -#ifndef KERNEL_CONF_STACKSIZE_DEFAULT -#define KERNEL_CONF_STACKSIZE_DEFAULT 8192 -#endif - -#define KERNEL_CONF_STACKSIZE_IDLE 4096 -#define NATIVE_ISR_STACKSIZE 8192 - -#define _SIG_LTC4150 SIGRTMIN + 0 - -/* TODO: check for overflow (SIGRTMAX) */ +#define KERNEL_CONF_STACKSIZE_DEFAULT (16384) +#define KERNEL_CONF_STACKSIZE_IDLE (4096) +#define NATIVE_ISR_STACKSIZE (16384) +#define TRANSCEIVER_STACK_SIZE (16384) /* for cc110x_ng */ #define RX_BUF_SIZE (10) diff --git a/cpu/native/include/cpu.h b/cpu/native/include/cpu.h index d2c0fbd144..0d64a967d3 100644 --- a/cpu/native/include/cpu.h +++ b/cpu/native/include/cpu.h @@ -46,5 +46,6 @@ int unregister_interrupt(int sig); /* this should be defined elsewhere */ void thread_yield(void); +extern volatile ucontext_t *interrupted_contexts[MAXTHREADS]; /** @} */ #endif //_CPU_H diff --git a/cpu/native/irq_cpu.c b/cpu/native/irq_cpu.c index 4ac6f47ea0..0defac2949 100644 --- a/cpu/native/irq_cpu.c +++ b/cpu/native/irq_cpu.c @@ -37,6 +37,74 @@ struct int_handler_t { }; static struct int_handler_t native_irq_handlers[255]; +volatile ucontext_t *interrupted_contexts[MAXTHREADS]; + +void print_thread_sigmask(ucontext_t *cp) +{ + sigset_t *p = &cp->uc_sigmask; + if (sigemptyset(p) == -1) { + err(1, "print_thread_sigmask: sigemptyset"); + } + + for (int i = 1; i<(SIGRTMAX); i++) { + if (native_irq_handlers[i].func != NULL) { + printf("%s: %s\n", + strsignal(i), + (sigismember(&native_sig_set, i) ? "blocked": "unblocked") + ); + } + if (sigismember(p, i)) { + printf("%s: pending\n", strsignal(i)); + } + } +} + +void print_sigmasks(void) +{ + ucontext_t *p; + //tcb_t *cb = NULL; + + for (int i=0; iname); + //print_thread_sigmask(sched_threads[i]->sp); + p = sched_threads[i]->stack_start; + print_thread_sigmask(p); + puts(""); + } + } +} + +void native_print_signals() +{ + sigset_t p, q; + puts("native signals:\n"); + if (sigemptyset(&p) == -1) { + err(1, "native_print_signals: sigemptyset"); + } + if (sigpending(&p) == -1) { + err(1, "native_print_signals: sigpending"); + } + if (sigprocmask(SIG_SETMASK, NULL, &q) == -1) { + err(1, "native_print_signals(): sigprocmask"); + } + + for (int i = 1; i<(SIGRTMAX); i++) { + if (native_irq_handlers[i].func != NULL || i == SIGUSR1) { + printf("%s: %s\n", + strsignal(i), + (sigismember(&native_sig_set, i) ? "blocked": "unblocked") + ); + } + if (sigismember(&p, i)) { + printf("%s: pending\n", strsignal(i)); + } + if (sigismember(&q, i)) { + printf("%s: currently blocked\n", strsignal(i)); + } + } +} + /** * block signals */ @@ -83,6 +151,9 @@ unsigned enableIRQ(void) prev_state = native_interrupts_enabled; native_interrupts_enabled = 1; + //print_sigmasks(); + //native_print_signals(); + return prev_state; } @@ -188,6 +259,15 @@ void native_isr_entry(int sig, siginfo_t *info, void *context) makecontext(&native_context, native_irq_handler, 0); +#ifdef NATIVEUSESWAPCONTEXT + /** + * XXX: + * This seems to be the cause of undefined behavior. Try saving + * the context passed to this function and using setcontext to + * leave the handler. + * Also it is probably wise to makecontext the isr context + * elsewehere. + * */ if ((swapcontext((ucontext_t*)active_thread->sp, &native_context)) == -1) { err(1, "swapcontext failed"); } @@ -196,6 +276,15 @@ void native_isr_entry(int sig, siginfo_t *info, void *context) } native_in_irs = 0; enableIRQ(); +#else + interrupted_contexts[thread_getpid()] = context; + /** + * signal masks are broken + */ + //active_thread->sp = context; + setcontext(&native_context); + DEBUG("\n\n\tnever reached\n\n\n"); +#endif } /** @@ -210,13 +299,14 @@ int register_interrupt(int sig, void *handler) struct sigaction sa; DEBUG("XXX: register_interrupt()\n"); - if (sigaddset(&native_sig_set, sig)) { - err(1, "register_interrupt: sigaddset"); + if (sigdelset(&native_sig_set, sig)) { + err(1, "register_interrupt: sigdelset"); } native_irq_handlers[sig].func = handler; sa.sa_sigaction = (void*) native_isr_entry; + /* sa.sa_handler = (void*) native_isr_entry; */ if (sigemptyset(&sa.sa_mask) == -1) { err(1, "register_interrupt: sigemptyset"); @@ -242,12 +332,13 @@ int unregister_interrupt(int sig) struct sigaction sa; DEBUG("XXX: unregister_interrupt()\n"); - if (sigdelset(&native_sig_set, sig) == -1) { - err(1, "unregister_interrupt: sigdelset"); + if (sigaddset(&native_sig_set, sig) == -1) { + err(1, "unregister_interrupt: sigaddset"); } native_irq_handlers[sig].func = NULL; - sa.sa_sigaction = SIG_IGN; + /* sa.sa_sigaction = SIG_IGN; */ + sa.sa_handler = SIG_IGN; if (sigemptyset(&sa.sa_mask) == -1) { err(1, "unregister_interrupt: sigemptyset"); } @@ -271,6 +362,8 @@ void native_interrupt_init(void) struct sigaction sa; DEBUG("XXX: native_interrupt_init()\n"); + native_interrupts_enabled = 1; + for (int i = 0; i<255; i++) { native_irq_handlers[i].func = NULL; } @@ -281,17 +374,38 @@ void native_interrupt_init(void) } sa.sa_flags = SA_RESTART | SA_SIGINFO; + /* if (sigemptyset(&native_sig_set) == -1) { err(1, "native_interrupt_init: sigemptyset"); } - if (sigaddset(&native_sig_set, SIGUSR1) == -1) { - err(1, "native_interrupt_init: sigaddset"); + */ + if (sigprocmask(SIG_SETMASK, NULL, &native_sig_set) == -1) { + err(1, "native_interrupt_init(): sigprocmask"); + } + + if (sigdelset(&native_sig_set, SIGUSR1) == -1) { + err(1, "native_interrupt_init: sigdelset"); } if (sigaction(SIGUSR1, &sa, NULL)) { err(1, "native_interrupt_init: sigaction"); } + if (sigdelset(&native_sig_set, SIGALRM) == -1) { + err(1, "native_interrupt_init: sigdelset"); + } + + if (sigaction(SIGALRM, &sa, NULL)) { + err(1, "native_interrupt_init: sigaction"); + } + if (sigprocmask(SIG_SETMASK, &native_sig_set, NULL) == -1) { + err(1, "native_interrupt_init(): sigprocmask"); + } + + for (int i = 0; iname); - if (setcontext((ucontext_t*)(active_thread->sp)) == -1) { + if (interrupted_contexts[thread_getpid()] == NULL) { + ctx = (ucontext_t*)(active_thread->sp); + } + else { + ctx = interrupted_contexts[thread_getpid()]; + interrupted_contexts[thread_getpid()] = NULL; + } + if (setcontext(ctx) == -1) { err(1, "cpu_switch_context_exit(): setcontext():"); } } void thread_yield() { - ucontext_t *oc; + /** + * XXX: check whether it is advisable to switch context for sched_run() + */ + ucontext_t *oc, *nc; DEBUG("thread_yield()\n"); - oc = (ucontext_t*)(active_thread->sp); + if (interrupted_contexts[thread_getpid()] == NULL) { + oc = (ucontext_t*)(active_thread->sp); + } + else { + oc = interrupted_contexts[thread_getpid()]; + interrupted_contexts[thread_getpid()] = NULL; + } + sched_run(); - DEBUG("thread_yield(): calling swapcontext(%s)\n\n", active_thread->name); - if (swapcontext(oc, (ucontext_t*)(active_thread->sp)) == -1) { - err(1, "thread_yield(): swapcontext()"); + nc = (ucontext_t*)(active_thread->sp); + if (nc != oc) { + DEBUG("thread_yield(): calling swapcontext(%s)\n\n", active_thread->name); + if (swapcontext(oc, nc) == -1) { + err(1, "thread_yield(): swapcontext()"); + } + } + else { + DEBUG("thread_yield(): old = new, returning to context (%s)\n\n", active_thread->name); } } diff --git a/sys/include/transceiver.h b/sys/include/transceiver.h index 9d2732baf0..f6cb927684 100644 --- a/sys/include/transceiver.h +++ b/sys/include/transceiver.h @@ -4,11 +4,13 @@ #include /* Stack size for transceiver thread */ +#ifndef TRANSCEIVER_STACK_SIZE #ifdef ENABLE_DEBUG #define TRANSCEIVER_STACK_SIZE (2048) #else #define TRANSCEIVER_STACK_SIZE (512) #endif +#endif #define PAYLOAD_SIZE (58) From c6553f64922e72eba8ab6f68b218a49af8970edf Mon Sep 17 00:00:00 2001 From: Ludwig Ortmann Date: Tue, 14 May 2013 18:31:47 +0200 Subject: [PATCH 06/12] interrupt handling rewrite (including uart0 integration, rt-extension removal) --- Makefile.base | 12 +- core/include/thread.h | 2 + cpu/native/hwtimer_cpu.c | 6 + cpu/native/include/cpu-conf.h | 3 +- cpu/native/include/cpu.h | 7 +- cpu/native/irq_cpu.c | 226 +++++++++++++++++++--------------- cpu/native/lpm_cpu.c | 43 ++++++- cpu/native/native_cpu.c | 34 ++--- cpu/native/tramp.S | 29 +++++ 9 files changed, 232 insertions(+), 130 deletions(-) create mode 100644 cpu/native/tramp.S diff --git a/Makefile.base b/Makefile.base index 8419c511af..392c07bafb 100644 --- a/Makefile.base +++ b/Makefile.base @@ -1,5 +1,8 @@ ASMSRC = $(wildcard *.s) +ASSMSRC = $(wildcard *.S) ASMOBJ = $(ASMSRC:%.s=$(BINDIR)%.o) +ASMOBJ += $(ASSMSRC:%.S=$(BINDIR)%.o) + SRC = $(wildcard *.c) OBJ = $(SRC:%.c=$(BINDIR)%.o) DEP = $(SRC:%.c=$(BINDIR)%.d) @@ -7,8 +10,8 @@ DEP = $(SRC:%.c=$(BINDIR)%.d) include $(RIOTCPU)/Makefile.base include $(RIOTBOARD)/Makefile.base -$(BINDIR)$(MODULE).a: $(OBJ) $(ASMOBJ) - $(AR) -rc $(BINDIR)$(MODULE).a $(OBJ) $(ASMOBJ) +$(BINDIR)$(MODULE).a: $(OBJ) $(ASMOBJ) $(ASSMOBJ) + $(AR) -rc $(BINDIR)$(MODULE).a $(OBJ) $(ASMOBJ) $(ASSMOBJ) # pull in dependency info for *existing* .o files -include $(OBJ:.o=.d) @@ -22,7 +25,10 @@ $(BINDIR)%.o: %.c $(BINDIR)%.o: %.s @$(AS) $(ASFLAGS) $*.s -o $(BINDIR)$*.o +$(BINDIR)%.o: %.S + @gcc -c -m32 $*.S -o $(BINDIR)$*.o + # remove compilation products clean:: - rm -f $(BINDIR)$(MODULE).a $(OBJ) $(DEP) $(ASMOBJ) + rm -f $(BINDIR)$(MODULE).a $(OBJ) $(DEP) $(ASMOBJ) $(ASSMOBJ) diff --git a/core/include/thread.h b/core/include/thread.h index f4cb0bad5e..5e2e181b17 100644 --- a/core/include/thread.h +++ b/core/include/thread.h @@ -17,7 +17,9 @@ #include /** Minimum stack size */ +#ifndef MINIMUM_STACK_SIZE #define MINIMUM_STACK_SIZE (sizeof(tcb_t)) +#endif /** * @brief Creates a new thread. diff --git a/cpu/native/hwtimer_cpu.c b/cpu/native/hwtimer_cpu.c index 608304d90a..bda90b6b5e 100644 --- a/cpu/native/hwtimer_cpu.c +++ b/cpu/native/hwtimer_cpu.c @@ -34,6 +34,8 @@ #include "debug.h" +#define HWTIMERMINOFFSET 1000 + static unsigned long native_hwtimer_now; static int native_hwtimer_irq[ARCH_MAXTIMERS]; @@ -172,6 +174,10 @@ void hwtimer_arch_unset(short timer) void hwtimer_arch_set(unsigned long offset, short timer) { DEBUG("hwtimer_arch_set(%li, %i)\n", offset, timer); + if (offset < HWTIMERMINOFFSET) { + offset = HWTIMERMINOFFSET; + DEBUG("hwtimer_arch_set: offset < MIN, set to: %i\n", offset); + } native_hwtimer_irq[timer] = 1; native_hwtimer_isset[timer] = 1; diff --git a/cpu/native/include/cpu-conf.h b/cpu/native/include/cpu-conf.h index f83318f582..6156b05d94 100644 --- a/cpu/native/include/cpu-conf.h +++ b/cpu/native/include/cpu-conf.h @@ -18,9 +18,10 @@ /* TODO: choose more sensibly? */ #define KERNEL_CONF_STACKSIZE_DEFAULT (16384) -#define KERNEL_CONF_STACKSIZE_IDLE (4096) +#define KERNEL_CONF_STACKSIZE_IDLE (16384) #define NATIVE_ISR_STACKSIZE (16384) #define TRANSCEIVER_STACK_SIZE (16384) +#define MINIMUM_STACK_SIZE (1024) /* for cc110x_ng */ #define RX_BUF_SIZE (10) diff --git a/cpu/native/include/cpu.h b/cpu/native/include/cpu.h index 0d64a967d3..ad29479cf8 100644 --- a/cpu/native/include/cpu.h +++ b/cpu/native/include/cpu.h @@ -46,6 +46,11 @@ int unregister_interrupt(int sig); /* this should be defined elsewhere */ void thread_yield(void); -extern volatile ucontext_t *interrupted_contexts[MAXTHREADS]; +extern void _native_sig_leave_tramp(void); +extern ucontext_t *_native_cur_ctx, *_native_isr_ctx; +extern unsigned int _native_saved_eip; +extern int _native_in_isr; +extern int _native_in_syscall; +extern int _native_sigpend; /** @} */ #endif //_CPU_H diff --git a/cpu/native/irq_cpu.c b/cpu/native/irq_cpu.c index 0defac2949..70bc44054e 100644 --- a/cpu/native/irq_cpu.c +++ b/cpu/native/irq_cpu.c @@ -1,9 +1,6 @@ /** * Native CPU irq.h implementation * - * uses POSIX real-time extension signals to create interrupts - * TODO: needs to be rewritten for better portability - * * Copyright (C) 2013 Ludwig Ortmann * * This file subject to the terms and conditions of the GNU General Public @@ -15,29 +12,41 @@ * @file * @author Ludwig Ortmann */ -#include #include +#include +#include -#include +// __USE_GNU for gregs[REG_EIP] access +#define __USE_GNU +#include +#undef __USE_GNU + +#include "irq.h" #include "cpu.h" #include "debug.h" static int native_interrupts_enabled; -static int native_in_irs; -static int last_sig; -static ucontext_t native_context; +int _native_sigpend; +int _native_in_isr; +int _native_in_syscall; +static ucontext_t native_isr_context; static sigset_t native_sig_set; static char __isr_stack[SIGSTKSZ]; extern volatile tcb_t *active_thread; +unsigned int _native_saved_eip; +ucontext_t *_native_cur_ctx, *_native_isr_ctx; +int _native_in_isr; + +static int pipefd[2]; + struct int_handler_t { void (*func)(void); }; static struct int_handler_t native_irq_handlers[255]; - -volatile ucontext_t *interrupted_contexts[MAXTHREADS]; +char sigalt_stk[SIGSTKSZ]; void print_thread_sigmask(ucontext_t *cp) { @@ -113,6 +122,7 @@ unsigned disableIRQ(void) unsigned int prev_state; sigset_t mask; + _native_in_syscall = 1; DEBUG("disableIRQ()\n"); if (sigfillset(&mask) == -1) { @@ -132,6 +142,16 @@ unsigned disableIRQ(void) } prev_state = native_interrupts_enabled; native_interrupts_enabled = 0; + if (_native_sigpend > 0) { + DEBUG("\n\n\t\treturn from syscall, calling native_irq_handler\n\n"); + _native_in_syscall = 0; + printf("calling swapcontext()\n"); + swapcontext(_native_cur_ctx, _native_isr_ctx); + } + else { + _native_in_syscall = 0; + } + DEBUG("disableIRQ(): return\n"); return prev_state; } @@ -143,6 +163,7 @@ unsigned enableIRQ(void) { unsigned int prev_state; + _native_in_syscall = 1; DEBUG("enableIRQ()\n"); if (sigprocmask(SIG_SETMASK, &native_sig_set, NULL) == -1) { @@ -153,6 +174,16 @@ unsigned enableIRQ(void) //print_sigmasks(); //native_print_signals(); + if (_native_sigpend > 0) { + DEBUG("\n\n\t\treturn from syscall, calling native_irq_handler\n\n"); + _native_in_syscall = 0; + printf("calling swapcontext()\n"); + swapcontext(_native_cur_ctx, _native_isr_ctx); + } + else { + _native_in_syscall = 0; + } + DEBUG("enableIRQ(): return\n"); return prev_state; } @@ -172,8 +203,8 @@ void restoreIRQ(unsigned state) int inISR(void) { - DEBUG("inISR()\n"); - return native_in_irs; + DEBUG("inISR(): %i\n", _native_in_isr); + return _native_in_isr; } @@ -187,104 +218,86 @@ void eINT(void) enableIRQ(); } +int _native_popsig(void) +{ + int nread, nleft, i; + int sig; + + nleft = sizeof(int); + i = 0; + while ((nleft>0) && ((nread = read(pipefd[0], &sig + i, nleft)) != -1)) { + i += nread; + nleft -= nread; + } + if (nread == -1) { + err(1, "_native_popsig(): read()"); + } + + return sig; +} + /** - * call signal handler, + * call signal handlers, * restore user context */ void native_irq_handler() { - if (last_sig == -1) { - errx(1, "XXX: internal error"); + int sig; + + DEBUG("\n\n\t\tnative_irq_handler\n\n"); + while (_native_sigpend > 0) { + + sig = _native_popsig(); + _native_sigpend--; + + if (native_irq_handlers[sig].func != NULL) { + DEBUG("calling interrupt handler for %i\n", sig); + native_irq_handlers[sig].func(); + } + else if (sig == SIGUSR1) { + DEBUG("ignoring SIGUSR1\n"); + } + else { + printf("XXX: no handler for signal %i\n", sig); + errx(1, "XXX: this should not have happened!\n"); + } } - if (native_irq_handlers[last_sig].func != NULL) { - DEBUG("calling interrupt handler for %i\n", last_sig); - native_irq_handlers[last_sig].func(); - } - else if (last_sig == SIGUSR1) { - DEBUG("ignoring SIGUSR1\n"); - } - else { - printf("XXX: no handler for signal %i\n", last_sig); - errx(1, "XXX: this should not have happened!\n"); - } - last_sig = -1; - native_in_irs = 0; + DEBUG("native_irq_handler(): return"); + _native_in_isr = 0; cpu_switch_context_exit(); } /** - * load isr context, save signal + * save signal, return to _native_sig_leave_tramp if possible */ void native_isr_entry(int sig, siginfo_t *info, void *context) { - /* - * This is how it goes: - * We create a new context "R" for the RIOT interrupt service - * routine. - * We save the current (signalhandler) context "S" to the active - * threads context. - * We then jump into the R context. - * Later, when jumping back into "S", we start out in the signal - * handler context only to immediately return into the context we - * originally left. This step is done by the kernel for us. - * - * So the thing to wrap your head around is that the active thread - * remains within in the signal handler context (which is pushed - * onto the active threads own stack by swapcontext) until the - * thread is activated again, at which point the kernel handles - * the context switch back onto the interrupted context for us. - * */ + DEBUG("\n\n\t\tnative_isr_entry\n\n"); + if (native_interrupts_enabled == 0) { + errx(1, "interrupts are off, but I caught a signal."); + } /* save the signal */ - last_sig = sig; + if (write(pipefd[1], &sig, sizeof(int)) == -1) { + err(1, "native_isr_entry(): write()"); + } + _native_sigpend++; /* indicate irs status */ - native_in_irs = 1; - if (getcontext(&native_context) == -1) { - err(1, "native_isr_entry(): getcontext()"); - } + makecontext(&native_isr_context, native_irq_handler, 0); + _native_cur_ctx = (ucontext_t*)active_thread->sp; - native_context.uc_stack.ss_sp = __isr_stack; - native_context.uc_stack.ss_size = SIGSTKSZ; - native_context.uc_stack.ss_flags = 0; - - /* XXX: disable interrupts - * -> sigfillset(&(native_context.uc_sigmask)); - * else: */ - //sigemptyset(&(native_context.uc_sigmask)); - if (sigfillset(&(native_context.uc_sigmask)) == -1) { - err(1, "native_isr_entry(): sigfillset()"); - } - - makecontext(&native_context, native_irq_handler, 0); - -#ifdef NATIVEUSESWAPCONTEXT - /** - * XXX: - * This seems to be the cause of undefined behavior. Try saving - * the context passed to this function and using setcontext to - * leave the handler. - * Also it is probably wise to makecontext the isr context - * elsewehere. - * */ - if ((swapcontext((ucontext_t*)active_thread->sp, &native_context)) == -1) { - err(1, "swapcontext failed"); + if (_native_in_syscall == 0) { + _native_in_isr = 1; + DEBUG("\n\n\t\treturn to _native_sig_leave_tramp\n\n"); + _native_saved_eip = ((ucontext_t*)context)->uc_mcontext.gregs[REG_EIP]; + ((ucontext_t*)context)->uc_mcontext.gregs[REG_EIP] = (unsigned int)&_native_sig_leave_tramp; + // TODO: change sigmask? } else { - DEBUG("returning to interrupted thread\n"); + DEBUG("\n\n\t\treturn to syscall\n\n"); } - native_in_irs = 0; - enableIRQ(); -#else - interrupted_contexts[thread_getpid()] = context; - /** - * signal masks are broken - */ - //active_thread->sp = context; - setcontext(&native_context); - DEBUG("\n\n\tnever reached\n\n\n"); -#endif } /** @@ -312,7 +325,7 @@ int register_interrupt(int sig, void *handler) err(1, "register_interrupt: sigemptyset"); } - sa.sa_flags = SA_RESTART | SA_SIGINFO; + sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; if (sigaction(sig, &sa, NULL)) { err(1, "register_interrupt: sigaction"); @@ -342,7 +355,7 @@ int unregister_interrupt(int sig) if (sigemptyset(&sa.sa_mask) == -1) { err(1, "unregister_interrupt: sigemptyset"); } - sa.sa_flags = SA_RESTART | SA_SIGINFO; + sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; if (sigaction(sig, &sa, NULL)) { err(1, "unregister_interrupt: sigaction"); @@ -363,6 +376,7 @@ void native_interrupt_init(void) DEBUG("XXX: native_interrupt_init()\n"); native_interrupts_enabled = 1; + _native_sigpend = 0; for (int i = 0; i<255; i++) { native_irq_handlers[i].func = NULL; @@ -372,7 +386,7 @@ void native_interrupt_init(void) if (sigemptyset(&sa.sa_mask) == -1) { err(1, "native_interrupt_init: sigemptyset"); } - sa.sa_flags = SA_RESTART | SA_SIGINFO; + sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; /* if (sigemptyset(&native_sig_set) == -1) { @@ -391,19 +405,31 @@ void native_interrupt_init(void) err(1, "native_interrupt_init: sigaction"); } - if (sigdelset(&native_sig_set, SIGALRM) == -1) { - err(1, "native_interrupt_init: sigdelset"); + if (getcontext(&native_isr_context) == -1) { + err(1, "native_isr_entry(): getcontext()"); } - if (sigaction(SIGALRM, &sa, NULL)) { - err(1, "native_interrupt_init: sigaction"); - } - if (sigprocmask(SIG_SETMASK, &native_sig_set, NULL) == -1) { - err(1, "native_interrupt_init(): sigprocmask"); + if (sigfillset(&(native_isr_context.uc_sigmask)) == -1) { + err(1, "native_isr_entry(): sigfillset()"); } + native_isr_context.uc_stack.ss_sp = __isr_stack; + native_isr_context.uc_stack.ss_size = SIGSTKSZ; + native_isr_context.uc_stack.ss_flags = 0; + _native_isr_ctx = &native_isr_context; - for (int i = 0; i #include #include +#ifdef MODULE_UART0 +#include +#include +#endif #include "lpm.h" #include "debug.h" +#include "cpu.h" +#ifdef MODULE_UART0 +#include "board.h" +#endif static enum lpm_mode native_lpm; @@ -31,6 +39,32 @@ void lpm_init(void) return; } +void _native_lpm_sleep() +{ +#ifdef MODULE_UART0 + int retval; + retval = select(1, &_native_uart_rfds, NULL, NULL, NULL); + DEBUG("_native_lpm_sleep: retval: %i\n", retval); + if (retval != -1) { + DEBUG("\n\n\t\treturn from syscall, calling _native_handle_uart0_input\n\n"); + makecontext(_native_isr_ctx, _native_handle_uart0_input, 0); + swapcontext(_native_cur_ctx, _native_isr_ctx); + } + else if (errno != EINTR) { + err(1, "lpm_set(): select()"); + } +#else + pause(); +#endif + + if (_native_sigpend > 0) { + DEBUG("\n\n\t\treturn from syscall, calling native_irq_handler\n\n"); + _native_in_syscall = 0; + _native_in_isr = 1; + swapcontext(_native_cur_ctx, _native_isr_ctx); + } +} + /** * LPM_IDLE uses sleep() to wait for interrupts * LPM_OFF exits process @@ -40,7 +74,7 @@ enum lpm_mode lpm_set(enum lpm_mode target) { enum lpm_mode last_lpm; - DEBUG("lpm_set(%i)\n", target); + //DEBUG("lpm_set(%i)\n", target); last_lpm = native_lpm; native_lpm = target; @@ -51,8 +85,11 @@ enum lpm_mode lpm_set(enum lpm_mode target) break; case LPM_IDLE: - DEBUG("lpm_set(): pause()\n"); - pause(); + //DEBUG("lpm_set(): pause()\n"); + + _native_in_syscall = 1; + //pause(); + _native_lpm_sleep(); break; /* XXX: unfinished modes: */ diff --git a/cpu/native/native_cpu.c b/cpu/native/native_cpu.c index 962fd4f9b7..89337e7495 100644 --- a/cpu/native/native_cpu.c +++ b/cpu/native/native_cpu.c @@ -26,7 +26,7 @@ #include "debug.h" extern volatile tcb_t *active_thread; -static ucontext_t native_context; +static ucontext_t end_context; static char __isr_stack[SIGSTKSZ]; /** @@ -63,7 +63,7 @@ char *thread_stack_init(void *task_func, void *stack_start, int stacksize) p->uc_stack.ss_sp = stk; p->uc_stack.ss_size = stacksize; p->uc_stack.ss_flags = 0; - p->uc_link = &native_context; + p->uc_link = &end_context; if (sigemptyset(&(p->uc_sigmask)) == -1) { err(1, "thread_stack_init(): sigemptyset()"); } @@ -82,13 +82,8 @@ void cpu_switch_context_exit(void) sched_run(); DEBUG("XXX: cpu_switch_context_exit(): calling setcontext(%s)\n\n", active_thread->name); - if (interrupted_contexts[thread_getpid()] == NULL) { - ctx = (ucontext_t*)(active_thread->sp); - } - else { - ctx = interrupted_contexts[thread_getpid()]; - interrupted_contexts[thread_getpid()] = NULL; - } + ctx = (ucontext_t*)(active_thread->sp); + eINT(); // XXX: workaround for bug (?) in sched_task_exit if (setcontext(ctx) == -1) { err(1, "cpu_switch_context_exit(): setcontext():"); } @@ -103,13 +98,7 @@ void thread_yield() DEBUG("thread_yield()\n"); - if (interrupted_contexts[thread_getpid()] == NULL) { - oc = (ucontext_t*)(active_thread->sp); - } - else { - oc = interrupted_contexts[thread_getpid()]; - interrupted_contexts[thread_getpid()] = NULL; - } + oc = (ucontext_t*)(active_thread->sp); sched_run(); @@ -127,13 +116,14 @@ void thread_yield() void native_cpu_init() { - if (getcontext(&native_context) == -1) { - err(1, "native_context(): getcontext()"); + if (getcontext(&end_context) == -1) { + err(1, "end_context(): getcontext()"); } - native_context.uc_stack.ss_sp = __isr_stack; - native_context.uc_stack.ss_size = SIGSTKSZ; - native_context.uc_stack.ss_flags = 0; - makecontext(&native_context, sched_task_exit, 0); + end_context.uc_stack.ss_sp = __isr_stack; + end_context.uc_stack.ss_size = SIGSTKSZ; + end_context.uc_stack.ss_flags = 0; + makecontext(&end_context, sched_task_exit, 0); + puts("RIOT native cpu initialized."); } /** @} */ diff --git a/cpu/native/tramp.S b/cpu/native/tramp.S new file mode 100644 index 0000000000..427f485ff1 --- /dev/null +++ b/cpu/native/tramp.S @@ -0,0 +1,29 @@ +.text + +.extern $_native_saved_eip +.extern $_native_isr_ctx +.extern $_native_cur_ctx +.extern $_native_in_isr + +.globl _native_sig_leave_tramp + +_native_sig_leave_tramp: + pushl %eax + pushf + pushl %ebp + pushl %esp + + movl %esp, %ebp + subl $24, %esp + movl $_native_isr_ctx, 4(%esp) + movl $_native_cur_ctx, (%esp) + call swapcontext + + addl $24, %esp + popl %esp + popl %ebp + popf + popl %eax + movl $0x0, _native_in_isr; + + jmp *_native_saved_eip From 7bf9fa0314b5d52d6d8eec3d04409fc122fa4dfb Mon Sep 17 00:00:00 2001 From: Ludwig Ortmann Date: Wed, 15 May 2013 10:46:09 +0200 Subject: [PATCH 07/12] increase MINIMUM_STACK_SIZE to allow for DEBUG --- cpu/native/include/cpu-conf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/native/include/cpu-conf.h b/cpu/native/include/cpu-conf.h index 6156b05d94..98be2377d9 100644 --- a/cpu/native/include/cpu-conf.h +++ b/cpu/native/include/cpu-conf.h @@ -21,7 +21,7 @@ #define KERNEL_CONF_STACKSIZE_IDLE (16384) #define NATIVE_ISR_STACKSIZE (16384) #define TRANSCEIVER_STACK_SIZE (16384) -#define MINIMUM_STACK_SIZE (1024) +#define MINIMUM_STACK_SIZE (16384) /* for cc110x_ng */ #define RX_BUF_SIZE (10) From 5cb68df9e2ab01cee0276912f3643c1e6a404c7c Mon Sep 17 00:00:00 2001 From: Ludwig Ortmann Date: Wed, 15 May 2013 10:47:46 +0200 Subject: [PATCH 08/12] add missing newline in debug output --- sys/chardev_thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/chardev_thread.c b/sys/chardev_thread.c index 84fb97a3b4..e51c2c0347 100644 --- a/sys/chardev_thread.c +++ b/sys/chardev_thread.c @@ -30,7 +30,7 @@ void chardev_loop(ringbuffer_t *rb) { msg_receive(&m); if (m.sender_pid != pid) { - DEBUG("Receiving message from another thread"); + DEBUG("Receiving message from another thread\n"); switch (m.type) { case OPEN: if (reader_pid == -1) { From 2c744bc1e8e858209ef8787c9a76fdcefa8739bb Mon Sep 17 00:00:00 2001 From: Ludwig Ortmann Date: Wed, 15 May 2013 11:18:18 +0200 Subject: [PATCH 09/12] generalize .S compilation target flags --- Makefile.base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.base b/Makefile.base index 392c07bafb..3f5ceb542c 100644 --- a/Makefile.base +++ b/Makefile.base @@ -26,7 +26,7 @@ $(BINDIR)%.o: %.s @$(AS) $(ASFLAGS) $*.s -o $(BINDIR)$*.o $(BINDIR)%.o: %.S - @gcc -c -m32 $*.S -o $(BINDIR)$*.o + @gcc -c $(CFLAGS) $*.S -o $(BINDIR)$*.o # remove compilation products clean:: From 35f9062e37a7d6493b9b82da4da9440ec42a621a Mon Sep 17 00:00:00 2001 From: Ludwig Ortmann Date: Wed, 15 May 2013 17:45:43 +0200 Subject: [PATCH 10/12] inital OSX support for native port --- Makefile.include | 12 ++++++++++++ cpu/native/hwtimer_cpu.c | 16 ++++++++++++++++ cpu/native/include/cpu-conf.h | 8 ++++++++ cpu/native/include/cpu.h | 6 ++++++ cpu/native/irq_cpu.c | 11 +++++++++-- cpu/native/native_cpu.c | 6 ++++++ cpu/native/tramp.S | 23 +++++++++++++++++++++++ sys/lib/ringbuffer.c | 7 ++++++- 8 files changed, 86 insertions(+), 3 deletions(-) diff --git a/Makefile.include b/Makefile.include index 56cddaa8dc..c195d5bc21 100644 --- a/Makefile.include +++ b/Makefile.include @@ -21,14 +21,26 @@ BASELIBS += $(PROJBINDIR)/${PROJECT}.a PROJBINDIR =$(CURDIR)/bin +# clumsy way to enable building native on osx: +BUILDOSXNATIVE = 0 +ifeq ($(CPU),native) +ifeq ($(shell uname -s),Darwin) + BUILDOSXNATIVE = 1 +endif +endif + ## make script for your project. Build RIOT-base here! all: $(PROJBINDIR)/$(PROJECT).a @echo "Building project $(PROJECT) for $(BOARD) w/ MCU $(MCU)." $(MAKE) -C $(RIOTBOARD) $(MAKE) -C $(RIOTBASE) +ifeq ($(BUILDOSXNATIVE),1) + @$(LINK) $(UNDEF) -o $(PROJBINDIR)/$(PROJECT).elf $(BASELIBS) $(LINKFLAGS) -Wl,-no_pie +else @$(LINK) $(UNDEF) -o $(PROJBINDIR)/$(PROJECT).elf -Wl,--start-group $(BASELIBS) -lm -Wl,--end-group -Wl,-Map=$(PROJBINDIR)/$(PROJECT).map $(LINKFLAGS) @$(SIZE) $(PROJBINDIR)/$(PROJECT).elf @$(OBJCOPY) -O ihex $(PROJBINDIR)/$(PROJECT).elf $(PROJBINDIR)/$(PROJECT).hex +endif ## your make rules ## Only basic example - modify it for larger projects!! diff --git a/cpu/native/hwtimer_cpu.c b/cpu/native/hwtimer_cpu.c index bda90b6b5e..db7b09ca34 100644 --- a/cpu/native/hwtimer_cpu.c +++ b/cpu/native/hwtimer_cpu.c @@ -20,6 +20,11 @@ * @} */ +#ifdef __MACH__ +#include +#include +#endif + #include #include #include @@ -204,9 +209,20 @@ unsigned long hwtimer_arch_now(void) DEBUG("hwtimer_arch_now()\n"); +#ifdef __MACH__ + clock_serv_t cclock; + mach_timespec_t mts; + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + t.tv_sec = mts.tv_sec; + t.tv_nsec = mts.tv_nsec; +#else if (clock_gettime(CLOCK_MONOTONIC, &t) == -1) { err(1, "hwtimer_arch_now: clock_gettime"); } +#endif + native_hwtimer_now = ts2ticks(&t); DEBUG("hwtimer_arch_now(): it is now %lis %lins\n", t.tv_sec, t.tv_nsec); diff --git a/cpu/native/include/cpu-conf.h b/cpu/native/include/cpu-conf.h index 98be2377d9..2471a2b657 100644 --- a/cpu/native/include/cpu-conf.h +++ b/cpu/native/include/cpu-conf.h @@ -17,11 +17,19 @@ #include /* TODO: choose more sensibly? */ +#ifdef __MACH__ +#define KERNEL_CONF_STACKSIZE_DEFAULT (163840) +#define KERNEL_CONF_STACKSIZE_IDLE (163840) +#define NATIVE_ISR_STACKSIZE (163840) +#define TRANSCEIVER_STACK_SIZE (163840) +#define MINIMUM_STACK_SIZE (163840) +#else #define KERNEL_CONF_STACKSIZE_DEFAULT (16384) #define KERNEL_CONF_STACKSIZE_IDLE (16384) #define NATIVE_ISR_STACKSIZE (16384) #define TRANSCEIVER_STACK_SIZE (16384) #define MINIMUM_STACK_SIZE (16384) +#endif /* for cc110x_ng */ #define RX_BUF_SIZE (10) diff --git a/cpu/native/include/cpu.h b/cpu/native/include/cpu.h index ad29479cf8..2a51e9deef 100644 --- a/cpu/native/include/cpu.h +++ b/cpu/native/include/cpu.h @@ -19,7 +19,13 @@ #ifndef _CPU_H #define _CPU_H +#ifdef __MACH__ +#define _XOPEN_SOURCE +#endif #include +#ifdef __MACH__ +#undef _XOPEN_SOURCE +#endif #include "kernel_intern.h" #include "sched.h" diff --git a/cpu/native/irq_cpu.c b/cpu/native/irq_cpu.c index 70bc44054e..2da242cb97 100644 --- a/cpu/native/irq_cpu.c +++ b/cpu/native/irq_cpu.c @@ -48,6 +48,8 @@ struct int_handler_t { static struct int_handler_t native_irq_handlers[255]; char sigalt_stk[SIGSTKSZ]; +#define SIGMAX (255) // XXX: do this properly if possible + void print_thread_sigmask(ucontext_t *cp) { sigset_t *p = &cp->uc_sigmask; @@ -55,7 +57,7 @@ void print_thread_sigmask(ucontext_t *cp) err(1, "print_thread_sigmask: sigemptyset"); } - for (int i = 1; i<(SIGRTMAX); i++) { + for (int i = 1; i<(SIGMAX); i++) { if (native_irq_handlers[i].func != NULL) { printf("%s: %s\n", strsignal(i), @@ -98,7 +100,7 @@ void native_print_signals() err(1, "native_print_signals(): sigprocmask"); } - for (int i = 1; i<(SIGRTMAX); i++) { + for (int i = 1; i<(SIGMAX); i++) { if (native_irq_handlers[i].func != NULL || i == SIGUSR1) { printf("%s: %s\n", strsignal(i), @@ -291,8 +293,13 @@ void native_isr_entry(int sig, siginfo_t *info, void *context) if (_native_in_syscall == 0) { _native_in_isr = 1; DEBUG("\n\n\t\treturn to _native_sig_leave_tramp\n\n"); +#ifdef __MACH__ + _native_saved_eip = ((ucontext_t*)context)->uc_mcontext->__ss.__eip; + ((ucontext_t*)context)->uc_mcontext->__ss.__eip = (unsigned int)&_native_sig_leave_tramp; +#else _native_saved_eip = ((ucontext_t*)context)->uc_mcontext.gregs[REG_EIP]; ((ucontext_t*)context)->uc_mcontext.gregs[REG_EIP] = (unsigned int)&_native_sig_leave_tramp; +#endif // TODO: change sigmask? } else { diff --git a/cpu/native/native_cpu.c b/cpu/native/native_cpu.c index 89337e7495..369a988fcb 100644 --- a/cpu/native/native_cpu.c +++ b/cpu/native/native_cpu.c @@ -15,7 +15,13 @@ * @author Ludwig Ortmann */ #include +#ifdef __MACH__ +#define _XOPEN_SOURCE +#endif #include +#ifdef __MACH__ +#undef _XOPEN_SOURCE +#endif #include #include "kernel_intern.h" diff --git a/cpu/native/tramp.S b/cpu/native/tramp.S index 427f485ff1..4ba4b5d536 100644 --- a/cpu/native/tramp.S +++ b/cpu/native/tramp.S @@ -1,5 +1,27 @@ .text +#ifdef __MACH__ +.globl __native_sig_leave_tramp +__native_sig_leave_tramp: + pushl %eax + pushf + pushl %ebp + pushl %esp + + movl %esp, %ebp + subl $24, %esp + movl $__native_isr_ctx, 4(%esp) + movl $__native_cur_ctx, (%esp) + call _swapcontext + + addl $24, %esp + popl %esp + popl %ebp + popf + popl %eax + + jmp *__native_saved_eip +#else .extern $_native_saved_eip .extern $_native_isr_ctx .extern $_native_cur_ctx @@ -27,3 +49,4 @@ _native_sig_leave_tramp: movl $0x0, _native_in_isr; jmp *_native_saved_eip +#endif diff --git a/sys/lib/ringbuffer.c b/sys/lib/ringbuffer.c index 4e021942d5..3d6083f803 100755 --- a/sys/lib/ringbuffer.c +++ b/sys/lib/ringbuffer.c @@ -1,8 +1,13 @@ #include #include -#include #include +#ifdef __MACH__ +#include +#else +#include "malloc.h" +#endif + #include "ringbuffer.h" //#define DEBUG(...) printf (__VA_ARGS__) From 42f897fc4a6d92244e05e488a431f6e5089e64cc Mon Sep 17 00:00:00 2001 From: Ludwig Ortmann Date: Tue, 21 May 2013 10:53:59 +0200 Subject: [PATCH 11/12] use NSIG macro from signal.h for number of signals --- cpu/native/irq_cpu.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cpu/native/irq_cpu.c b/cpu/native/irq_cpu.c index 2da242cb97..d0560e728f 100644 --- a/cpu/native/irq_cpu.c +++ b/cpu/native/irq_cpu.c @@ -48,8 +48,6 @@ struct int_handler_t { static struct int_handler_t native_irq_handlers[255]; char sigalt_stk[SIGSTKSZ]; -#define SIGMAX (255) // XXX: do this properly if possible - void print_thread_sigmask(ucontext_t *cp) { sigset_t *p = &cp->uc_sigmask; @@ -57,7 +55,7 @@ void print_thread_sigmask(ucontext_t *cp) err(1, "print_thread_sigmask: sigemptyset"); } - for (int i = 1; i<(SIGMAX); i++) { + for (int i = 1; i<(NSIG); i++) { if (native_irq_handlers[i].func != NULL) { printf("%s: %s\n", strsignal(i), @@ -100,9 +98,9 @@ void native_print_signals() err(1, "native_print_signals(): sigprocmask"); } - for (int i = 1; i<(SIGMAX); i++) { + for (int i = 1; i<(NSIG); i++) { if (native_irq_handlers[i].func != NULL || i == SIGUSR1) { - printf("%s: %s\n", + printf("%s: %s in active thread\n", strsignal(i), (sigismember(&native_sig_set, i) ? "blocked": "unblocked") ); @@ -111,7 +109,7 @@ void native_print_signals() printf("%s: pending\n", strsignal(i)); } if (sigismember(&q, i)) { - printf("%s: currently blocked\n", strsignal(i)); + printf("%s: blocked in this context\n", strsignal(i)); } } } From a900065fb0ac6d8013fbdfa79489e7d2312bf642 Mon Sep 17 00:00:00 2001 From: Ludwig Ortmann Date: Thu, 30 May 2013 17:52:54 +0200 Subject: [PATCH 12/12] remove cruft in Makefile.base --- Makefile.base | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.base b/Makefile.base index 3f5ceb542c..cbd79d771a 100644 --- a/Makefile.base +++ b/Makefile.base @@ -10,8 +10,8 @@ DEP = $(SRC:%.c=$(BINDIR)%.d) include $(RIOTCPU)/Makefile.base include $(RIOTBOARD)/Makefile.base -$(BINDIR)$(MODULE).a: $(OBJ) $(ASMOBJ) $(ASSMOBJ) - $(AR) -rc $(BINDIR)$(MODULE).a $(OBJ) $(ASMOBJ) $(ASSMOBJ) +$(BINDIR)$(MODULE).a: $(OBJ) $(ASMOBJ) + $(AR) -rc $(BINDIR)$(MODULE).a $(OBJ) $(ASMOBJ) # pull in dependency info for *existing* .o files -include $(OBJ:.o=.d) @@ -30,5 +30,5 @@ $(BINDIR)%.o: %.S # remove compilation products clean:: - rm -f $(BINDIR)$(MODULE).a $(OBJ) $(DEP) $(ASMOBJ) $(ASSMOBJ) + rm -f $(BINDIR)$(MODULE).a $(OBJ) $(DEP) $(ASMOBJ)