Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Tue Aug 9 2022 00:37:14 by
1.7.2