/* mbed Microcontroller Library * Copyright (c) 2018-2018 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "greentea-client/test_env.h" #include "utest/utest.h" #include "unity/unity.h" #include "rtos/Kernel.h" #include "mbed.h" using utest::v1::Case; #define TEST_REPEAT_COUNT 1000 #define NUM_WAIT_TICKS 1000 // all in [us] #define ONE_SECOND 1000000 #define SMALL_DELTA 1500 // 0.15% #define BIG_DELTA 15000 // 1.5% /** Test if kernel ticker frequency is 1kHz Given a RTOS kernel ticker When check it frequency Then the the frequency is 1kHz */ void test_frequency() { uint32_t freq = osKernelGetTickFreq(); TEST_ASSERT_EQUAL_UINT32_MESSAGE(1000, freq, "Expected SysTick frequency is 1kHz"); } /** Test if kernel ticker increments by one Given a RTOS kernel ticker When perform subsequent calls of @a rtos::Kernel::get_ms_count Then subsequent reads should not differ by more than one */ void test_increment(void) { for (uint32_t i = 0; i < TEST_REPEAT_COUNT; i++) { const uint64_t start = rtos::Kernel::get_ms_count(); while (true) { uint64_t diff = rtos::Kernel::get_ms_count() - start; if (diff != 0) { TEST_ASSERT_EQUAL_UINT64(1, diff); break; } } } } /** Test if kernel ticker interval is 1ms Given a RTOS kernel ticker When perform subsequent calls of @a rtos::Kernel::get_ms_count Then the ticker interval should be 1ms */ void test_interval() { uint64_t start, stop; Timer timer; start = rtos::Kernel::get_ms_count(); // wait for tick do { stop = rtos::Kernel::get_ms_count(); } while ((stop - start) == 0); timer.start(); start = stop; // wait for NUM_WAIT_TICKS ticks do { stop = rtos::Kernel::get_ms_count(); } while ((stop - start) != NUM_WAIT_TICKS); timer.stop(); TEST_ASSERT_EQUAL_UINT64(NUM_WAIT_TICKS, (stop - start)); #if defined(NO_SYSTICK) || defined(MBED_TICKLESS) // On targets with NO_SYSTICK/MBED_TICKLESS enabled, systick is emulated by lp_ticker what makes it less accurate // for more details https://os.mbed.com/docs/latest/reference/tickless.html TEST_ASSERT_UINT64_WITHIN(BIG_DELTA, ONE_SECOND, timer.read_high_resolution_us()); #else TEST_ASSERT_UINT64_WITHIN(SMALL_DELTA, ONE_SECOND, timer.read_high_resolution_us()); #endif } // Test cases Case cases[] = { Case("Test kernel ticker frequency", test_frequency), Case("Test if kernel ticker increments by one", test_increment), Case("Test if kernel ticker interval is 1ms", test_interval) }; utest::v1::status_t greentea_test_setup(const size_t number_of_cases) { GREENTEA_SETUP(10, "timing_drift_auto"); return utest::v1::greentea_test_setup_handler(number_of_cases); } utest::v1::Specification specification(greentea_test_setup, cases); int main() { return !utest::v1::Harness::run(specification); }