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.
Fork of OmniWheels by
timeout_tests.h
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_TIMEOUT_TESTS_H 00017 #define MBED_TIMEOUT_TESTS_H 00018 00019 #include "mbed.h" 00020 #include "unity/unity.h" 00021 00022 #define NUM_TIMEOUTS 16 00023 #define DRIFT_TEST_PERIOD_US 10000 00024 00025 const float TEST_DELAY_S = 0.01; 00026 const uint32_t TEST_DELAY_MS = 1000.0F * TEST_DELAY_S; 00027 const us_timestamp_t TEST_DELAY_US = 1000000.0F * TEST_DELAY_S; 00028 00029 /* Timeouts are quite arbitrary due to large number of boards with varying level of accuracy */ 00030 #define LONG_DELTA_US (100000) 00031 #define SHORT_DELTA_US (2000) 00032 00033 void sem_callback(Semaphore *sem) 00034 { 00035 sem->release(); 00036 } 00037 00038 void cnt_callback(volatile uint32_t *cnt) 00039 { 00040 (*cnt)++; 00041 } 00042 00043 template<typename TimeoutType> 00044 class AttachTester: public TimeoutType { 00045 public: 00046 void attach_callback(Callback<void()> func, us_timestamp_t delay_us) 00047 { 00048 TimeoutType::attach(func, (float) delay_us / 1000000.0f); 00049 } 00050 }; 00051 00052 template<typename TimeoutType> 00053 class AttachUSTester: public TimeoutType { 00054 public: 00055 void attach_callback(Callback<void()> func, us_timestamp_t delay_us) 00056 { 00057 TimeoutType::attach_us(func, delay_us); 00058 } 00059 }; 00060 00061 /** Template for tests: callback called once 00062 * 00063 * Test callback called once 00064 * Given a Timeout object with a callback attached with @a attach() 00065 * When given time elapses 00066 * Then the callback is called exactly one time 00067 * 00068 * Test callback called once 00069 * Given a Timeout object with a callback attached with @a attach_us() 00070 * When given time elapses 00071 * Then the callback is called exactly one time 00072 */ 00073 template<typename T> 00074 void test_single_call(void) 00075 { 00076 Semaphore sem(0, 1); 00077 T timeout; 00078 00079 timeout.attach_callback(mbed::callback(sem_callback, &sem), TEST_DELAY_US); 00080 00081 int32_t sem_slots = sem.wait(0); 00082 TEST_ASSERT_EQUAL(0, sem_slots); 00083 00084 sem_slots = sem.wait(TEST_DELAY_MS + 1); 00085 TEST_ASSERT_EQUAL(1, sem_slots); 00086 00087 sem_slots = sem.wait(TEST_DELAY_MS + 1); 00088 TEST_ASSERT_EQUAL(0, sem_slots); 00089 00090 timeout.detach(); 00091 } 00092 00093 /** Template for tests: callback not called when cancelled 00094 * 00095 * Test callback not called when cancelled 00096 * Given a Timeout object with a callback attached with @a attach() 00097 * When the callback is detached before being called 00098 * Then the callback is never called 00099 * 00100 * Test callback not called when cancelled 00101 * Given a Timeout object with a callback attached with @a attach_us() 00102 * When the callback is detached before being called 00103 * Then the callback is never called 00104 */ 00105 template<typename T> 00106 void test_cancel(void) 00107 { 00108 Semaphore sem(0, 1); 00109 T timeout; 00110 00111 timeout.attach_callback(mbed::callback(sem_callback, &sem), 2.0f * TEST_DELAY_US); 00112 00113 int32_t sem_slots = sem.wait(TEST_DELAY_MS); 00114 TEST_ASSERT_EQUAL(0, sem_slots); 00115 timeout.detach(); 00116 00117 sem_slots = sem.wait(TEST_DELAY_MS + 1); 00118 TEST_ASSERT_EQUAL(0, sem_slots); 00119 } 00120 00121 /** Template for tests: callback override 00122 * 00123 * Test callback override 00124 * Given a Timeout object with a callback attached with @a attach() 00125 * When another callback is attached before first one is called 00126 * and second callback's delay elapses 00127 * Then the second callback is called 00128 * and the first callback is never called 00129 * 00130 * Test callback override 00131 * Given a Timeout object with a callback attached with @a attach_us() 00132 * When another callback is attached before first one is called 00133 * and second callback's delay elapses 00134 * Then the second callback is called 00135 * and the first callback is never called 00136 */ 00137 template<typename T> 00138 void test_override(void) 00139 { 00140 Semaphore sem1(0, 1); 00141 Semaphore sem2(0, 1); 00142 T timeout; 00143 00144 timeout.attach_callback(mbed::callback(sem_callback, &sem1), 2.0f * TEST_DELAY_US); 00145 00146 int32_t sem_slots = sem1.wait(TEST_DELAY_MS); 00147 TEST_ASSERT_EQUAL(0, sem_slots); 00148 timeout.attach_callback(mbed::callback(sem_callback, &sem2), 2.0f * TEST_DELAY_US); 00149 00150 sem_slots = sem2.wait(2 * TEST_DELAY_MS + 1); 00151 TEST_ASSERT_EQUAL(1, sem_slots); 00152 sem_slots = sem1.wait(0); 00153 TEST_ASSERT_EQUAL(0, sem_slots); 00154 00155 timeout.detach(); 00156 } 00157 00158 /** Template for tests: multiple Timeouts 00159 * 00160 * Test multiple Timeouts 00161 * Given multiple separate Timeout objects 00162 * When a callback is attached to all of these Timeout objects with @a attach() 00163 * and delay for every Timeout elapses 00164 * Then all callbacks are called 00165 * 00166 * Test multiple Timeouts 00167 * Given multiple separate Timeout objects 00168 * When a callback is attached to all of these Timeout objects with @a attach_us() 00169 * and delay for every Timeout elapses 00170 * Then all callbacks are called 00171 */ 00172 template<typename T> 00173 void test_multiple(void) 00174 { 00175 volatile uint32_t callback_count = 0; 00176 T timeouts[NUM_TIMEOUTS]; 00177 for (size_t i = 0; i < NUM_TIMEOUTS; i++) { 00178 timeouts[i].attach_callback(mbed::callback(cnt_callback, &callback_count), TEST_DELAY_US); 00179 } 00180 Thread::wait(TEST_DELAY_MS + 1); 00181 TEST_ASSERT_EQUAL(NUM_TIMEOUTS, callback_count); 00182 } 00183 00184 /** Template for tests: zero delay 00185 * 00186 * Test zero delay 00187 * Given a Timeout object 00188 * When a callback is attached with 0.0 s delay, with @a attach() 00189 * Then the callback is called instantly 00190 * 00191 * Test zero delay 00192 * Given a Timeout object 00193 * When a callback is attached with 0.0 s delay, with @a attach_us() 00194 * Then the callback is called instantly 00195 */ 00196 template<typename T> 00197 void test_no_wait(void) 00198 { 00199 Semaphore sem(0, 1); 00200 T timeout; 00201 timeout.attach_callback(mbed::callback(sem_callback, &sem), 0ULL); 00202 00203 int32_t sem_slots = sem.wait(0); 00204 TEST_ASSERT_EQUAL(1, sem_slots); 00205 timeout.detach(); 00206 } 00207 00208 /** Template for tests: accuracy of timeout delay 00209 * 00210 * Test delay accuracy 00211 * Given a Timeout object with a callback attached with @a attach() 00212 * When the callback is called 00213 * Then elapsed time matches given delay 00214 * 00215 * Test delay accuracy 00216 * Given a Timeout object with a callback attached with @a attach_us() 00217 * When the callback is called 00218 * Then elapsed time matches given delay 00219 */ 00220 template<typename T, us_timestamp_t delay_us, us_timestamp_t delta_us> 00221 void test_delay_accuracy(void) 00222 { 00223 Semaphore sem(0, 1); 00224 T timeout; 00225 Timer timer; 00226 00227 timer.start(); 00228 timeout.attach_callback(mbed::callback(sem_callback, &sem), delay_us); 00229 00230 int32_t sem_slots = sem.wait(osWaitForever); 00231 timer.stop(); 00232 TEST_ASSERT_EQUAL(1, sem_slots); 00233 TEST_ASSERT_UINT64_WITHIN(delta_us, delay_us, timer.read_high_resolution_us()); 00234 00235 timeout.detach(); 00236 } 00237 00238 #if DEVICE_SLEEP 00239 /** Template for tests: timeout during sleep 00240 * 00241 * Test timeout during sleep 00242 * Given a Timeout object with a callback attached with @a attach() 00243 * and the uC in a sleep mode 00244 * When given delay elapses 00245 * Then the callback is called 00246 * and elapsed time matches given delay 00247 * 00248 * Test timeout during sleep 00249 * Given a Timeout object with a callback attached with @a attach_us() 00250 * and the uC in a sleep mode 00251 * When given delay elapses 00252 * Then the callback is called 00253 * and elapsed time matches given delay 00254 */ 00255 template<typename T, us_timestamp_t delay_us, us_timestamp_t delta_us> 00256 void test_sleep(void) 00257 { 00258 Semaphore sem(0, 1); 00259 T timeout; 00260 Timer timer; 00261 00262 sleep_manager_lock_deep_sleep(); 00263 timer.start(); 00264 timeout.attach_callback(mbed::callback(sem_callback, &sem), delay_us); 00265 00266 bool deep_sleep_allowed = sleep_manager_can_deep_sleep(); 00267 TEST_ASSERT_FALSE_MESSAGE(deep_sleep_allowed, "Deep sleep should be disallowed"); 00268 while (sem.wait(0) != 1) { 00269 sleep(); 00270 } 00271 timer.stop(); 00272 00273 sleep_manager_unlock_deep_sleep(); 00274 TEST_ASSERT_UINT64_WITHIN(delta_us, delay_us, timer.read_high_resolution_us()); 00275 00276 timeout.detach(); 00277 } 00278 00279 #if DEVICE_LOWPOWERTIMER 00280 /** Template for tests: timeout during deepsleep 00281 * 00282 * Test timeout during deepsleep 00283 * Given a LowPowerTimeout object with a callback attached with @a attach() 00284 * and the uC in a deepsleep mode 00285 * When given delay elapses 00286 * Then the callback is called 00287 * and elapsed time matches given delay 00288 * 00289 * Test timeout during deepsleep 00290 * Given a LowPowerTimeout object with a callback attached with @a attach_us() 00291 * and the uC in a deepsleep mode 00292 * When given delay elapses 00293 * Then the callback is called 00294 * and elapsed time matches given delay 00295 */ 00296 template<typename T, us_timestamp_t delay_us, us_timestamp_t delta_us> 00297 void test_deepsleep(void) 00298 { 00299 Semaphore sem(0, 1); 00300 T timeout; 00301 /* 00302 * We use here the low power timer instead of microsecond timer for start and 00303 * end because the microseconds timer might be disabled during deepsleep. 00304 */ 00305 LowPowerTimer timer; 00306 00307 /* 00308 * Since deepsleep() may shut down the UART peripheral, we wait for 10ms 00309 * to allow for hardware serial buffers to completely flush. 00310 00311 * This should be replaced with a better function that checks if the 00312 * hardware buffers are empty. However, such an API does not exist now, 00313 * so we'll use the wait_ms() function for now. 00314 */ 00315 wait_ms(10); 00316 00317 timer.start(); 00318 timeout.attach_callback(mbed::callback(sem_callback, &sem), delay_us); 00319 00320 bool deep_sleep_allowed = sleep_manager_can_deep_sleep(); 00321 TEST_ASSERT_TRUE_MESSAGE(deep_sleep_allowed, "Deep sleep should be allowed"); 00322 while (sem.wait(0) != 1) { 00323 sleep(); 00324 } 00325 timer.stop(); 00326 00327 TEST_ASSERT_UINT64_WITHIN(delta_us, delay_us, timer.read_high_resolution_us()); 00328 00329 timeout.detach(); 00330 } 00331 #endif 00332 #endif 00333 00334 template<typename TimeoutTesterType> 00335 class TimeoutDriftTester { 00336 public: 00337 TimeoutDriftTester(us_timestamp_t period = 1000) : 00338 _callback_count(0), _period(period), _timeout() 00339 { 00340 } 00341 00342 void reschedule_callback(void) 00343 { 00344 _timeout.attach_callback(mbed::callback(this, &TimeoutDriftTester::reschedule_callback), _period); 00345 _callback_count++; 00346 } 00347 00348 void detach_callback(void) 00349 { 00350 _timeout.detach(); 00351 } 00352 00353 uint32_t get_callback_count(void) 00354 { 00355 return _callback_count; 00356 } 00357 00358 private: 00359 volatile uint32_t _callback_count; 00360 us_timestamp_t _period; 00361 TimeoutTesterType _timeout; 00362 }; 00363 00364 /** Template for tests: accuracy of timeout delay scheduled repeatedly 00365 * 00366 * Test time drift -- device part 00367 * Given a Timeout object with a callback repeatedly attached with @a attach() 00368 * When the testing host computes test duration based on values received from uC 00369 * Then computed time and actual time measured by host are equal within given tolerance 00370 * 00371 * Test time drift -- device part 00372 * Given a Timeout object with a callback repeatedly attached with @a attach_us() 00373 * When the testing host computes test duration based on values received from uC 00374 * Then computed time and actual time measured by host are equal within given tolerance 00375 * 00376 * Original description: 00377 * 1) DUT would start to update callback_trigger_count every milli sec 00378 * 2) Host would query what is current count base_time, Device responds by the callback_trigger_count 00379 * 3) Host after waiting for measurement stretch. It will query for device time again final_time. 00380 * 4) Host computes the drift considering base_time, final_time, transport delay and measurement stretch 00381 * 5) Finally host send the results back to device pass/fail based on tolerance. 00382 * 6) More details on tests can be found in timing_drift_auto.py 00383 */ 00384 template<typename T> 00385 void test_drift(void) 00386 { 00387 char _key[11] = { }; 00388 char _value[128] = { }; 00389 int expected_key = 1; 00390 TimeoutDriftTester<T> timeout(DRIFT_TEST_PERIOD_US); 00391 00392 greentea_send_kv("timing_drift_check_start", 0); 00393 timeout.reschedule_callback(); 00394 00395 // wait for 1st signal from host 00396 do { 00397 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00398 expected_key = strcmp(_key, "base_time"); 00399 } while (expected_key); 00400 00401 greentea_send_kv(_key, timeout.get_callback_count() * DRIFT_TEST_PERIOD_US); 00402 00403 // wait for 2nd signal from host 00404 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00405 greentea_send_kv(_key, timeout.get_callback_count() * DRIFT_TEST_PERIOD_US); 00406 00407 timeout.detach_callback(); 00408 00409 //get the results from host 00410 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00411 00412 TEST_ASSERT_EQUAL_STRING_MESSAGE("pass", _key, "Host script reported a failure"); 00413 } 00414 00415 #endif
Generated on Fri Jul 22 2022 04:54:03 by
 1.7.2
 1.7.2 
    