mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #24 from LudwigOrtmann/master
primitive native cpu target
This commit is contained in:
commit
bd5b46628f
@ -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/
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
16
cpu/native/Makefile
Normal file
16
cpu/native/Makefile
Normal file
@ -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 ;
|
||||
|
35
cpu/native/atomic_cpu.c
Normal file
35
cpu/native/atomic_cpu.c
Normal file
@ -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;
|
||||
}
|
165
cpu/native/hwtimer_cpu.c
Normal file
165
cpu/native/hwtimer_cpu.c
Normal file
@ -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;
|
||||
}
|
33
cpu/native/include/cpu-conf.h
Normal file
33
cpu/native/include/cpu-conf.h
Normal file
@ -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_ */
|
37
cpu/native/include/cpu.h
Normal file
37
cpu/native/include/cpu.h
Normal file
@ -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
|
24
cpu/native/include/hwtimer_cpu.h
Normal file
24
cpu/native/include/hwtimer_cpu.h
Normal file
@ -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_ */
|
271
cpu/native/irq_cpu.c
Normal file
271
cpu/native/irq_cpu.c
Normal file
@ -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.");
|
||||
}
|
96
cpu/native/lpm_cpu.c
Normal file
96
cpu/native/lpm_cpu.c
Normal file
@ -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;
|
||||
}
|
111
cpu/native/native_cpu.c
Normal file
111
cpu/native/native_cpu.c
Normal file
@ -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.");
|
||||
}
|
6
cpu/native/rtc/Makefile
Normal file
6
cpu/native/rtc/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
INCLUDES = -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/core/include
|
||||
|
||||
MODULE =rtc
|
||||
|
||||
include $(MAKEBASE)/Makefile.base
|
||||
|
75
cpu/native/rtc/posix-rtc.c
Normal file
75
cpu/native/rtc/posix-rtc.c
Normal file
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
33
cpu/native/startup.c
Normal file
33
cpu/native/startup.c
Normal file
@ -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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user