diff --git a/TESTS/mbed_drivers/timer/main.cpp b/TESTS/mbed_drivers/timer/main.cpp index dbd13b149b..694b52aad9 100644 --- a/TESTS/mbed_drivers/timer/main.cpp +++ b/TESTS/mbed_drivers/timer/main.cpp @@ -26,12 +26,21 @@ #else using namespace utest::v1; +using namespace std::chrono; extern uint32_t SystemCoreClock; -#define US_PER_SEC 1000000 -#define US_PER_MSEC 1000 -#define MSEC_PER_SEC 1000 +#define TEST_ASSERT_EQUAL_DURATION(expected, actual) \ + do { \ + using ct = std::common_type_t; \ + TEST_ASSERT_EQUAL(ct(expected).count(), ct(actual).count()); \ + } while (0) + +#define TEST_ASSERT_DURATION_WITHIN(delta, expected, actual) \ + do { \ + using ct = std::common_type_t; \ + TEST_ASSERT_INT_WITHIN(ct(delta).count(), ct(expected).count(), ct(actual).count()); \ + } while (0) /* * Define tolerance as follows: @@ -50,14 +59,16 @@ extern uint32_t SystemCoreClock; #define TOLERANCE 2 #endif -#define DELTA_US(delay_ms) (500 + (delay_ms) * US_PER_MSEC * TOLERANCE / 100) -#define DELTA_MS(delay_ms) (1 + (delay_ms) * TOLERANCE / 100) -#define DELTA_S(delay_ms) (0.000500f + ((float)(delay_ms)) * ((float)(TOLERANCE) / 100.f) / MSEC_PER_SEC) +template +static inline microseconds delta(Duration delay) +{ + return 500us + duration_cast(delay) * TOLERANCE / 100; +} #define TICKER_FREQ_1MHZ 1000000 #define TICKER_BITS 32 -static Timer *p_timer = NULL; +static TimerBase *p_timer = NULL; /* Global variable used to simulate passage of time * in case when timer which uses user ticker is tested. @@ -66,16 +77,11 @@ static uint32_t curr_ticker_ticks_val; /* Replacement for generic wait functions to avoid invoking OS scheduling stuff. */ -void busy_wait_us(int us) +void busy_wait(duration us) { const ticker_data_t *const ticker = get_us_ticker_data(); uint32_t start = ticker_read(ticker); - while ((ticker_read(ticker) - start) < (uint32_t)us); -} - -void busy_wait_ms(int ms) -{ - busy_wait_us(ms * US_PER_MSEC); + while ((ticker_read(ticker) - start) < (uint32_t)us.count()); } /* User ticker interface function. */ @@ -157,13 +163,18 @@ const ticker_data_t *get_user_ticker_data(void) return &us_data; } +class UserTimer : public TimerBase { +public: + UserTimer() : TimerBase(get_user_ticker_data()) { } +}; + /* Initialisation of the Timer object which uses * ticker data provided by the user. * * */ utest::v1::status_t timer_user_ticker_setup_handler(const Case *const source, const size_t index_of_case) { - p_timer = new Timer(get_user_ticker_data()); + p_timer = new UserTimer(); /* Check if Timer object has been created. */ TEST_ASSERT_NOT_NULL(p_timer); @@ -185,12 +196,24 @@ utest::v1::status_t timer_os_ticker_setup_handler(const Case *const source, cons return greentea_case_setup_handler(source, index_of_case); } -/* Test finalisation. - * - * */ -utest::v1::status_t cleanup_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) +/* Test finalisation of the Timer object which uses + * ticker data provided by the user. + */ +utest::v1::status_t timer_user_ticker_cleanup_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) { - delete p_timer; + delete static_cast(p_timer); + + p_timer = NULL; + + return greentea_case_teardown_handler(source, passed, failed, reason); +} + +/* Test finalisation of the Timer object which uses + * default os ticker data. + */ +utest::v1::status_t timer_os_ticker_cleanup_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) +{ + delete static_cast(p_timer); p_timer = NULL; @@ -209,20 +232,14 @@ utest::v1::status_t cleanup_handler(const Case *const source, const size_t passe void test_timer_creation_os_ticker() { /* Check results. */ - TEST_ASSERT_EQUAL_FLOAT(0, p_timer->read()); - TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms()); - TEST_ASSERT_EQUAL_INT32(0, p_timer->read_us()); - TEST_ASSERT_EQUAL_UINT64(0, p_timer->read_high_resolution_us()); + TEST_ASSERT_EQUAL_DURATION(0s, p_timer->elapsed_time()); /* Wait 10 ms. * After that operation timer read routines should still return 0. */ - busy_wait_ms(10); + busy_wait(10ms); /* Check results. */ - TEST_ASSERT_EQUAL_FLOAT(0, p_timer->read()); - TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms()); - TEST_ASSERT_EQUAL_INT32(0, p_timer->read_us()); - TEST_ASSERT_EQUAL_UINT64(0, p_timer->read_high_resolution_us()); + TEST_ASSERT_EQUAL_DURATION(0s, p_timer->elapsed_time()); } /* This test verifies if timer is stopped after @@ -243,20 +260,14 @@ void test_timer_creation_user_ticker() curr_ticker_ticks_val = 10000; /* Check results. */ - TEST_ASSERT_EQUAL_FLOAT(0, p_timer->read()); - TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms()); - TEST_ASSERT_EQUAL_INT32(0, p_timer->read_us()); - TEST_ASSERT_EQUAL_UINT64(0, p_timer->read_high_resolution_us()); + TEST_ASSERT_EQUAL_DURATION(0s, p_timer->elapsed_time()); /* Simulate that 10 ms has elapsed. * After that operation timer read routines should still return 0. */ curr_ticker_ticks_val += 10000; /* Check results. */ - TEST_ASSERT_EQUAL_FLOAT(0, p_timer->read()); - TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms()); - TEST_ASSERT_EQUAL_INT32(0, p_timer->read_us()); - TEST_ASSERT_EQUAL_UINT64(0, p_timer->read_high_resolution_us()); + TEST_ASSERT_EQUAL_DURATION(0s, p_timer->elapsed_time()); } /* This test verifies verifies if read(), read_us(), read_ms(), @@ -287,10 +298,7 @@ void test_timer_time_accumulation_user_ticker() p_timer->stop(); /* Check results - 1 us has elapsed. */ - TEST_ASSERT_EQUAL_FLOAT(0.000001f, p_timer->read()); - TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms()); - TEST_ASSERT_EQUAL_INT32(1, p_timer->read_us()); - TEST_ASSERT_EQUAL_UINT64(1, p_timer->read_high_resolution_us()); + TEST_ASSERT_EQUAL_DURATION(1us, p_timer->elapsed_time()); /* Simulate that 100 us has elapsed between stop and start. */ curr_ticker_ticks_val = 101; @@ -305,10 +313,7 @@ void test_timer_time_accumulation_user_ticker() p_timer->stop(); /* Check results - 125 us have elapsed. */ - TEST_ASSERT_EQUAL_FLOAT(0.000125f, p_timer->read()); - TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms()); - TEST_ASSERT_EQUAL_INT32(125, p_timer->read_us()); - TEST_ASSERT_EQUAL_UINT64(125, p_timer->read_high_resolution_us()); + TEST_ASSERT_EQUAL_DURATION(125us, p_timer->elapsed_time()); /* Simulate that 100 us has elapsed between stop and start. */ curr_ticker_ticks_val = 325; @@ -323,10 +328,7 @@ void test_timer_time_accumulation_user_ticker() p_timer->stop(); /* Check results - 1 ms has elapsed. */ - TEST_ASSERT_EQUAL_FLOAT(0.001000f, p_timer->read()); - TEST_ASSERT_EQUAL_INT32(1, p_timer->read_ms()); - TEST_ASSERT_EQUAL_INT32(1000, p_timer->read_us()); - TEST_ASSERT_EQUAL_UINT64(1000, p_timer->read_high_resolution_us()); + TEST_ASSERT_EQUAL_DURATION(1ms, p_timer->elapsed_time()); /* Simulate that 100 us has elapsed between stop and start. */ curr_ticker_ticks_val = 1300; @@ -341,10 +343,7 @@ void test_timer_time_accumulation_user_ticker() p_timer->stop(); /* Check results - 125 ms have elapsed. */ - TEST_ASSERT_EQUAL_FLOAT(0.125000f, p_timer->read()); - TEST_ASSERT_EQUAL_INT32(125, p_timer->read_ms()); - TEST_ASSERT_EQUAL_INT32(125000, p_timer->read_us()); - TEST_ASSERT_EQUAL_UINT64(125000, p_timer->read_high_resolution_us()); + TEST_ASSERT_EQUAL_DURATION(125ms, p_timer->elapsed_time()); /* Simulate that 100 us has elapsed between stop and start. */ curr_ticker_ticks_val = 125400; @@ -359,10 +358,7 @@ void test_timer_time_accumulation_user_ticker() p_timer->stop(); /* Check results - 1 s has elapsed. */ - TEST_ASSERT_EQUAL_FLOAT(1.000000f, p_timer->read()); - TEST_ASSERT_EQUAL_INT32(1000, p_timer->read_ms()); - TEST_ASSERT_EQUAL_INT32(1000000, p_timer->read_us()); - TEST_ASSERT_EQUAL_UINT64(1000000, p_timer->read_high_resolution_us()); + TEST_ASSERT_EQUAL_DURATION(1s, p_timer->elapsed_time()); /* Simulate that 100 us has elapsed between stop and start. */ curr_ticker_ticks_val = 1000500; @@ -377,10 +373,7 @@ void test_timer_time_accumulation_user_ticker() p_timer->stop(); /* Check results - 125 s have elapsed. */ - TEST_ASSERT_EQUAL_FLOAT(125.000000f, p_timer->read()); - TEST_ASSERT_EQUAL_INT32(125000, p_timer->read_ms()); - TEST_ASSERT_EQUAL_INT32(125000000, p_timer->read_us()); - TEST_ASSERT_EQUAL_UINT64(125000000, p_timer->read_high_resolution_us()); + TEST_ASSERT_EQUAL_DURATION(125s, p_timer->elapsed_time()); /* Simulate that 100 us has elapsed between stop and start. */ curr_ticker_ticks_val = 125000600; @@ -401,10 +394,7 @@ void test_timer_time_accumulation_user_ticker() p_timer->stop(); /* Check results - 2147483647 (MAX_INT_32) us have elapsed. */ - TEST_ASSERT_EQUAL_FLOAT(2147.483647f, p_timer->read()); - TEST_ASSERT_EQUAL_INT32(2147483, p_timer->read_ms()); - TEST_ASSERT_EQUAL_INT32(2147483647, p_timer->read_us()); - TEST_ASSERT_EQUAL_UINT64(2147483647, p_timer->read_high_resolution_us()); + TEST_ASSERT_EQUAL_DURATION(2147483647us, p_timer->elapsed_time()); } /* This test verifies if read(), read_us(), read_ms(), @@ -426,21 +416,18 @@ void test_timer_time_accumulation_os_ticker() p_timer->start(); /* Wait 10 ms. */ - busy_wait_ms(10); + busy_wait(10ms); /* Stop the timer. */ p_timer->stop(); /* Check results - totally 10 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(10), 10, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(10), 10000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(10), 10000, p_timer->read_high_resolution_us()); + TEST_ASSERT_DURATION_WITHIN(delta(10ms), 10ms, p_timer->elapsed_time()); /* Wait 50 ms - this is done to show that time elapsed when * the timer is stopped does not have influence on the * timer counted time. */ - busy_wait_ms(50); + busy_wait(50ms); /* ------ */ @@ -448,16 +435,13 @@ void test_timer_time_accumulation_os_ticker() p_timer->start(); /* Wait 20 ms. */ - busy_wait_ms(20); + busy_wait(20ms); /* Stop the timer. */ p_timer->stop(); /* Check results - totally 30 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(30), 0.030f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(30), 30, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(30), 30000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(30), 30000, p_timer->read_high_resolution_us()); + TEST_ASSERT_DURATION_WITHIN(delta(30ms), 30ms, p_timer->elapsed_time()); /* Wait 50 ms - this is done to show that time elapsed when * the timer is stopped does not have influence on the @@ -469,21 +453,18 @@ void test_timer_time_accumulation_os_ticker() p_timer->start(); /* Wait 30 ms. */ - busy_wait_ms(30); + busy_wait(30ms); /* Stop the timer. */ p_timer->stop(); /* Check results - totally 60 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(60), 0.060f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(60), 60, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(60), 60000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(60), 60000, p_timer->read_high_resolution_us()); + TEST_ASSERT_DURATION_WITHIN(delta(60ms), 60ms, p_timer->elapsed_time()); /* Wait 50 ms - this is done to show that time elapsed when * the timer is stopped does not have influence on the * timer time. */ - busy_wait_ms(50); + busy_wait(50ms); /* ------ */ @@ -491,16 +472,13 @@ void test_timer_time_accumulation_os_ticker() p_timer->start(); /* Wait 1 sec. */ - busy_wait_ms(1000); + busy_wait(1s); /* Stop the timer. */ p_timer->stop(); /* Check results - totally 1060 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1060), 1.060f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(1060), 1060, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(1060), 1060000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(1060), 1060000, p_timer->read_high_resolution_us()); + TEST_ASSERT_DURATION_WITHIN(delta(1060ms), 1060ms, p_timer->elapsed_time()); } /* This test verifies if reset() function resets the timer @@ -520,16 +498,13 @@ void test_timer_reset_os_ticker() p_timer->start(); /* Wait 10 ms. */ - busy_wait_ms(10); + busy_wait(10ms); /* Stop the timer. */ p_timer->stop(); /* Check results - totally 10 ms elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(10), 10, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(10), 10000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(10), 10000, p_timer->read_high_resolution_us()); + TEST_ASSERT_DURATION_WITHIN(delta(10ms), 10ms, p_timer->elapsed_time()); /* Reset the timer - previous measured time should be lost now. */ p_timer->reset(); @@ -538,16 +513,13 @@ void test_timer_reset_os_ticker() p_timer->start(); /* Wait 20 ms. */ - busy_wait_ms(20); + busy_wait(20ms); /* Stop the timer. */ p_timer->stop(); /* Check results - 20 ms elapsed since the reset. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(20), 0.020f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(20), 20, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(20), 20000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(20), 20000, p_timer->read_high_resolution_us()); + TEST_ASSERT_DURATION_WITHIN(delta(20ms), 20ms, p_timer->elapsed_time()); } /* This test verifies if reset() function resets the timer @@ -577,10 +549,7 @@ void test_timer_reset_user_ticker() p_timer->stop(); /* Check results - totally 10 ms elapsed. */ - TEST_ASSERT_EQUAL_FLOAT(0.010f, p_timer->read()); - TEST_ASSERT_EQUAL_INT32(10, p_timer->read_ms()); - TEST_ASSERT_EQUAL_INT32(10000, p_timer->read_us()); - TEST_ASSERT_EQUAL_UINT64(10000, p_timer->read_high_resolution_us()); + TEST_ASSERT_DURATION_WITHIN(delta(10ms), 10ms, p_timer->elapsed_time()); /* Reset the timer - previous measured time should be lost now. */ p_timer->reset(); @@ -595,10 +564,7 @@ void test_timer_reset_user_ticker() p_timer->stop(); /* Check results - 20 ms elapsed since the reset. */ - TEST_ASSERT_EQUAL_FLOAT(0.020f, p_timer->read()); - TEST_ASSERT_EQUAL_INT32(20, p_timer->read_ms()); - TEST_ASSERT_EQUAL_INT32(20000, p_timer->read_us()); - TEST_ASSERT_EQUAL_UINT64(20000, p_timer->read_high_resolution_us()); + TEST_ASSERT_DURATION_WITHIN(delta(20ms), 20ms, p_timer->elapsed_time()); } /* This test verifies if calling start() for already @@ -616,22 +582,19 @@ void test_timer_start_started_timer_os_ticker() p_timer->start(); /* Wait 10 ms. */ - busy_wait_ms(10); + busy_wait(10ms); /* Now start timer again. */ p_timer->start(); /* Wait 20 ms. */ - busy_wait_ms(20); + busy_wait(20ms); /* Stop the timer. */ p_timer->stop(); /* Check results - 30 ms have elapsed since the first start. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(30), 0.030f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(30), 30, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(30), 30000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(30), 30000, p_timer->read_high_resolution_us()); + TEST_ASSERT_DURATION_WITHIN(delta(30ms), 30ms, p_timer->elapsed_time()); } /* This test verifies if calling start() for already @@ -665,62 +628,7 @@ void test_timer_start_started_timer_user_ticker() p_timer->stop(); /* Check results - 30 ms have elapsed since the first start. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(30), 0.030f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(30), 30, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(30), 30000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(30), 30000, p_timer->read_high_resolution_us()); -} - -/* This test verifies Timer float operator. - * - * Note this function assumes that Timer uses os ticker. - * - * Given timer is created and a time period time is counted. - * When timer object is casted on float type. - * Then counted type in seconds is returned by means of - * read() function. - */ -void test_timer_float_operator_os_ticker() -{ - /* Start the timer. */ - p_timer->start(); - - /* Wait 10 ms. */ - busy_wait_ms(10); - - /* Stop the timer. */ - p_timer->stop(); - - /* Check result - 10 ms elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, (float)(*p_timer)); -} - -/* This test verifies Timer float operator. - * - * Note this function assumes that Timer uses user ticker. - * - * Given timer is created and a time period time is counted. - * When timer object is casted on float type. - * Then counted type in seconds is returned by means of - * read() function. - */ -void test_timer_float_operator_user_ticker() -{ - /* For timer which is using user ticker set current - * time (irrelevant in case of os ticker). */ - curr_ticker_ticks_val = 0; - - /* Start the timer. */ - p_timer->start(); - - /* Simulate that 10 ms have elapsed. */ - curr_ticker_ticks_val = 10000; - - /* Stop the timer. */ - p_timer->stop(); - - /* Check result - 10 ms elapsed. */ - TEST_ASSERT_EQUAL_FLOAT(0.010f, (float)(*p_timer)); + TEST_ASSERT_DURATION_WITHIN(delta(30ms), 30ms, p_timer->elapsed_time()); } /* This test verifies if time counted by the timer is @@ -737,20 +645,19 @@ void test_timer_float_operator_user_ticker() template void test_timer_time_measurement() { + microseconds wait_val(wait_val_us); + /* Start the timer. */ p_timer->start(); /* Wait us. */ - busy_wait_us(wait_val_us); + busy_wait(wait_val); /* Stop the timer. */ p_timer->stop(); /* Check results. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(wait_val_us / US_PER_MSEC), (float)wait_val_us / US_PER_SEC, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(wait_val_us / US_PER_MSEC), wait_val_us / US_PER_MSEC, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(wait_val_us / US_PER_MSEC), wait_val_us, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(wait_val_us / US_PER_MSEC), wait_val_us, p_timer->read_high_resolution_us()); + TEST_ASSERT_DURATION_WITHIN(delta(wait_val), wait_val, p_timer->elapsed_time()); } utest::v1::status_t test_setup(const size_t number_of_cases) @@ -760,25 +667,22 @@ utest::v1::status_t test_setup(const size_t number_of_cases) } Case cases[] = { - Case("Test: Timer (based on os ticker) is stopped after creation.", timer_os_ticker_setup_handler, test_timer_creation_os_ticker, cleanup_handler), - Case("Test: Timer (based on user ticker) is stopped after creation.", timer_user_ticker_setup_handler, test_timer_creation_user_ticker, cleanup_handler), + Case("Test: Timer (based on os ticker) is stopped after creation.", timer_os_ticker_setup_handler, test_timer_creation_os_ticker, timer_os_ticker_cleanup_handler), + Case("Test: Timer (based on user ticker) is stopped after creation.", timer_user_ticker_setup_handler, test_timer_creation_user_ticker, timer_user_ticker_cleanup_handler), - Case("Test: Timer (based on os ticker) - measured time accumulation.", timer_os_ticker_setup_handler, test_timer_time_accumulation_os_ticker, cleanup_handler), - Case("Test: Timer (based on user ticker) measured time accumulation.", timer_user_ticker_setup_handler, test_timer_time_accumulation_user_ticker, cleanup_handler), + Case("Test: Timer (based on os ticker) - measured time accumulation.", timer_os_ticker_setup_handler, test_timer_time_accumulation_os_ticker, timer_os_ticker_cleanup_handler), + Case("Test: Timer (based on user ticker) measured time accumulation.", timer_user_ticker_setup_handler, test_timer_time_accumulation_user_ticker, timer_user_ticker_cleanup_handler), - Case("Test: Timer (based on os ticker) - reset.", timer_os_ticker_setup_handler, test_timer_reset_os_ticker, cleanup_handler), - Case("Test: Timer (based on user ticker) - reset.", timer_user_ticker_setup_handler, test_timer_reset_user_ticker, cleanup_handler), + Case("Test: Timer (based on os ticker) - reset.", timer_os_ticker_setup_handler, test_timer_reset_os_ticker, timer_os_ticker_cleanup_handler), + Case("Test: Timer (based on user ticker) - reset.", timer_user_ticker_setup_handler, test_timer_reset_user_ticker, timer_user_ticker_cleanup_handler), - Case("Test: Timer (based on os ticker) - start started timer.", timer_os_ticker_setup_handler, test_timer_start_started_timer_os_ticker, cleanup_handler), - Case("Test: Timer (based on user ticker) - start started timer.", timer_user_ticker_setup_handler, test_timer_start_started_timer_user_ticker, cleanup_handler), + Case("Test: Timer (based on os ticker) - start started timer.", timer_os_ticker_setup_handler, test_timer_start_started_timer_os_ticker, timer_os_ticker_cleanup_handler), + Case("Test: Timer (based on user ticker) - start started timer.", timer_user_ticker_setup_handler, test_timer_start_started_timer_user_ticker, timer_user_ticker_cleanup_handler), - Case("Test: Timer (based on os ticker) - float operator.", timer_os_ticker_setup_handler, test_timer_float_operator_os_ticker, cleanup_handler), - Case("Test: Timer (based on user ticker) - float operator.", timer_user_ticker_setup_handler, test_timer_float_operator_user_ticker, cleanup_handler), - - Case("Test: Timer - time measurement 1 ms.", timer_os_ticker_setup_handler, test_timer_time_measurement<1000>, cleanup_handler), - Case("Test: Timer - time measurement 10 ms.", timer_os_ticker_setup_handler, test_timer_time_measurement<10000>, cleanup_handler), - Case("Test: Timer - time measurement 100 ms.", timer_os_ticker_setup_handler, test_timer_time_measurement<100000>, cleanup_handler), - Case("Test: Timer - time measurement 1 s.", timer_os_ticker_setup_handler, test_timer_time_measurement<1000000>, cleanup_handler), + Case("Test: Timer - time measurement 1 ms.", timer_os_ticker_setup_handler, test_timer_time_measurement<1000>, timer_os_ticker_cleanup_handler), + Case("Test: Timer - time measurement 10 ms.", timer_os_ticker_setup_handler, test_timer_time_measurement<10000>, timer_os_ticker_cleanup_handler), + Case("Test: Timer - time measurement 100 ms.", timer_os_ticker_setup_handler, test_timer_time_measurement<100000>, timer_os_ticker_cleanup_handler), + Case("Test: Timer - time measurement 1 s.", timer_os_ticker_setup_handler, test_timer_time_measurement<1000000>, timer_os_ticker_cleanup_handler), }; Specification specification(test_setup, cases); diff --git a/TESTS/mbedmicro-rtos-mbed/kernel_tick_count/main.cpp b/TESTS/mbedmicro-rtos-mbed/kernel_tick_count/main.cpp index 59b4954959..0b72099ea5 100644 --- a/TESTS/mbedmicro-rtos-mbed/kernel_tick_count/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/kernel_tick_count/main.cpp @@ -48,7 +48,7 @@ using utest::v1::Case; #define TEST_ASSERT_DURATION_WITHIN(delta, expected, actual) \ do { \ using ct = std::common_type_t; \ - TEST_ASSERT_WITHIN(ct(delta).count(), ct(expected).count(), ct(actual).count()); \ + TEST_ASSERT_INT_WITHIN(ct(delta).count(), ct(expected).count(), ct(actual).count()); \ } while (0) /** Test if declared kernel ticker frequency is 1kHz diff --git a/TESTS/mbedmicro-rtos-mbed/mutex/main.cpp b/TESTS/mbedmicro-rtos-mbed/mutex/main.cpp index 5b91f83c4e..52705edf91 100644 --- a/TESTS/mbedmicro-rtos-mbed/mutex/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/mutex/main.cpp @@ -27,6 +27,14 @@ #include "unity.h" #include "utest.h" #include "rtos.h" +#include + +#define TEST_ASSERT_DURATION_WITHIN(delta, expected, actual) \ + do { \ + using ct = std::common_type_t; \ + TEST_ASSERT_INT_WITHIN(ct(delta).count(), ct(expected).count(), ct(actual).count()); \ + } while (0) + using namespace utest::v1; using namespace std::chrono; @@ -47,7 +55,7 @@ volatile int change_counter = 0; volatile bool changing_counter = false; volatile bool mutex_defect = false; -bool manipulate_protected_zone(const int thread_delay) +bool manipulate_protected_zone(const Kernel::Clock::duration thread_delay) { bool result = true; osStatus stat; @@ -75,7 +83,7 @@ bool manipulate_protected_zone(const int thread_delay) return result; } -void test_thread(int const *thread_delay) +void test_thread(Kernel::Clock::duration const *thread_delay) { while (true) { manipulate_protected_zone(*thread_delay); @@ -201,7 +209,7 @@ void test_dual_thread_lock_lock_thread(Mutex *mutex) bool stat = mutex->trylock_for(TEST_DELAY); TEST_ASSERT_EQUAL(false, stat); - TEST_ASSERT_UINT32_WITHIN(5000, TEST_DELAY * 1000, timer.read_us()); + TEST_ASSERT_DURATION_WITHIN(5ms, TEST_DELAY, timer.elapsed_time()); } /** Test dual thread lock diff --git a/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp b/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp index f50d580a7a..6999f018d7 100644 --- a/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp @@ -23,42 +23,63 @@ #include "platform/source/SysTimer.h" +using namespace std::chrono; + #define TEST_TICKS 42 -#define TEST_TICK_US (TEST_TICKS * 1000) -#define DELAY_DELTA_US 2500ULL +#define TEST_TICK_PERIOD std::ratio::type +#define TEST_TICK_DURATION duration +#define DELAY TEST_TICK_DURATION(1) +#define DELAY_DELTA 2500us + +#define TEST_ASSERT_EQUAL_DURATION(expected, actual) \ + do { \ + using ct = std::common_type_t; \ + TEST_ASSERT_EQUAL(ct(expected).count(), ct(actual).count()); \ + } while (0) + +#define TEST_ASSERT_EQUAL_TIME_POINT(expected, actual) \ + do { \ + using ct = std::common_type_t; \ + TEST_ASSERT_EQUAL(ct(expected).time_since_epoch().count(), ct(actual).time_since_epoch().count()); \ + } while (0) + +#define TEST_ASSERT_DURATION_WITHIN(delta, expected, actual) \ + do { \ + using ct = std::common_type_t; \ + TEST_ASSERT_INT_WITHIN(ct(delta).count(), ct(expected).count(), ct(actual).count()); \ + } while (0) + /* Use a specific delta value for deep sleep, as entry/exit adds up extra latency. * Use deep sleep latency if defined and add 1ms extra delta */ #if defined MBED_CONF_TARGET_DEEP_SLEEP_LATENCY -#define DEEP_SLEEP_DELAY_DELTA_US ((MBED_CONF_TARGET_DEEP_SLEEP_LATENCY * 1000ULL) + 1000ULL) +#define DEEP_SLEEP_DELAY_DELTA milliseconds(MBED_CONF_TARGET_DEEP_SLEEP_LATENCY + 1) #else -#define DEEP_SLEEP_DELAY_DELTA_US 2500ULL +#define DEEP_SLEEP_DELAY_DELTA 2500us #endif using namespace utest::v1; using mbed::internal::SysTimer; -const us_timestamp_t DELAY_US = TEST_TICK_US; - // The SysTick interrupt must not be set as pending by the test code. -template -class SysTimerTest: public SysTimer { +template +class SysTimerTest: public SysTimer { private: Semaphore _sem; virtual void handler() { _sem.release(); - SysTimer::handler(); + SysTimer::handler(); } public: SysTimerTest() : - SysTimer(), _sem(0, 1) + SysTimer(), _sem(0, 1) { } SysTimerTest(const ticker_data_t *data) : - SysTimer(data), _sem(0, 1) + SysTimer(data), _sem(0, 1) { } @@ -66,7 +87,7 @@ public: { } - bool sem_try_acquire(uint32_t millisec) + bool sem_try_acquire(rtos::Kernel::Clock::duration_u32 millisec) { return _sem.try_acquire_for(millisec); } @@ -77,7 +98,7 @@ public: } }; -timestamp_t mock_ticker_timestamp; +duration mock_ticker_timestamp; void mock_ticker_init() { @@ -85,7 +106,7 @@ void mock_ticker_init() uint32_t mock_ticker_read() { - return mock_ticker_timestamp; + return mock_ticker_timestamp.count(); } void mock_ticker_disable_interrupt() @@ -137,7 +158,7 @@ const ticker_data_t mock_ticker_data = { void mock_ticker_reset() { - mock_ticker_timestamp = 0; + mock_ticker_timestamp = 0s; memset(&mock_ticker_event_queue, 0, sizeof mock_ticker_event_queue); } @@ -149,8 +170,9 @@ void mock_ticker_reset() */ void test_created_with_zero_tick_count(void) { - SysTimerTest<1000> st; - TEST_ASSERT_EQUAL_UINT32(0, st.get_tick()); + SysTimerTest st; + using time_point = decltype(st)::time_point; + TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(0)), st.get_tick()); } /** Test tick count is updated correctly @@ -167,20 +189,21 @@ void test_created_with_zero_tick_count(void) void test_update_tick(void) { mock_ticker_reset(); - SysTimerTest<1000> st(&mock_ticker_data); - st.set_wake_time(st.get_tick() + TEST_TICKS * 2); + SysTimerTest st(&mock_ticker_data); + using time_point = decltype(st)::time_point; + st.set_wake_time(st.get_tick() + TEST_TICK_DURATION(2)); st.cancel_wake(); - TEST_ASSERT_EQUAL_UINT32(0, st.get_tick()); + TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(0)), st.get_tick()); - st.set_wake_time(st.get_tick() + TEST_TICKS * 2); - mock_ticker_timestamp = DELAY_US; + st.set_wake_time(st.get_tick() + TEST_TICK_DURATION(2)); + mock_ticker_timestamp = TEST_TICK_DURATION(1); st.cancel_wake(); - TEST_ASSERT_EQUAL_UINT32(TEST_TICKS, st.update_and_get_tick()); - TEST_ASSERT_EQUAL_UINT32(TEST_TICKS, st.get_tick()); + TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(1)), st.update_and_get_tick()); + TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(1)), st.get_tick()); - st.set_wake_time(st.get_tick() + TEST_TICKS * 2); + st.set_wake_time(st.get_tick() + TEST_TICK_DURATION(2)); st.cancel_wake(); - TEST_ASSERT_EQUAL_UINT32(TEST_TICKS, st.get_tick()); + TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(1)), st.get_tick()); } /** Test get_time returns correct time @@ -192,12 +215,12 @@ void test_update_tick(void) void test_get_time(void) { mock_ticker_reset(); - SysTimerTest<1000> st(&mock_ticker_data); - us_timestamp_t t1 = st.get_time(); + SysTimerTest st(&mock_ticker_data); + auto t1 = st.get_time(); - mock_ticker_timestamp = DELAY_US; - us_timestamp_t t2 = st.get_time(); - TEST_ASSERT_EQUAL_UINT64(DELAY_US, t2 - t1); + mock_ticker_timestamp = TEST_TICK_DURATION(1); + auto t2 = st.get_time(); + TEST_ASSERT_EQUAL_DURATION(TEST_TICK_DURATION(1), t2 - t1); } /** Test cancel_tick @@ -209,14 +232,15 @@ void test_get_time(void) */ void test_cancel_tick(void) { - SysTimerTest st; + SysTimerTest st; + using time_point = decltype(st)::time_point; st.cancel_tick(); st.start_tick(); st.cancel_tick(); - bool acquired = st.sem_try_acquire((DELAY_US + DELAY_DELTA_US) / 1000ULL); + bool acquired = st.sem_try_acquire(duration_cast(TEST_TICK_DURATION(1) + DELAY_DELTA)); TEST_ASSERT_FALSE(acquired); - TEST_ASSERT_EQUAL_UINT32(0, st.get_tick()); + TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(0)), st.get_tick()); } /** Test handler called twice @@ -230,29 +254,30 @@ void test_cancel_tick(void) */ void test_handler_called_twice(void) { - SysTimerTest st; - us_timestamp_t t1 = st.get_time(); - bool acquired = st.sem_try_acquire(0); + SysTimerTest st; + using time_point = decltype(st)::time_point; + auto t1 = st.get_time(); + bool acquired = st.sem_try_acquire(0s); TEST_ASSERT_FALSE(acquired); st.start_tick(); // Wait in a busy loop to prevent entering sleep or deepsleep modes. do { - acquired = st.sem_try_acquire(0); + acquired = st.sem_try_acquire(0s); } while (!acquired); - us_timestamp_t t2 = st.get_time(); + auto t2 = st.get_time(); TEST_ASSERT_TRUE(acquired); - TEST_ASSERT_EQUAL_UINT32(1, st.get_tick()); - TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, t2 - t1); + TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(1)), st.get_tick()); + TEST_ASSERT_DURATION_WITHIN(DELAY_DELTA, TEST_TICK_DURATION(1), t2 - t1); // Wait in a busy loop to prevent entering sleep or deepsleep modes. do { - acquired = st.sem_try_acquire(0); + acquired = st.sem_try_acquire(0s); } while (!acquired); t2 = st.get_time(); TEST_ASSERT_TRUE(acquired); - TEST_ASSERT_EQUAL_UINT32(2, st.get_tick()); - TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US * 2, t2 - t1); + TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(2)), st.get_tick()); + TEST_ASSERT_DURATION_WITHIN(DELAY_DELTA, TEST_TICK_DURATION(2), t2 - t1); st.cancel_tick(); } @@ -269,7 +294,7 @@ void test_handler_called_twice(void) void test_sleep(void) { Timer timer; - SysTimerTest st; + SysTimerTest st; sleep_manager_lock_deep_sleep(); timer.start(); @@ -282,7 +307,7 @@ void test_sleep(void) st.cancel_tick(); sleep_manager_unlock_deep_sleep(); - TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, timer.read_high_resolution_us()); + TEST_ASSERT_DURATION_WITHIN(DELAY_DELTA, TEST_TICK_DURATION(1), timer.elapsed_time()); } #if DEVICE_LPTICKER && !MBED_CONF_TARGET_TICKLESS_FROM_US_TICKER @@ -305,10 +330,10 @@ void test_deepsleep(void) * hardware buffers are empty. However, such an API does not exist now, * so we'll use the ThisThread::sleep_for() function for now. */ - ThisThread::sleep_for(10); + ThisThread::sleep_for(10ms); // Regular Timer might be disabled during deepsleep. LowPowerTimer lptimer; - SysTimerTest st; + SysTimerTest st; lptimer.start(); st.start_tick(); @@ -317,7 +342,7 @@ void test_deepsleep(void) lptimer.stop(); st.cancel_tick(); - TEST_ASSERT_UINT64_WITHIN(DEEP_SLEEP_DELAY_DELTA_US, DELAY_US, lptimer.read_high_resolution_us()); + TEST_ASSERT_DURATION_WITHIN(DEEP_SLEEP_DELAY_DELTA, TEST_TICK_DURATION(1), lptimer.elapsed_time()); } #endif #endif diff --git a/TESTS/mbedmicro-rtos-mbed/threads/SynchronizedIntegral.h b/TESTS/mbedmicro-rtos-mbed/threads/SynchronizedIntegral.h index 8618fa0bec..148f1894d8 100644 --- a/TESTS/mbedmicro-rtos-mbed/threads/SynchronizedIntegral.h +++ b/TESTS/mbedmicro-rtos-mbed/threads/SynchronizedIntegral.h @@ -35,35 +35,35 @@ public: // preincrement operator T operator++() { - lock_guard lock(_mutex); + lock_guard lock(_mutex); return ++_value; } // predecrement operator T operator--() { - lock_guard lock(_mutex); + lock_guard lock(_mutex); return --_value; } // post increment operator T operator++(int) { - lock_guard lock(_mutex); + lock_guard lock(_mutex); return _value++; } // post decrement operator T operator--(int) { - lock_guard lock(_mutex); + lock_guard lock(_mutex); return _value--; } // conversion operator, used also for <,>,<=,>=,== and != operator T() const { - lock_guard lock(_mutex); + lock_guard lock(_mutex); return _value; } diff --git a/TESTS/mbedmicro-rtos-mbed/threads/main.cpp b/TESTS/mbedmicro-rtos-mbed/threads/main.cpp index 8c410416fe..b637ecc0d8 100644 --- a/TESTS/mbedmicro-rtos-mbed/threads/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/threads/main.cpp @@ -29,6 +29,7 @@ #include "rtos.h" #include "SynchronizedIntegral.h" #include +#include #define THREAD_STACK_SIZE 512 #if defined(__CORTEX_A9) || defined(__CORTEX_M23) || defined(__CORTEX_M33) || defined(TARGET_ARM_FM) || defined(TARGET_CY8CKIT_062_WIFI_BT_PSA) @@ -39,6 +40,12 @@ #define CHILD_THREAD_STACK_SIZE 384 #endif +#define TEST_ASSERT_DURATION_WITHIN(delta, expected, actual) \ + do { \ + using ct = std::common_type_t; \ + TEST_ASSERT_INT_WITHIN(ct(delta).count(), ct(expected).count(), ct(actual).count()); \ + } while (0) + using namespace utest::v1; using mstd::lock_guard; @@ -67,7 +74,7 @@ void increment_with_yield(counter_t *counter) void increment_with_wait(counter_t *counter) { - ThisThread::sleep_for(100); + ThisThread::sleep_for(100ms); (*counter)++; } @@ -93,7 +100,7 @@ void increment_with_murder(counter_t *counter) { // take ownership of the counter mutex so it prevent the child to // modify counter. - lock_guard lock(counter->internal_mutex()); + lock_guard lock(counter->internal_mutex()); Thread *child = new (std::nothrow) Thread(osPriorityNormal, CHILD_THREAD_STACK_SIZE); char *dummy = new (std::nothrow) char[CHILD_THREAD_STACK_SIZE]; delete[] dummy; @@ -476,7 +483,7 @@ void test_thread_wait() ThisThread::sleep_for(150ms); - TEST_ASSERT_UINT32_WITHIN(50000, 150000, timer.read_us()); + TEST_ASSERT_DURATION_WITHIN(50ms, 150ms, timer.elapsed_time()); } /** Testing thread name @@ -703,7 +710,7 @@ void test_msg_get() void test_msg_put_thread(Queue *queue) { - queue->put((int32_t *)0xDEADBEEF, osWaitForever); + queue->put((int32_t *)0xDEADBEEF, Kernel::wait_for_u32_forever); } diff --git a/platform/source/SysTimer.h b/platform/source/SysTimer.h index 76e54f41e5..229d535695 100644 --- a/platform/source/SysTimer.h +++ b/platform/source/SysTimer.h @@ -74,8 +74,10 @@ public: SysTimer(const ticker_data_t *data); - virtual ~SysTimer(); +protected: + ~SysTimer(); +public: /** * Get the interrupt number for the tick * @@ -237,7 +239,7 @@ public: protected: using highres_duration_u32 = std::chrono::duration; - virtual void handler(); + void handler() override; void _increment_tick(); void _schedule_tick(); duration _elapsed_ticks() const;