diff options
Diffstat (limited to 'bsp_howto/clock.rst')
-rw-r--r-- | bsp_howto/clock.rst | 297 |
1 files changed, 0 insertions, 297 deletions
diff --git a/bsp_howto/clock.rst b/bsp_howto/clock.rst deleted file mode 100644 index 38b6d62..0000000 --- a/bsp_howto/clock.rst +++ /dev/null @@ -1,297 +0,0 @@ -.. comment SPDX-License-Identifier: CC-BY-SA-4.0 - -.. COMMENT: COPYRIGHT (c) 1988-2002. -.. COMMENT: On-Line Applications Research Corporation (OAR). -.. COMMENT: All rights reserved. - -Clock Driver -############ - -Introduction -============ - -The purpose of the clock driver is to provide two services for the operating -system. - -- A steady time basis to the kernel, so that the RTEMS primitives that need a - clock tick work properly. See the *Clock Manager* chapter of the *RTEMS - Application C User's Guide* for more details. - -- An optional time counter to generate timestamps of the uptime and wall clock - time. - -The clock driver is usually located in the :file:`clock` directory of the BSP. -Clock drivers should use the :dfn:`Clock Driver Shell` available via the -:file:`clockdrv_shell.h` include file. - -Clock Driver Shell -================== - -The :dfn:`Clock Driver Shell` include file defines the clock driver functions -declared in ``#include <rtems/clockdrv.h>`` which are used by RTEMS -configuration file ``#include <rtems/confdefs.h>``. In case the application -configuration defines ``#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER``, -then the clock driver is registered and should provide its services to the -operating system. A hardware specific clock driver must provide some -functions, defines and macros for the :dfn:`Clock Driver Shell` which are -explained here step by step. A clock driver file looks in general like this. - -.. code-block:: c - - /* - * A section with functions, defines and macros to provide hardware specific - * functions for the Clock Driver Shell. - */ - #include "../../../shared/clockdrv_shell.h" - -Initialization --------------- - -Depending on the hardware capabilities one out of three clock driver variants -must be selected. - -- The most basic clock driver provides only a periodic interrupt service - routine which calls ``rtems_clock_tick()``. The interval is determined by - the application configuration via ``#define CONFIGURE_MICROSECONDS_PER_TICK`` - and can be obtained via ``rtems_configuration_get_microseconds_per_tick()``. - The timestamp resolution is limited to the clock tick interval. - -- In case the hardware lacks support for a free running counter, then the - module used for the clock tick may provide support for timestamps with a - resolution below the clock tick interval. For this so called simple - timecounters can be used. - -- The desired variant uses a free running counter to provide accurate - timestamps. This variant is mandatory on SMP configurations. - -Clock Tick Only Variant -~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: c - - static void some_support_initialize_hardware( void ) - { - /* Initialize hardware */ - } - - #define Clock_driver_support_initialize_hardware() \ - some_support_initialize_hardware() - - /* Indicate that this clock driver lacks a proper timecounter in hardware */ - - #define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER - - #include "../../../shared/clockdrv_shell.h" - -Simple Timecounter Variant -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: c - - #include <rtems/timecounter.h> - - static rtems_timecounter_simple some_tc; - - static uint32_t some_tc_get( rtems_timecounter_simple *tc ) - { - return some.counter; - } - - static bool some_tc_is_pending( rtems_timecounter_simple *tc ) - { - return some.is_pending; - } - - static uint32_t some_tc_get_timecount( struct timecounter *tc ) - { - return rtems_timecounter_simple_downcounter_get( - tc, - some_tc_get, - some_tc_is_pending - ); - } - - static void some_tc_tick( void ) - { - rtems_timecounter_simple_downcounter_tick( &some_tc, some_tc_get ); - } - - static void some_support_initialize_hardware( void ) - { - uint32_t frequency = 123456; - uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); - uint32_t timecounter_ticks_per_clock_tick = - ( frequency * us_per_tick ) / 1000000; - - /* Initialize hardware */ - rtems_timecounter_simple_install( - &some_tc, - frequency, - timecounter_ticks_per_clock_tick, - some_tc_get_timecount - ); - } - - #define Clock_driver_support_initialize_hardware() \ - some_support_initialize_hardware() - #define Clock_driver_timecounter_tick() \ - some_tc_tick() - - #include "../../../shared/clockdrv_shell.h" - -Timecounter Variant -~~~~~~~~~~~~~~~~~~~ - -This variant is preferred since it is the most efficient and yields the most -accurate timestamps. It is also mandatory on SMP configurations to obtain -valid timestamps. The hardware must provide a periodic interrupt to service -the clock tick and a free running counter for the timecounter. The free -running counter must have a power of two period. The ``tc_counter_mask`` must -be initialized to the free running counter period minus one, e.g. for a 32-bit -counter this is 0xffffffff. The ``tc_get_timecount`` function must return the -current counter value (the counter values must increase, so if the counter -counts down, a conversion is necessary). Use -``RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER`` for the ``tc_quality``. Set -``tc_frequency`` to the frequency of the free running counter in Hz. All other -fields of the ``struct timecounter`` must be zero initialized. Install the -initialized timecounter via ``rtems_timecounter_install()``. - -.. code-block:: c - - #include <rtems/timecounter.h> - - static struct timecounter some_tc; - - static uint32_t some_tc_get_timecount( struct timecounter *tc ) - { - some.free_running_counter; - } - - static void some_support_initialize_hardware( void ) - { - uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); - uint32_t frequency = 123456; - - /* - * The multiplication must be done in 64-bit arithmetic to avoid an integer - * overflow on targets with a high enough counter frequency. - */ - uint32_t interval = (uint32_t) ( ( frequency * us_per_tick ) / 1000000 ); - - /* - * Initialize hardware and set up a periodic interrupt for the configuration - * based interval. - */ - some_tc.tc_get_timecount = some_tc_get_timecount; - some_tc.tc_counter_mask = 0xffffffff; - some_tc.tc_frequency = frequency; - some_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; - rtems_timecounter_install( &some_tc ); - } - - #define Clock_driver_support_initialize_hardware() \ - some_support_initialize_hardware() - - #include "../../../shared/clockdrv_shell.h" - -Install Clock Tick Interrupt Service Routine --------------------------------------------- - -The clock driver must provide a function to install the clock tick interrupt -service routine via ``Clock_driver_support_install_isr()``. - -.. code-block:: c - - #include <bsp/irq.h> - #include <bsp/fatal.h> - - static void some_support_install_isr( rtems_interrupt_handler isr ) - { - rtems_status_code sc; - sc = rtems_interrupt_handler_install( - SOME_IRQ, - "Clock", - RTEMS_INTERRUPT_UNIQUE, - isr, - NULL - ); - if ( sc != RTEMS_SUCCESSFUL ) { - bsp_fatal( SOME_FATAL_IRQ_INSTALL ); - } - } - - #define Clock_driver_support_install_isr( isr, old ) \ - some_support_install_isr( isr ) - - #include "../../../shared/clockdrv_shell.h" - -Support At Tick ---------------- - -The hardware specific support at tick is specified by -``Clock_driver_support_at_tick()``. - -.. code-block:: c - - static void some_support_at_tick( void ) - { - /* Clear interrupt */ - } - - #define Clock_driver_support_at_tick() \ - some_support_at_tick() - - #include "../../../shared/clockdrv_shell.h" - -System Shutdown Support ------------------------ - -The :dfn:`Clock Driver Shell` provides the routine ``Clock_exit()`` that is -scheduled to be run during system shutdown via the ``atexit()`` routine. The -hardware specific shutdown support is specified by -``Clock_driver_support_shutdown_hardware()`` which is used by ``Clock_exit()``. -It should disable the clock tick source if it was enabled. This can be used to -prevent clock ticks after the system is shutdown. - -.. code-block:: c - - static void some_support_shutdown_hardware( void ) - { - /* Shutdown hardware */ - } - - #define Clock_driver_support_shutdown_hardware() \ - some_support_shutdown_hardware() - - #include "../../../shared/clockdrv_shell.h" - -Multiple Clock Driver Ticks Per Clock Tick ------------------------------------------- - -In case the hardware needs more than one clock driver tick per clock tick (e.g. -due to a limited range of the hardware timer), then this can be specified with -the optional ``#define CLOCK_DRIVER_ISRS_PER_TICK`` and ``#define -CLOCK_DRIVER_ISRS_PER_TICK_VALUE`` defines. This is currently used only for -x86 and it hopefully remains that way. - -.. code-block:: c - - /* Enable multiple clock driver ticks per clock tick */ - #define CLOCK_DRIVER_ISRS_PER_TICK 1 - - /* Specifiy the clock driver ticks per clock tick value */ - #define CLOCK_DRIVER_ISRS_PER_TICK_VALUE 123 - - #include "../../../shared/clockdrv_shell.h" - -Clock Driver Ticks Counter --------------------------- - -The :dfn:`Clock Driver Shell` provide a global variable that is simply a count -of the number of clock driver interrupt service routines that have occurred. -This information is valuable when debugging a system. This variable is -declared as follows: - -.. code-block:: c - - volatile uint32_t Clock_driver_ticks; |