removed posix real-time extension timers from cpu
This commit is contained in:
parent
671cb6560f
commit
2f74d35709
@ -1,8 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* Native CPU hwtimer_arch.h implementation
|
* Native CPU hwtimer_arch.h implementation
|
||||||
*
|
*
|
||||||
* Uses POSIX real-time extension timers to mimic hardware timers.
|
* Uses POSIX realtime clock and POSIX itimer to mimic hardware.
|
||||||
* XXX: see hwtimer_isr_timer()
|
* 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
|
* Copyright (C) 2013 Ludwig Ortmann
|
||||||
*
|
*
|
||||||
@ -18,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
@ -31,17 +35,30 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
static unsigned long native_hwtimer_now;
|
static unsigned long native_hwtimer_now;
|
||||||
|
|
||||||
static int native_hwtimer_irq[ARCH_MAXTIMERS];
|
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);
|
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_sec = ticks / HWTIMER_SPEED;
|
||||||
tp->tv_nsec = (ticks % HWTIMER_SPEED)*1000 ;
|
tp->tv_usec = (ticks % HWTIMER_SPEED) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns ticks for give timeval
|
||||||
|
*/
|
||||||
|
unsigned long tv2ticks(struct timeval *tp)
|
||||||
|
{
|
||||||
|
/* TODO: check for overflow */
|
||||||
|
return((tp->tv_sec * HWTIMER_SPEED) + (tp->tv_usec));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,22 +71,72 @@ unsigned long ts2ticks(struct timespec *tp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* native timer signal handler,
|
* set next_timer to the next lowest enabled timer index
|
||||||
|
*/
|
||||||
|
void schedule_timer(void)
|
||||||
|
{
|
||||||
|
int l = next_timer;
|
||||||
|
for (
|
||||||
|
int i = ((next_timer +1) % ARCH_MAXTIMERS);
|
||||||
|
i != next_timer;
|
||||||
|
i = ((i+1) % ARCH_MAXTIMERS)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( native_hwtimer_isset[l] != 1 ) {
|
||||||
|
/* make sure we dont compare to garbage in the following
|
||||||
|
* if condition */
|
||||||
|
l = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
( native_hwtimer_isset[i] == 1 ) &&
|
||||||
|
( tv2ticks(&(native_hwtimer[i].it_value)) < tv2ticks(&(native_hwtimer[l].it_value)) )
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* set l to the lowest active time */
|
||||||
|
l = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
next_timer = l;
|
||||||
|
/* l could still point to some unused (garbage) timer if no timers
|
||||||
|
* are set at all */
|
||||||
|
if (native_hwtimer_isset[next_timer] == 1) {
|
||||||
|
if (setitimer(ITIMER_REAL, &native_hwtimer[next_timer], NULL) == -1) {
|
||||||
|
err(1, "schedule_timer");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DEBUG("schedule_timer(): set next timer.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DEBUG("schedule_timer(): no next timer!? This looks suspicous.\n");
|
||||||
|
// TODO: unset timer.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* native timer signal handler
|
||||||
*
|
*
|
||||||
* XXX: Calls callback for all timers whenever any timer finishes.
|
* set new system timer, call timer interrupt handler
|
||||||
*/
|
*/
|
||||||
void hwtimer_isr_timer()
|
void hwtimer_isr_timer()
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
DEBUG("hwtimer_isr_timer()\n");
|
DEBUG("hwtimer_isr_timer()\n");
|
||||||
|
|
||||||
for (int i = 0; i<ARCH_MAXTIMERS; i++) {
|
i = next_timer;
|
||||||
|
native_hwtimer_isset[next_timer] = 0;
|
||||||
|
schedule_timer();
|
||||||
|
|
||||||
if (native_hwtimer_irq[i] == 1) {
|
if (native_hwtimer_irq[i] == 1) {
|
||||||
DEBUG("hwtimer_isr_timer(): calling hwtimer.int_handler(%i)\n", i);
|
DEBUG("hwtimer_isr_timer(): calling hwtimer.int_handler(%i)\n", i);
|
||||||
int_handler(i);
|
int_handler(i);
|
||||||
}
|
}
|
||||||
if (timer_getoverrun(native_hwtimer_timer[i]) > 0 ) {
|
else {
|
||||||
errx(1, "XXX: unhandled hwtimer situation");
|
DEBUG("hwtimer_isr_timer(): this should not have happened");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,39 +160,27 @@ void hwtimer_arch_disable_interrupt(void)
|
|||||||
|
|
||||||
void hwtimer_arch_unset(short timer)
|
void hwtimer_arch_unset(short timer)
|
||||||
{
|
{
|
||||||
struct itimerspec its;
|
|
||||||
|
|
||||||
DEBUG("hwtimer_arch_unset(%d)\n", timer);
|
DEBUG("hwtimer_arch_unset(%d)\n", timer);
|
||||||
|
|
||||||
native_hwtimer_irq[timer] = 0;
|
native_hwtimer_irq[timer] = 0;
|
||||||
|
native_hwtimer_isset[timer] = 0;
|
||||||
its.it_interval.tv_nsec = 0;
|
schedule_timer();
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hwtimer_arch_set(unsigned long offset, short timer)
|
void hwtimer_arch_set(unsigned long offset, short timer)
|
||||||
{
|
{
|
||||||
struct itimerspec its;
|
|
||||||
|
|
||||||
DEBUG("hwtimer_arch_set(%li, %i)\n", offset, timer);
|
DEBUG("hwtimer_arch_set(%li, %i)\n", offset, timer);
|
||||||
native_hwtimer_irq[timer] = 1;
|
native_hwtimer_irq[timer] = 1;
|
||||||
|
native_hwtimer_isset[timer] = 1;
|
||||||
|
|
||||||
ticks2ts(offset, &its.it_value);
|
ticks2tv(offset, &(native_hwtimer[timer].it_value));
|
||||||
DEBUG("hwtimer_arch_set(): that is %lis %lins from now\n", its.it_value.tv_sec, its.it_value.tv_nsec);
|
DEBUG("hwtimer_arch_set(): that is %lis %lius from now\n",
|
||||||
|
native_hwtimer[timer].it_value.tv_sec,
|
||||||
|
native_hwtimer[timer].it_value.tv_usec);
|
||||||
|
|
||||||
its.it_interval.tv_sec = 0;
|
schedule_timer();
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
@ -155,24 +210,18 @@ unsigned long hwtimer_arch_now(void)
|
|||||||
|
|
||||||
void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu)
|
void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu)
|
||||||
{
|
{
|
||||||
struct sigevent sev;
|
|
||||||
|
|
||||||
DEBUG("hwtimer_arch_init()\n");
|
DEBUG("hwtimer_arch_init()\n");
|
||||||
|
|
||||||
hwtimer_arch_disable_interrupt();
|
hwtimer_arch_disable_interrupt();
|
||||||
|
|
||||||
int_handler = handler;
|
int_handler = handler;
|
||||||
|
|
||||||
sev.sigev_notify = SIGEV_SIGNAL;
|
|
||||||
for (int i = 0; i<ARCH_MAXTIMERS; i++) {
|
for (int i = 0; i<ARCH_MAXTIMERS; i++) {
|
||||||
native_hwtimer_irq[i] = 0;
|
native_hwtimer_irq[i] = 0;
|
||||||
//sev.sigev_signo = _SIG_TIMER + i;;
|
native_hwtimer_isset[i] = 0;
|
||||||
sev.sigev_signo = SIGALRM;
|
native_hwtimer[i].it_interval.tv_sec = 0;
|
||||||
//sev.sigev_value.sival_ptr = &native_hwtimer_timer[i];
|
native_hwtimer[i].it_interval.tv_usec = 0;
|
||||||
if (timer_create(CLOCK_REALTIME, &sev, &native_hwtimer_timer[i]) == -1) {
|
|
||||||
err(1, "timer_create");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hwtimer_arch_enable_interrupt();
|
hwtimer_arch_enable_interrupt();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,9 +24,7 @@
|
|||||||
#define KERNEL_CONF_STACKSIZE_IDLE 4096
|
#define KERNEL_CONF_STACKSIZE_IDLE 4096
|
||||||
#define NATIVE_ISR_STACKSIZE 8192
|
#define NATIVE_ISR_STACKSIZE 8192
|
||||||
|
|
||||||
#define _SIG_UNDEF SIGRTMIN + 0
|
#define _SIG_LTC4150 SIGRTMIN + 0
|
||||||
#define _SIG_TIMER SIGRTMIN + 10 // check hwtimer_cpu.h for compliance
|
|
||||||
#define _SIG_LTC4150 SIGRTMIN + 20
|
|
||||||
|
|
||||||
/* TODO: check for overflow (SIGRTMAX) */
|
/* TODO: check for overflow (SIGRTMAX) */
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user