summaryrefslogtreecommitdiffstats
path: root/c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2008-02-07 21:28:11 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2008-02-07 21:28:11 +0000
commitb62009c38ac9b3971bb0d9ec0dfa785b1f574167 (patch)
treef28fc04c1b706f0e9229429b977768e89a28b962 /c
parent2008-02-06 Joel Sherrill <joel.sherrill@oarcorp.com> (diff)
downloadrtems-b62009c38ac9b3971bb0d9ec0dfa785b1f574167.tar.bz2
2008-02-07 Joel Sherrill <joel.sherrill@oarcorp.com>
* clock/ckinit.c: Rework clock driver to use template and to provide nanoseconds since last tick capability.
Diffstat (limited to 'c')
-rw-r--r--c/src/lib/libbsp/i386/pc386/ChangeLog5
-rw-r--r--c/src/lib/libbsp/i386/pc386/clock/ckinit.c349
2 files changed, 140 insertions, 214 deletions
diff --git a/c/src/lib/libbsp/i386/pc386/ChangeLog b/c/src/lib/libbsp/i386/pc386/ChangeLog
index ce0257c2d2..78ba5e62e0 100644
--- a/c/src/lib/libbsp/i386/pc386/ChangeLog
+++ b/c/src/lib/libbsp/i386/pc386/ChangeLog
@@ -1,3 +1,8 @@
+2008-02-07 Joel Sherrill <joel.sherrill@oarcorp.com>
+
+ * clock/ckinit.c: Rework clock driver to use template and to provide
+ nanoseconds since last tick capability.
+
2007-12-11 Joel Sherrill <joel.sherrill@OARcorp.com>
* clock/ckinit.c, include/bsp.h, startup/bspstart.c: Eliminate copies
diff --git a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c
index 29a746a9d0..daee42d62b 100644
--- a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c
+++ b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c
@@ -1,237 +1,158 @@
-/*-------------------------------------------------------------------------+
-| ckinit.c v1.1 - PC386 BSP - 1997/08/07
-+--------------------------------------------------------------------------+
-| This file contains the PC386 clock package.
-+--------------------------------------------------------------------------+
-| (C) Copyright 1997 -
-| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
-|
-| http://pandora.ist.utl.pt
-|
-| Instituto Superior Tecnico * Lisboa * PORTUGAL
-+--------------------------------------------------------------------------+
-| Disclaimer:
-|
-| This file is provided "AS IS" without warranty of any kind, either
-| expressed or implied.
-+--------------------------------------------------------------------------+
-| This code is based on:
-| ckinit.c,v 1.4 1995/12/19 20:07:13 joel Exp - go32 BSP
-| With the following copyright notice:
-| **************************************************************************
-| * COPYRIGHT (c) 1989-1999.
-| * On-Line Applications Research Corporation (OAR).
-| *
-| * The license and distribution terms for this file may be
-| * found in found in the file LICENSE in this distribution or at
-| * http://www.rtems.com/license/LICENSE.
-| **************************************************************************
-|
-| $Id$
-+--------------------------------------------------------------------------*/
-
-#include <stdlib.h>
+/*
+ * Clock Tick Device Driver
+ *
+ * History:
+ * + Original driver was go32 clock by Joel Sherrill
+ * + go32 clock driver hardware code was inserted into new
+ * boilerplate when the pc386 BSP by:
+ * Pedro Miguel Da Cruz Neto Romano <pmcnr@camoes.rnl.ist.utl.pt>
+ * Jose Rufino <ruf@asterix.ist.utl.pt>
+ * + Reworked by Joel Sherrill to use clock driver template.
+ * This removes all boilerplate and leave original hardware
+ * code I developed for the go32 BSP.
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
#include <bsp.h>
#include <bsp/irq.h>
-#include <rtems/libio.h>
-
-/*-------------------------------------------------------------------------+
-| Macros
-+--------------------------------------------------------------------------*/
-#if 0
-/* This was dropped in the last revision. Its a nice thing to know. */
-#define TICKS_PER_SECOND() \
- (1000000 / (Clock_isrs_per_tick * microseconds_per_isr))
-#endif /* 0 */
-
-/*-------------------------------------------------------------------------+
-| Global Variables
-+--------------------------------------------------------------------------*/
-
-volatile uint32_t Clock_driver_ticks; /* Tick (interrupt) counter. */
- uint32_t Clock_isrs_per_tick; /* ISRs per tick. */
- uint32_t Clock_isrs; /* ISRs until next tick. */
-
-/* The following variables are set by the clock driver during its init */
-
-rtems_device_major_number rtems_clock_major = ~0;
-rtems_device_minor_number rtems_clock_minor;
-
-/*-------------------------------------------------------------------------+
-| Function: clockIsr
-| Description: Interrupt Service Routine for clock (0h) interruption.
-| Global Variables: Clock_driver_ticks, Clock_isrs.
-| Arguments: vector - standard RTEMS argument - see documentation.
-| Returns: standard return value - see documentation.
-+--------------------------------------------------------------------------*/
-static void clockIsr()
-{
- /*-------------------------------------------------------------------------+
- | PLEASE NOTE: The following is directly transcribed from the go32 BSP for
- | those who wish to use it with PENTIUM based machine. It needs
- | to be correctly integrated with the rest of the code!!!
- +--------------------------------------------------------------------------*/
-
-#if 0 && defined(pentium) /* more accurate clock for PENTIUMs (not supported) */
- {
- extern long long Last_RDTSC;
- __asm __volatile(".byte 0x0F, 0x31" : "=A" (Last_RDTSC));
- }
-#endif /* 0 && pentium */
-
- Clock_driver_ticks++;
-
- if ( Clock_isrs == 1 )
- {
- rtems_clock_tick();
- Clock_isrs = Clock_isrs_per_tick;
- }
- else
- Clock_isrs--;
-
-} /* clockIsr */
-
-/*-------------------------------------------------------------------------+
-| Function: Clock_exit
-| Description: Clock cleanup routine at RTEMS exit. NOTE: This routine is
-| not really necessary, since there will be a reset at exit.
-| Global Variables: None.
-| Arguments: None.
-| Returns: Nothing.
-+--------------------------------------------------------------------------*/
-void clockOff(const rtems_irq_connect_data* unused)
-{
- /* reset timer mode to standard (BIOS) value */
- outport_byte(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
- outport_byte(TIMER_CNTR0, 0);
- outport_byte(TIMER_CNTR0, 0);
-} /* Clock_exit */
+#include <bspopts.h>
-/*-------------------------------------------------------------------------+
-| Function: Install_clock
-| Description: Initialize and install clock interrupt handler.
-| Global Variables: None.
-| Arguments: None.
-| Returns: Nothing.
-+--------------------------------------------------------------------------*/
-static void clockOn(const rtems_irq_connect_data* unused)
-{
- uint32_t microseconds_per_isr;
+#define CLOCK_VECTOR 0
-#if 0
- /* Initialize clock from on-board real time clock. This breaks the */
- /* test code which assumes which assumes the application will do it. */
- {
- rtems_time_of_day now;
+volatile uint32_t pc386_microseconds_per_isr;
+volatile uint32_t pc386_isrs_per_tick;
+uint32_t pc386_clock_click_count;
- /* External Prototypes */
- extern void init_rtc(void); /* defined in 'rtc.c' */
- extern long rtc_read(rtems_time_of_day *); /* defined in 'rtc.c' */
- init_rtc();
- if (rtc_read(&now) >= 0)
- clock_set(&now);
- }
-#endif /* 0 */
-
- /* Start by assuming hardware counter is large enough, then scale it until
- it actually fits. */
-
- Clock_driver_ticks = 0;
- Clock_isrs_per_tick = 1;
-
- if (rtems_configuration_get_microseconds_per_tick() == 0)
- microseconds_per_isr = 10000; /* default 10 ms */
- else
- microseconds_per_isr = rtems_configuration_get_microseconds_per_tick();
- while (US_TO_TICK(microseconds_per_isr) > 65535)
- {
- Clock_isrs_per_tick *= 10;
- microseconds_per_isr /= 10;
- }
-
- Clock_isrs = Clock_isrs_per_tick; /* Initialize Clock_isrs */
+/* this driver may need to count ISRs per tick */
- {
- /* 105/88 approximates TIMER_TICK * 1e-6 */
- uint32_t count = US_TO_TICK(microseconds_per_isr);
+#define CLOCK_DRIVER_ISRS_PER_TICK pc386_isrs_per_tick
- outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
- outport_byte(TIMER_CNTR0, count >> 0 & 0xff);
- outport_byte(TIMER_CNTR0, count >> 8 & 0xff);
- }
+#define Clock_driver_support_at_tick()
-}
+#define Clock_driver_support_install_isr( _new, _old ) \
+ do { \
+ } while(0)
-int clockIsOn(const rtems_irq_connect_data* unused)
+uint32_t bsp_clock_nanoseconds_since_last_tick(void)
{
- return ((i8259s_cache & 0x1) == 0);
+ uint32_t usecs, clicks, isrs;
+ uint32_t usecs1, usecs2;
+ uint8_t lsb, msb;
+ extern volatile uint32_t Clock_driver_isrs;
+ rtems_interrupt_level level;
+
+ /*
+ * Fetch all the data in an interrupt critical section.
+ */
+ rtems_interrupt_disable(level);
+ outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
+ inport_byte(TIMER_CNTR0, lsb);
+ inport_byte(TIMER_CNTR0, msb);
+ isrs = Clock_driver_isrs;
+ rtems_interrupt_enable(level);
+
+ /*
+ * Now do the math
+ */
+ /* convert values read into counter clicks */
+ clicks = ((msb << 8) | lsb);
+
+ /* whole ISRs we have done since the last tick */
+ usecs1 = (pc386_isrs_per_tick - isrs - 1) * pc386_microseconds_per_isr;
+
+ /* the partial ISR we in the middle of now */
+ usecs2 = pc386_microseconds_per_isr - TICK_TO_US(clicks);
+
+ /* total microseconds */
+ usecs = usecs1 + usecs2;
+ #if 0
+ printk( "usecs1=%d usecs2=%d ", usecs1, usecs2 );
+ printk( "maxclicks=%d clicks=%d ISRs=%d ISRsper=%d usersPer=%d usecs=%d\n",
+ pc386_clock_click_count, clicks,
+ Clock_driver_isrs, pc386_isrs_per_tick,
+ pc386_microseconds_per_isr, usecs );
+ #endif
+
+ /* return it in nanoseconds */
+ return usecs * 1000;
}
-static rtems_irq_connect_data clockIrqData = {BSP_PERIODIC_TIMER,
- clockIsr,
- 0,
- clockOn,
- clockOff,
- clockIsOn};
-
-/*-------------------------------------------------------------------------+
-| Clock device driver INITIALIZE entry point.
-+--------------------------------------------------------------------------+
-| Initilizes the clock driver.
-+--------------------------------------------------------------------------*/
-rtems_device_driver
-Clock_initialize(rtems_device_major_number major,
- rtems_device_minor_number minor,
- void *pargp)
+#define Clock_driver_nanoseconds_since_last_tick \
+ bsp_clock_nanoseconds_since_last_tick
+
+static void clockOn(
+ const rtems_irq_connect_data* unused
+)
{
+ pc386_isrs_per_tick = 1;
+ pc386_microseconds_per_isr = rtems_configuration_get_microseconds_per_tick();
- if (!BSP_install_rtems_irq_handler (&clockIrqData)) {
- printk("Unable to initialize system clock\n");
- rtems_fatal_error_occurred(1);
+ while (US_TO_TICK(pc386_microseconds_per_isr) > 65535) {
+ pc386_isrs_per_tick *= 10;
+ pc386_microseconds_per_isr /= 10;
}
- /* make major/minor avail to others such as shared memory driver */
-
- rtems_clock_major = major;
- rtems_clock_minor = minor;
-
- return RTEMS_SUCCESSFUL;
-} /* Clock_initialize */
+ pc386_clock_click_count = US_TO_TICK(pc386_microseconds_per_isr);
+
+ #if 0
+ printk( "configured usecs per tick=%d \n",
+ rtems_configuration_get_microseconds_per_tick() );
+ printk( "Microseconds per ISR =%d\n", pc386_microseconds_per_isr );
+ printk( "final ISRs per=%d\n", pc386_isrs_per_tick );
+ printk( "final timer counts=%d\n", pc386_clock_click_count );
+ #endif
+
+ outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
+ outport_byte(TIMER_CNTR0, pc386_clock_click_count >> 0 & 0xff);
+ outport_byte(TIMER_CNTR0, pc386_clock_click_count >> 8 & 0xff);
+}
-/*-------------------------------------------------------------------------+
-| Console device driver CONTROL entry point
-+--------------------------------------------------------------------------*/
-rtems_device_driver
-Clock_control(rtems_device_major_number major,
- rtems_device_minor_number minor,
- void *pargp)
+void clockOff(const rtems_irq_connect_data* unused)
{
- if (pargp != NULL)
- {
- rtems_libio_ioctl_args_t *args = pargp;
-
- /*-------------------------------------------------------------------------+
- | This is hokey, but until we get a defined interface to do this, it will
- | just be this simple...
- +-------------------------------------------------------------------------*/
-
- if (args->command == rtems_build_name('I', 'S', 'R', ' '))
- clockIsr();
- else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
- {
- if (!BSP_install_rtems_irq_handler (&clockIrqData)) {
- printk("Error installing clock interrupt handler!\n");
- rtems_fatal_error_occurred(1);
- }
- }
- }
-
- return RTEMS_SUCCESSFUL;
-} /* Clock_control */
+ /* reset timer mode to standard (BIOS) value */
+ outport_byte(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
+ outport_byte(TIMER_CNTR0, 0);
+ outport_byte(TIMER_CNTR0, 0);
+} /* Clock_exit */
-void Clock_exit()
+int clockIsOn(const rtems_irq_connect_data* unused)
{
- BSP_remove_rtems_irq_handler (&clockIrqData);
+ return ((i8259s_cache & 0x1) == 0);
}
+/* a bit of a hack since the ISR models do not match */
+rtems_isr Clock_isr(
+ rtems_vector_number vector
+);
+static rtems_irq_connect_data clockIrqData = {
+ BSP_PERIODIC_TIMER,
+ (void *)Clock_isr,
+ 0,
+ clockOn,
+ clockOff,
+ clockIsOn
+};
+
+#define Clock_driver_support_initialize_hardware() \
+ do { \
+ if (!BSP_install_rtems_irq_handler (&clockIrqData)) { \
+ printk("Unable to initialize system clock\n"); \
+ rtems_fatal_error_occurred(1); \
+ } \
+ } while (0)
+
+#define Clock_driver_support_shutdown_hardware() \
+ do { \
+ BSP_remove_rtems_irq_handler (&clockIrqData); \
+ } while (0)
+
+#include "../../../shared/clockdrv_shell.c"
+