diff --git a/.gitignore b/.gitignore index 270f8cf773..2b922cb6f0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ doc/doxygen/html doc/doxygen/latex doc/doxygen/man *bin +*~ diff --git a/Makefile b/Makefile index 1100e9a6ae..27df73ed17 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ all: clean: @for i in $(DIRS) ; do "$(MAKE)" -C $$i clean ; done ; -@if [ -d $(BINDIR) ] ; \ - then rmdir $(BINDIR) ; \ + then rm -rf $(BINDIR) ; \ fi doc: diff --git a/Makefile.base b/Makefile.base index 8419c511af..cbd79d771a 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) @@ -22,6 +25,9 @@ $(BINDIR)%.o: %.c $(BINDIR)%.o: %.s @$(AS) $(ASFLAGS) $*.s -o $(BINDIR)$*.o +$(BINDIR)%.o: %.S + @gcc -c $(CFLAGS) $*.S -o $(BINDIR)$*.o + # remove compilation products clean:: rm -f $(BINDIR)$(MODULE).a $(OBJ) $(DEP) $(ASMOBJ) diff --git a/Makefile.include b/Makefile.include index 56cddaa8dc..6f6b4171de 100644 --- a/Makefile.include +++ b/Makefile.include @@ -21,14 +21,35 @@ 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 + +# backward compatability with glibc <= 2.17 for native +ifeq ($(CPU),native) +ifeq ($(shell uname -s),Linux) +ifeq ($(shell ldd --version | awk '/^ldd/{if ($$NF < 2.17) {print "yes"} else {print "no"} }'),yes) + LINKFLAGS += -lrt +endif +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/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/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/hwtimer_cpu.c b/cpu/native/hwtimer_cpu.c index 7082094d38..db7b09ca34 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 * @@ -17,7 +20,13 @@ * @} */ +#ifdef __MACH__ +#include +#include +#endif + #include +#include #include #include #include @@ -30,18 +39,33 @@ #include "debug.h" +#define HWTIMERMINOFFSET 1000 + 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,19 +78,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 /* TODO: choose more sensibly? */ -#ifndef KERNEL_CONF_STACKSIZE_DEFAULT -#define KERNEL_CONF_STACKSIZE_DEFAULT 8192 +#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 -#define KERNEL_CONF_STACKSIZE_IDLE 2048 -#define NATIVE_ISR_STACKSIZE 8192 - -#define _SIG_UNDEF SIGRTMIN + 0 -#define _SIG_TIMER SIGRTMIN + 10 // check hwtimer_cpu.h for compliance -#define _SIG_LTC4150 SIGRTMIN + 20 - -/* TODO: check for overflow (SIGRTMAX) */ +/* for cc110x_ng */ +#define RX_BUF_SIZE (10) +#define TRANSCEIVER_BUFFER_SIZE (3) #endif /* CPUCONF_H_ */ diff --git a/cpu/native/include/cpu.h b/cpu/native/include/cpu.h index d2c0fbd144..2f5ba22af9 100644 --- a/cpu/native/include/cpu.h +++ b/cpu/native/include/cpu.h @@ -19,7 +19,23 @@ #ifndef _CPU_H #define _CPU_H +#include + +/* enable signal handler register access on different platforms + * check here for more: + * http://sourceforge.net/p/predef/wiki/OperatingSystems/ + */ +#ifdef BSD // BSD = (FreeBSD, Darwin, ...) +#define _XOPEN_SOURCE +#elif defined(__linux__) +#define __USE_GNU +#endif #include +#ifdef BSD +#undef _XOPEN_SOURCE +#elif defined(__linux__) +#undef __USE_GNU +#endif #include "kernel_intern.h" #include "sched.h" @@ -46,5 +62,11 @@ int unregister_interrupt(int sig); /* this should be defined elsewhere */ void thread_yield(void); +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 07d9adfb21..1b9b2f5cd8 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,27 +12,107 @@ * @file * @author Ludwig Ortmann */ -#include #include +#include +#include -#include +// __USE_GNU for gregs[REG_EIP] access under Linux +#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]; +char sigalt_stk[SIGSTKSZ]; + +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<(NSIG); 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<(NSIG); i++) { + if (native_irq_handlers[i].func != NULL || i == SIGUSR1) { + printf("%s: %s in active thread\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: blocked in this context\n", strsignal(i)); + } + } +} /** * block signals @@ -45,23 +122,36 @@ unsigned disableIRQ(void) unsigned int prev_state; sigset_t mask; + _native_in_syscall = 1; DEBUG("disableIRQ()\n"); if (sigfillset(&mask) == -1) { 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()"); } } 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; } @@ -73,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) { @@ -81,6 +172,19 @@ unsigned enableIRQ(void) prev_state = native_interrupts_enabled; native_interrupts_enabled = 1; + //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; } @@ -99,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; } @@ -114,79 +218,94 @@ 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 (native_irq_handlers[last_sig].func != NULL) { - DEBUG("calling interrupt handler for %i\n", last_sig); - native_irq_handlers[last_sig].func(); + 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"); + } } - else { - printf("XXX: no handler for signal %i\n", last_sig); - errx(1, "XXX: this should not have happened!\n"); - } - 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); - - 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"); +#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; +#elif BSD + _native_saved_eip = ((struct sigcontext*)context)->sc_eip; + ((struct sigcontext*)context)->sc_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 { - DEBUG("returning to interrupted thread\n"); + DEBUG("\n\n\t\treturn to syscall\n\n"); } - native_in_irs = 0; - enableIRQ(); } /** @@ -201,19 +320,20 @@ 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"); } - 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"); @@ -233,16 +353,17 @@ 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"); } - 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"); @@ -262,6 +383,9 @@ void native_interrupt_init(void) struct sigaction sa; 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; } @@ -270,19 +394,52 @@ 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) { 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 (getcontext(&native_isr_context) == -1) { + err(1, "native_isr_entry(): getcontext()"); + } + + 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; + + static stack_t sigstk; + sigstk.ss_sp = sigalt_stk; + sigstk.ss_size = SIGSTKSZ; + sigstk.ss_flags = 0; + if (sigaltstack(&sigstk, NULL) < 0) { + err(1, "main: sigaltstack"); + } + makecontext(&native_isr_context, native_irq_handler, 0); + + _native_in_syscall = 0; + + if (pipe(pipefd) == -1) { + err(1, "native_interrupt_init(): pipe()"); + } + puts("RIOT native interrupts/signals initialized."); } /** @} */ diff --git a/cpu/native/lpm_cpu.c b/cpu/native/lpm_cpu.c index 9d13ab7229..f621c96062 100644 --- a/cpu/native/lpm_cpu.c +++ b/cpu/native/lpm_cpu.c @@ -18,9 +18,17 @@ #include #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 cb6b8b722a..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" @@ -26,7 +32,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 +69,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()"); } @@ -75,40 +81,55 @@ char *thread_stack_init(void *task_func, void *stack_start, int stacksize) void cpu_switch_context_exit(void) { + ucontext_t *ctx; + DEBUG("XXX: cpu_switch_context_exit()\n"); //active_thread = sched_threads[0]; sched_run(); DEBUG("XXX: cpu_switch_context_exit(): calling setcontext(%s)\n\n", active_thread->name); - if (setcontext((ucontext_t*)(active_thread->sp)) == -1) { + 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():"); } } 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); + 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); } } 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..4ba4b5d536 --- /dev/null +++ b/cpu/native/tramp.S @@ -0,0 +1,52 @@ +.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 +.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 +#endif 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 ; 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) { 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) diff --git a/sys/lib/ringbuffer.c b/sys/lib/ringbuffer.c index 4e021942d5..a64fa836a5 100755 --- a/sys/lib/ringbuffer.c +++ b/sys/lib/ringbuffer.c @@ -1,8 +1,13 @@ #include #include -#include #include +#if (defined(__MACH__) || defined(__FreeBSD__)) +#include +#else +#include "malloc.h" +#endif + #include "ringbuffer.h" //#define DEBUG(...) printf (__VA_ARGS__) diff --git a/sys/net/destiny/socket.c b/sys/net/destiny/socket.c index a0982c2610..eaaf4d9a82 100644 --- a/sys/net/destiny/socket.c +++ b/sys/net/destiny/socket.c @@ -16,8 +16,8 @@ #include "hwtimer.h" #include "tcp_timer.h" #include "tcp_hc.h" -#include "sys/net/net_help/net_help.h" -#include "sys/net/net_help/msg_help.h" +#include "../net_help/net_help.h" +#include "../net_help/msg_help.h" socket_internal_t sockets[MAX_SOCKETS]; diff --git a/sys/net/destiny/socket.h b/sys/net/destiny/socket.h index 7737ae414e..bcda907332 100644 --- a/sys/net/destiny/socket.h +++ b/sys/net/destiny/socket.h @@ -12,7 +12,7 @@ #include "tcp.h" #include "udp.h" #include "in.h" -#include "sys/net/sixlowpan/sixlowip.h" +#include "../sixlowpan/sixlowip.h" /* * Types diff --git a/sys/net/destiny/tcp.c b/sys/net/destiny/tcp.c index 2dfd4cdf61..76cd6f4a50 100644 --- a/sys/net/destiny/tcp.c +++ b/sys/net/destiny/tcp.c @@ -16,9 +16,9 @@ #include "tcp.h" #include "in.h" #include "socket.h" -#include "sys/net/net_help/net_help.h" -#include "sys/net/net_help/msg_help.h" -#include "sys/net/sixlowpan/sixlowpan.h" +#include "../net_help/net_help.h" +#include "../net_help/msg_help.h" +#include "../sixlowpan/sixlowpan.h" void printTCPHeader(tcp_hdr_t *tcp_header) { diff --git a/sys/net/destiny/tcp.h b/sys/net/destiny/tcp.h index 576b2c73fa..f2c37dbb66 100644 --- a/sys/net/destiny/tcp.h +++ b/sys/net/destiny/tcp.h @@ -71,7 +71,7 @@ enum tcp_codes #define TCP_STACK_SIZE 1024 -#include "sys/net/sixlowpan/sixlowip.h" +#include "../sixlowpan/sixlowip.h" typedef struct __attribute__ ((packed)) tcp_mms_o_t { diff --git a/sys/net/destiny/tcp_hc.c b/sys/net/destiny/tcp_hc.c index b3b6d14fd4..97f3827eae 100644 --- a/sys/net/destiny/tcp_hc.c +++ b/sys/net/destiny/tcp_hc.c @@ -12,8 +12,8 @@ #include "tcp_hc.h" #include "socket.h" #include "tcp.h" -#include "sys/net/sixlowpan/sixlowip.h" -#include "sys/net/net_help/net_help.h" +#include "../sixlowpan/sixlowip.h" +#include "../net_help/net_help.h" #ifdef TCP_HC diff --git a/sys/net/destiny/tcp_hc.h b/sys/net/destiny/tcp_hc.h index 579c0d7417..9482d3a45b 100644 --- a/sys/net/destiny/tcp_hc.h +++ b/sys/net/destiny/tcp_hc.h @@ -9,7 +9,7 @@ #define TCP_HC_H_ #include "tcp.h" -#include "sys/net/sixlowpan/sixlowip.h" +#include "../sixlowpan/sixlowip.h" #include "socket.h" #ifdef TCP_HC diff --git a/sys/net/destiny/tcp_timer.c b/sys/net/destiny/tcp_timer.c index d87db1f27f..983a11ec70 100644 --- a/sys/net/destiny/tcp_timer.c +++ b/sys/net/destiny/tcp_timer.c @@ -16,7 +16,7 @@ #include "destiny.h" #include "socket.h" #include "net_help/msg_help.h" -#include "sys/net/sixlowpan/sixlowpan.h" +#include "../sixlowpan/sixlowpan.h" void handle_synchro_timeout(socket_internal_t *current_socket) { diff --git a/sys/net/destiny/udp.c b/sys/net/destiny/udp.c index 30a0c8b786..b96738e2c8 100644 --- a/sys/net/destiny/udp.c +++ b/sys/net/destiny/udp.c @@ -5,12 +5,12 @@ #include "udp.h" #include "msg.h" -#include "sys/net/sixlowpan/sixlowip.h" -#include "sys/net/sixlowpan/sixlowpan.h" +#include "../sixlowpan/sixlowip.h" +#include "../sixlowpan/sixlowpan.h" #include "socket.h" #include "in.h" -#include "sys/net/net_help/net_help.h" -#include "sys/net/net_help/msg_help.h" +#include "../net_help/net_help.h" +#include "../net_help/msg_help.h" uint16_t udp_csum(ipv6_hdr_t *ipv6_header, udp_hdr_t *udp_header) { diff --git a/sys/net/destiny/udp.h b/sys/net/destiny/udp.h index a5cdbdbd6f..5a232ab1fa 100644 --- a/sys/net/destiny/udp.h +++ b/sys/net/destiny/udp.h @@ -12,7 +12,7 @@ #define UDP_STACK_SIZE 512 -#include "sys/net/sixlowpan/sixlowip.h" +#include "../sixlowpan/sixlowip.h" typedef struct __attribute__ ((packed)) udp_h_t{ uint16_t src_port;