/* * Copyright (c) 2016 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 * 82178 Puchheim * Germany * * * 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 #include "tmacros.h" #include #include #include #include const char rtems_test_name[] = "TMTIMER 1"; typedef struct { size_t cache_line_size; size_t data_cache_size; int dummy_value; volatile int *dummy_data; rtems_id first; } test_context; static test_context test_instance; static void prepare_cache(test_context *ctx) { volatile int *data = ctx->dummy_data; size_t m = ctx->data_cache_size / sizeof(*data); size_t k = ctx->cache_line_size / sizeof(*data); size_t j = ctx->dummy_value; size_t i; for (i = 0; i < m; i += k) { data[i] = i + j; } ctx->dummy_value = i + j; rtems_cache_invalidate_entire_instruction(); } static void never(rtems_id id, void *arg) { rtems_test_assert(0); } static rtems_interval interval(size_t i) { rtems_interval d = 50000; return i * d + d; } static void test_fire_and_cancel( test_context *ctx, size_t i, size_t j, const char *name ) { rtems_status_code sc; rtems_status_code sc2; rtems_counter_ticks a; rtems_counter_ticks b; rtems_counter_ticks d; rtems_id id; rtems_interrupt_level level; id = ctx->first + i; prepare_cache(ctx); rtems_interrupt_local_disable(level); a = rtems_counter_read(); sc = rtems_timer_fire_after(id, interval(j), never, NULL); sc2 = rtems_timer_cancel(id); b = rtems_counter_read(); rtems_interrupt_local_enable(level); d = rtems_counter_difference(b, a); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(sc2 == RTEMS_SUCCESSFUL); printf( "<%s unit=\"ns\">%" PRIu64 "", name, rtems_counter_ticks_to_nanoseconds(d), name ); } static void test_case(test_context *ctx, size_t j, size_t k) { rtems_status_code sc; size_t s; size_t t; s = j - k; for (t = 0; t < s; ++t) { size_t u = k + t; sc = rtems_timer_fire_after(ctx->first + u, interval(u + 1), never, NULL); rtems_test_assert(sc == RTEMS_SUCCESSFUL); } printf(" \n %zu", j); test_fire_and_cancel(ctx, j, 0, "First"); test_fire_and_cancel(ctx, j, j / 2, "Middle"); test_fire_and_cancel(ctx, j, j + 1, "Last"); printf("\n \n"); } static void test(void) { test_context *ctx = &test_instance; rtems_status_code sc; rtems_id id; rtems_name n; size_t j; size_t k; size_t timer_count; ctx->cache_line_size = rtems_cache_get_data_line_size(); if (ctx->cache_line_size == 0) { ctx->cache_line_size = 32; } ctx->data_cache_size = rtems_cache_get_data_cache_size(0); if (ctx->data_cache_size == 0) { ctx->data_cache_size = ctx->cache_line_size; } ctx->dummy_data = malloc(ctx->data_cache_size); rtems_test_assert(ctx->dummy_data != NULL); n = 1; timer_count = 1; sc = rtems_timer_create(n, &ctx->first); rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(rtems_object_id_get_index(ctx->first) == n); while (true) { ++n; sc = rtems_timer_create(n, &id); if (sc != RTEMS_SUCCESSFUL) { break; } rtems_test_assert(rtems_object_id_get_index(id) == n); timer_count = n; } printf("\n", timer_count); k = 0; j = 0; while (j < timer_count) { test_case(ctx, j, k); k = j; j = (123 * (j + 1) + 99) / 100; } test_case(ctx, n - 2, k); printf("\n"); } static void Init(rtems_task_argument arg) { TEST_BEGIN(); test(); TEST_END(); rtems_test_exit(0); } #define CONFIGURE_MICROSECONDS_PER_TICK 50000 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER #define CONFIGURE_UNIFIED_WORK_AREAS #define CONFIGURE_MAXIMUM_TASKS 1 #define CONFIGURE_MAXIMUM_TIMERS rtems_resource_unlimited(32) #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION #define CONFIGURE_RTEMS_INIT_TASKS_TABLE #define CONFIGURE_INIT #include