From 612735732aa70884aca72d664cdb7c0be5dfaa12 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Wed, 24 Oct 2012 15:49:53 +0200 Subject: [PATCH] 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'. --- base-hw/src/core/kernel.cc | 4 +- .../include/platform/panda_a2/drivers/board.h | 2 + base/mk/spec-platform_panda_a2.mk | 3 +- os/include/drivers/timer/sp804_base.h | 4 +- .../timer/hw/omap4/platform_timer_base.h | 270 ++++++++++++++++++ os/src/drivers/timer/hw/omap4/target.mk | 23 ++ 6 files changed, 301 insertions(+), 5 deletions(-) create mode 100644 os/src/drivers/timer/hw/omap4/platform_timer_base.h create mode 100755 os/src/drivers/timer/hw/omap4/target.mk diff --git a/base-hw/src/core/kernel.cc b/base-hw/src/core/kernel.cc index 6276cbaf99..0d702e6aae 100644 --- a/base-hw/src/core/kernel.cc +++ b/base-hw/src/core/kernel.cc @@ -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(); } }; diff --git a/base/include/platform/panda_a2/drivers/board.h b/base/include/platform/panda_a2/drivers/board.h index 6f2fe11f44..ecb6a67a4c 100644 --- a/base/include/platform/panda_a2/drivers/board.h +++ b/base/include/platform/panda_a2/drivers/board.h @@ -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, }; }; } diff --git a/base/mk/spec-platform_panda_a2.mk b/base/mk/spec-platform_panda_a2.mk index dab5d2c913..2ea29ffc4a 100644 --- a/base/mk/spec-platform_panda_a2.mk +++ b/base/mk/spec-platform_panda_a2.mk @@ -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) diff --git a/os/include/drivers/timer/sp804_base.h b/os/include/drivers/timer/sp804_base.h index 1cff29b175..80f4519953 100644 --- a/os/include/drivers/timer/sp804_base.h +++ b/os/include/drivers/timer/sp804_base.h @@ -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 diff --git a/os/src/drivers/timer/hw/omap4/platform_timer_base.h b/os/src/drivers/timer/hw/omap4/platform_timer_base.h new file mode 100644 index 0000000000..614061250f --- /dev/null +++ b/os/src/drivers/timer/hw/omap4/platform_timer_base.h @@ -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 +#include +#include +#include + +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(0); } + + /** + * Unfreeze timer counter + */ + void _unfreeze() { write(1); } + + /** + * Get remaining counting amount + */ + unsigned long _value() { return max_value() - read(); } + + /** + * Apply counting amount + */ + void _value(unsigned long const v) { write(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(1); + while (read()) ; + + /* configure Idle mode */ + write(Tiocp_cfg::Idlemode::FORCE_IDLE); + + /* enable wake-up interrupt events */ + write(Twer::init_timer()); + + /* select posted mode */ + write(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::init_run_and_wrap()); + write(1); + + /* install value */ + _value(value); + write(0); + + /* start timer */ + _unfreeze(); + } + + /** + * Clear interrupt output + */ + void clear_interrupt() { + write(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(); + 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_ */ + diff --git a/os/src/drivers/timer/hw/omap4/target.mk b/os/src/drivers/timer/hw/omap4/target.mk new file mode 100755 index 0000000000..23fab1bf51 --- /dev/null +++ b/os/src/drivers/timer/hw/omap4/target.mk @@ -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)/../..