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 #include "mbed.h" 00017 #include "greentea-client/test_env.h" 00018 #include "unity.h" 00019 #include "utest.h" 00020 #include "rtos.h" 00021 00022 using namespace utest::v1; 00023 00024 #define DELAY_MS 50 00025 #define DELTA_MS 5 00026 #define RESTART_DELAY_MS 10 00027 #define DELAY2_MS 30 00028 00029 #if RESTART_DELAY_MS >= DELAY_MS 00030 #error invalid RESTART_DELAY_MS value 00031 #endif 00032 00033 class Stopwatch: public Timer { 00034 private: 00035 Semaphore _sem; 00036 00037 public: 00038 Stopwatch() : 00039 Timer(), _sem(1) 00040 { 00041 } 00042 00043 ~Stopwatch() 00044 { 00045 } 00046 00047 void start(void) 00048 { 00049 _sem.wait(0); 00050 Timer::start(); 00051 } 00052 00053 void stop(void) 00054 { 00055 Timer::stop(); 00056 _sem.release(); 00057 } 00058 00059 int32_t wait_until_stopped(uint32_t millisec = osWaitForever) 00060 { 00061 core_util_critical_section_enter(); 00062 int running = _running; 00063 core_util_critical_section_exit(); 00064 if (!running) { 00065 return 1; 00066 } 00067 return _sem.wait(millisec); 00068 } 00069 }; 00070 00071 void sem_callback(Semaphore *sem) 00072 { 00073 sem->release(); 00074 } 00075 00076 /* In order to successfully run this test suite when compiled with --profile=debug 00077 * error() has to be redefined as noop. 00078 * 00079 * RtosTimer calls RTX API which uses Event Recorder functionality. When compiled 00080 * with MBED_TRAP_ERRORS_ENABLED=1 (set in debug profile) EvrRtxTimerError() calls error() 00081 * which aborts test program. 00082 */ 00083 #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED 00084 void error(const char* format, ...) 00085 { 00086 (void) format; 00087 } 00088 #endif 00089 00090 /** Test one-shot not restarted when elapsed 00091 * 00092 * Given a one-shot RtosTimer 00093 * When the timer is started 00094 * and given time elapses 00095 * Then timer stops 00096 * and elapsed time matches given delay 00097 * and timer stays stopped 00098 */ 00099 void test_oneshot_not_restarted() 00100 { 00101 Stopwatch stopwatch; 00102 RtosTimer rtostimer(mbed::callback(&stopwatch, &Stopwatch::stop), osTimerOnce); 00103 00104 stopwatch.start(); 00105 osStatus status = rtostimer.start(DELAY_MS); 00106 TEST_ASSERT_EQUAL(osOK, status); 00107 00108 int32_t slots = stopwatch.wait_until_stopped(); 00109 TEST_ASSERT_EQUAL(1, slots); 00110 TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY_MS, stopwatch.read_ms()); 00111 stopwatch.start(); 00112 00113 slots = stopwatch.wait_until_stopped(DELAY_MS + DELTA_MS); 00114 TEST_ASSERT_EQUAL(0, slots); 00115 status = rtostimer.stop(); 00116 TEST_ASSERT_EQUAL(osErrorResource, status); 00117 } 00118 00119 /** Test periodic repeats continuously 00120 * 00121 * Given a periodic RtosTimer 00122 * When timer is started 00123 * and given time elapses 00124 * Then timer repeats its operation 00125 * When timer is stopped 00126 * Then timer stops operation 00127 */ 00128 void test_periodic_repeats() 00129 { 00130 Stopwatch stopwatch; 00131 RtosTimer rtostimer(mbed::callback(&stopwatch, &Stopwatch::stop), osTimerPeriodic); 00132 00133 stopwatch.start(); 00134 osStatus status = rtostimer.start(DELAY_MS); 00135 TEST_ASSERT_EQUAL(osOK, status); 00136 00137 int32_t slots = stopwatch.wait_until_stopped(); 00138 int t1 = stopwatch.read_ms(); 00139 stopwatch.reset(); 00140 stopwatch.start(); 00141 TEST_ASSERT_EQUAL(1, slots); 00142 TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY_MS, t1); 00143 00144 slots = stopwatch.wait_until_stopped(); 00145 TEST_ASSERT_EQUAL(1, slots); 00146 TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY_MS, stopwatch.read_ms()); 00147 stopwatch.start(); 00148 00149 status = rtostimer.stop(); 00150 TEST_ASSERT_EQUAL(osOK, status); 00151 00152 slots = stopwatch.wait_until_stopped(DELAY_MS + DELTA_MS); 00153 TEST_ASSERT_EQUAL(0, slots); 00154 status = rtostimer.stop(); 00155 TEST_ASSERT_EQUAL(osErrorResource, status); 00156 } 00157 00158 /** Test timer can be started again 00159 * 00160 * Given a one-shot Rtosimer 00161 * When the timer is started 00162 * and given time elapses 00163 * Then timer stops 00164 * When the timer is started again 00165 * and given time elapses 00166 * Then timer stops again 00167 */ 00168 void test_start_again() 00169 { 00170 Semaphore sem(0, 1); 00171 RtosTimer rtostimer(mbed::callback(sem_callback, &sem), osTimerOnce); 00172 00173 osStatus status = rtostimer.start(DELAY_MS); 00174 TEST_ASSERT_EQUAL(osOK, status); 00175 00176 int32_t slots = sem.wait(DELAY_MS + DELTA_MS); 00177 TEST_ASSERT_EQUAL(1, slots); 00178 00179 status = rtostimer.stop(); 00180 TEST_ASSERT_EQUAL(osErrorResource, status); 00181 00182 status = rtostimer.start(DELAY_MS); 00183 TEST_ASSERT_EQUAL(osOK, status); 00184 00185 slots = sem.wait(DELAY_MS + DELTA_MS); 00186 TEST_ASSERT_EQUAL(1, slots); 00187 00188 status = rtostimer.stop(); 00189 TEST_ASSERT_EQUAL(osErrorResource, status); 00190 } 00191 00192 /** Test timer restart updates delay 00193 * 00194 * Given a one-shot RtosTimer 00195 * When the timer is started 00196 * and @a start is called again with a different delay before given time elapses 00197 * and updated delay elapses 00198 * Then timer stops 00199 * and time elapsed since the second @a start call matches updated delay 00200 */ 00201 void test_restart_updates_delay() 00202 { 00203 Stopwatch stopwatch; 00204 RtosTimer rtostimer(mbed::callback(&stopwatch, &Stopwatch::stop), osTimerOnce); 00205 00206 stopwatch.start(); 00207 osStatus status = rtostimer.start(DELAY_MS); 00208 TEST_ASSERT_EQUAL(osOK, status); 00209 00210 int32_t slots = stopwatch.wait_until_stopped(RESTART_DELAY_MS); 00211 TEST_ASSERT_EQUAL(0, slots); 00212 00213 stopwatch.reset(); 00214 stopwatch.start(); 00215 status = rtostimer.start(DELAY2_MS); 00216 TEST_ASSERT_EQUAL(osOK, status); 00217 00218 slots = stopwatch.wait_until_stopped(); 00219 TEST_ASSERT_EQUAL(1, slots); 00220 TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY2_MS, stopwatch.read_ms()); 00221 00222 status = rtostimer.stop(); 00223 TEST_ASSERT_EQUAL(osErrorResource, status); 00224 } 00225 00226 /** Test timer is created in stopped state 00227 * 00228 * Given a one-shot RtosTimer 00229 * When the timer has not been started 00230 * Then the timer is stopped 00231 */ 00232 void test_created_stopped() 00233 { 00234 RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce); 00235 osStatus status = rtostimer.stop(); 00236 TEST_ASSERT_EQUAL(osErrorResource, status); 00237 } 00238 00239 /** Test one-shot can be stopped 00240 * 00241 * Given a one-shot RtosTimer 00242 * When the timer is started 00243 * and timer is stopped while still running 00244 * Then timer stops operation 00245 */ 00246 void test_stop() 00247 { 00248 Semaphore sem(0, 1); 00249 RtosTimer rtostimer(mbed::callback(sem_callback, &sem), osTimerOnce); 00250 00251 osStatus status = rtostimer.start(DELAY_MS); 00252 TEST_ASSERT_EQUAL(osOK, status); 00253 00254 int32_t slots = sem.wait(RESTART_DELAY_MS); 00255 TEST_ASSERT_EQUAL(0, slots); 00256 00257 status = rtostimer.stop(); 00258 TEST_ASSERT_EQUAL(osOK, status); 00259 00260 slots = sem.wait(DELAY_MS + DELTA_MS); 00261 TEST_ASSERT_EQUAL(0, slots); 00262 00263 status = rtostimer.stop(); 00264 TEST_ASSERT_EQUAL(osErrorResource, status); 00265 } 00266 00267 /** Test timer started with infinite delay 00268 * 00269 * Given a one-shot RtosTimer 00270 * When the timer is started with @a osWaitForever delay 00271 * Then @a start return status is @a osOK 00272 */ 00273 void test_wait_forever() 00274 { 00275 RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce); 00276 00277 osStatus status = rtostimer.start(osWaitForever); 00278 TEST_ASSERT_EQUAL(osOK, status); 00279 00280 status = rtostimer.stop(); 00281 TEST_ASSERT_EQUAL(osOK, status); 00282 } 00283 00284 /** Test timer started with zero delay 00285 * 00286 * Given a one-shot RtosTimer 00287 * When the timer is started with 0 delay 00288 * Then @a start return status is @a osErrorParameter 00289 */ 00290 void test_no_wait() 00291 { 00292 RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce); 00293 00294 osStatus status = rtostimer.start(0); 00295 TEST_ASSERT_EQUAL(osErrorParameter, status); 00296 00297 status = rtostimer.stop(); 00298 TEST_ASSERT_EQUAL(osErrorResource, status); 00299 } 00300 00301 void rtostimer_isr_call(RtosTimer *rtostimer) 00302 { 00303 osStatus status = rtostimer->start(DELAY_MS); 00304 TEST_ASSERT_EQUAL(osErrorISR, status); 00305 00306 status = rtostimer->stop(); 00307 TEST_ASSERT_EQUAL(osErrorISR, status); 00308 } 00309 00310 /** Test timer method calls from an ISR fail 00311 * 00312 * Given a one-shot RtosTimer 00313 * When a timer method is called from an ISR 00314 * Then method return status is @a osErrorISR 00315 */ 00316 void test_isr_calls_fail() 00317 { 00318 RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce); 00319 00320 Ticker ticker; 00321 ticker.attach(mbed::callback(rtostimer_isr_call, &rtostimer), (float) DELAY_MS / 1000.0); 00322 00323 wait_ms(DELAY_MS + DELTA_MS); 00324 } 00325 00326 utest::v1::status_t test_setup(const size_t number_of_cases) 00327 { 00328 GREENTEA_SETUP(5, "default_auto"); 00329 return verbose_test_setup_handler(number_of_cases); 00330 } 00331 00332 Case cases[] = { 00333 Case("One-shot not restarted when elapsed", test_oneshot_not_restarted), 00334 Case("Periodic repeats continuously", test_periodic_repeats), 00335 Case("Stopped timer can be started again", test_start_again), 00336 Case("Restart changes timeout", test_restart_updates_delay), 00337 Case("Timer can be stopped", test_stop), 00338 Case("Timer is created in stopped state", test_created_stopped), 00339 Case("Timer started with infinite delay", test_wait_forever), 00340 Case("Timer started with zero delay", test_no_wait), 00341 Case("Calls from ISR fail", test_isr_calls_fail) 00342 }; 00343 00344 Specification specification(test_setup, cases); 00345 00346 int main() 00347 { 00348 return !Harness::run(specification); 00349 }
Generated on Thu Jul 14 2022 14:36:19 by
