diff --git a/Makefile.base b/Makefile.base index fd8a00d70c04144772d3ec059d1c443361246668..9aefd1102c8f461de992e29b45ec01b7ba8a5a0b 100644 --- a/Makefile.base +++ b/Makefile.base @@ -20,6 +20,9 @@ ifeq ($(CPU),cc430) INCLUDES += -I$(MAKEBASE)/cpu/msp430-common/include/ INCLUDES += -I$(MAKEBASE)/cpu/cc430/include/ endif +ifeq ($(CPU),native) + INCLUDES += -I$(MAKEBASE)/cpu/native/include/ +endif ifeq ($(BOARD),msba2) INCLUDES += -I$(RIOTBOARD)/msba2/include/ INCLUDES += -I$(RIOTBOARD)/msba2-common/include/ diff --git a/core/include/kernel_intern.h b/core/include/kernel_intern.h index 4eb1a9e9b651ddbaa54271363f1e43a169a31601..606bc6e49928f451bcce4716cb931a9a05730edf 100644 --- a/core/include/kernel_intern.h +++ b/core/include/kernel_intern.h @@ -18,7 +18,7 @@ void kernel_init(void); void board_init_drivers(void); -char *thread_stack_init(void *task_func, void *stack_start); +char *thread_stack_init(void *task_func, void *stack_start, int stack_size); void sched_task_exit(void); void thread_print_stack (void); int thread_measure_stack_usage(char* stack); diff --git a/core/thread.c b/core/thread.c index d38580de07619774531b19a2672b8f2048dcd60d..8ba7e15bd10d2d9c890e94c42a93cba942b3de4a 100644 --- a/core/thread.c +++ b/core/thread.c @@ -143,7 +143,7 @@ int thread_create(char *stack, int stacksize, char priority, int flags, void (*f return -EOVERFLOW; } - cb->sp = thread_stack_init(function,stack+stacksize); + cb->sp = thread_stack_init(function,stack,stacksize); cb->stack_start = stack; cb->stack_size = total_stacksize; diff --git a/cpu/Makefile b/cpu/Makefile index 192319998746c3fe2adf366013c0f52cb26f2bc8..25ef332df1b0fa1bb71ef1ca8b96ec1d117d2296 100644 --- a/cpu/Makefile +++ b/cpu/Makefile @@ -14,6 +14,10 @@ ifeq ($(CPU),msp430x16x) DIRS = msp430-common msp430x16x endif +ifeq ($(CPU),native) + DIRS = native +endif + .PHONY: cpus .PHONY: $(DIRS) @@ -28,6 +32,5 @@ clean: @$(MAKE) -C cc430 clean @$(MAKE) -C msp430-common clean @$(MAKE) -C msp430x16x clean - - + @$(MAKE) -C native clean diff --git a/cpu/native/Makefile b/cpu/native/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..bc80511fb536e59f2bcdf92805726fd4d99c64b9 --- /dev/null +++ b/cpu/native/Makefile @@ -0,0 +1,16 @@ +MODULE = cpu + +INCLUDES = -I../include -I$(RIOTBASE)/core/include +DIRS = +ifneq (,$(findstring rtc,$(USEMODULE))) + DIRS += rtc +endif + +all: $(BINDIR)$(MODULE).a + @for i in $(DIRS) ; do $(MAKE) -C $$i ; done ; + +include $(RIOTBASE)/Makefile.base + +clean:: + @for i in $(DIRS) ; do $(MAKE) -C $$i clean ; done ; + diff --git a/cpu/native/atomic_cpu.c b/cpu/native/atomic_cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..ca0f4487192fe64906239d6111fcef4231b5b268 --- /dev/null +++ b/cpu/native/atomic_cpu.c @@ -0,0 +1,35 @@ +/** + * Native CPU atomic.h implementation + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup arch + * @{ + * @file + * @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de> + * @} + */ + +#include <atomic.h> +#include <irq.h> +#include <debug.h> + +unsigned int atomic_set_return(unsigned int* val, unsigned int set) +{ + unsigned int old_val; + unsigned int old_state; + + DEBUG("atomic_set_return\n"); + + old_state = disableIRQ(); + + old_val = *val; + *val = set; + + restoreIRQ(old_state); + + return old_val; +} diff --git a/cpu/native/hwtimer_cpu.c b/cpu/native/hwtimer_cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..3d362575d41a43cc55c2da1e1f64f92de5cdf126 --- /dev/null +++ b/cpu/native/hwtimer_cpu.c @@ -0,0 +1,165 @@ +/** + * Native CPU hwtimer_arch.h implementation + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup arch + * @{ + * @file + * @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de> + * @} + */ + +#include <time.h> +#include <signal.h> +#include <stdint.h> +#include <err.h> +#include "hwtimer.h" +#include "hwtimer_arch.h" + +#include "hwtimer_cpu.h" +#include "cpu.h" +#include "cpu-conf.h" + +#include "debug.h" + +#define HWTIMER_MINTICKS (1000) + +static unsigned long native_hwtimer_now; +static int native_hwtimer_irq[ARCH_MAXTIMERS]; +static timer_t native_hwtimer_timer[ARCH_MAXTIMERS]; +static void (*int_handler)(int); + +void ticks2ts(unsigned long ticks, struct timespec *tp) +{ + tp->tv_sec = ticks / HWTIMER_SPEED; + tp->tv_nsec = (ticks % HWTIMER_SPEED)*1000 ; +} + +unsigned long ts2ticks(struct timespec *tp) +{ + /* TODO: check for overflow */ + return((tp->tv_sec * HWTIMER_SPEED) + (tp->tv_nsec/1000)); +} + +void hwtimer_isr_timer() +{ + DEBUG("hwtimer_isr_timer()\n"); + + for (int i = 0; i<ARCH_MAXTIMERS; i++) { + if (native_hwtimer_irq[i] == 1) { + DEBUG("hwtimer_isr_timer(): calling hwtimer.int_handler(%i)\n", i); + int_handler(i); + } + } +} + +void hwtimer_arch_enable_interrupt(void) +{ + DEBUG("hwtimer_arch_enable_interrupt()\n"); + if (register_interrupt(SIGALRM, hwtimer_isr_timer) != 0) { + DEBUG("darn!\n\n"); + } + return; +} + +void hwtimer_arch_disable_interrupt(void) +{ + DEBUG("hwtimer_arch_disable_interrupt()\n"); + if (unregister_interrupt(SIGALRM) != 0) { + DEBUG("darn!\n\n"); + } + return; +} + +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"); + } + + return; +} + +/** + * Set a kernel timer to raise an interrupt after ::offset kernel timer ticks + * from now. + */ +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; + + 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); + + 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"); + } + + return; +} + +void hwtimer_arch_set_absolute(unsigned long value, short timer) +{ + DEBUG("hwtimer_arch_set_absolute(%li, %i)\n", value, timer); + value -= native_hwtimer_now; + return(hwtimer_arch_set(value, timer)); +} + +unsigned long hwtimer_arch_now(void) +{ + struct timespec t; + + DEBUG("hwtimer_arch_now()\n"); + + if (clock_gettime(CLOCK_MONOTONIC, &t) == -1) { + err(1, "hwtimer_arch_now: clock_gettime"); + } + native_hwtimer_now = ts2ticks(&t); + + DEBUG("hwtimer_arch_now(): it is now %lis %lins\n", t.tv_sec, t.tv_nsec); + DEBUG("hwtimer_arch_now(): returning %li\n", native_hwtimer_now); + return native_hwtimer_now; +} + +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<ARCH_MAXTIMERS; i++) { + native_hwtimer_irq[i] = 0; + //sev.sigev_signo = _SIG_TIMER + i;; + sev.sigev_signo = SIGALRM; + sev.sigev_value.sival_ptr = &native_hwtimer_timer[i]; + if (timer_create(CLOCK_REALTIME, &sev, &native_hwtimer_timer[i]) == -1) { + err(1, "timer_create"); + } + } + return; +} diff --git a/cpu/native/include/cpu-conf.h b/cpu/native/include/cpu-conf.h new file mode 100644 index 0000000000000000000000000000000000000000..eebbe2e30b301d095f874729f7dbc75474f1a600 --- /dev/null +++ b/cpu/native/include/cpu-conf.h @@ -0,0 +1,33 @@ +/** + * Native CPU configuration + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup arch + * @{ + * @file + * @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de> + * @} + */ +#ifndef CPUCONF_H_ +#define CPUCONF_H_ +#include <signal.h> + +/* TODO: choose more sensibly? */ +#ifndef KERNEL_CONF_STACKSIZE_DEFAULT +#define KERNEL_CONF_STACKSIZE_DEFAULT 8192 +#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) */ + +#endif /* CPUCONF_H_ */ diff --git a/cpu/native/include/cpu.h b/cpu/native/include/cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..50effea7cb47d5a89d6f6bbfa752d5a8680e7c45 --- /dev/null +++ b/cpu/native/include/cpu.h @@ -0,0 +1,37 @@ +/** + * Native CPU interface + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup arch + * @{ + * @file + * @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de> + * @} + */ + +#ifndef _CPU_H +#define _CPU_H + +#include <ucontext.h> + +#include "kernel_intern.h" +#include "sched.h" +#include "debug.h" + +#include "cpu-conf.h" + +/* TODO: choose better value? */ +#define F_CPU 1000000 + +void dINT(void); +void eINT(void); + +int register_interrupt(int sig, void *handler); +int unregister_interrupt(int sig); +void thread_yield(void); + +#endif //_CPU_H diff --git a/cpu/native/include/hwtimer_cpu.h b/cpu/native/include/hwtimer_cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..630741dfc34122e624b9f8c749e633d1e8eda22f --- /dev/null +++ b/cpu/native/include/hwtimer_cpu.h @@ -0,0 +1,24 @@ +/** + * Native CPU hwtimer_cpu configuration + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup arch + * @{ + * @file + * @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de> + * @} + */ + +#ifndef HWTIMER_CPU_H_ +#define HWTIMER_CPU_H_ + +/* TODO: choose more appropriate values here? */ +#define ARCH_MAXTIMERS 4 +#define HWTIMER_SPEED 1000000 +#define HWTIMER_MAXTICKS (0xFFFFFFFF) + +#endif /* HWTIMER_CPU_H_ */ diff --git a/cpu/native/irq_cpu.c b/cpu/native/irq_cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..abc88f8884ef1fb1fc750b9222d866c95e70b606 --- /dev/null +++ b/cpu/native/irq_cpu.c @@ -0,0 +1,271 @@ +/** + * Native CPU irq.h implementation + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup arch + * @{ + * @file + * @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de> + * @} + */ +#include <signal.h> +#include <err.h> + +#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; +static sigset_t native_sig_set; +static char __isr_stack[SIGSTKSZ]; +extern volatile tcb_t *active_thread; + +struct int_handler_t { + void (*func)(void); +}; +static struct int_handler_t native_irq_handlers[255]; + +unsigned disableIRQ(void) +{ + unsigned int prev_state; + sigset_t mask; + + DEBUG("disableIRQ()\n"); + + if (sigfillset(&mask) == -1) { + err(1, "disableIRQ(): sigfillset"); + } + if (native_interrupts_enabled == 1) { + if (sigprocmask(SIG_SETMASK, &mask, &native_sig_set) == -1) { + err(1, "disableIRQ(): sigprocmask"); + } + } + else { + if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1) { + err(1, "disableIRQ(): sigprocmask()"); + } + } + prev_state = native_interrupts_enabled; + native_interrupts_enabled = 0; + + return prev_state; +} + +unsigned enableIRQ(void) +{ + unsigned int prev_state; + + DEBUG("enableIRQ()\n"); + + if (sigprocmask(SIG_SETMASK, &native_sig_set, NULL) == -1) { + err(1, "enableIRQ(): sigprocmask()"); + } + prev_state = native_interrupts_enabled; + native_interrupts_enabled = 1; + + return prev_state; +} + +void restoreIRQ(unsigned state) +{ + DEBUG("restoreIRQ()\n"); + + if (state == 1) { + enableIRQ(); + } + else { + disableIRQ(); + } + return; +} + +int inISR(void) +{ + DEBUG("inISR()\n"); + return native_in_irs; +} + + +void dINT(void) +{ + disableIRQ(); +} + +void eINT(void) +{ + enableIRQ(); +} + +/** + * call signal handler, + * 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(); + } + else { + printf("XXX: no handler for signal %i\n", last_sig); + errx(1, "XXX: this should not have happened!\n"); + } + native_in_irs = 0; + cpu_switch_context_exit(); +} + + +/** + * load isr context, save signal + */ +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. + * */ + + /* save the signal */ + last_sig = sig; + /* indicate irs status */ + native_in_irs = 1; + + if (getcontext(&native_context) == -1) { + err(1, "native_isr_entry(): getcontext()"); + } + + 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"); + } + else { + DEBUG("returning to interrupted thread\n"); + } + native_in_irs = 0; + enableIRQ(); +} + +/** + * TODO: check sa_flags for appropriateness + * TODO: use appropriate data structure (hashmap?) for signal + * handlers. + */ +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"); + } + + native_irq_handlers[sig].func = handler; + + sa.sa_sigaction = (void*) native_isr_entry; + + if (sigemptyset(&sa.sa_mask) == -1) { + err(1, "register_interrupt: sigemptyset"); + } + + sa.sa_flags = SA_RESTART | SA_SIGINFO; + + if (sigaction(sig, &sa, NULL)) { + err(1, "register_interrupt: sigaction"); + } + + return 0; +} + +/** + * TODO: see register_interrupt + * TODO: ignore signal + */ +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"); + } + native_irq_handlers[sig].func = NULL; + + sa.sa_sigaction = SIG_IGN; + if (sigemptyset(&sa.sa_mask) == -1) { + err(1, "unregister_interrupt: sigemptyset"); + } + sa.sa_flags = SA_RESTART | SA_SIGINFO; + + if (sigaction(sig, &sa, NULL)) { + err(1, "register_interrupt: sigaction"); + } + return 0; +} + + +/** + * TODO: see register_interrupt + */ +void native_interrupt_init(void) +{ + struct sigaction sa; + DEBUG("XXX: native_interrupt_init()\n"); + + for (int i = 0; i<255; i++) { + native_irq_handlers[i].func = NULL; + } + + sa.sa_sigaction = (void*) native_isr_entry; + if (sigemptyset(&sa.sa_mask) == -1) { + err(1, "native_interrupt_init: sigemptyset"); + } + 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 (sigaction(SIGUSR1, &sa, NULL)) { + err(1, "native_interrupt_init: sigaction"); + } + + puts("RIOT native interrupts/signals initialized."); +} diff --git a/cpu/native/lpm_cpu.c b/cpu/native/lpm_cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..6e39ce3aeb3c2eb1a6e2d548cafc9b98e5e19dd2 --- /dev/null +++ b/cpu/native/lpm_cpu.c @@ -0,0 +1,96 @@ +/** + * Native CPU lpm.h implementation + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup arch + * @{ + * @file + * @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de> + * @} + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "lpm.h" +#include "debug.h" + +static enum lpm_mode native_lpm; + +void lpm_init(void) +{ + DEBUG("lpm_init()\n"); + native_lpm = LPM_ON; + return; +} + +enum lpm_mode lpm_set(enum lpm_mode target) +{ + enum lpm_mode last_lpm; + + DEBUG("lpm_set(%i)\n", target); + + last_lpm = native_lpm; + native_lpm = target; + + switch(native_lpm) /* @contiki :-p */ + { + case LPM_ON: + break; + + case LPM_IDLE: + DEBUG("lpm_set(): pause()\n"); + pause(); + break; + + /* XXX: unfinished modes: */ + case LPM_SLEEP: + /*TODO: implement*/ + printf("XXX: lpm_set(): LPM_SLEEP not implemented\n"); + //sigsuspend(); + + case LPM_POWERDOWN: + /*TODO: implement*/ + printf("XXX: lpm_set(): LPM_POWERDOWN not implemented\n"); + //sigsuspend(); + + case LPM_OFF: + printf("lpm_set(): exit()\n"); + exit(0); + break; + + default: + DEBUG("XXX: unsupported power mode: %i\n", native_lpm); + exit(1); + } + + return last_lpm; +} + +void lpm_awake(void) +{ + DEBUG("XXX: lpm_awake()\n"); + native_lpm = LPM_ON; + return; +} + +void lpm_begin_awake(void) +{ + DEBUG("XXX: lpm_begin_awake()\n"); + return; +} + +void lpm_end_awake(void) +{ + DEBUG("XXX: lpm_end_awake()\n"); + native_lpm = LPM_ON; + return; +} +enum lpm_mode lpm_get(void) +{ + return native_lpm; +} diff --git a/cpu/native/native_cpu.c b/cpu/native/native_cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..b4f49e9a54709840e55e86a1efb705e2324de9a0 --- /dev/null +++ b/cpu/native/native_cpu.c @@ -0,0 +1,111 @@ +/** + * Native CPU kernel_intern.h and sched.h implementation + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup arch + * @{ + * @file + * @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de> + * @} + */ +#include <stdio.h> +#include <ucontext.h> +#include <err.h> + +#include "kernel_intern.h" +#include "sched.h" + +#include "cpu.h" +#include "cpu-conf.h" +#include "debug.h" + +extern volatile tcb_t *active_thread; +static ucontext_t native_context; +static char __isr_stack[SIGSTKSZ]; + +/** + * TODO: implement + */ +void thread_print_stack(void) +{ + DEBUG("XXX: thread_print_stack()\n"); + return; +} + +char *thread_stack_init(void *task_func, void *stack_start, int stacksize) +{ + unsigned int *stk; + ucontext_t *p; + + DEBUG("thread_stack_init()\n"); + + stk = stack_start; + +#ifdef NATIVESPONTOP + p = (ucontext_t*)stk; + stk += sizeof(ucontext_t)/sizeof(void*); + stacksize -= sizeof(ucontext_t); +#else + p = (ucontext_t*)(stk + ((stacksize-sizeof(ucontext_t))/sizeof(void*))); + stacksize -= sizeof(ucontext_t); +#endif + + if (getcontext(p) == -1) { + err(1, "thread_stack_init(): getcontext()"); + } + + p->uc_stack.ss_sp = stk; + p->uc_stack.ss_size = stacksize; + p->uc_stack.ss_flags = 0; + p->uc_link = &native_context; + if (sigemptyset(&(p->uc_sigmask)) == -1) { + err(1, "thread_stack_init(): sigemptyset()"); + } + + makecontext(p, task_func, 0); + + return (char *) p; +} + +void cpu_switch_context_exit(void) +{ + 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) { + err(1, "cpu_switch_context_exit(): setcontext():"); + } +} + +void thread_yield() +{ + ucontext_t *oc; + + 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()"); + } +} + +void native_cpu_init() +{ + if (getcontext(&native_context) == -1) { + err(1, "native_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); + puts("RIOT native cpu initialized."); +} diff --git a/cpu/native/rtc/Makefile b/cpu/native/rtc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8cd5c1e0af1de5ade99fbd0d4920ad59a722a852 --- /dev/null +++ b/cpu/native/rtc/Makefile @@ -0,0 +1,6 @@ +INCLUDES = -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/core/include + +MODULE =rtc + +include $(MAKEBASE)/Makefile.base + diff --git a/cpu/native/rtc/posix-rtc.c b/cpu/native/rtc/posix-rtc.c new file mode 100644 index 0000000000000000000000000000000000000000..98629d281bfe7e78a74a9e8f88e8167103408c09 --- /dev/null +++ b/cpu/native/rtc/posix-rtc.c @@ -0,0 +1,75 @@ +/** + * Native CPU rtc.h implementation + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup arch + * @{ + * @file + * @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de> + * @} + */ + +#include <time.h> +#include <err.h> + +#include "debug.h" + +#include <rtc.h> + +static int native_rtc_enabled; + +/** + * @brief Initializes the RTC for calendar mode + */ +void rtc_init(void) +{ + native_rtc_enabled = 0; + printf("native rtc initialized\n"); +} + +/** + * @brief Starts the RTC + */ +void rtc_enable(void) +{ + DEBUG("rtc_enable\n"); + native_rtc_enabled = 1; +} + +/** + * @brief Stops the RTC + */ +void rtc_disable(void) +{ + DEBUG("rtc_disable()\n"); + native_rtc_enabled = 0; +} + +/** + * @brief Sets the current time in broken down format directly from to RTC + * @param[in] localt Pointer to structure with time to set + */ +void rtc_set_localtime(struct tm* localt) +{ + DEBUG("rtc_set_localtime()\n"); + printf("setting time not supported."); +} + +/** + * @brief Returns the current time in broken down format directly from the RTC + * @param[out] localt Pointer to structure to receive time + */ +void rtc_get_localtime(struct tm* localt) +{ + time_t t; + if(native_rtc_enabled == 1) { + t = time(NULL); + if (localtime_r(&t, localt) == NULL) { + err(1, "rtc_get_localtime: localtime_r"); + } + } +} diff --git a/cpu/native/startup.c b/cpu/native/startup.c new file mode 100644 index 0000000000000000000000000000000000000000..0181103eeb8cc2c9fca1a964b474fc9fc942e528 --- /dev/null +++ b/cpu/native/startup.c @@ -0,0 +1,33 @@ +/** + * Native CPU entry code + * + * Copyright (C) 2013 Ludwig Ortmann + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup arch + * @{ + * @file + * @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de> + * @} + */ + +#include <stdio.h> +#include <kernel_intern.h> +#include <cpu.h> + +extern void board_init(void); +extern void native_cpu_init(void); +extern void native_interrupt_init(void); + +__attribute__ ((constructor)) static void startup(void) +{ + native_cpu_init(); + native_interrupt_init(); + + board_init(); + + puts("RIOT native hardware initialization complete.\n"); + kernel_init(); +}