base_hw & omap4: Timer driver.

Fix bug regarding idle thread in thread scheduling in
'base-hw/src/core/kernel.cc'.

Fix regarding signal submit in signal framework in
'base-hw/src/core/kernel.cc'.
This commit is contained in:
Martin Stein 2012-10-24 15:49:53 +02:00 committed by Norman Feske
parent 31d57a6257
commit 612735732a
6 changed files with 301 additions and 5 deletions

View File

@ -895,7 +895,7 @@ namespace Kernel
/* update current entry */
ENTRY_T * e = _entries.head();
if (!e) {
t = _idle->Entry::_time;
t = _lap_time;
return _idle;
}
e->Entry::_consume(t);
@ -1422,7 +1422,7 @@ namespace Kernel
void add_pending_context(Signal_context * const c)
{
assert(c->_receiver == this);
_pending_contexts.enqueue(c);
if(!c->is_enqueued()) _pending_contexts.enqueue(c);
_listen();
}
};

View File

@ -47,7 +47,9 @@ namespace Genode
EMIF1_EMIF2_CS0_SDRAM_BASE = 0x80000000,
EMIF1_EMIF2_CS0_SDRAM_SIZE = 0x40000000,
/* misc */
SECURITY_EXTENSION = 0,
SYS_CLK = 38400000,
};
};
}

View File

@ -5,12 +5,13 @@
#
# denote wich specs are also fullfilled by this spec
SPECS += cortex_a9 tl16c750 omap44xx
SPECS += cortex_a9 tl16c750 omap4 platform_panda
# add repository relative include paths
REP_INC_DIR += include/platform/panda_a2
# include implied specs
include $(call select_from_repositories,mk/spec-platform_panda.mk)
include $(call select_from_repositories,mk/spec-cortex_a9.mk)
include $(call select_from_repositories,mk/spec-tl16c750.mk)

View File

@ -169,8 +169,8 @@ namespace Genode
/**
* Translate microseconds to a native timer value
*/
static unsigned long us_to_tics(unsigned long const tics) {
return tics / TICS_PER_US; }
static unsigned long us_to_tics(unsigned long const us) {
return us * TICS_PER_US; }
/**
* Translate native timer value to microseconds

View File

@ -0,0 +1,270 @@
/*
* \brief Basic driver behind platform timer
* \author Martin Stein
* \date 2012-05-03
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _HW__OMAP4__PLATFORM_TIMER_BASE_H_
#define _HW__OMAP4__PLATFORM_TIMER_BASE_H_
/* Genode includes */
#include <io_mem_session/connection.h>
#include <util/mmio.h>
#include <irq_session/connection.h>
#include <drivers/board.h>
namespace Genode
{
/**
* Omap4 general purpose timer 3 through 9 and 11
*/
class Omap4_gp_timer_1 : public Mmio
{
/**
* Timer tics per microsecond
*/
static float tics_per_us() {
return (float)Board::SYS_CLK / 1000000; }
/**
* Microsecodns per timer tic
*/
static float us_per_tic() { return 1 / tics_per_us(); }
/**
* L4 interface control
*/
struct Tiocp_cfg : Register<0x10, 32>
{
struct Softreset : Bitfield<0, 1> { }; /* SW reset active */
struct Idlemode : Bitfield<2, 2> /* action on IDLE request */
{
enum { FORCE_IDLE = 0 };
};
};
/**
* Timer wake-up enable register
*/
struct Twer : Register<0x20, 32>
{
struct Mat_wup_ena : Bitfield<0, 1> { }; /* wakeup on match */
struct Ovf_wup_ena : Bitfield<1, 1> { }; /* wakeup on overflow */
struct Tcar_wup_ena : Bitfield<2, 1> { }; /* wakeup on capture */
/**
* Timer initialization value
*/
static access_t init_timer()
{
return Mat_wup_ena::bits(0) |
Ovf_wup_ena::bits(0) |
Tcar_wup_ena::bits(0);
}
};
/**
* Timer synchronous interface control register
*/
struct Tsicr : Register<0x54, 32>
{
struct Posted : Bitfield<2, 1> { }; /* enable posted mode */
};
/**
* Control timer-functionality dependent features
*/
struct Tclr : Register<0x38, 32>
{
struct St : Bitfield<0, 1> { }; /* start/stop timer */
struct Ar : Bitfield<1, 1> { }; /* enable eutoreload */
struct Pre : Bitfield<5, 1> { }; /* enable prescaler */
/**
* Run-and-wrap configuration
*/
static access_t init_run_and_wrap()
{
return St::bits(0) |
Ar::bits(1) |
Pre::bits(0);
}
};
/**
* Set IRQ enables
*/
struct Irqenable_set : Register<0x2c, 32>
{
struct Ovf_en_flag : Bitfield<1, 1> { }; /* enable overflow IRQ */
};
/**
* IRQ status
*/
struct Irqstatus : Register<0x28, 32>
{
struct Ovf_it_flag : Bitfield<1, 1> { }; /* clear overflow IRQ */
};
/**
* Timer counter register
*/
struct Tcrr : Register<0x3c, 32>
{
/**
* maximum counter value
*/
static access_t max_value() { return ~0; }
};
/**
* Timer load value register
*/
struct Tldr : Register<0x40, 32> { };
/**
* Freeze timer counter
*/
void _freeze() { write<Tclr::St>(0); }
/**
* Unfreeze timer counter
*/
void _unfreeze() { write<Tclr::St>(1); }
/**
* Get remaining counting amount
*/
unsigned long _value() { return max_value() - read<Tcrr>(); }
/**
* Apply counting amount
*/
void _value(unsigned long const v) { write<Tcrr>(max_value() - v); }
public:
/**
* Constructor
*
* \param base MMIO base
*/
Omap4_gp_timer_1(addr_t const base) : Mmio(base)
{
_freeze();
/* do a software reset */
write<Tiocp_cfg::Softreset>(1);
while (read<Tiocp_cfg::Softreset>()) ;
/* configure Idle mode */
write<Tiocp_cfg::Idlemode>(Tiocp_cfg::Idlemode::FORCE_IDLE);
/* enable wake-up interrupt events */
write<Twer>(Twer::init_timer());
/* select posted mode */
write<Tsicr::Posted>(0);
}
/**
* Count down 'value', raise IRQ output, wrap counter and continue
*/
void run_and_wrap(unsigned long value)
{
enum { MIN_VALUE = 1 };
/* stop timer */
_freeze();
clear_interrupt();
value = value ? value : MIN_VALUE;
/* configure for a run and wrap */
write<Tclr>(Tclr::init_run_and_wrap());
write<Irqenable_set::Ovf_en_flag>(1);
/* install value */
_value(value);
write<Tldr>(0);
/* start timer */
_unfreeze();
}
/**
* Clear interrupt output
*/
void clear_interrupt() {
write<Irqstatus::Ovf_it_flag>(1); }
/**
* Maximum timeout value
*/
unsigned long max_value() { return Tcrr::max_value(); }
/**
* Translate timer tics to microseconds
*/
unsigned long tics_to_us(unsigned long const tics)
{
float const us = tics * us_per_tic();
return (unsigned long)us;
}
/**
* Translate microseconds to timer tics
*/
unsigned long us_to_tics(unsigned long const us)
{
float const tics = us * tics_per_us();
return (unsigned long)tics;
}
/**
* Sample the timer counter and according wrapped status
*/
unsigned long value(bool & wrapped)
{
Tcrr::access_t const v = _value();
wrapped = (bool)read<Irqstatus::Ovf_it_flag>();
return wrapped ? _value() : v;
}
};
}
/**
* Basic driver behind platform timer
*/
class Platform_timer_base : public Genode::Io_mem_connection,
public Genode::Omap4_gp_timer_1
{
/* FIXME these should be located in a omap4-defs file */
enum {
GP_TIMER_3_IRQ = 71,
GP_TIMER_3_MMIO_BASE = 0x48034000,
GP_TIMER_3_MMIO_SIZE = 0x00001000,
};
public:
enum { IRQ = GP_TIMER_3_IRQ };
/**
* Constructor
*/
Platform_timer_base() :
Io_mem_connection(GP_TIMER_3_MMIO_BASE, GP_TIMER_3_MMIO_SIZE),
Genode::Omap4_gp_timer_1((Genode::addr_t)Genode::env()->rm_session()->attach(dataspace()))
{ }
};
#endif /* _HW__OMAP4__PLATFORM_TIMER_BASE_H_ */

View File

@ -0,0 +1,23 @@
#
# \brief Timer session server
# \author Martin Stein
# \date 2012-05-03
#
# Set program name
TARGET = timer
# Add C++ sources
SRC_CC += main.cc
# Skip build if required specs not fullfilled
REQUIRES += hw omap4
# Add libraries
LIBS += cxx server env alarm
# Add include paths
INC_DIR += $(PRG_DIR) $(PRG_DIR)/../ $(PRG_DIR)/../../nova/
# Declare source paths
vpath main.cc $(PRG_DIR)/../..