File indexing completed on 2025-05-11 08:24:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031
0032 #include <stdio.h>
0033 #include <inttypes.h>
0034
0035 #include <rtems.h>
0036 #include <rtems/counter.h>
0037
0038 #include "tmacros.h"
0039
0040 const char rtems_test_name[] = "SPCPUCOUNTER 1";
0041
0042 #define NS_PER_TICK 1000000
0043
0044 #define N 10
0045
0046 typedef struct {
0047 rtems_counter_ticks delay_ns_t[N][2];
0048 rtems_counter_ticks delay_ticks_t[N][2];
0049 rtems_counter_ticks overhead_t[N][5];
0050 rtems_counter_ticks overhead_delta;
0051 } test_context;
0052
0053 static test_context test_instance;
0054
0055 static rtems_interval sync_with_clock_tick(void)
0056 {
0057 rtems_interval start = rtems_clock_get_ticks_since_boot();
0058 rtems_interval current;
0059
0060 do {
0061 current = rtems_clock_get_ticks_since_boot();
0062 } while (current == start);
0063
0064 return current;
0065 }
0066
0067 static void test_converter(void)
0068 {
0069 CPU_Counter_ticks frequency;
0070 CPU_Counter_ticks frequency2;
0071 uint64_t ns;
0072 int64_t sbt;
0073
0074 frequency = rtems_counter_nanoseconds_to_ticks(1000000000);
0075 ns = rtems_counter_ticks_to_nanoseconds(frequency);
0076
0077 printf("CPU counter frequency: %" PRIu32 "Hz\n", frequency);
0078 printf("nanoseconds for frequency count ticks: %" PRIu64 "\n", ns);
0079
0080 rtems_test_assert(ns == 1000000000);
0081
0082 sbt = rtems_counter_ticks_to_sbintime(frequency);
0083 rtems_test_assert(sbt == (INT64_C(1) << 32));
0084
0085 frequency2 = rtems_counter_sbintime_to_ticks(sbt);
0086 rtems_test_assert(frequency == frequency2);
0087 }
0088
0089 static void test_delay_nanoseconds(test_context *ctx)
0090 {
0091 int i;
0092
0093 for (i = 0; i < N; ++i) {
0094 rtems_counter_ticks t0;
0095 rtems_counter_ticks t1;
0096 rtems_interval tick;
0097
0098 tick = sync_with_clock_tick();
0099
0100 t0 = rtems_counter_read();
0101 rtems_counter_delay_nanoseconds(NS_PER_TICK);
0102 t1 = rtems_counter_read();
0103
0104 ctx->delay_ns_t[i][0] = t0;
0105 ctx->delay_ns_t[i][1] = t1;
0106
0107 rtems_test_assert(tick < rtems_clock_get_ticks_since_boot());
0108 }
0109 }
0110
0111 static void test_delay_ticks(test_context *ctx)
0112 {
0113 rtems_counter_ticks ticks = rtems_counter_nanoseconds_to_ticks(NS_PER_TICK);
0114 int i;
0115
0116 for (i = 0; i < N; ++i) {
0117 rtems_counter_ticks t0;
0118 rtems_counter_ticks t1;
0119 rtems_interval tick;
0120
0121 tick = sync_with_clock_tick();
0122
0123 t0 = rtems_counter_read();
0124 rtems_counter_delay_ticks(ticks);
0125 t1 = rtems_counter_read();
0126
0127 ctx->delay_ticks_t[i][0] = t0;
0128 ctx->delay_ticks_t[i][1] = t1;
0129
0130 rtems_test_assert(tick < rtems_clock_get_ticks_since_boot());
0131 }
0132 }
0133
0134 static void test_overheads(test_context *ctx)
0135 {
0136 int i;
0137
0138 for (i = 0; i < N; ++i) {
0139 rtems_counter_ticks t0;
0140 rtems_counter_ticks t1;
0141 rtems_counter_ticks t2;
0142 rtems_counter_ticks t3;
0143 rtems_counter_ticks t4;
0144 rtems_counter_ticks d;
0145
0146 t0 = rtems_counter_read();
0147 t1 = rtems_counter_read();
0148 d = rtems_counter_difference(t1, t0);
0149 t2 = rtems_counter_read();
0150 rtems_counter_delay_nanoseconds(0);
0151 t3 = rtems_counter_read();
0152 rtems_counter_delay_ticks(0);
0153 t4 = rtems_counter_read();
0154
0155 ctx->overhead_t[i][0] = t0;
0156 ctx->overhead_t[i][1] = t1;
0157 ctx->overhead_t[i][2] = t2;
0158 ctx->overhead_t[i][3] = t3;
0159 ctx->overhead_t[i][4] = t4;
0160 ctx->overhead_delta = d;
0161 }
0162 }
0163
0164 static void report_overhead(
0165 const char *name,
0166 rtems_counter_ticks t1,
0167 rtems_counter_ticks t0
0168 )
0169 {
0170 rtems_counter_ticks d;
0171 uint64_t ns;
0172
0173 d = rtems_counter_difference(t1, t0);
0174 ns = rtems_counter_ticks_to_nanoseconds(d);
0175
0176 printf(
0177 "overhead %s: %" PRIu64 " ticks, %" PRIu64 "ns\n",
0178 name,
0179 (uint64_t) d,
0180 ns
0181 );
0182 }
0183
0184 static uint64_t large_delta_to_ns(rtems_counter_ticks d)
0185 {
0186 uint64_t ns;
0187
0188 ns = rtems_counter_ticks_to_nanoseconds(d);
0189
0190
0191 if (ns < rtems_configuration_get_nanoseconds_per_tick()) {
0192 printf(
0193 "warning: the RTEMS counter seems to be unable to\n"
0194 " measure intervals greater than the clock tick interval\n"
0195 );
0196
0197 ns += rtems_configuration_get_nanoseconds_per_tick();
0198 }
0199
0200 return ns;
0201 }
0202
0203 static void test_report(test_context *ctx)
0204 {
0205 double ns_per_tick = NS_PER_TICK;
0206 rtems_counter_ticks d;
0207 uint64_t ns;
0208 size_t i;
0209
0210 printf("test delay nanoseconds (%i times)\n", N);
0211
0212 for (i = 0; i < N; ++i) {
0213 d = rtems_counter_difference(ctx->delay_ns_t[i][1], ctx->delay_ns_t[i][0]);
0214 ns = large_delta_to_ns(d);
0215
0216 printf(
0217 "ns busy wait duration: %" PRIu64 "ns\n"
0218 "ns busy wait relative to clock tick: %f\n",
0219 ns,
0220 (ns - ns_per_tick) / ns_per_tick
0221 );
0222 }
0223
0224 printf("test delay ticks (%i times)\n", N);
0225
0226 for (i = 0; i < N; ++i) {
0227 d = rtems_counter_difference(
0228 ctx->delay_ticks_t[i][1],
0229 ctx->delay_ticks_t[i][0]
0230 );
0231 ns = large_delta_to_ns(d);
0232
0233 printf(
0234 "ticks busy wait duration: %" PRIu64 "ns\n"
0235 "ticks busy wait relative to clock tick: %f\n",
0236 ns,
0237 (ns - ns_per_tick) / ns_per_tick
0238 );
0239 }
0240
0241 printf("test overheads (%i times)\n", N);
0242
0243 for (i = 0; i < N; ++i) {
0244 report_overhead("read", ctx->overhead_t[i][1], ctx->overhead_t[i][0]);
0245 report_overhead("difference", ctx->overhead_t[i][2], ctx->overhead_t[i][1]);
0246 report_overhead("delay ns", ctx->overhead_t[i][3], ctx->overhead_t[i][2]);
0247 report_overhead("delay ticks", ctx->overhead_t[i][4], ctx->overhead_t[i][3]);
0248 }
0249 }
0250
0251 static void Init(rtems_task_argument arg)
0252 {
0253 test_context *ctx = &test_instance;
0254
0255 rtems_print_printer_fprintf_putc(&rtems_test_printer);
0256 TEST_BEGIN();
0257
0258 test_delay_nanoseconds(ctx);
0259 test_delay_ticks(ctx);
0260 test_overheads(ctx);
0261 test_converter();
0262 test_report(ctx);
0263
0264 TEST_END();
0265
0266 rtems_test_exit(0);
0267 }
0268
0269 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0270 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0271
0272 #define CONFIGURE_MICROSECONDS_PER_TICK (NS_PER_TICK / 1000)
0273
0274 #define CONFIGURE_MAXIMUM_TASKS 1
0275
0276 #define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT
0277
0278 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0279
0280 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0281
0282 #define CONFIGURE_INIT
0283
0284 #include <rtems/confdefs.h>