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 #if !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 const ticker_info_t *mock_ticker_get_info() 00103 { 00104 static const ticker_info_t mock_ticker_info = { 00105 .frequency = 1000000, 00106 .bits = 32 00107 }; 00108 return &mock_ticker_info; 00109 } 00110 00111 ticker_interface_t mock_ticker_interface = { 00112 .init = mock_ticker_init, 00113 .read = mock_ticker_read, 00114 .disable_interrupt = mock_ticker_disable_interrupt, 00115 .clear_interrupt = mock_ticker_clear_interrupt, 00116 .set_interrupt = mock_ticker_set_interrupt, 00117 .fire_interrupt = mock_ticker_fire_interrupt, 00118 .get_info = mock_ticker_get_info, 00119 }; 00120 00121 ticker_event_queue_t mock_ticker_event_queue; 00122 00123 const ticker_data_t mock_ticker_data = { 00124 .interface = &mock_ticker_interface, 00125 .queue = &mock_ticker_event_queue 00126 }; 00127 00128 void mock_ticker_reset() 00129 { 00130 mock_ticker_timestamp = 0; 00131 memset(&mock_ticker_event_queue, 0, sizeof mock_ticker_event_queue); 00132 } 00133 00134 /** Test tick count is zero upon creation 00135 * 00136 * Given a SysTimer 00137 * When the timer is created 00138 * Then tick count is zero 00139 */ 00140 void test_created_with_zero_tick_count(void) 00141 { 00142 SysTimerTest st; 00143 TEST_ASSERT_EQUAL_UINT32(0, st.get_tick()); 00144 } 00145 00146 /** Test tick count is updated correctly 00147 * 00148 * Given a SysTimer 00149 * When the @a suspend and @a resume methods are called immediately after creation 00150 * Then the tick count is not updated 00151 * When @a suspend and @a resume methods are called again after a delay 00152 * Then the tick count is updated 00153 * and the number of ticks incremented is equal TEST_TICKS - 1 00154 * When @a suspend and @a resume methods are called again without a delay 00155 * Then the tick count is not updated 00156 */ 00157 void test_update_tick(void) 00158 { 00159 mock_ticker_reset(); 00160 SysTimerTest st(&mock_ticker_data); 00161 st.suspend(TEST_TICKS * 2); 00162 TEST_ASSERT_EQUAL_UINT32(0, st.resume()); 00163 TEST_ASSERT_EQUAL_UINT32(0, st.get_tick()); 00164 00165 st.suspend(TEST_TICKS * 2); 00166 mock_ticker_timestamp = DELAY_US; 00167 TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.resume()); 00168 TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick()); 00169 00170 st.suspend(TEST_TICKS * 2); 00171 TEST_ASSERT_EQUAL_UINT32(0, st.resume()); 00172 TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick()); 00173 } 00174 00175 /** Test get_time returns correct time 00176 * 00177 * Given a SysTimer 00178 * When @a get_time method is called before and after a delay 00179 * Then time difference is equal the delay 00180 */ 00181 void test_get_time(void) 00182 { 00183 mock_ticker_reset(); 00184 SysTimerTest st(&mock_ticker_data); 00185 us_timestamp_t t1 = st.get_time(); 00186 00187 mock_ticker_timestamp = DELAY_US; 00188 us_timestamp_t t2 = st.get_time(); 00189 TEST_ASSERT_EQUAL_UINT64(DELAY_US, t2 - t1); 00190 } 00191 00192 /** Test cancel_tick 00193 * 00194 * Given a SysTimer with a scheduled tick 00195 * When @a cancel_tick is called before the given number of ticks elapse 00196 * Then the handler is never called 00197 * and the tick count is not incremented 00198 */ 00199 void test_cancel_tick(void) 00200 { 00201 SysTimerTest st; 00202 st.cancel_tick(); 00203 st.schedule_tick(TEST_TICKS); 00204 00205 st.cancel_tick(); 00206 int32_t sem_slots = st.sem_wait((DELAY_US + DELAY_DELTA_US) / 1000ULL); 00207 TEST_ASSERT_EQUAL_INT32(0, sem_slots); 00208 TEST_ASSERT_EQUAL_UINT32(0, st.get_tick()); 00209 } 00210 00211 /** Test schedule zero 00212 * 00213 * Given a SysTimer 00214 * When a tick is scheduled with delta = 0 ticks 00215 * Then the handler is called instantly 00216 */ 00217 void test_schedule_zero(void) 00218 { 00219 SysTimerTest st; 00220 00221 st.schedule_tick(0UL); 00222 int32_t sem_slots = st.sem_wait(0UL); 00223 TEST_ASSERT_EQUAL_INT32(1, sem_slots); 00224 } 00225 00226 /** Test handler called once 00227 * 00228 * Given a SysTimer with a tick scheduled with delta = TEST_TICKS 00229 * When the handler is called 00230 * Then the tick count is incremented by 1 00231 * and elapsed time is equal 1000000ULL * TEST_TICKS / OS_TICK_FREQ; 00232 * When more time elapses 00233 * Then the handler is not called again 00234 */ 00235 void test_handler_called_once(void) 00236 { 00237 SysTimerTest st; 00238 st.schedule_tick(TEST_TICKS); 00239 us_timestamp_t t1 = st.get_time(); 00240 int32_t sem_slots = st.sem_wait(0); 00241 TEST_ASSERT_EQUAL_INT32(0, sem_slots); 00242 00243 sem_slots = st.sem_wait(osWaitForever); 00244 us_timestamp_t t2 = st.get_time(); 00245 TEST_ASSERT_EQUAL_INT32(1, sem_slots); 00246 TEST_ASSERT_EQUAL_UINT32(1, st.get_tick()); 00247 TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, t2 - t1); 00248 00249 sem_slots = st.sem_wait((DELAY_US + DELAY_DELTA_US) / 1000ULL); 00250 TEST_ASSERT_EQUAL_INT32(0, sem_slots); 00251 TEST_ASSERT_EQUAL_UINT32(1, st.get_tick()); 00252 } 00253 00254 #if DEVICE_SLEEP 00255 /** Test wake up from sleep 00256 * 00257 * Given a SysTimer with a tick scheduled in the future 00258 * and a core in sleep mode 00259 * When given time elapses 00260 * Then the uC is woken up from sleep 00261 * and the tick handler is called 00262 * and measured time matches requested delay 00263 */ 00264 void test_sleep(void) 00265 { 00266 Timer timer; 00267 SysTimerTest st; 00268 00269 sleep_manager_lock_deep_sleep(); 00270 timer.start(); 00271 st.schedule_tick(TEST_TICKS); 00272 00273 TEST_ASSERT_FALSE_MESSAGE(sleep_manager_can_deep_sleep(), "Deep sleep should be disallowed"); 00274 while (st.sem_wait(0) != 1) { 00275 sleep(); 00276 } 00277 timer.stop(); 00278 sleep_manager_unlock_deep_sleep(); 00279 00280 TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, timer.read_high_resolution_us()); 00281 } 00282 00283 #if DEVICE_LPTICKER 00284 /** Test wake up from deepsleep 00285 * 00286 * Given a SysTimer with a tick scheduled in the future 00287 * and a core in deepsleep mode 00288 * When given time elapses 00289 * Then the uC is woken up from deepsleep 00290 * and the tick handler is called 00291 * and measured time matches requested delay 00292 */ 00293 void test_deepsleep(void) 00294 { 00295 /* 00296 * Since deepsleep() may shut down the UART peripheral, we wait for 10ms 00297 * to allow for hardware serial buffers to completely flush. 00298 00299 * This should be replaced with a better function that checks if the 00300 * hardware buffers are empty. However, such an API does not exist now, 00301 * so we'll use the wait_ms() function for now. 00302 */ 00303 wait_ms(10); 00304 00305 // Regular Timer might be disabled during deepsleep. 00306 LowPowerTimer lptimer; 00307 SysTimerTest st; 00308 00309 lptimer.start(); 00310 st.schedule_tick(TEST_TICKS); 00311 TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep(), "Deep sleep should be allowed"); 00312 while (st.sem_wait(0) != 1) { 00313 sleep(); 00314 } 00315 lptimer.stop(); 00316 00317 TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, lptimer.read_high_resolution_us()); 00318 } 00319 #endif 00320 #endif 00321 00322 utest::v1::status_t test_setup(const size_t number_of_cases) 00323 { 00324 GREENTEA_SETUP(5, "default_auto"); 00325 return verbose_test_setup_handler(number_of_cases); 00326 } 00327 00328 Case cases[] = { 00329 Case("Tick count is zero upon creation", test_created_with_zero_tick_count), 00330 Case("Tick count is updated correctly", test_update_tick), 00331 Case("Time is updated correctly", test_get_time), 00332 Case("Tick can be cancelled", test_cancel_tick), 00333 Case("Schedule zero ticks", test_schedule_zero), 00334 Case("Handler called once", test_handler_called_once), 00335 #if DEVICE_SLEEP 00336 Case("Wake up from sleep", test_sleep), 00337 #if DEVICE_LPTICKER 00338 Case("Wake up from deep sleep", test_deepsleep), 00339 #endif 00340 #endif 00341 00342 }; 00343 00344 Specification specification(test_setup, cases); 00345 00346 int main() 00347 { 00348 return !Harness::run(specification); 00349 }
Generated on Tue Jul 12 2022 12:45:24 by
