From 8f1e8f8f26525a8819c8982a2d2c4e339e9921a0 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 7 Feb 2022 16:10:45 +0100 Subject: kern_ntptime.c: Port to RTEMS Remove previous adjtime() implementation. Update #2348. --- cpukit/include/rtems/score/timecounter.h | 9 ++ cpukit/include/sys/timex.h | 4 +- cpukit/posix/src/adjtime.c | 93 -------------------- cpukit/score/src/kern_ntptime.c | 138 ++++++++++++++++++++++++++++++ cpukit/score/src/kern_tc.c | 6 +- spec/build/cpukit/librtemscpu.yml | 2 +- spec/build/testsuites/sptests/grp.yml | 2 + spec/build/testsuites/sptests/spntp01.yml | 19 ++++ testsuites/psxtests/psxtime/test.c | 10 +-- testsuites/sptests/spntp01/init.c | 111 ++++++++++++++++++++++++ 10 files changed, 289 insertions(+), 105 deletions(-) delete mode 100644 cpukit/posix/src/adjtime.c create mode 100644 spec/build/testsuites/sptests/spntp01.yml create mode 100644 testsuites/sptests/spntp01/init.c diff --git a/cpukit/include/rtems/score/timecounter.h b/cpukit/include/rtems/score/timecounter.h index 39f0dc353e..954da65676 100644 --- a/cpukit/include/rtems/score/timecounter.h +++ b/cpukit/include/rtems/score/timecounter.h @@ -270,6 +270,15 @@ void _Timecounter_Set_NTP_update_second( Timecounter_NTP_update_second handler ); +/** + * @brief Updates the time adjustment and seconds according to the NTP state. + * + * @param[in, out] adjustment is the NTP time adjustment. + * + * @param[in, out] newsec is the number of seconds since Unix epoch. + */ +void _Timecounter_NTP_update_second(int64_t *adjustment, time_t *newsec); + /** @} */ #ifdef __cplusplus diff --git a/cpukit/include/sys/timex.h b/cpukit/include/sys/timex.h index d2d2012ff5..8e763bb30f 100644 --- a/cpukit/include/sys/timex.h +++ b/cpukit/include/sys/timex.h @@ -37,7 +37,7 @@ #define NTP_API 4 /* NTP API version */ -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__rtems__) #include #endif /* __FreeBSD__ */ @@ -153,7 +153,7 @@ struct timex { long stbcnt; /* stability limit exceeded (ro) */ }; -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__rtems__) #ifdef _KERNEL void ntp_update_second(int64_t *adjustment, time_t *newsec); diff --git a/cpukit/posix/src/adjtime.c b/cpukit/posix/src/adjtime.c deleted file mode 100644 index ec8cb19a2e..0000000000 --- a/cpukit/posix/src/adjtime.c +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @file - * - * @brief Adjust the Time to Synchronize the System Clock - * @ingroup POSIXAPI - */ - -/* - * COPYRIGHT (c) 1989-2014. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _BSD_SOURCE -#include -#include -#include - -#include -#include -#include -#include -#include - -/** - * This method was initially added as part of porting NTP to RTEMS. - * It is a BSD compatability function and now is available on - * GNU/Linux. - * - * At one point there was a static variable named adjustment - * used by this implementation. I don't see any reason for it - * to be here based upon the GNU/Linux documentation. - */ -int adjtime( - const struct timeval *delta, - struct timeval *olddelta -) -{ - struct timespec delta_as_timespec; - Status_Control status; - - /* - * Simple validations - */ - if ( !delta ) - rtems_set_errno_and_return_minus_one( EINVAL ); - - if ( delta->tv_usec >= TOD_MICROSECONDS_PER_SECOND ) - rtems_set_errno_and_return_minus_one( EINVAL ); - - /* - * An adjustment of zero is pretty easy. - */ - if ( delta->tv_sec == 0 && delta->tv_usec == 0 ) - return 0; - - /* - * Currently, RTEMS does the adjustment in one movement so there - * is no way an adjustment was currently underway. - * - * Given interest, requirements, and sponsorship, a future - * enhancement would be to adjust the time in smaller increments - * at each clock tick. Until then, there is no outstanding - * adjustment. - */ - if ( olddelta ) { - olddelta->tv_sec = 0; - olddelta->tv_usec = 0; - } - - /* - * convert delta timeval to timespec - */ - delta_as_timespec.tv_sec = delta->tv_sec; - delta_as_timespec.tv_nsec = delta->tv_usec * 1000; - - /* - * Now apply the adjustment - */ - status = _TOD_Adjust( &delta_as_timespec ); - if ( status != STATUS_SUCCESSFUL ) { - rtems_set_errno_and_return_minus_one( STATUS_GET_POSIX( status ) ); - } - - return 0; -} diff --git a/cpukit/score/src/kern_ntptime.c b/cpukit/score/src/kern_ntptime.c index 96f14a408b..cb39133408 100644 --- a/cpukit/score/src/kern_ntptime.c +++ b/cpukit/score/src/kern_ntptime.c @@ -1,3 +1,12 @@ +/** + * @file + * + * @ingroup RTEMSScoreTimecounter + * + * @brief This source file contains the implementation of ntp_gettime(), + * ntp_adjtime(), adjtime(), and _Timecounter_NTP_update_second(). + */ + /*- *********************************************************************** * * @@ -36,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ntp.h" #include +#ifndef __rtems__ #include #include #include @@ -44,12 +54,24 @@ __FBSDID("$FreeBSD$"); #include #include #include +#endif /* __rtems__ */ #include #include #include #include +#ifndef __rtems__ #include #include +#else /* __rtems__ */ +#include +#include +#include +#include +#define nanotime(_tsp) _Timecounter_Nanotime(_tsp) +#define ntp_update_second _Timecounter_NTP_update_second +#define time_uptime _Timecounter_Time_uptime +struct thread; +#endif /* __rtems__ */ #ifdef PPS_SYNC FEATURE(pps_sync, "Support usage of external PPS signal by kernel PLL"); @@ -148,12 +170,18 @@ typedef int64_t l_fp; #define SHIFT_FLL 2 /* FLL loop gain (shift) */ static int time_state = TIME_OK; /* clock state */ +#ifdef __rtems__ +static +#endif /* __rtems__ */ int time_status = STA_UNSYNC; /* clock status bits */ static long time_tai; /* TAI offset (s) */ static long time_monitor; /* last time offset scaled (ns) */ static long time_constant; /* poll interval (shift) (s) */ static long time_precision = 1; /* clock precision (ns) */ static long time_maxerror = MAXPHASE / 1000; /* maximum error (us) */ +#ifdef __rtems__ +static +#endif /* __rtems__ */ long time_esterror = MAXPHASE / 1000; /* estimated error (us) */ static long time_reftime; /* uptime at last adjustment (s) */ static l_fp time_offset; /* time offset (ns) */ @@ -162,12 +190,24 @@ static l_fp time_adj; /* tick adjust (ns/s) */ static int64_t time_adjtime; /* correction from adjtime(2) (usec) */ +#ifndef __rtems__ static struct mtx ntp_lock; MTX_SYSINIT(ntp, &ntp_lock, "ntp", MTX_SPIN); #define NTP_LOCK() mtx_lock_spin(&ntp_lock) #define NTP_UNLOCK() mtx_unlock_spin(&ntp_lock) #define NTP_ASSERT_LOCKED() mtx_assert(&ntp_lock, MA_OWNED) +#else /* __rtems__ */ +#define NTP_LOCK() \ + do { \ + ISR_lock_Context lock_context; \ + _Timecounter_Acquire(&lock_context); +#define NTP_UNLOCK() \ + _Timecounter_Release(&lock_context); \ + } while (0) +#define NTP_ASSERT_LOCKED() \ + _Assert(_ISR_lock_Is_owner(&_Timecounter_Lock)) +#endif /* __rtems__ */ #ifdef PPS_SYNC /* @@ -273,6 +313,7 @@ ntp_gettime1(struct ntptimeval *ntvp) * See the timex.h header file for synopsis and API description. Note that * the TAI offset is returned in the ntvtimeval.tai structure member. */ +#ifndef __rtems__ #ifndef _SYS_SYSPROTO_H_ struct ntp_gettime_args { struct ntptimeval *ntvp; @@ -293,7 +334,27 @@ sys_ntp_gettime(struct thread *td, struct ntp_gettime_args *uap) td->td_retval[0] = ntv.time_state; return (copyout(&ntv, uap->ntvp, sizeof(ntv))); } +#else /* __rtems__ */ +int +ntp_gettime(struct ntptimeval *ntv) +{ + + if (ntv == NULL) { + errno = EFAULT; + return (-1); + } + + ntv = memset(ntv, 0, sizeof(*ntv)); + NTP_LOCK(); + ntp_gettime1(ntv); + NTP_UNLOCK(); + + return (ntv->time_state); +} +#endif /* __rtems__ */ + +#ifndef __rtems__ static int ntp_sysctl(SYSCTL_HANDLER_ARGS) { @@ -313,6 +374,7 @@ SYSCTL_NODE(_kern, OID_AUTO, ntp_pll, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, SYSCTL_PROC(_kern_ntp_pll, OID_AUTO, gettime, CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, 0, sizeof(struct ntptimeval) , ntp_sysctl, "S,ntptimeval", ""); +#endif /* __rtems__ */ #ifdef PPS_SYNC SYSCTL_INT(_kern_ntp_pll, OID_AUTO, pps_shiftmax, CTLFLAG_RW, @@ -337,12 +399,19 @@ SYSCTL_S64(_kern_ntp_pll, OID_AUTO, time_freq, CTLFLAG_RD | CTLFLAG_MPSAFE, * the timex.constant structure member has a dual purpose to set the time * constant and to set the TAI offset. */ +#ifdef __rtems__ +static +#endif /* __rtems__ */ int kern_ntp_adjtime(struct thread *td, struct timex *ntv, int *retvalp) { long freq; /* frequency ns/s) */ int modes; /* mode bits from structure */ +#ifndef __rtems__ int error, retval; +#else /* __rtems__ */ + int retval; +#endif /* __rtems__ */ /* * Update selected clock variables - only the superuser can @@ -354,11 +423,13 @@ kern_ntp_adjtime(struct thread *td, struct timex *ntv, int *retvalp) * status words are reset to the initial values at boot. */ modes = ntv->modes; +#ifndef __rtems__ error = 0; if (modes) error = priv_check(td, PRIV_NTP_ADJTIME); if (error != 0) return (error); +#endif /* __rtems__ */ NTP_LOCK(); if (modes & MOD_MAXERROR) time_maxerror = ntv->maxerror; @@ -460,6 +531,16 @@ kern_ntp_adjtime(struct thread *td, struct timex *ntv, int *retvalp) ntv->jitcnt = pps_jitcnt; ntv->stbcnt = pps_stbcnt; #endif /* PPS_SYNC */ +#ifdef __rtems__ + ntv->ppsfreq = 0; + ntv->jitter = 0; + ntv->shift = 0; + ntv->stabil = 0; + ntv->jitcnt = 0; + ntv->calcnt = 0; + ntv->errcnt = 0; + ntv->stbcnt = 0; +#endif /* __rtems__ */ retval = ntp_is_time_error(time_status) ? TIME_ERROR : time_state; NTP_UNLOCK(); @@ -473,6 +554,7 @@ struct ntp_adjtime_args { }; #endif +#ifndef __rtems__ int sys_ntp_adjtime(struct thread *td, struct ntp_adjtime_args *uap) { @@ -490,6 +572,23 @@ sys_ntp_adjtime(struct thread *td, struct ntp_adjtime_args *uap) } return (error); } +#else /* __rtems__ */ +int +ntp_adjtime(struct timex *ntv) +{ + int error; + int retval; + + if (ntv == NULL) { + errno = EFAULT; + return (-1); + } + + error = kern_ntp_adjtime(NULL, ntv, &retval); + _Assert_Unused_variable_equals(error, 0); + return (retval); +} +#endif /* __rtems__ */ /* * second_overflow() - called after ntp_tick_adjust() @@ -505,7 +604,11 @@ ntp_update_second(int64_t *adjustment, time_t *newsec) int tickrate; l_fp ftemp; /* 32/64-bit temporary */ +#ifndef __rtems__ NTP_LOCK(); +#else /* __rtems__ */ + NTP_ASSERT_LOCKED(); +#endif /* __rtems__ */ /* * On rollover of the second both the nanosecond and microsecond @@ -628,9 +731,22 @@ ntp_update_second(int64_t *adjustment, time_t *newsec) time_status &= ~STA_PPSSIGNAL; #endif /* PPS_SYNC */ +#ifndef __rtems__ NTP_UNLOCK(); +#endif /* __rtems__ */ +} +#ifdef __rtems__ +static void +_NTP_Initialize(void) +{ + + _Timecounter_Set_NTP_update_second(ntp_update_second); } +RTEMS_SYSINIT_ITEM(_NTP_Initialize, RTEMS_SYSINIT_DEVICE_DRIVERS, + RTEMS_SYSINIT_ORDER_FOURTH); +#endif /* __rtems__ */ + /* * hardupdate() - local clock update * @@ -930,6 +1046,7 @@ out: } #endif /* PPS_SYNC */ +#ifndef __rtems__ #ifndef _SYS_SYSPROTO_H_ struct adjtime_args { struct timeval *delta; @@ -958,15 +1075,23 @@ sys_adjtime(struct thread *td, struct adjtime_args *uap) int kern_adjtime(struct thread *td, struct timeval *delta, struct timeval *olddelta) +#else /* __rtems__ */ +static int +kern_adjtime(const struct timeval *delta, struct timeval *olddelta) +#endif /* __rtems__ */ { struct timeval atv; int64_t ltr, ltw; +#ifndef __rtems__ int error; +#endif /* __rtems__ */ if (delta != NULL) { +#ifndef __rtems__ error = priv_check(td, PRIV_ADJTIME); if (error != 0) return (error); +#endif /* __rtems__ */ ltw = (int64_t)delta->tv_sec * 1000000 + delta->tv_usec; } NTP_LOCK(); @@ -985,7 +1110,19 @@ kern_adjtime(struct thread *td, struct timeval *delta, struct timeval *olddelta) } return (0); } +#ifdef __rtems__ +int +adjtime(const struct timeval *delta, struct timeval *olddelta) +{ + int error; + + error = kern_adjtime(delta, olddelta); + _Assert_Unused_variable_equals(error, 0); + return (0); +} +#endif /* __rtems__ */ +#ifndef __rtems__ static struct callout resettodr_callout; static int resettodr_period = 1800; @@ -1051,3 +1188,4 @@ start_periodic_resettodr(void *arg __unused) SYSINIT(periodic_resettodr, SI_SUB_LAST, SI_ORDER_MIDDLE, start_periodic_resettodr, NULL); +#endif /* __rtems__ */ diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c index b757a2e28c..e57da2c0ca 100644 --- a/cpukit/score/src/kern_tc.c +++ b/cpukit/score/src/kern_tc.c @@ -135,13 +135,13 @@ atomic_load_ptr(void *ptr) return ((void *)_Atomic_Load_uintptr(ptr, ATOMIC_ORDER_RELAXED)); } -static Timecounter_NTP_update_second _Timecounter_NTP_update_second; +static Timecounter_NTP_update_second _Timecounter_NTP_update_second_handler; void _Timecounter_Set_NTP_update_second(Timecounter_NTP_update_second handler) { - _Timecounter_NTP_update_second = handler; + _Timecounter_NTP_update_second_handler = handler; } #define ntp_update_second(a, b) (*ntp_update_second_handler)(a, b) @@ -1721,7 +1721,7 @@ _Timecounter_Windup(struct bintime *new_boottimebin, bt = th->th_offset; bintime_add(&bt, &th->th_boottime); #ifdef __rtems__ - ntp_update_second_handler = _Timecounter_NTP_update_second; + ntp_update_second_handler = _Timecounter_NTP_update_second_handler; if (ntp_update_second_handler != NULL) { #endif /* __rtems__ */ i = bt.sec - tho->th_microtime.tv_sec; diff --git a/spec/build/cpukit/librtemscpu.yml b/spec/build/cpukit/librtemscpu.yml index 7d6dbae0db..c224937348 100644 --- a/spec/build/cpukit/librtemscpu.yml +++ b/spec/build/cpukit/librtemscpu.yml @@ -983,7 +983,6 @@ source: - cpukit/libtrace/record/record-util.c - cpukit/libtrace/record/record.c - cpukit/posix/src/_execve.c -- cpukit/posix/src/adjtime.c - cpukit/posix/src/aio_suspend.c - cpukit/posix/src/barrierattrdestroy.c - cpukit/posix/src/barrierattrgetpshared.c @@ -1424,6 +1423,7 @@ source: - cpukit/score/src/isrisinprogress.c - cpukit/score/src/isrvectortable.c - cpukit/score/src/iterateoverthreads.c +- cpukit/score/src/kern_ntptime.c - cpukit/score/src/kern_tc.c - cpukit/score/src/libatomic.c - cpukit/score/src/log2table.c diff --git a/spec/build/testsuites/sptests/grp.yml b/spec/build/testsuites/sptests/grp.yml index 740684a0e4..a69a4d20f7 100644 --- a/spec/build/testsuites/sptests/grp.yml +++ b/spec/build/testsuites/sptests/grp.yml @@ -337,6 +337,8 @@ links: uid: spmutex01 - role: build-dependency uid: spnsext01 +- role: build-dependency + uid: spntp01 - role: build-dependency uid: spobjgetnext - role: build-dependency diff --git a/spec/build/testsuites/sptests/spntp01.yml b/spec/build/testsuites/sptests/spntp01.yml new file mode 100644 index 0000000000..1b6a16f1a1 --- /dev/null +++ b/spec/build/testsuites/sptests/spntp01.yml @@ -0,0 +1,19 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +build-type: test-program +cflags: [] +copyrights: +- Copyright (C) 2022 embedded brains GmbH (http://www.embedded-brains.de) +cppflags: [] +cxxflags: [] +enabled-by: true +features: c cprogram +includes: [] +ldflags: [] +links: [] +source: +- testsuites/sptests/spntp01/init.c +stlib: [] +target: testsuites/sptests/spntp01.exe +type: build +use-after: [] +use-before: [] diff --git a/testsuites/psxtests/psxtime/test.c b/testsuites/psxtests/psxtime/test.c index d9f5537152..f5544b19dd 100644 --- a/testsuites/psxtests/psxtime/test.c +++ b/testsuites/psxtests/psxtime/test.c @@ -122,17 +122,15 @@ void test_adjtime(void) olddelta.tv_sec = 0; olddelta.tv_usec = 0; - puts( "adjtime - NULL delta - EINVAL" ); + puts( "adjtime - NULL delta - OK" ); sc = adjtime( NULL, &olddelta ); - rtems_test_assert( sc == -1 ); - rtems_test_assert( errno == EINVAL ); + rtems_test_assert( sc == 0 ); - puts( "adjtime - delta out of range - EINVAL" ); + puts( "adjtime - large us delta - OK" ); delta.tv_sec = 0; delta.tv_usec = 1000000000; /* 100 seconds worth */ sc = adjtime( &delta, &olddelta ); - rtems_test_assert( sc == -1 ); - rtems_test_assert( errno == EINVAL ); + rtems_test_assert( sc == 0 ); puts( "adjtime - delta range of 0 - OK" ); delta.tv_sec = 0; diff --git a/testsuites/sptests/spntp01/init.c b/testsuites/sptests/spntp01/init.c new file mode 100644 index 0000000000..eeee472e9d --- /dev/null +++ b/testsuites/sptests/spntp01/init.c @@ -0,0 +1,111 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2022 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include + +const char rtems_test_name[] = "SPNTP 1"; + +T_TEST_CASE( NTP ) +{ + struct ntptimeval ntv; + struct timex tx; + int status; + + errno = 0; + status = ntp_gettime( NULL ); + T_eq_int( status, -1 ); + T_eq_int( errno, EFAULT ); + + memset( &ntv, 0xff, sizeof( ntv ) ); + status = ntp_gettime( &ntv ); + T_eq_int( status, TIME_ERROR ); + + T_eq_i64( ntv.time.tv_sec, 567993600 ); + T_eq_long( ntv.time.tv_nsec, 0 ); + T_eq_long( ntv.maxerror, 500000 ); + T_eq_long( ntv.esterror, 500000 ); + T_eq_long( ntv.tai, 0 ); + T_eq_long( ntv.time_state, TIME_ERROR ); + + errno = 0; + status = ntp_adjtime( NULL ); + T_eq_int( status, -1 ); + T_eq_int( errno, EFAULT ); + + memset( &tx, 0xff, sizeof( tx ) ); + tx.modes = 0; + status = ntp_adjtime( &tx ); + T_eq_int( status, TIME_ERROR ); + T_eq_uint( tx.modes, 0 ); + T_eq_long( tx.offset, 0 ); + T_eq_long( tx.freq, 0 ); + T_eq_long( tx.maxerror, 500000 ); + T_eq_long( tx.esterror, 500000 ); + T_eq_int( tx.status, STA_UNSYNC ); + T_eq_long( tx.constant, 0 ); + T_eq_long( tx.precision, 0 ); + T_eq_long( tx.tolerance, 32500000 ); + T_eq_long( tx.ppsfreq, 0 ); + T_eq_long( tx.jitter, 0 ); + T_eq_int( tx.shift, 0 ); + T_eq_long( tx.stabil, 0 ); + T_eq_long( tx.jitcnt, 0 ); + T_eq_long( tx.calcnt, 0 ); + T_eq_long( tx.errcnt, 0 ); + T_eq_long( tx.stbcnt, 0 ); + + status = adjtime( NULL, NULL ); + T_eq_int( status, 0 ); +} + +static rtems_task Init( rtems_task_argument argument ) +{ + rtems_test_run( argument, TEST_STATE ); +} + +#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER + +#define CONFIGURE_MAXIMUM_TASKS 1 + +#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include -- cgit v1.2.3