Rtos API example

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 #include "mbed.h"
00017 #include "greentea-client/test_env.h"
00018 #include "utest/utest.h"
00019 #include "unity/unity.h"
00020 
00021 using utest::v1::Case;
00022 
00023 
00024 #if defined(MBED_RTOS_SINGLE_THREAD)
00025   #error [NOT_SUPPORTED] test not supported
00026 #endif
00027 
00028 #define TEST_STACK_SIZE   512
00029 #define MAX_FLAG_POS 30
00030 
00031 #define ALL_SIGNALS       0x7fffffff
00032 #define NO_SIGNALS        0x0
00033 #define PROHIBITED_SIGNAL 0x80000000
00034 #define SIGNAL1 0x1
00035 #define SIGNAL2 0x2
00036 #define SIGNAL3 0x4
00037 
00038 struct Sync {
00039     Sync(Semaphore &parent, Semaphore &child): sem_parent(parent), sem_child(child)
00040     {}
00041 
00042     Semaphore &sem_parent;
00043     Semaphore &sem_child;
00044 };
00045 
00046 
00047 /* In order to successfully run this test suite when compiled with --profile=debug
00048  * error() has to be redefined as noop.
00049  *
00050  * ThreadFlags calls RTX API which uses Event Recorder functionality. When compiled
00051  * with MBED_TRAP_ERRORS_ENABLED=1 (set in debug profile) EvrRtxEventFlagsError() calls error()
00052  * which aborts test program.
00053  */
00054 #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED
00055 void error(const char* format, ...) {
00056     (void) format;
00057 }
00058 #endif
00059 
00060 
00061 template <int32_t signals, uint32_t timeout, int32_t test_val>
00062 void run_signal_wait(void)
00063 {
00064     osEvent ev = Thread::signal_wait(signals, timeout);
00065     TEST_ASSERT_EQUAL(test_val, ev.status);
00066 }
00067 
00068 template <int32_t signals, uint32_t timeout, int32_t test_val>
00069 void run_release_signal_wait(Semaphore *sem)
00070 {
00071     sem->release();
00072     osEvent ev = Thread::signal_wait(signals, timeout);
00073     TEST_ASSERT_EQUAL(test_val, ev.status);
00074 }
00075 
00076 template <int32_t signals, uint32_t timeout, int32_t test_val>
00077 void run_release_wait_signal_wait(Sync *sync)
00078 {
00079     sync->sem_parent.release();
00080     sync->sem_child.wait();
00081     osEvent ev = Thread::signal_wait(signals, timeout);
00082     TEST_ASSERT_EQUAL(test_val, ev.status);
00083 }
00084 
00085 template <int32_t signals, int32_t test_val>
00086 void run_clear(void)
00087 {
00088     int32_t ret = Thread::signal_clr(signals);
00089     TEST_ASSERT_EQUAL(test_val, ret);
00090 }
00091 
00092 template <int32_t signals, int32_t test_val>
00093 void run_wait_clear(Sync *sync)
00094 {
00095     sync->sem_parent.release();
00096     sync->sem_child.wait();
00097     int32_t ret = Thread::signal_clr(signals);
00098     TEST_ASSERT_EQUAL(test_val, ret);
00099 }
00100 
00101 template <int32_t signals1, int32_t signals2, int32_t test_val1, int32_t test_val2>
00102 void run_double_wait_clear(Sync *sync)
00103 {
00104     int32_t ret;
00105 
00106     sync->sem_parent.release();
00107     sync->sem_child.wait();
00108     ret = Thread::signal_clr(signals1);
00109     TEST_ASSERT_EQUAL(test_val1, ret);
00110 
00111     ret = Thread::signal_clr(signals2);
00112     TEST_ASSERT_EQUAL(test_val2, ret);
00113 }
00114 
00115 void run_loop_wait_clear(Sync *sync)
00116 {
00117     int32_t signals = NO_SIGNALS;
00118     for (int i = 0; i <= MAX_FLAG_POS; i++) {
00119         int32_t signal = 1 << i;
00120         signals |= signal;
00121         sync->sem_child.wait();
00122         int32_t ret = Thread::signal_clr(NO_SIGNALS);
00123         TEST_ASSERT_EQUAL(signals, ret);
00124         sync->sem_parent.release();
00125     }
00126 }
00127 
00128 
00129 /** Validate that call signal_clr(NO_SIGNALS) doesn't change thread signals and return actual signals
00130 
00131     Given two threads A & B are started, B with all signals already set
00132     When thread B calls @a signal_clr(NO_SIGNALS)
00133     Then thread B @a signal_clr status should be ALL_SIGNALS indicating that thread B state is unchanged
00134  */
00135 void test_clear_no_signals(void)
00136 {
00137     Semaphore sem_parent(0, 1);
00138     Semaphore sem_child(0, 1);
00139     Sync sync(sem_parent, sem_child);
00140 
00141     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00142     t.start(callback(run_double_wait_clear<NO_SIGNALS, NO_SIGNALS, ALL_SIGNALS, ALL_SIGNALS>, &sync));
00143     sem_parent.wait();
00144     t.signal_set(ALL_SIGNALS);
00145     sem_child.release();
00146     t.join();
00147 }
00148 
00149 /** Validate if any signals are set on just created thread
00150 
00151     Given the thread is running
00152     When thread execute @a signal_clr(NO_SIGNALS)
00153     Then thread @a signal_clr return status should be NO_SIGNALS(0) indicating no signals set
00154  */
00155 void test_init_state(void)
00156 {
00157     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00158     t.start(callback(run_clear<NO_SIGNALS, NO_SIGNALS>));
00159     t.join();
00160 }
00161 
00162 /** Validate all signals set in one shot
00163 
00164     Given two threads A & B are started
00165     When thread A call @a signal_set(ALL_SIGNALS) with all possible signals
00166     Then thread B @a signal_clr(NO_SIGNALS) status should be ALL_SIGNALS indicating all signals set correctly
00167  */
00168 void test_set_all(void)
00169 {
00170     int32_t ret;
00171     Semaphore sem_parent(0, 1);
00172     Semaphore sem_child(0, 1);
00173     Sync sync(sem_parent, sem_child);
00174 
00175     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00176     t.start(callback(run_wait_clear<NO_SIGNALS, ALL_SIGNALS>, &sync));
00177 
00178     sem_parent.wait();
00179     ret = t.signal_set(ALL_SIGNALS);
00180     TEST_ASSERT_EQUAL(ALL_SIGNALS, ret);
00181 
00182     sem_child.release();
00183     t.join();
00184 }
00185 
00186 /** Validate that call signal_set with prohibited signal doesn't change thread signals
00187 
00188     Given two threads A & B are started, B with all signals set
00189     When thread A executes @a signal_set(PROHIBITED_SIGNAL) with prohibited signal
00190     Then thread B @a signal_clr(NO_SIGNALS) status should be ALL_SIGNALS indicating that thread B signals are unchanged
00191 
00192     @note Each signal has up to 31 event flags 0x1, 0x2, 0x4, 0x8, ...,  0x40000000
00193           Most significant bit is reserved and thereby flag 0x80000000 is prohibited
00194  */
00195 void test_set_prohibited(void)
00196 {
00197     int32_t ret;
00198     Semaphore sem_parent(0, 1);
00199     Semaphore sem_child(0, 1);
00200     Sync sync(sem_parent, sem_child);
00201 
00202     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00203     t.start(callback(run_wait_clear<NO_SIGNALS, ALL_SIGNALS>, &sync));
00204 
00205     sem_parent.wait();
00206     t.signal_set(ALL_SIGNALS);
00207 
00208     ret = t.signal_set(PROHIBITED_SIGNAL);
00209     TEST_ASSERT_EQUAL(osErrorParameter, ret);
00210 
00211     sem_child.release();
00212     t.join();
00213 }
00214 
00215 /** Validate all signals clear in one shot
00216 
00217     Given two threads A & B are started, B with all signals set
00218     When thread B execute @a signal_clr(ALL_SIGNALS) with all possible signals
00219     Then thread B @a signal_clr(NO_SIGNALS) status should be NO_SIGNALS(0) indicating all signals cleared correctly
00220  */
00221 void test_clear_all(void)
00222 {
00223     Semaphore sem_parent(0, 1);
00224     Semaphore sem_child(0, 1);
00225     Sync sync(sem_parent, sem_child);
00226 
00227     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00228     t.start(callback(run_double_wait_clear<ALL_SIGNALS, NO_SIGNALS, ALL_SIGNALS, NO_SIGNALS>, &sync));
00229     sem_parent.wait();
00230     t.signal_set(ALL_SIGNALS);
00231     sem_child.release();
00232     t.join();
00233 }
00234 
00235 /** Validate all signals set one by one in loop
00236 
00237     Given two threads A & B are started
00238     When thread A executes @a signal_set(signal) in loop with all possible signals
00239  */
00240 void test_set_all_loop(void)
00241 {
00242     int32_t ret;
00243     Semaphore sem_parent(0, 1);
00244     Semaphore sem_child(0, 1);
00245     Sync sync(sem_parent, sem_child);
00246 
00247     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00248     t.start(callback(run_loop_wait_clear, &sync));
00249 
00250     int32_t signals = 0;
00251     for (int i = 0; i <= MAX_FLAG_POS; i++) {
00252         int32_t signal = 1 << i;
00253 
00254         ret = t.signal_set(signal);
00255         signals |= signal;
00256         TEST_ASSERT_EQUAL(signals, ret);
00257         sem_child.release();
00258         sem_parent.wait();
00259     }
00260     t.join();
00261 }
00262 
00263 /** Validate signal_wait return status if timeout specified
00264 
00265     Given the thread is running
00266     When thread executes @a signal_wait(signals, timeout) with specified signals and timeout
00267     Then thread @a signal_wait status should be osEventTimeout indicating a timeout
00268          thread @a signal_wait status should be osOK indicating 0[ms] timeout set
00269  */
00270 template <int32_t signals, uint32_t timeout, int32_t status>
00271 void test_wait_timeout(void)
00272 {
00273     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00274     t.start(callback(run_signal_wait<signals, timeout, status>));
00275     t.join();
00276 }
00277 
00278 /** Validate that call of signal_wait return correctly when thread has all signals already set
00279 
00280     Given two threads A & B are started, B with all signals already set
00281     When thread B executes @a signal_wait(ALL_SIGNALS, osWaitForever),
00282     Then thread B @a signal_wait return immediately with status osEventSignal indicating all wait signals was already set
00283  */
00284 void test_wait_all_already_set(void)
00285 {
00286     Semaphore sem_parent(0, 1);
00287     Semaphore sem_child(0, 1);
00288     Sync sync(sem_parent, sem_child);
00289 
00290     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00291     t.start(callback(run_release_wait_signal_wait<ALL_SIGNALS, osWaitForever, osEventSignal>, &sync));
00292 
00293     sem_parent.wait();
00294     TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state());
00295     t.signal_set(ALL_SIGNALS);
00296     sem_child.release();
00297     t.join();
00298 }
00299 
00300 /** Validate if signal_wait return correctly when all signals set
00301 
00302     Given two threads A & B are started and B waiting for a thread flag to be set
00303     When thread A executes @a signal_set(ALL_SIGNALS) with all possible signals
00304     Then thread B @a signal_wait status is osEventSignal indicating all wait signals was set
00305  */
00306 void test_wait_all(void)
00307 {
00308     Semaphore sem(0, 1);
00309 
00310     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00311     t.start(callback(run_release_signal_wait<ALL_SIGNALS, osWaitForever, osEventSignal>, &sem));
00312 
00313     sem.wait();
00314     TEST_ASSERT_EQUAL(Thread::WaitingThreadFlag, t.get_state());
00315 
00316     t.signal_set(ALL_SIGNALS);
00317     t.join();
00318 }
00319 
00320 /** Validate if signal_wait accumulate signals and return correctly when all signals set
00321 
00322     Given two threads A & B are started and B waiting for a thread signals to be set
00323     When thread A executes @a signal_set setting all signals in loop
00324     Then thread B @a signal_wait status is osEventSignal indicating that all wait signals was set
00325  */
00326 void test_wait_all_loop(void)
00327 {
00328     int32_t ret;
00329     Semaphore sem(0, 1);
00330 
00331     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00332     t.start(callback(run_release_signal_wait<ALL_SIGNALS, osWaitForever, osEventSignal>, &sem));
00333 
00334     sem.wait();
00335     TEST_ASSERT_EQUAL(Thread::WaitingThreadFlag, t.get_state());
00336 
00337     for (int i = 0; i < MAX_FLAG_POS; i++) {
00338         int32_t signal = 1 << i;
00339         ret = t.signal_set(signal);
00340     }
00341     ret = t.signal_set(1 << MAX_FLAG_POS);
00342     TEST_ASSERT_EQUAL(NO_SIGNALS, ret);
00343     t.join();
00344 }
00345 
00346 /** Validate if setting same signal twice cause any unwanted behaviour
00347 
00348     Given two threads A & B are started and B waiting for a thread signals to be set
00349     When thread A executes @a signal_set twice for the same signal
00350     Then thread A @a signal_set status is current signal set
00351          thread B @a signal_wait status is osEventSignal indicating that all wait signals was set
00352  */
00353 void test_set_double(void)
00354 {
00355     int32_t ret;
00356     Semaphore sem(0, 1);
00357 
00358     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00359     t.start(callback(run_release_signal_wait<SIGNAL1|SIGNAL2|SIGNAL3, osWaitForever, osEventSignal>, &sem));
00360 
00361     sem.wait();
00362     TEST_ASSERT_EQUAL(Thread::WaitingThreadFlag, t.get_state());
00363 
00364     ret = t.signal_set(SIGNAL1);
00365     TEST_ASSERT_EQUAL(SIGNAL1, ret);
00366 
00367     ret = t.signal_set(SIGNAL2);
00368     TEST_ASSERT_EQUAL(SIGNAL1 | SIGNAL2, ret);
00369 
00370     ret = t.signal_set(SIGNAL2);
00371     TEST_ASSERT_EQUAL(SIGNAL1 | SIGNAL2, ret);
00372     TEST_ASSERT_EQUAL(Thread::WaitingThreadFlag, t.get_state());
00373 
00374     ret = t.signal_set(SIGNAL3);
00375     TEST_ASSERT_EQUAL(NO_SIGNALS, ret);
00376     t.join();
00377 }
00378 
00379 
00380 utest::v1::status_t test_setup(const size_t number_of_cases)
00381 {
00382     GREENTEA_SETUP(10, "default_auto");
00383     return utest::v1::verbose_test_setup_handler(number_of_cases);
00384 }
00385 
00386 Case cases[] = {
00387     Case("Validate that call signal_clr(NO_SIGNALS) doesn't change thread signals and return actual signals", test_clear_no_signals),
00388     Case("Validate if any signals are set on just created thread", test_init_state),
00389     Case("Validate all signals set in one shot", test_set_all),
00390     Case("Validate that call signal_set with prohibited signal doesn't change thread signals", test_set_prohibited),
00391     Case("Validate all signals clear in one shot", test_clear_all),
00392     Case("Validate all signals set one by one in loop", test_set_all_loop),
00393     Case("Validate signal_wait return status if timeout specified: 0[ms] no signals", test_wait_timeout<0, 0, osOK>),
00394     Case("Validate signal_wait return status if timeout specified: 0[ms] all signals", test_wait_timeout<ALL_SIGNALS, 0, osOK>),
00395     Case("Validate signal_wait return status if timeout specified: 1[ms] no signals", test_wait_timeout<0, 1, osEventTimeout>),
00396     Case("Validate signal_wait return status if timeout specified: 1[ms] all signals", test_wait_timeout<ALL_SIGNALS, 1, osEventTimeout>),
00397     Case("Validate that call of signal_wait return correctly when thread has all signals already set", test_wait_all_already_set),
00398     Case("Validate if signal_wait return correctly when all signals set", test_wait_all),
00399     Case("Validate if signal_wait accumulate signals and return correctly when all signals set", test_wait_all_loop),
00400     Case("Validate if setting same signal twice cause any unwanted behaviour", test_set_double)
00401 };
00402 
00403 utest::v1::Specification specification(test_setup, cases);
00404 
00405 int main()
00406 {
00407     return !utest::v1::Harness::run(specification);
00408 }