summaryrefslogtreecommitdiffstats
path: root/bsp_howto/clock.rst
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2016-06-17 15:05:41 +1000
committerChris Johns <chrisj@rtems.org>2016-06-17 15:05:41 +1000
commit6d7a4d2ee7053488f625faccc8bd4dc4d25d6460 (patch)
tree3fc4381b5f891ab47c200d819c290a5ba319d249 /bsp_howto/clock.rst
parentAdd Eclipse user manual for RTEMS. (diff)
downloadrtems-docs-6d7a4d2ee7053488f625faccc8bd4dc4d25d6460.tar.bz2
Update the BSP howto.
Closes #2590.
Diffstat (limited to 'bsp_howto/clock.rst')
-rw-r--r--bsp_howto/clock.rst262
1 files changed, 151 insertions, 111 deletions
diff --git a/bsp_howto/clock.rst b/bsp_howto/clock.rst
index 9f6e9a2..38b6d62 100644
--- a/bsp_howto/clock.rst
+++ b/bsp_howto/clock.rst
@@ -1,5 +1,9 @@
.. 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
############
@@ -9,14 +13,16 @@ 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.
+- 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.
+- 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 drivers should use the :dfn:`Clock Driver Shell` available via the
+:file:`clockdrv_shell.h` include file.
Clock Driver Shell
==================
@@ -29,12 +35,13 @@ 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:: c
+
+.. code-block:: c
/*
- * A section with functions, defines and macros to provide hardware specific
- * functions for the Clock Driver Shell.
- \*/
+ * A section with functions, defines and macros to provide hardware specific
+ * functions for the Clock Driver Shell.
+ */
#include "../../../shared/clockdrv_shell.h"
Initialization
@@ -45,9 +52,9 @@ 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.
+ 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
@@ -60,63 +67,76 @@ must be selected.
Clock Tick Only Variant
~~~~~~~~~~~~~~~~~~~~~~~
-.. code:: c
+.. code-block:: c
static void some_support_initialize_hardware( void )
{
- /* Initialize hardware \*/
+ /* 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_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:: c
+.. code-block:: c
#include <rtems/timecounter.h>
+
static rtems_timecounter_simple some_tc;
- static uint32_t some_tc_get( rtems_timecounter_simple \*tc )
+
+ static uint32_t some_tc_get( rtems_timecounter_simple *tc )
{
- return some.counter;
+ return some.counter;
}
- static bool some_tc_is_pending( rtems_timecounter_simple \*tc )
+
+ static bool some_tc_is_pending( rtems_timecounter_simple *tc )
{
- return some.is_pending;
+ return some.is_pending;
}
- static uint32_t some_tc_get_timecount( struct timecounter \*tc )
+
+ static uint32_t some_tc_get_timecount( struct timecounter *tc )
{
- return rtems_timecounter_simple_downcounter_get(
- tc,
- some_tc_get,
- some_tc_is_pending
- );
+ 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 );
+ 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
- );
+ 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()
+
+ #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
@@ -126,42 +146,52 @@ 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:: c
+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 )
+
+ static uint32_t some_tc_get_timecount( struct timecounter *tc )
{
- some.free_running_counter;
+ 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 );
+ 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()
+
+ #define Clock_driver_support_initialize_hardware() \
+ some_support_initialize_hardware()
+
#include "../../../shared/clockdrv_shell.h"
Install Clock Tick Interrupt Service Routine
@@ -169,57 +199,70 @@ 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:: c
+
+.. 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 );
+ 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 )
+
+ #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:: c
+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 \*/
+ /* Clear interrupt */
}
- #define Clock_driver_support_at_tick() \\
- some_support_at_tick()
+
+ #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:: c
+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 \*/
+ /* Shutdown hardware */
}
- #define Clock_driver_support_shutdown_hardware() \\
- some_support_shutdown_hardware()
+
+ #define Clock_driver_support_shutdown_hardware() \
+ some_support_shutdown_hardware()
+
#include "../../../shared/clockdrv_shell.h"
Multiple Clock Driver Ticks Per Clock Tick
@@ -228,14 +271,17 @@ 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:: c
+CLOCK_DRIVER_ISRS_PER_TICK_VALUE`` defines. This is currently used only for
+x86 and it hopefully remains that way.
- /* Enable multiple clock driver ticks per clock tick \*/
+.. 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 \*/
+
+ /* 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
@@ -245,13 +291,7 @@ 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:: c
- volatile uint32_t Clock_driver_ticks;
-
-.. COMMENT: COPYRIGHT (c) 1988-2002.
-
-.. COMMENT: On-Line Applications Research Corporation (OAR).
-
-.. COMMENT: All rights reserved.
+.. code-block:: c
+ volatile uint32_t Clock_driver_ticks;