takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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 #ifndef MBED_TICKLESS
00017 #error [NOT_SUPPORTED] Tickless mode not supported for this target.
00018 #endif
00019 
00020 #if !DEVICE_LPTICKER
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 #include "ticker_api.h"
00029 
00030 extern "C" {
00031 #include "rtx_lib.h"
00032 }
00033 #include "rtos/TARGET_CORTEX/SysTimer.h"
00034 
00035 #define TEST_TICKS 42UL
00036 #define DELAY_DELTA_US 2500ULL
00037 
00038 using namespace utest::v1;
00039 
00040 const us_timestamp_t DELAY_US = 1000000ULL * TEST_TICKS / OS_TICK_FREQ;
00041 
00042 // Override the handler() -- the SysTick interrupt must not be set as pending by the test code.
00043 class SysTimerTest: public rtos::internal::SysTimer {
00044 private:
00045     Semaphore _sem;
00046     virtual void handler()
00047     {
00048         core_util_critical_section_enter();
00049         _increment_tick();
00050         core_util_critical_section_exit();
00051         _sem.release();
00052     }
00053 
00054 public:
00055     SysTimerTest() :
00056         SysTimer(), _sem(0, 1)
00057     {
00058     }
00059 
00060     SysTimerTest(const ticker_data_t *data) :
00061         SysTimer(data), _sem(0, 1)
00062     {
00063     }
00064 
00065     virtual ~SysTimerTest()
00066     {
00067     }
00068 
00069     int32_t sem_wait(uint32_t millisec)
00070     {
00071         return _sem.wait(millisec);
00072     }
00073 };
00074 
00075 timestamp_t mock_ticker_timestamp;
00076 
00077 void mock_ticker_init()
00078 {
00079 }
00080 
00081 uint32_t mock_ticker_read()
00082 {
00083     return mock_ticker_timestamp;
00084 }
00085 
00086 void mock_ticker_disable_interrupt()
00087 {
00088 }
00089 
00090 void mock_ticker_clear_interrupt()
00091 {
00092 }
00093 
00094 void mock_ticker_set_interrupt(timestamp_t timestamp)
00095 {
00096 }
00097 
00098 void mock_ticker_fire_interrupt()
00099 {
00100 }
00101 
00102 void mock_ticker_free()
00103 {
00104 }
00105 
00106 const ticker_info_t *mock_ticker_get_info()
00107 {
00108     static const ticker_info_t mock_ticker_info = {
00109         .frequency = 1000000,
00110         .bits = 32
00111     };
00112     return &mock_ticker_info;
00113 }
00114 
00115 ticker_interface_t mock_ticker_interface = {
00116     .init = mock_ticker_init,
00117     .read = mock_ticker_read,
00118     .disable_interrupt = mock_ticker_disable_interrupt,
00119     .clear_interrupt = mock_ticker_clear_interrupt,
00120     .set_interrupt = mock_ticker_set_interrupt,
00121     .fire_interrupt = mock_ticker_fire_interrupt,
00122     .free = mock_ticker_free,
00123     .get_info = mock_ticker_get_info,
00124 };
00125 
00126 ticker_event_queue_t mock_ticker_event_queue;
00127 
00128 const ticker_data_t mock_ticker_data = {
00129     .interface = &mock_ticker_interface,
00130     .queue = &mock_ticker_event_queue
00131 };
00132 
00133 void mock_ticker_reset()
00134 {
00135     mock_ticker_timestamp = 0;
00136     memset(&mock_ticker_event_queue, 0, sizeof mock_ticker_event_queue);
00137 }
00138 
00139 /** Test tick count is zero upon creation
00140  *
00141  * Given a SysTimer
00142  * When the timer is created
00143  * Then tick count is zero
00144  */
00145 void test_created_with_zero_tick_count(void)
00146 {
00147     SysTimerTest st;
00148     TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
00149 }
00150 
00151 /** Test tick count is updated correctly
00152  *
00153  * Given a SysTimer
00154  * When the @a suspend and @a resume methods are called immediately after creation
00155  * Then the tick count is not updated
00156  * When @a suspend and @a resume methods are called again after a delay
00157  * Then the tick count is updated
00158  *     and the number of ticks incremented is equal TEST_TICKS - 1
00159  * When @a suspend and @a resume methods are called again without a delay
00160  * Then the tick count is not updated
00161  */
00162 void test_update_tick(void)
00163 {
00164     mock_ticker_reset();
00165     SysTimerTest st(&mock_ticker_data);
00166     st.suspend(TEST_TICKS * 2);
00167     TEST_ASSERT_EQUAL_UINT32(0, st.resume());
00168     TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
00169 
00170     st.suspend(TEST_TICKS * 2);
00171     mock_ticker_timestamp = DELAY_US;
00172     TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.resume());
00173     TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick());
00174 
00175     st.suspend(TEST_TICKS * 2);
00176     TEST_ASSERT_EQUAL_UINT32(0, st.resume());
00177     TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick());
00178 }
00179 
00180 /** Test get_time returns correct time
00181  *
00182  * Given a SysTimer
00183  * When @a get_time method is called before and after a delay
00184  * Then time difference is equal the delay
00185  */
00186 void test_get_time(void)
00187 {
00188     mock_ticker_reset();
00189     SysTimerTest st(&mock_ticker_data);
00190     us_timestamp_t t1 = st.get_time();
00191 
00192     mock_ticker_timestamp = DELAY_US;
00193     us_timestamp_t t2 = st.get_time();
00194     TEST_ASSERT_EQUAL_UINT64(DELAY_US, t2 - t1);
00195 }
00196 
00197 /** Test cancel_tick
00198  *
00199  * Given a SysTimer with a scheduled tick
00200  * When @a cancel_tick is called before the given number of ticks elapse
00201  * Then the handler is never called
00202  *     and the tick count is not incremented
00203  */
00204 void test_cancel_tick(void)
00205 {
00206     SysTimerTest st;
00207     st.cancel_tick();
00208     st.schedule_tick(TEST_TICKS);
00209 
00210     st.cancel_tick();
00211     int32_t sem_slots = st.sem_wait((DELAY_US + DELAY_DELTA_US) / 1000ULL);
00212     TEST_ASSERT_EQUAL_INT32(0, sem_slots);
00213     TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
00214 }
00215 
00216 /** Test schedule zero
00217  *
00218  * Given a SysTimer
00219  * When a tick is scheduled with delta = 0 ticks
00220  * Then the handler is called instantly
00221  */
00222 void test_schedule_zero(void)
00223 {
00224     SysTimerTest st;
00225 
00226     st.schedule_tick(0UL);
00227     int32_t sem_slots = st.sem_wait(0UL);
00228     TEST_ASSERT_EQUAL_INT32(1, sem_slots);
00229 }
00230 
00231 /** Test handler called once
00232  *
00233  * Given a SysTimer with a tick scheduled with delta = TEST_TICKS
00234  * When the handler is called
00235  * Then the tick count is incremented by 1
00236  *     and elapsed time is equal 1000000ULL * TEST_TICKS / OS_TICK_FREQ;
00237  * When more time elapses
00238  * Then the handler is not called again
00239  */
00240 void test_handler_called_once(void)
00241 {
00242     SysTimerTest st;
00243     st.schedule_tick(TEST_TICKS);
00244     us_timestamp_t t1 = st.get_time();
00245     int32_t sem_slots = st.sem_wait(0);
00246     TEST_ASSERT_EQUAL_INT32(0, sem_slots);
00247 
00248     sem_slots = st.sem_wait(osWaitForever);
00249     us_timestamp_t t2 = st.get_time();
00250     TEST_ASSERT_EQUAL_INT32(1, sem_slots);
00251     TEST_ASSERT_EQUAL_UINT32(1, st.get_tick());
00252     TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, t2 - t1);
00253 
00254     sem_slots = st.sem_wait((DELAY_US + DELAY_DELTA_US) / 1000ULL);
00255     TEST_ASSERT_EQUAL_INT32(0, sem_slots);
00256     TEST_ASSERT_EQUAL_UINT32(1, st.get_tick());
00257 }
00258 
00259 #if DEVICE_SLEEP
00260 /** Test wake up from sleep
00261  *
00262  * Given a SysTimer with a tick scheduled in the future
00263  *     and a core in sleep mode
00264  * When given time elapses
00265  * Then the uC is woken up from sleep
00266  *     and the tick handler is called
00267  *     and measured time matches requested delay
00268  */
00269 void test_sleep(void)
00270 {
00271     Timer timer;
00272     SysTimerTest st;
00273 
00274     sleep_manager_lock_deep_sleep();
00275     timer.start();
00276     st.schedule_tick(TEST_TICKS);
00277 
00278     TEST_ASSERT_FALSE_MESSAGE(sleep_manager_can_deep_sleep(), "Deep sleep should be disallowed");
00279     while (st.sem_wait(0) != 1) {
00280         sleep();
00281     }
00282     timer.stop();
00283     sleep_manager_unlock_deep_sleep();
00284 
00285     TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, timer.read_high_resolution_us());
00286 }
00287 
00288 #if DEVICE_LPTICKER
00289 /** Test wake up from deepsleep
00290  *
00291  * Given a SysTimer with a tick scheduled in the future
00292  *     and a core in deepsleep mode
00293  * When given time elapses
00294  * Then the uC is woken up from deepsleep
00295  *     and the tick handler is called
00296  *     and measured time matches requested delay
00297  */
00298 void test_deepsleep(void)
00299 {
00300     /*
00301      * Since deepsleep() may shut down the UART peripheral, we wait for 10ms
00302      * to allow for hardware serial buffers to completely flush.
00303 
00304      * This should be replaced with a better function that checks if the
00305      * hardware buffers are empty. However, such an API does not exist now,
00306      * so we'll use the wait_ms() function for now.
00307      */
00308     wait_ms(10);
00309 
00310     // Regular Timer might be disabled during deepsleep.
00311     LowPowerTimer lptimer;
00312     SysTimerTest st;
00313 
00314     lptimer.start();
00315     st.schedule_tick(TEST_TICKS);
00316     TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep_test_check(), "Deep sleep should be allowed");
00317     while (st.sem_wait(0) != 1) {
00318         sleep();
00319     }
00320     lptimer.stop();
00321 
00322     TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, lptimer.read_high_resolution_us());
00323 }
00324 #endif
00325 #endif
00326 
00327 utest::v1::status_t test_setup(const size_t number_of_cases)
00328 {
00329     GREENTEA_SETUP(5, "default_auto");
00330     return verbose_test_setup_handler(number_of_cases);
00331 }
00332 
00333 Case cases[] = {
00334     Case("Tick count is zero upon creation", test_created_with_zero_tick_count),
00335     Case("Tick count is updated correctly", test_update_tick),
00336     Case("Time is updated correctly", test_get_time),
00337     Case("Tick can be cancelled", test_cancel_tick),
00338     Case("Schedule zero ticks", test_schedule_zero),
00339     Case("Handler called once", test_handler_called_once),
00340 #if DEVICE_SLEEP
00341     Case("Wake up from sleep", test_sleep),
00342 #if DEVICE_LPTICKER
00343     Case("Wake up from deep sleep", test_deepsleep),
00344 #endif
00345 #endif
00346 
00347 };
00348 
00349 Specification specification(test_setup, cases);
00350 
00351 int main()
00352 {
00353     return !Harness::run(specification);
00354 }