Changeset 31be416 in rtems


Ignore:
Timestamp:
Apr 20, 2015, 9:08:22 AM (4 years ago)
Author:
Alexander Krutwig <alexander.krutwig@…>
Branches:
4.11, 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.

Files:
9 added
10 edited

Legend:

Unmodified
Added
Removed
  • cpukit/sapi/Makefile.am

    rcc693845 r31be416  
    55
    66include_rtems_HEADERS = include/confdefs.h
     7include_rtems_HEADERS += include/rtems/bsd.h
    78include_rtems_HEADERS += include/rtems/chain.h
    89include_rtems_HEADERS += include/rtems/config.h
     
    2021include_rtems_HEADERS += include/rtems/scheduler.h
    2122include_rtems_HEADERS += include/rtems/sptables.h
     23include_rtems_HEADERS += include/rtems/timecounter.h
    2224include_rtems_HEADERS += include/rtems/timespec.h
    2325
     
    4042libsapi_a_SOURCES += src/profilingiterate.c
    4143libsapi_a_SOURCES += src/profilingreportxml.c
     44libsapi_a_SOURCES += src/tcsimpleinstall.c
    4245libsapi_a_CPPFLAGS = $(AM_CPPFLAGS)
    4346
  • cpukit/sapi/preinstall.am

    rcc693845 r31be416  
    2222        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/confdefs.h
    2323PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/confdefs.h
     24
     25$(PROJECT_INCLUDE)/rtems/bsd.h: include/rtems/bsd.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
     26        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/bsd.h
     27PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/bsd.h
    2428
    2529$(PROJECT_INCLUDE)/rtems/chain.h: include/rtems/chain.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
     
    8387PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/sptables.h
    8488
     89$(PROJECT_INCLUDE)/rtems/timecounter.h: include/rtems/timecounter.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
     90        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/timecounter.h
     91PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/timecounter.h
     92
    8593$(PROJECT_INCLUDE)/rtems/timespec.h: include/rtems/timespec.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
    8694        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/timespec.h
  • cpukit/score/Makefile.am

    rcc693845 r31be416  
    55
    66## include
     7
     8include_sysdir = $(includedir)/sys
     9
     10include_sys_HEADERS =
     11include_sys_HEADERS += include/sys/_ffcounter.h
     12include_sys_HEADERS += include/sys/timeffc.h
     13include_sys_HEADERS += include/sys/timepps.h
     14include_sys_HEADERS += include/sys/timetc.h
     15include_sys_HEADERS += include/sys/timex.h
    716
    817include_rtemsdir = $(includedir)/rtems
     
    8695include_rtems_score_HEADERS += include/rtems/score/timestamp.h
    8796include_rtems_score_HEADERS += include/rtems/score/timestamp64.h
     97include_rtems_score_HEADERS += include/rtems/score/timecounter.h
     98include_rtems_score_HEADERS += include/rtems/score/timecounterimpl.h
    8899include_rtems_score_HEADERS += include/rtems/score/tls.h
    89100include_rtems_score_HEADERS += include/rtems/score/tod.h
     
    345356libscore_a_SOURCES += src/resourceiterate.c
    346357libscore_a_SOURCES += src/smpbarrierwait.c
     358libscore_a_SOURCES += src/kern_tc.c
    347359
    348360EXTRA_DIST = src/Unlimited.txt
  • cpukit/score/include/sys/timeffc.h

    rcc693845 r31be416  
    5656#ifdef _KERNEL
    5757
     58#ifndef __rtems__
    5859/* Define the kern.sysclock sysctl tree. */
    5960SYSCTL_DECL(_kern_sysclock);
     
    6162/* Define the kern.sysclock.ffclock sysctl tree. */
    6263SYSCTL_DECL(_kern_sysclock_ffclock);
     64#endif /* __rtems__ */
    6365
    6466/*
  • cpukit/score/include/sys/timetc.h

    rcc693845 r31be416  
    1313#define _SYS_TIMETC_H_
    1414
     15#ifndef __rtems__
    1516#ifndef _KERNEL
    1617#error "no user-serviceable parts inside"
    1718#endif
     19#endif /* __rtems__ */
    1820
    1921/*-
  • cpukit/score/preinstall.am

    rcc693845 r31be416  
    1414CLEANFILES = $(PREINSTALL_FILES)
    1515
     16$(PROJECT_INCLUDE)/sys/$(dirstamp):
     17        @$(MKDIR_P) $(PROJECT_INCLUDE)/sys
     18        @: > $(PROJECT_INCLUDE)/sys/$(dirstamp)
     19PREINSTALL_DIRS += $(PROJECT_INCLUDE)/sys/$(dirstamp)
     20
     21$(PROJECT_INCLUDE)/sys/_ffcounter.h: include/sys/_ffcounter.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
     22        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/_ffcounter.h
     23PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/_ffcounter.h
     24
     25$(PROJECT_INCLUDE)/sys/timeffc.h: include/sys/timeffc.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
     26        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/timeffc.h
     27PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/timeffc.h
     28
     29$(PROJECT_INCLUDE)/sys/timepps.h: include/sys/timepps.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
     30        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/timepps.h
     31PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/timepps.h
     32
     33$(PROJECT_INCLUDE)/sys/timetc.h: include/sys/timetc.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
     34        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/timetc.h
     35PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/timetc.h
     36
     37$(PROJECT_INCLUDE)/sys/timex.h: include/sys/timex.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
     38        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/timex.h
     39PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/timex.h
     40
    1641$(PROJECT_INCLUDE)/rtems/$(dirstamp):
    1742        @$(MKDIR_P) $(PROJECT_INCLUDE)/rtems
     
    323348        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/timestamp64.h
    324349PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/timestamp64.h
     350
     351$(PROJECT_INCLUDE)/rtems/score/timecounter.h: include/rtems/score/timecounter.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
     352        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/timecounter.h
     353PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/timecounter.h
     354
     355$(PROJECT_INCLUDE)/rtems/score/timecounterimpl.h: include/rtems/score/timecounterimpl.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
     356        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/timecounterimpl.h
     357PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/timecounterimpl.h
    325358
    326359$(PROJECT_INCLUDE)/rtems/score/tls.h: include/rtems/score/tls.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
  • cpukit/score/src/kern_tc.c

    rcc693845 r31be416  
    1414 */
    1515
     16#ifdef __rtems__
     17#define _KERNEL
     18#define bintime _Timecounter_Bintime
     19#define binuptime _Timecounter_Binuptime
     20#define boottimebin _Timecounter_Boottimebin
     21#define getbintime _Timecounter_Getbintime
     22#define getbinuptime _Timecounter_Getbinuptime
     23#define getmicrotime _Timecounter_Getmicrotime
     24#define getmicrouptime _Timecounter_Getmicrouptime
     25#define getnanotime _Timecounter_Getnanotime
     26#define getnanouptime _Timecounter_Getnanouptime
     27#define microtime _Timecounter_Microtime
     28#define microuptime _Timecounter_Microuptime
     29#define nanotime _Timecounter_Nanotime
     30#define nanouptime _Timecounter_Nanouptime
     31#define tc_init _Timecounter_Install
     32#define timecounter _Timecounter
     33#define time_second _Timecounter_Time_second
     34#define time_uptime _Timecounter_Time_uptime
     35#include <rtems/score/timecounterimpl.h>
     36#endif /* __rtems__ */
    1637#include <sys/cdefs.h>
    1738__FBSDID("$FreeBSD r277406 2015-01-20T03:54:30Z$");
     
    2243
    2344#include <sys/param.h>
     45#ifndef __rtems__
    2446#include <sys/kernel.h>
    2547#include <sys/limits.h>
     48#else /* __rtems__ */
     49#include <limits.h>
     50#endif /* __rtems__ */
    2651#ifdef FFCLOCK
    2752#include <sys/lock.h>
    2853#include <sys/mutex.h>
    2954#endif
     55#ifndef __rtems__
    3056#include <sys/sysctl.h>
    3157#include <sys/syslog.h>
    3258#include <sys/systm.h>
     59#endif /* __rtems__ */
    3360#include <sys/timeffc.h>
    3461#include <sys/timepps.h>
    3562#include <sys/timetc.h>
    3663#include <sys/timex.h>
     64#ifndef __rtems__
    3765#include <sys/vdso.h>
     66#endif /* __rtems__ */
     67#ifdef __rtems__
     68#include <rtems.h>
     69ISR_LOCK_DEFINE(static, _Timecounter_Lock, "Timecounter");
     70#define hz rtems_clock_get_ticks_per_second()
     71#define printf(...)
     72#define log(...)
     73static inline int
     74fls(int x)
     75{
     76        return x ? sizeof(x) * 8 - __builtin_clz(x) : 0;
     77}
     78/* FIXME: https://devel.rtems.org/ticket/2348 */
     79#define ntp_update_second(a, b) do { (void) a; (void) b; } while (0)
     80#endif /* __rtems__ */
    3881
    3982/*
     
    5497dummy_get_timecount(struct timecounter *tc)
    5598{
     99#ifndef __rtems__
    56100        static uint32_t now;
    57101
    58102        return (++now);
     103#else /* __rtems__ */
     104        return 0;
     105#endif /* __rtems__ */
    59106}
    60107
     
    77124};
    78125
     126#if defined(RTEMS_SMP)
    79127static struct timehands th0;
    80128static struct timehands th9 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th0};
     
    87135static struct timehands th2 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th3};
    88136static struct timehands th1 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th2};
     137#endif
    89138static struct timehands th0 = {
    90139        &dummy_timecounter,
     
    96145        {0, 0},
    97146        1,
     147#if defined(RTEMS_SMP)
    98148        &th1
     149#else
     150        &th0
     151#endif
    99152};
    100153
     
    103156static struct timecounter *timecounters = &dummy_timecounter;
    104157
     158#ifndef __rtems__
    105159int tc_min_ticktock_freq = 1;
     160#endif /* __rtems__ */
    106161
    107162volatile time_t time_second = 1;
     
    109164
    110165struct bintime boottimebin;
     166#ifndef __rtems__
    111167struct timeval boottime;
    112168static int sysctl_kern_boottime(SYSCTL_HANDLER_ARGS);
     
    134190    sysctl_kern_timecounter_adjprecision, "I",
    135191    "Allowed time interval deviation in percents");
     192#endif /* __rtems__ */
    136193
    137194static void tc_windup(void);
     195#ifndef __rtems__
    138196static void cpu_tick_calibrate(int);
     197#endif /* __rtems__ */
    139198
    140199void dtrace_getnanotime(struct timespec *tsp);
    141200
     201#ifndef __rtems__
    142202static int
    143203sysctl_kern_boottime(SYSCTL_HANDLER_ARGS)
     
    176236        return sysctl_handle_64(oidp, &freq, 0, req);
    177237}
     238#endif /* __rtems__ */
    178239
    179240/*
     
    9771038#endif /* FFCLOCK */
    9781039
     1040#ifndef __rtems__
    9791041/*
    9801042 * This is a clone of getnanotime and used for walltimestamps.
     
    9941056        } while (gen == 0 || gen != th->th_generation);
    9951057}
     1058#endif /* __rtems__ */
    9961059
    9971060#ifdef FFCLOCK
     
    10071070extern long time_esterror;
    10081071
     1072#ifndef __rtems__
    10091073/*
    10101074 * Take a snapshot of sysclock data which can be used to compare system clocks
     
    11381202        return (0);
    11391203}
     1204#endif /* __rtems__ */
    11401205
    11411206/*
     
    11451210tc_init(struct timecounter *tc)
    11461211{
     1212#ifndef __rtems__
    11471213        uint32_t u;
    11481214        struct sysctl_oid *tc_root;
     
    11641230                    tc->tc_quality);
    11651231        }
     1232#endif /* __rtems__ */
    11661233
    11671234        tc->tc_next = timecounters;
    11681235        timecounters = tc;
     1236#ifndef __rtems__
    11691237        /*
    11701238         * Set up sysctl tree for this counter.
     
    11971265            tc->tc_frequency < timecounter->tc_frequency)
    11981266                return;
     1267#endif /* __rtems__ */
    11991268        (void)tc->tc_get_timecount(tc);
    12001269        (void)tc->tc_get_timecount(tc);
    12011270        timecounter = tc;
    1202 }
    1203 
     1271#ifdef __rtems__
     1272        tc_windup();
     1273#endif /* __rtems__ */
     1274}
     1275
     1276#ifndef __rtems__
    12041277/* Report the frequency of the current timecounter. */
    12051278uint64_t
     
    12091282        return (timehands->th_counter->tc_frequency);
    12101283}
     1284#endif /* __rtems__ */
    12111285
    12121286/*
     
    12151289 * XXX: not locked.
    12161290 */
     1291#ifndef __rtems__
    12171292void
    12181293tc_setclock(struct timespec *ts)
    1219 {
     1294#else /* __rtems__ */
     1295void
     1296_Timecounter_Set_clock(const struct timespec *ts)
     1297#endif /* __rtems__ */
     1298{
     1299#ifndef __rtems__
    12201300        struct timespec tbef, taft;
     1301#endif /* __rtems__ */
    12211302        struct bintime bt, bt2;
    12221303
     1304#ifndef __rtems__
    12231305        cpu_tick_calibrate(1);
    12241306        nanotime(&tbef);
     1307#endif /* __rtems__ */
    12251308        timespec2bintime(ts, &bt);
    12261309        binuptime(&bt2);
     
    12281311        bintime_add(&bt2, &boottimebin);
    12291312        boottimebin = bt;
     1313#ifndef __rtems__
    12301314        bintime2timeval(&bt, &boottime);
     1315#endif /* __rtems__ */
    12311316
    12321317        /* XXX fiddle all the little crinkly bits around the fiords... */
    12331318        tc_windup();
     1319#ifndef __rtems__
    12341320        nanotime(&taft);
    12351321        if (timestepwarnings) {
     
    12411327        }
    12421328        cpu_tick_calibrate(1);
     1329#endif /* __rtems__ */
    12431330}
    12441331
     
    12571344        int i;
    12581345        time_t t;
     1346#ifdef __rtems__
     1347        ISR_lock_Context lock_context;
     1348
     1349        _ISR_lock_ISR_disable_and_acquire(&_Timecounter_Lock, &lock_context);
     1350#endif /* __rtems__ */
    12591351
    12601352        /*
     
    13341426        /* Now is a good time to change timecounters. */
    13351427        if (th->th_counter != timecounter) {
     1428#ifndef __rtems__
    13361429#ifndef __arm__
    13371430                if ((timecounter->tc_flags & TC_FLAGS_C2STOP) != 0)
     
    13401433                        cpu_disable_c2_sleep--;
    13411434#endif
     1435#endif /* __rtems__ */
    13421436                th->th_counter = timecounter;
    13431437                th->th_offset_count = ncount;
     1438#ifndef __rtems__
    13441439                tc_min_ticktock_freq = max(1, timecounter->tc_frequency /
    13451440                    (((uint64_t)timecounter->tc_counter_mask + 1) / 3));
     1441#endif /* __rtems__ */
    13461442#ifdef FFCLOCK
    13471443                ffclock_change_tc(th);
     
    14021498
    14031499        timehands = th;
     1500#ifndef __rtems__
    14041501        timekeep_push_vdso();
    1405 }
    1406 
     1502#endif /* __rtems__ */
     1503#ifdef __rtems__
     1504        _ISR_lock_Release_and_ISR_enable(&_Timecounter_Lock, &lock_context);
     1505#endif /* __rtems__ */
     1506}
     1507
     1508#ifndef __rtems__
    14071509/* Report or change the active timecounter hardware. */
    14081510static int
     
    14691571SYSCTL_PROC(_kern_timecounter, OID_AUTO, choice, CTLTYPE_STRING | CTLFLAG_RD,
    14701572    0, 0, sysctl_kern_timecounter_choice, "A", "Timecounter hardware detected");
    1471 
     1573#endif /* __rtems__ */
     1574
     1575#ifndef __rtems__
    14721576/*
    14731577 * RFC 2783 PPS-API implementation.
     
    17501854        wakeup(pps);
    17511855}
     1856#else /* __rtems__ */
     1857/* FIXME: https://devel.rtems.org/ticket/2349 */
     1858#endif /* __rtems__ */
    17521859
    17531860/*
     
    17581865 */
    17591866
     1867#ifndef __rtems__
    17601868static int tc_tick;
    17611869SYSCTL_INT(_kern_timecounter, OID_AUTO, tick, CTLFLAG_RD, &tc_tick, 0,
    17621870    "Approximate number of hardclock ticks in a millisecond");
    1763 
     1871#endif /* __rtems__ */
     1872
     1873#ifndef __rtems__
    17641874void
    17651875tc_ticktock(int cnt)
     
    17711881                return;
    17721882        count = 0;
     1883#else /* __rtems__ */
     1884void
     1885_Timecounter_Tick(void)
     1886{
     1887#endif /* __rtems__ */
    17731888        tc_windup();
    17741889}
    1775 
     1890#ifdef __rtems__
     1891void
     1892_Timecounter_Tick_simple(uint32_t delta, uint32_t offset)
     1893{
     1894        struct bintime bt;
     1895        struct timehands *th;
     1896        uint32_t ogen;
     1897        ISR_lock_Context lock_context;
     1898
     1899        _ISR_lock_ISR_disable_and_acquire(&_Timecounter_Lock, &lock_context);
     1900
     1901        th = timehands;
     1902        ogen = th->th_generation;
     1903        th->th_offset_count = offset;
     1904        bintime_addx(&th->th_offset, th->th_scale * delta);
     1905
     1906        bt = th->th_offset;
     1907        bintime_add(&bt, &boottimebin);
     1908
     1909        /* Update the UTC timestamps used by the get*() functions. */
     1910        /* XXX shouldn't do this here.  Should force non-`get' versions. */
     1911        bintime2timeval(&bt, &th->th_microtime);
     1912        bintime2timespec(&bt, &th->th_nanotime);
     1913
     1914        /*
     1915         * Now that the struct timehands is again consistent, set the new
     1916         * generation number, making sure to not make it zero.
     1917         */
     1918        if (++ogen == 0)
     1919                ogen = 1;
     1920        th->th_generation = ogen;
     1921
     1922        /* Go live with the new struct timehands. */
     1923        time_second = th->th_microtime.tv_sec;
     1924        time_uptime = th->th_offset.sec;
     1925
     1926        _ISR_lock_Release_and_ISR_enable(&_Timecounter_Lock, &lock_context);
     1927}
     1928#endif /* __rtems__ */
     1929
     1930#ifndef __rtems__
    17761931static void __inline
    17771932tc_adjprecision(void)
     
    17951950        sbt_tickthreshold = bttosbt(bt_tickthreshold);
    17961951}
    1797 
     1952#endif /* __rtems__ */
     1953
     1954#ifndef __rtems__
    17981955static int
    17991956sysctl_kern_timecounter_adjprecision(SYSCTL_HANDLER_ARGS)
     
    18121969        return (0);
    18131970}
    1814 
     1971#endif /* __rtems__ */
     1972
     1973#ifndef __rtems__
    18151974static void
    18161975inittimecounter(void *dummy)
    1817 {
     1976#else /* __rtems__ */
     1977void
     1978_Timecounter_Initialize(void)
     1979#endif /* __rtems__ */
     1980{
     1981#ifndef __rtems__
    18181982        u_int p;
    18191983        int tick_rate;
     
    18392003        p = (tc_tick * 1000000) / hz;
    18402004        printf("Timecounters tick every %d.%03u msec\n", p / 1000, p % 1000);
     2005#endif /* __rtems__ */
    18412006
    18422007#ifdef FFCLOCK
     
    18492014}
    18502015
     2016#ifndef __rtems__
    18512017SYSINIT(timecounter, SI_SUB_CLOCKS, SI_ORDER_SECOND, inittimecounter, NULL);
    1852 
     2018#endif /* __rtems__ */
     2019
     2020#ifndef __rtems__
    18532021/* Cpu tick handling -------------------------------------------------*/
    18542022
     
    19832151
    19842152cpu_tick_f      *cpu_ticks = tc_cpu_ticks;
    1985 
     2153#endif /* __rtems__ */
     2154
     2155#ifndef __rtems__
    19862156static int vdso_th_enable = 1;
    19872157static int
     
    20192189        return (enabled);
    20202190}
     2191#endif /* __rtems__ */
    20212192
    20222193#ifdef COMPAT_FREEBSD32
  • 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 
  • testsuites/sptests/Makefile.am

    rcc693845 r31be416  
    3939endif
    4040_SUBDIRS += spintrcritical23
     41_SUBDIRS += sptimecounter01
    4142_SUBDIRS += spatomic01
    4243_SUBDIRS += spintrcritical22
  • testsuites/sptests/configure.ac

    rcc693845 r31be416  
    4242AC_CONFIG_FILES([Makefile
    4343spintrcritical23/Makefile
     44sptimecounter01/Makefile
    4445spatomic01/Makefile
    4546spglobalcon01/Makefile
Note: See TracChangeset for help on using the changeset viewer.