Changeset 31be416 in rtems for doc


Ignore:
Timestamp:
04/20/15 09:08:22 (9 years ago)
Author:
Alexander Krutwig <alexander.krutwig@…>
Branches:
4.11, 5, master
Children:
7cd2484
Parents:
cc693845
git-author:
Alexander Krutwig <alexander.krutwig@…> (04/20/15 09:08:22)
git-committer:
Sebastian Huber <sebastian.huber@…> (05/20/15 06:40:29)
Message:

timecounter: Port to RTEMS

New test sptests/timecounter01.

Update #2271.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • doc/bsp_howto/clock.t

    rcc693845 r31be416  
    88@section Introduction
    99
    10 The purpose of the clock driver is to provide a steady time
    11 basis to the kernel, so that the RTEMS primitives that need
    12 a clock tick work properly.  See the @code{Clock Manager} chapter
    13 of the @b{RTEMS Application C User's Guide} for more details.
    14 
    15 The clock driver is located in the @code{clock} directory of the BSP.
    16 
    17 @section Clock Driver Global Variables
    18 
    19 This section describes the global variables expected to be provided by
    20 this driver.
    21 
    22 @subsection Ticks Counter
    23 
    24 Most of the clock device drivers provide a global variable
    25 that is simply a count of the number of clock driver interrupt service
    26 routines that have occured.  This information is valuable when debugging
    27 a system.  This variable is declared as follows:
     10The purpose of the clock driver is to provide two services for the operating
     11system.
     12@itemize @bullet
     13@item A steady time basis to the kernel, so that the RTEMS primitives that need
     14a clock tick work properly.  See the @cite{Clock Manager} chapter of the
     15@cite{RTEMS Application C User's Guide} for more details.
     16@item An optional time counter to generate timestamps of the uptime and wall
     17clock time.
     18@end itemize
     19
     20The clock driver is usually located in the @file{clock} directory of the BSP.
     21Clock drivers should use the @dfn{Clock Driver Shell} available via the
     22@file{clockdrv_shell.h} include file.
     23
     24@section Clock Driver Shell
     25
     26The @dfn{Clock Driver Shell} include file defines the clock driver functions
     27declared in @code{#include <rtems/clockdrv.h>} which are used by RTEMS
     28configuration file @code{#include <rtems/confdefs.h>}.  In case the application
     29configuration defines @code{#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER},
     30then the clock driver is registered and should provide its services to the
     31operating system.  A hardware specific clock driver must provide some
     32functions, defines and macros for the @dfn{Clock Driver Shell} which are
     33explained here step by step.  A clock driver file looks in general like this.
     34
     35@example
     36/*
     37 * A section with functions, defines and macros to provide hardware specific
     38 * functions for the Clock Driver Shell.
     39 */
     40
     41#include "../../../shared/clockdrv_shell.h"
     42@end example
     43
     44@subsection Initialization
     45
     46Depending on the hardware capabilities one out of three clock driver variants
     47must be selected.
     48@itemize @bullet
     49@item The most basic clock driver provides only a periodic interrupt service
     50routine which calls @code{rtems_clock_tick()}.  The interval is determined by
     51the application configuration via @code{#define
     52CONFIGURE_MICROSECONDS_PER_TICK} and can be obtained via
     53@code{rtems_configuration_get_microseconds_per_tick()}.  The timestamp
     54resolution is limited to the clock tick interval.
     55@item In case the hardware lacks support for a free running counter, then the
     56module used for the clock tick may provide support for timestamps with a
     57resolution below the clock tick interval.  For this so called simple
     58timecounters can be used.
     59@item The desired variant uses a free running counter to provide accurate
     60timestamps.  This variant is mandatory on SMP configurations.
     61@end itemize
     62
     63@subsubsection Clock Tick Only Variant
     64
     65@example
     66static void some_support_initialize_hardware( void )
     67@{
     68  /* Initialize hardware */
     69@}
     70
     71#define Clock_driver_support_initialize_hardware() \
     72  some_support_initialize_hardware()
     73
     74/* Indicate that this clock driver lacks a proper timecounter in hardware */
     75#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
     76
     77#include "../../../shared/clockdrv_shell.h"
     78@end example
     79
     80@subsubsection Simple Timecounter Variant
     81
     82@example
     83#include <rtems/timecounter.h>
     84
     85static rtems_timecounter_simple some_tc;
     86
     87static uint32_t some_tc_get( rtems_timecounter_simple *tc )
     88@{
     89  return some.counter;
     90@}
     91
     92static bool some_tc_is_pending( rtems_timecounter_simple *tc )
     93@{
     94  return some.is_pending;
     95@}
     96
     97static uint32_t some_tc_get_timecount( struct timecounter *tc )
     98@{
     99  return rtems_timecounter_simple_downcounter_get(
     100    tc,
     101    some_tc_get,
     102    some_tc_is_pending
     103  );
     104@}
     105
     106static void some_tc_tick( void )
     107@{
     108  rtems_timecounter_simple_downcounter_tick( &some_tc, some_tc_get );
     109@}
     110
     111static void some_support_initialize_hardware( void )
     112@{
     113  uint32_t frequency = 123456;
     114  uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
     115  uint32_t timecounter_ticks_per_clock_tick =
     116    ( frequency * us_per_tick ) / 1000000;
     117
     118  /* Initialize hardware */
     119
     120  rtems_timecounter_simple_install(
     121    &some_tc,
     122    frequency,
     123    timecounter_ticks_per_clock_tick,
     124    some_tc_get_timecount
     125  );
     126@}
     127
     128#define Clock_driver_support_initialize_hardware() \
     129  some_support_initialize_hardware()
     130
     131#define Clock_driver_timecounter_tick() \
     132  some_tc_tick()
     133
     134#include "../../../shared/clockdrv_shell.h"
     135@end example
     136
     137@subsubsection Timecounter Variant
     138
     139This variant is preferred since it is the most efficient and yields the most
     140accurate timestamps.  It is also mandatory on SMP configurations to obtain
     141valid timestamps.  The hardware must provide a periodic interrupt to service
     142the clock tick and a free running counter for the timecounter.  The free
     143running counter must have a power of two period.  The @code{tc_counter_mask}
     144must be initialized to the free running counter period minus one, e.g. for a
     14532-bit counter this is 0xffffffff.  The @code{tc_get_timecount} function must
     146return the current counter value (the counter values must increase, so if the
     147counter counts down, a conversion is necessary).  Use
     148@code{RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER} for the @code{tc_quality}.  Set
     149@code{tc_frequency} to the frequency of the free running counter in Hz.  All
     150other fields of the @code{struct timecounter} must be zero initialized.
     151Install the initialized timecounter via @code{rtems_timecounter_install()}.
     152
     153@example
     154#include <rtems/timecounter.h>
     155
     156static struct timecounter some_tc;
     157
     158static uint32_t some_tc_get_timecount( struct timecounter *tc )
     159@{
     160  some.free_running_counter;
     161@}
     162
     163static void some_support_initialize_hardware( void )
     164@{
     165  uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
     166  uint32_t frequency = 123456;
     167
     168  /*
     169   * The multiplication must be done in 64-bit arithmetic to avoid an integer
     170   * overflow on targets with a high enough counter frequency.
     171   */
     172  uint32_t interval = (uint32_t) ( ( frequency * us_per_tick ) / 1000000 );
     173
     174  /*
     175   * Initialize hardware and set up a periodic interrupt for the configuration
     176   * based interval.
     177   */
     178
     179  some_tc.tc_get_timecount = some_tc_get_timecount;
     180  some_tc.tc_counter_mask = 0xffffffff;
     181  some_tc.tc_frequency = frequency;
     182  some_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
     183  rtems_timecounter_install( &some_tc );
     184@}
     185
     186#define Clock_driver_support_initialize_hardware() \
     187  some_support_initialize_hardware()
     188
     189#include "../../../shared/clockdrv_shell.h"
     190@end example
     191
     192@subsection Install Clock Tick Interrupt Service Routine
     193
     194The clock driver must provide a function to install the clock tick interrupt
     195service routine via @code{Clock_driver_support_install_isr()}.
     196
     197@example
     198#include <bsp/irq.h>
     199#include <bsp/fatal.h>
     200
     201static void some_support_install_isr( rtems_interrupt_handler isr )
     202@{
     203  rtems_status_code sc;
     204
     205  sc = rtems_interrupt_handler_install(
     206    SOME_IRQ,
     207    "Clock",
     208    RTEMS_INTERRUPT_UNIQUE,
     209    isr,
     210    NULL
     211  );
     212  if ( sc != RTEMS_SUCCESSFUL ) @{
     213    bsp_fatal( SOME_FATAL_IRQ_INSTALL );
     214  @}
     215@}
     216
     217#define Clock_driver_support_install_isr( isr, old ) \
     218  some_support_install_isr( isr )
     219
     220#include "../../../shared/clockdrv_shell.h"
     221@end example
     222
     223@subsection Support At Tick
     224
     225The hardware specific support at tick is specified by
     226@code{Clock_driver_support_at_tick()}.
     227
     228@example
     229static void some_support_at_tick( void )
     230@{
     231  /* Clear interrupt */
     232@}
     233
     234#define Clock_driver_support_at_tick() \
     235  some_support_at_tick()
     236
     237#include "../../../shared/clockdrv_shell.h"
     238@end example
     239
     240@subsection System Shutdown Support
     241
     242The @dfn{Clock Driver Shell} provides the routine @code{Clock_exit()} that is
     243scheduled to be run during system shutdown via the @code{atexit()} routine.
     244The hardware specific shutdown support is specified by
     245@code{Clock_driver_support_shutdown_hardware()} which is used by
     246@code{Clock_exit()}.  It should disable the clock tick source if it was
     247enabled.  This can be used to prevent clock ticks after the system is shutdown.
     248
     249@example
     250static void some_support_shutdown_hardware( void )
     251@{
     252  /* Shutdown hardware */
     253@}
     254
     255#define Clock_driver_support_shutdown_hardware() \
     256  some_support_shutdown_hardware()
     257
     258#include "../../../shared/clockdrv_shell.h"
     259@end example
     260
     261@subsection Multiple Clock Driver Ticks Per Clock Tick
     262
     263In case the hardware needs more than one clock driver tick per clock tick (e.g.
     264due to a limited range of the hardware timer), then this can be specified with
     265the optional @code{#define CLOCK_DRIVER_ISRS_PER_TICK} and @code{#define
     266CLOCK_DRIVER_ISRS_PER_TICK_VALUE} defines.  This is currently used only for x86
     267and it hopefully remains that way.
     268
     269@example
     270/* Enable multiple clock driver ticks per clock tick */
     271#define CLOCK_DRIVER_ISRS_PER_TICK 1
     272
     273/* Specifiy the clock driver ticks per clock tick value */
     274#define CLOCK_DRIVER_ISRS_PER_TICK_VALUE 123
     275
     276#include "../../../shared/clockdrv_shell.h"
     277@end example
     278
     279@subsection Clock Driver Ticks Counter
     280
     281The @dfn{Clock Driver Shell} provide a global variable that is simply a count
     282of the number of clock driver interrupt service routines that have occurred.
     283This information is valuable when debugging a system.  This variable is
     284declared as follows:
    28285
    29286@example
    30287volatile uint32_t Clock_driver_ticks;
    31288@end example
    32 
    33 @section Initialization
    34 
    35 The initialization routine is responsible for
    36 programming the hardware that will periodically
    37 generate an interrupt.  A programmable interval timer is commonly
    38 used as the source of the clock tick.
    39 
    40 The device should be programmed such that an interrupt is generated
    41 every @i{m} microseconds, where @i{m} is equal to
    42 @code{rtems_configuration_get_microseconds_per_tick()}. Sometimes
    43 the periodic interval timer can use a prescaler so you have to look
    44 carefully at your user's manual to determine the correct value.
    45 
    46 You must use the RTEMS primitive @code{rtems_interrupt_catch} to install
    47 your clock interrupt service routine:
    48 
    49 @example
    50 rtems_interrupt_catch (Clock_ISR, CLOCK_VECTOR, &old_handler);
    51 @end example
    52 
    53 Since there is currently not a driver entry point invoked at system
    54 shutdown, many clock device drivers use the @code{atexit} routine
    55 to schedule their @code{Clock_exit} routine to execute when the
    56 system is shutdown.
    57 
    58 By convention, many of the clock drivers do not install the clock
    59 tick if the @code{ticks_per_timeslice} field of the Configuration
    60 Table is 0.
    61 
    62 @section System shutdown
    63 
    64 Many drivers provide the routine @code{Clock_exit} that is scheduled
    65 to be run during system shutdown via the @code{atexit} routine.
    66 The @code{Clock_exit} routine will disable the clock tick source
    67 if it was enabled.  This can be used to prevent clock ticks after the
    68 system is shutdown.
    69 
    70 @section Clock Interrupt Subroutine
    71 
    72 It only has to inform the kernel that a ticker has elapsed, so call :
    73 
    74 @example
    75 @group
    76 rtems_isr Clock_isr( rtems_vector_number vector )
    77 @{
    78   invoke the rtems_clock_tick() directive to announce the tick
    79   if necessary for this hardware
    80     reload the programmable timer
    81 @}
    82 @end group
    83 @end example
    84 
    85 @section IO Control
    86 
    87 Prior to RTEMS 4.9, the Shared Memory MPCI Driver required a special
    88 IOCTL in the Clock Driver.  This is no longer required and the Clock
    89 Driver does not have to provide an IOCTL method at all.
    90 
Note: See TracChangeset for help on using the changeset viewer.