BA / Mbed OS BaBoRo_test2
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2017 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #if !MBED_TICKLESS
00017 #error [NOT_SUPPORTED] Tickless mode not supported for this target.
00018 #endif
00019 
00020 #if !DEVICE_LOWPOWERTIMER
00021 #error [NOT_SUPPORTED] Current SysTimer implementation requires lp ticker support.
00022 #endif
00023 
00024 #include "mbed.h"
00025 #include "greentea-client/test_env.h"
00026 #include "unity.h"
00027 #include "utest.h"
00028 
00029 extern "C" {
00030 #include "rtx_lib.h"
00031 }
00032 #include "rtos/TARGET_CORTEX/SysTimer.h"
00033 
00034 #define TEST_TICKS 42UL
00035 #define DELAY_DELTA_US 2500ULL
00036 
00037 using namespace utest::v1;
00038 
00039 const us_timestamp_t DELAY_US = 1000000ULL * TEST_TICKS / OS_TICK_FREQ;
00040 
00041 // Override the handler() -- the SysTick interrupt must not be set as pending by the test code.
00042 class SysTimerTest: public rtos::internal::SysTimer {
00043 private:
00044     Semaphore _sem;
00045     virtual void handler()
00046     {
00047         increment_tick();
00048         _sem.release();
00049     }
00050 
00051 public:
00052     SysTimerTest() :
00053             SysTimer(), _sem(0, 1)
00054     {
00055     }
00056 
00057     virtual ~SysTimerTest()
00058     {
00059     }
00060 
00061     int32_t sem_wait(uint32_t millisec)
00062     {
00063         return _sem.wait(millisec);
00064     }
00065 };
00066 
00067 /** Test tick count is zero upon creation
00068  *
00069  * Given a SysTimer
00070  * When the timer is created
00071  * Then tick count is zero
00072  */
00073 void test_created_with_zero_tick_count(void)
00074 {
00075     SysTimerTest st;
00076     TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
00077 }
00078 
00079 /** Test tick count is updated correctly
00080  *
00081  * Given a SysTimer
00082  * When @a update_tick method is called immediately after creation
00083  * Then the tick count is not updated
00084  * When @a update_tick is called again after a delay
00085  * Then the tick count is updated
00086  *     and the number of ticks incremented is equal TEST_TICKS - 1
00087  * When @a update_tick is called again without a delay
00088  * Then the tick count is not updated
00089  */
00090 void test_update_tick(void)
00091 {
00092     SysTimerTest st;
00093     TEST_ASSERT_EQUAL_UINT32(0, st.update_tick());
00094     TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
00095     us_timestamp_t test_ticks_elapsed_ts = st.get_time() + DELAY_US;
00096 
00097     while (st.get_time() <= test_ticks_elapsed_ts) {}
00098     TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.update_tick());
00099     TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick());
00100 
00101     TEST_ASSERT_EQUAL_UINT32(0, st.update_tick());
00102     TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick());
00103 }
00104 
00105 /** Test get_time returns correct time
00106  *
00107  * Given a SysTimer
00108  * When @a get_time method is called before and after a delay
00109  * Then time difference is equal the delay
00110  */
00111 void test_get_time(void)
00112 {
00113     SysTimerTest st;
00114     us_timestamp_t t1 = st.get_time();
00115 
00116     wait_us(DELAY_US);
00117     us_timestamp_t t2 = st.get_time();
00118     TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, t2 - t1);
00119 }
00120 
00121 /** Test cancel_tick
00122  *
00123  * Given a SysTimer with a scheduled tick
00124  * When @a cancel_tick is called before the given number of ticks elapse
00125  * Then the handler is never called
00126  *     and the tick count is not incremented
00127  */
00128 void test_cancel_tick(void)
00129 {
00130     SysTimerTest st;
00131     st.cancel_tick();
00132     st.schedule_tick(TEST_TICKS);
00133 
00134     st.cancel_tick();
00135     int32_t sem_slots = st.sem_wait((DELAY_US + DELAY_DELTA_US) / 1000ULL);
00136     TEST_ASSERT_EQUAL_INT32(0, sem_slots);
00137     TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
00138 }
00139 
00140 /** Test schedule zero
00141  *
00142  * Given a SysTimer
00143  * When a tick is scheduled with delta = 0 ticks
00144  * Then the handler is called instantly
00145  */
00146 void test_schedule_zero(void)
00147 {
00148     SysTimerTest st;
00149 
00150     st.schedule_tick(0UL);
00151     int32_t sem_slots = st.sem_wait(0UL);
00152     TEST_ASSERT_EQUAL_INT32(1, sem_slots);
00153 }
00154 
00155 /** Test handler called once
00156  *
00157  * Given a SysTimer with a tick scheduled with delta = TEST_TICKS
00158  * When the handler is called
00159  * Then the tick count is incremented by 1
00160  *     and elapsed time is equal 1000000ULL * TEST_TICKS / OS_TICK_FREQ;
00161  * When more time elapses
00162  * Then the handler is not called again
00163  */
00164 void test_handler_called_once(void)
00165 {
00166     SysTimerTest st;
00167     st.schedule_tick(TEST_TICKS);
00168     us_timestamp_t t1 = st.get_time();
00169     int32_t sem_slots = st.sem_wait(0);
00170     TEST_ASSERT_EQUAL_INT32(0, sem_slots);
00171 
00172     sem_slots = st.sem_wait(osWaitForever);
00173     us_timestamp_t t2 = st.get_time();
00174     TEST_ASSERT_EQUAL_INT32(1, sem_slots);
00175     TEST_ASSERT_EQUAL_UINT32(1, st.get_tick());
00176     TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, t2 - t1);
00177 
00178     sem_slots = st.sem_wait((DELAY_US + DELAY_DELTA_US) / 1000ULL);
00179     TEST_ASSERT_EQUAL_INT32(0, sem_slots);
00180     TEST_ASSERT_EQUAL_UINT32(1, st.get_tick());
00181 }
00182 
00183 /** Test wake up from sleep
00184  *
00185  * Given a SysTimer with a tick scheduled in the future
00186  *     and a core in sleep mode
00187  * When given time elapses
00188  * Then the uC is woken up from sleep
00189  *     and the tick handler is called
00190  *     and measured time matches requested delay
00191  */
00192 void test_sleep(void)
00193 {
00194     Timer timer;
00195     SysTimerTest st;
00196 
00197     sleep_manager_lock_deep_sleep();
00198     timer.start();
00199     st.schedule_tick(TEST_TICKS);
00200 
00201     TEST_ASSERT_FALSE_MESSAGE(sleep_manager_can_deep_sleep(), "Deep sleep should be disallowed");
00202     while (st.sem_wait(0) != 1) {
00203         sleep();
00204     }
00205     timer.stop();
00206     sleep_manager_unlock_deep_sleep();
00207 
00208     TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, timer.read_high_resolution_us());
00209 }
00210 
00211 #if DEVICE_LOWPOWERTIMER
00212 /** Test wake up from deepsleep
00213  *
00214  * Given a SysTimer with a tick scheduled in the future
00215  *     and a core in deepsleep mode
00216  * When given time elapses
00217  * Then the uC is woken up from deepsleep
00218  *     and the tick handler is called
00219  *     and measured time matches requested delay
00220  */
00221 void test_deepsleep(void)
00222 {
00223     /*
00224      * Since deepsleep() may shut down the UART peripheral, we wait for 10ms
00225      * to allow for hardware serial buffers to completely flush.
00226 
00227      * This should be replaced with a better function that checks if the
00228      * hardware buffers are empty. However, such an API does not exist now,
00229      * so we'll use the wait_ms() function for now.
00230      */
00231     wait_ms(10);
00232 
00233     // Regular Timer might be disabled during deepsleep.
00234     LowPowerTimer lptimer;
00235     SysTimerTest st;
00236 
00237     lptimer.start();
00238     st.schedule_tick(TEST_TICKS);
00239     TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep(), "Deep sleep should be allowed");
00240     while (st.sem_wait(0) != 1) {
00241         sleep();
00242     }
00243     lptimer.stop();
00244 
00245     TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, lptimer.read_high_resolution_us());
00246 }
00247 #endif
00248 
00249 utest::v1::status_t test_setup(const size_t number_of_cases)
00250 {
00251     GREENTEA_SETUP(5, "default_auto");
00252     return verbose_test_setup_handler(number_of_cases);
00253 }
00254 
00255 Case cases[] = {
00256     Case("Tick count is zero upon creation", test_created_with_zero_tick_count),
00257     Case("Tick count is updated correctly", test_update_tick),
00258     Case("Time is updated correctly", test_get_time),
00259     Case("Tick can be cancelled", test_cancel_tick),
00260     Case("Schedule zero ticks", test_schedule_zero),
00261     Case("Handler called once", test_handler_called_once),
00262     Case("Wake up from sleep", test_sleep),
00263 #if DEVICE_LOWPOWERTIMER
00264     Case("Wake up from deep sleep", test_deepsleep),
00265 #endif
00266 
00267 };
00268 
00269 Specification specification(test_setup, cases);
00270 
00271 int main()
00272 {
00273     return !Harness::run(specification);
00274 }