Skip to content
Snippets Groups Projects
Commit d65536f7 authored by Ludwig Knüpfer's avatar Ludwig Knüpfer
Browse files

native cpu initial import

parent 64434fee
No related branches found
No related tags found
No related merge requests found
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
void kernel_init(void); void kernel_init(void);
void board_init_drivers(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 sched_task_exit(void);
void thread_print_stack (void); void thread_print_stack (void);
int thread_measure_stack_usage(char* stack); int thread_measure_stack_usage(char* stack);
......
...@@ -143,7 +143,7 @@ int thread_create(char *stack, int stacksize, char priority, int flags, void (*f ...@@ -143,7 +143,7 @@ int thread_create(char *stack, int stacksize, char priority, int flags, void (*f
return -EOVERFLOW; return -EOVERFLOW;
} }
cb->sp = thread_stack_init(function,stack+stacksize); cb->sp = thread_stack_init(function,stack,stacksize);
cb->stack_start = stack; cb->stack_start = stack;
cb->stack_size = total_stacksize; cb->stack_size = total_stacksize;
......
...@@ -14,6 +14,10 @@ ifeq ($(CPU),msp430x16x) ...@@ -14,6 +14,10 @@ ifeq ($(CPU),msp430x16x)
DIRS = msp430-common msp430x16x DIRS = msp430-common msp430x16x
endif endif
ifeq ($(CPU),native)
DIRS = native
endif
.PHONY: cpus .PHONY: cpus
.PHONY: $(DIRS) .PHONY: $(DIRS)
...@@ -28,6 +32,5 @@ clean: ...@@ -28,6 +32,5 @@ clean:
@$(MAKE) -C cc430 clean @$(MAKE) -C cc430 clean
@$(MAKE) -C msp430-common clean @$(MAKE) -C msp430-common clean
@$(MAKE) -C msp430x16x clean @$(MAKE) -C msp430x16x clean
@$(MAKE) -C native clean
#include <atomic.h>
#include <cpu.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;
}
#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;
}
#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_ */
#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
#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_ */
#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.");
}
#include <stdio.h>
#include <stdlib.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;
}
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 ;
#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.");
}
INCLUDES = -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/core/include
MODULE =rtc
include $(MAKEBASE)/makefile.base
#include <time.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");
}
}
}
#include <stdio.h>
#include <kernel_intern.h>
extern void board_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();
}
...@@ -20,6 +20,9 @@ ifeq ($(CPU),cc430) ...@@ -20,6 +20,9 @@ ifeq ($(CPU),cc430)
INCLUDES += -I$(MAKEBASE)/cpu/msp430-common/include/ INCLUDES += -I$(MAKEBASE)/cpu/msp430-common/include/
INCLUDES += -I$(MAKEBASE)/cpu/cc430/include/ INCLUDES += -I$(MAKEBASE)/cpu/cc430/include/
endif endif
ifeq ($(CPU),native)
INCLUDES += -I$(MAKEBASE)/cpu/native/include/
endif
ifeq ($(BOARD),msba2) ifeq ($(BOARD),msba2)
INCLUDES += -I$(RIOTBOARD)/msba2/include/ INCLUDES += -I$(RIOTBOARD)/msba2/include/
INCLUDES += -I$(RIOTBOARD)/msba2-common/include/ INCLUDES += -I$(RIOTBOARD)/msba2-common/include/
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment