Changeset b62009c3 in rtems


Ignore:
Timestamp:
Feb 7, 2008, 9:28:11 PM (12 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.9, master
Children:
761bfaa
Parents:
78b4e2e
Message:

2008-02-07 Joel Sherrill <joel.sherrill@…>

  • clock/ckinit.c: Rework clock driver to use template and to provide nanoseconds since last tick capability.
Location:
c/src/lib/libbsp/i386/pc386
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/i386/pc386/ChangeLog

    r78b4e2e rb62009c3  
     12008-02-07      Joel Sherrill <joel.sherrill@oarcorp.com>
     2
     3        * clock/ckinit.c: Rework clock driver to use template and to provide
     4        nanoseconds since last tick capability.
     5
    162007-12-11      Joel Sherrill <joel.sherrill@OARcorp.com>
    27
  • c/src/lib/libbsp/i386/pc386/clock/ckinit.c

    r78b4e2e rb62009c3  
    1 /*-------------------------------------------------------------------------+
    2 | ckinit.c v1.1 - PC386 BSP - 1997/08/07
    3 +--------------------------------------------------------------------------+
    4 | This file contains the PC386 clock package.
    5 +--------------------------------------------------------------------------+
    6 | (C) Copyright 1997 -
    7 | - NavIST Group - Real-Time Distributed Systems and Industrial Automation
    8 |
    9 | http://pandora.ist.utl.pt
    10 |
    11 | Instituto Superior Tecnico * Lisboa * PORTUGAL
    12 +--------------------------------------------------------------------------+
    13 | Disclaimer:
    14 |
    15 | This file is provided "AS IS" without warranty of any kind, either
    16 | expressed or implied.
    17 +--------------------------------------------------------------------------+
    18 | This code is based on:
    19 |   ckinit.c,v 1.4 1995/12/19 20:07:13 joel Exp - go32 BSP
    20 | With the following copyright notice:
    21 | **************************************************************************
    22 | *  COPYRIGHT (c) 1989-1999.
    23 | *  On-Line Applications Research Corporation (OAR).
    24 | *
    25 | *  The license and distribution terms for this file may be
    26 | *  found in found in the file LICENSE in this distribution or at
    27 | *  http://www.rtems.com/license/LICENSE.
    28 | **************************************************************************
    29 |
    30 |  $Id$
    31 +--------------------------------------------------------------------------*/
    32 
    33 #include <stdlib.h>
     1/*
     2 *  Clock Tick Device Driver
     3 *
     4 *  History:
     5 *    + Original driver was go32 clock by Joel Sherrill
     6 *    + go32 clock driver hardware code was inserted into new
     7 *      boilerplate when the pc386 BSP by:
     8 *        Pedro Miguel Da Cruz Neto Romano <pmcnr@camoes.rnl.ist.utl.pt>
     9 *        Jose Rufino <ruf@asterix.ist.utl.pt>
     10 *    + Reworked by Joel Sherrill to use clock driver template.
     11 *      This removes all boilerplate and leave original hardware
     12 *      code I developed for the go32 BSP.
     13 *
     14 *  COPYRIGHT (c) 1989-2008.
     15 *  On-Line Applications Research Corporation (OAR).
     16 *
     17 *  The license and distribution terms for this file may be
     18 *  found in the file LICENSE in this distribution or at
     19 *  http://www.rtems.com/license/LICENSE.
     20 *
     21 *  $Id$
     22 */
    3423
    3524#include <bsp.h>
    3625#include <bsp/irq.h>
    37 #include <rtems/libio.h>
     26#include <bspopts.h>
    3827
    39 /*-------------------------------------------------------------------------+
    40 | Macros
    41 +--------------------------------------------------------------------------*/
    42 #if 0
    43 /* This was dropped in the last revision.  Its a nice thing to know. */
    44 #define TICKS_PER_SECOND() \
    45           (1000000 / (Clock_isrs_per_tick * microseconds_per_isr))
    46 #endif /* 0 */
     28#define CLOCK_VECTOR 0
    4729
    48 /*-------------------------------------------------------------------------+
    49 | Global Variables
    50 +--------------------------------------------------------------------------*/
     30volatile uint32_t pc386_microseconds_per_isr;
     31volatile uint32_t pc386_isrs_per_tick;
     32uint32_t pc386_clock_click_count;
    5133
    52 volatile uint32_t         Clock_driver_ticks;   /* Tick (interrupt) counter. */
    53          uint32_t         Clock_isrs_per_tick;  /* ISRs per tick.            */
    54          uint32_t         Clock_isrs;           /* ISRs until next tick.     */
    5534
    56 /* The following variables are set by the clock driver during its init */
     35/* this driver may need to count ISRs per tick */
    5736
    58 rtems_device_major_number rtems_clock_major = ~0;
    59 rtems_device_minor_number rtems_clock_minor;
     37#define CLOCK_DRIVER_ISRS_PER_TICK pc386_isrs_per_tick
    6038
    61 /*-------------------------------------------------------------------------+
    62 |         Function: clockIsr
    63 |      Description: Interrupt Service Routine for clock (0h) interruption.
    64 | Global Variables: Clock_driver_ticks, Clock_isrs.
    65 |        Arguments: vector - standard RTEMS argument - see documentation.
    66 |          Returns: standard return value - see documentation.
    67 +--------------------------------------------------------------------------*/
    68 static void clockIsr()
     39#define Clock_driver_support_at_tick()
     40
     41#define Clock_driver_support_install_isr( _new, _old ) \
     42  do { \
     43  } while(0)
     44
     45uint32_t bsp_clock_nanoseconds_since_last_tick(void)
    6946{
    70   /*-------------------------------------------------------------------------+
    71   | PLEASE NOTE: The following is directly transcribed from the go32 BSP for
    72   |              those who wish to use it with PENTIUM based machine. It needs
    73   |              to be correctly integrated with the rest of the code!!!
    74   +--------------------------------------------------------------------------*/
     47  uint32_t                 usecs, clicks, isrs;
     48  uint32_t                 usecs1, usecs2;
     49  uint8_t                  lsb, msb;
     50  extern volatile uint32_t Clock_driver_isrs;
     51  rtems_interrupt_level    level;
    7552
    76 #if 0 && defined(pentium) /* more accurate clock for PENTIUMs (not supported) */
    77   {
    78     extern long long Last_RDTSC;
    79     __asm __volatile(".byte 0x0F, 0x31" : "=A" (Last_RDTSC));
     53  /*
     54   * Fetch all the data in an interrupt critical section.
     55   */
     56  rtems_interrupt_disable(level);
     57    outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
     58    inport_byte(TIMER_CNTR0, lsb);
     59    inport_byte(TIMER_CNTR0, msb);
     60    isrs = Clock_driver_isrs;
     61  rtems_interrupt_enable(level);
     62
     63  /*
     64   *  Now do the math
     65   */
     66  /* convert values read into counter clicks */
     67  clicks = ((msb << 8) | lsb);
     68
     69  /* whole ISRs we have done since the last tick */
     70  usecs1 = (pc386_isrs_per_tick - isrs - 1) * pc386_microseconds_per_isr;
     71
     72  /* the partial ISR we in the middle of now */
     73  usecs2 = pc386_microseconds_per_isr - TICK_TO_US(clicks);
     74
     75  /* total microseconds */
     76  usecs = usecs1 + usecs2;
     77  #if 0
     78    printk( "usecs1=%d usecs2=%d ", usecs1, usecs2 );
     79    printk( "maxclicks=%d clicks=%d ISRs=%d ISRsper=%d usersPer=%d usecs=%d\n",
     80    pc386_clock_click_count, clicks,
     81    Clock_driver_isrs, pc386_isrs_per_tick,
     82    pc386_microseconds_per_isr, usecs );
     83  #endif
     84
     85  /* return it in nanoseconds */
     86  return usecs * 1000;
     87}
     88
     89#define Clock_driver_nanoseconds_since_last_tick \
     90  bsp_clock_nanoseconds_since_last_tick
     91
     92static void clockOn(
     93  const rtems_irq_connect_data* unused
     94)
     95{
     96  pc386_isrs_per_tick        = 1;
     97  pc386_microseconds_per_isr = rtems_configuration_get_microseconds_per_tick();
     98
     99  while (US_TO_TICK(pc386_microseconds_per_isr) > 65535) {
     100    pc386_isrs_per_tick  *= 10;
     101    pc386_microseconds_per_isr /= 10;
    80102  }
    81 #endif /* 0 && pentium */
     103  pc386_clock_click_count = US_TO_TICK(pc386_microseconds_per_isr);
    82104
    83   Clock_driver_ticks++;
     105  #if 0
     106    printk( "configured usecs per tick=%d \n",
     107      rtems_configuration_get_microseconds_per_tick() );
     108    printk( "Microseconds per ISR =%d\n", pc386_microseconds_per_isr );
     109    printk( "final ISRs per=%d\n", pc386_isrs_per_tick );
     110    printk( "final timer counts=%d\n", pc386_clock_click_count );
     111  #endif
    84112
    85   if ( Clock_isrs == 1 )
    86   {
    87     rtems_clock_tick();
    88     Clock_isrs = Clock_isrs_per_tick;
    89   }
    90   else
    91     Clock_isrs--;
     113  outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
     114  outport_byte(TIMER_CNTR0, pc386_clock_click_count >> 0 & 0xff);
     115  outport_byte(TIMER_CNTR0, pc386_clock_click_count >> 8 & 0xff);
     116}
    92117
    93 } /* clockIsr */
    94 
    95 /*-------------------------------------------------------------------------+
    96 |         Function: Clock_exit
    97 |      Description: Clock cleanup routine at RTEMS exit. NOTE: This routine is
    98 |                   not really necessary, since there will be a reset at exit.
    99 | Global Variables: None.
    100 |        Arguments: None.
    101 |          Returns: Nothing.
    102 +--------------------------------------------------------------------------*/
    103118void clockOff(const rtems_irq_connect_data* unused)
    104119{
     
    109124} /* Clock_exit */
    110125
    111 /*-------------------------------------------------------------------------+
    112 |         Function: Install_clock
    113 |      Description: Initialize and install clock interrupt handler.
    114 | Global Variables: None.
    115 |        Arguments: None.
    116 |          Returns: Nothing.
    117 +--------------------------------------------------------------------------*/
    118 static void clockOn(const rtems_irq_connect_data* unused)
    119 {
    120   uint32_t          microseconds_per_isr;
    121 
    122 #if 0
    123   /* Initialize clock from on-board real time clock.  This breaks the  */
    124   /* test code which assumes which assumes the application will do it. */
    125   {
    126     rtems_time_of_day now;
    127 
    128     /* External Prototypes */
    129     extern void init_rtc(void);                /* defined in 'rtc.c' */
    130     extern long rtc_read(rtems_time_of_day *); /* defined in 'rtc.c' */
    131 
    132     init_rtc();
    133     if (rtc_read(&now) >= 0)
    134       clock_set(&now);
    135   }
    136 #endif /* 0 */
    137 
    138   /* Start by assuming hardware counter is large enough, then  scale it until
    139      it actually fits. */
    140 
    141   Clock_driver_ticks  = 0;
    142   Clock_isrs_per_tick = 1;
    143 
    144   if (rtems_configuration_get_microseconds_per_tick() == 0)
    145     microseconds_per_isr = 10000; /* default 10 ms */
    146   else
    147     microseconds_per_isr = rtems_configuration_get_microseconds_per_tick();
    148   while (US_TO_TICK(microseconds_per_isr) > 65535)
    149   {
    150     Clock_isrs_per_tick  *= 10;
    151     microseconds_per_isr /= 10;
    152   }
    153 
    154   Clock_isrs = Clock_isrs_per_tick; /* Initialize Clock_isrs */
    155 
    156   {
    157     /* 105/88 approximates TIMER_TICK * 1e-6 */
    158     uint32_t         count = US_TO_TICK(microseconds_per_isr);
    159 
    160     outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
    161     outport_byte(TIMER_CNTR0, count >> 0 & 0xff);
    162     outport_byte(TIMER_CNTR0, count >> 8 & 0xff);
    163   }
    164 
    165 }
    166 
    167126int clockIsOn(const rtems_irq_connect_data* unused)
    168127{
     
    170129}
    171130
    172 static rtems_irq_connect_data clockIrqData = {BSP_PERIODIC_TIMER,
    173                                               clockIsr,
    174                                               0,
    175                                               clockOn,
    176                                               clockOff,
    177                                               clockIsOn};
     131/* a bit of a hack since the ISR models do not match */
     132rtems_isr Clock_isr(
     133  rtems_vector_number vector
     134);
     135static rtems_irq_connect_data clockIrqData = {
     136  BSP_PERIODIC_TIMER,
     137  (void *)Clock_isr,
     138  0,
     139  clockOn,
     140  clockOff,
     141  clockIsOn
     142};
    178143
    179 /*-------------------------------------------------------------------------+
    180 | Clock device driver INITIALIZE entry point.
    181 +--------------------------------------------------------------------------+
    182 | Initilizes the clock driver.
    183 +--------------------------------------------------------------------------*/
    184 rtems_device_driver
    185 Clock_initialize(rtems_device_major_number major,
    186                  rtems_device_minor_number minor,
    187                  void                      *pargp)
    188 {
     144#define Clock_driver_support_initialize_hardware() \
     145  do { \
     146    if (!BSP_install_rtems_irq_handler (&clockIrqData)) { \
     147      printk("Unable to initialize system clock\n"); \
     148      rtems_fatal_error_occurred(1); \
     149    } \
     150  } while (0)
    189151
    190   if (!BSP_install_rtems_irq_handler (&clockIrqData)) {
    191     printk("Unable to initialize system clock\n");
    192     rtems_fatal_error_occurred(1);
    193   }
    194   /* make major/minor avail to others such as shared memory driver */
     152#define Clock_driver_support_shutdown_hardware() \
     153  do { \
     154    BSP_remove_rtems_irq_handler (&clockIrqData); \
     155  } while (0)
    195156
    196   rtems_clock_major = major;
    197   rtems_clock_minor = minor;
     157#include "../../../shared/clockdrv_shell.c"
    198158
    199   return RTEMS_SUCCESSFUL;
    200 } /* Clock_initialize */
    201 
    202 /*-------------------------------------------------------------------------+
    203 | Console device driver CONTROL entry point
    204 +--------------------------------------------------------------------------*/
    205 rtems_device_driver
    206 Clock_control(rtems_device_major_number major,
    207               rtems_device_minor_number minor,
    208               void                      *pargp)
    209 {
    210   if (pargp != NULL)
    211   {
    212     rtems_libio_ioctl_args_t *args = pargp;
    213 
    214     /*-------------------------------------------------------------------------+
    215     | This is hokey, but until we get a defined interface to do this, it will
    216     | just be this simple...
    217     +-------------------------------------------------------------------------*/
    218 
    219     if      (args->command == rtems_build_name('I', 'S', 'R', ' '))
    220       clockIsr();
    221     else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
    222     {
    223       if (!BSP_install_rtems_irq_handler (&clockIrqData)) {
    224         printk("Error installing clock interrupt handler!\n");
    225         rtems_fatal_error_occurred(1);
    226       }
    227     }
    228   }
    229 
    230   return RTEMS_SUCCESSFUL;
    231 } /* Clock_control */
    232 
    233 void Clock_exit()
    234 {
    235   BSP_remove_rtems_irq_handler (&clockIrqData);
    236 }
    237 
Note: See TracChangeset for help on using the changeset viewer.