Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * Copyright (c) 2013-2017, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "mbed.h"
00019 #include "greentea-client/test_env.h"
00020 #include "unity/unity.h"
00021 #include "utest/utest.h"
00022 
00023 using utest::v1::Case;
00024 
00025 #if defined(MBED_RTOS_SINGLE_THREAD)
00026   #error [NOT_SUPPORTED] test not supported
00027 #endif
00028 
00029 #define THREAD_STACK_SIZE   320 /* 512B stack on GCC_ARM compiler cause out of memory on some 16kB RAM boards e.g. NUCLEO_F070RB */
00030 
00031 #define MAX_FLAG_POS 30
00032 #define PROHIBITED_FLAG_POS 31
00033 
00034 /* flags */
00035 #define FLAG01          0x1FFF       /* 00000000000000000001111111111111 */
00036 #define FLAG02          0x3FFE000    /* 00000011111111111110000000000000 */
00037 #define FLAG03          0x7C000000   /* 01111100000000000000000000000000 */
00038 #define PROHIBITED_FLAG 0x80000000   /* 10000000000000000000000000000000 */
00039 #define NO_FLAGS 0x0
00040 
00041 Semaphore sync_sem(0, 1);
00042 
00043 /* In order to successfully run this test suite when compiled with --profile=debug
00044  * error() has to be redefined as noop.
00045  *
00046  * EventFlags calls RTX API which uses Event Recorder functionality. When compiled
00047  * with MBED_TRAP_ERRORS_ENABLED=1 (set in debug profile) EvrRtxEventFlagsError() calls error()
00048  * which aborts test program.
00049  */
00050 #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED
00051 void error(const char* format, ...) {
00052     (void) format;
00053 }
00054 #endif
00055 
00056 template<uint32_t flags, uint32_t wait_ms>
00057 void send_thread(EventFlags *ef)
00058 {
00059     for (uint32_t i = 0; i <= MAX_FLAG_POS; i++) {
00060         const uint32_t flag = flags & (1 << i);
00061         if (flag) {
00062             ef->set(flag);
00063             Thread::wait(wait_ms);
00064         }
00065     }
00066 }
00067 
00068 template<uint32_t flags, uint32_t wait_ms>
00069 void send_thread_sync(EventFlags *ef)
00070 {
00071     for (uint32_t i = 0; i <= MAX_FLAG_POS; i++) {
00072         const uint32_t flag = flags & (1 << i);
00073         if (flag) {
00074             sync_sem.wait();
00075             ef->set(flag);
00076             Thread::wait(wait_ms);
00077         }
00078     }
00079 }
00080 
00081 template<uint32_t flags>
00082 void wait_thread_all(EventFlags *ef)
00083 {
00084     uint32_t ret, flags_after_clear;
00085     ret = ef->wait_all(flags);
00086     flags_after_clear = ef->get();
00087     TEST_ASSERT(flags | ret);
00088     TEST_ASSERT(flags | ~flags_after_clear);
00089 }
00090 
00091 
00092 /** Test if get on empty EventFlags object return NO_FLAGS
00093 
00094     Given a empty EventFlags object
00095     When call @a get
00096     Then @a get return status is NO_FLAGS
00097  */
00098 void test_empty_get(void)
00099 {
00100     EventFlags ev;
00101     uint32_t flags;
00102 
00103     flags = ev.get();
00104     TEST_ASSERT_EQUAL(NO_FLAGS, flags);
00105 }
00106 
00107 /** Test if clear on empty EventFlags object return NO_FLAGS
00108 
00109     Given a empty EventFlags object
00110     When call @a clear(NO_FLAGS)
00111     Then @a clear return status is NO_FLAGS
00112  */
00113 void test_empty_clear(void)
00114 {
00115     EventFlags ev;
00116     uint32_t flags;
00117 
00118     flags = ev.clear(NO_FLAGS);
00119     TEST_ASSERT_EQUAL(NO_FLAGS, flags);
00120 }
00121 
00122 /** Test if set on empty EventFlags object return NO_FLAGS
00123 
00124     Given a empty EventFlags object
00125     When call @a set(NO_FLAGS)
00126     Then @a set return status is NO_FLAGS
00127  */
00128 void test_empty_set(void)
00129 {
00130     EventFlags ev;
00131     uint32_t flags;
00132 
00133     flags = ev.set(NO_FLAGS);
00134     TEST_ASSERT_EQUAL(NO_FLAGS, flags);
00135 }
00136 
00137 /** Test if call of set/clean with PROHIBITED_FLAG doesn't invalidates object flags
00138 
00139     Given a EventFlags object with all flags already set
00140     When call @a clear(PROHIBITED_FLAG) with prohibited flag
00141     Then @a clear return status is osFlagsErrorParameter and object flags stays unchanged
00142     When call @a set(PROHIBITED_FLAG) with prohibited flag
00143     Then @a set return status is osFlagsErrorParameter and object flags stays unchanged
00144 
00145     @note Each signal has up to 31 event flags 0x1, 0x2, 0x4, 0x8, ...,  0x40000000
00146           Most significant bit is reserved and thereby flag 0x80000000 is prohibited
00147  */
00148 void test_prohibited(void)
00149 {
00150     EventFlags ev;
00151     uint32_t flags;
00152 
00153     ev.set(FLAG01 | FLAG02 | FLAG03);
00154 
00155     flags = ev.clear(PROHIBITED_FLAG);
00156     TEST_ASSERT_EQUAL(osFlagsErrorParameter, flags);
00157 
00158     flags = ev.get();
00159     TEST_ASSERT_EQUAL(FLAG01 | FLAG02 | FLAG03, flags);
00160 
00161     flags = ev.set(PROHIBITED_FLAG);
00162     TEST_ASSERT_EQUAL(osFlagsErrorParameter, flags);
00163 
00164     flags = ev.get();
00165     TEST_ASSERT_EQUAL(FLAG01 | FLAG02 | FLAG03, flags);
00166 }
00167 
00168 /** Test set/get/clear for full flag range
00169 
00170     Given a EventFlags object
00171     When call @a clear
00172     Then @a clear return status is already set flags
00173     When call @a set with specified flag
00174     Then @a set return status is flags after setting
00175     When call @a get
00176     Then @a get return status is set flags
00177  */
00178 void test_set_get_clear_full_flag_range(void)
00179 {
00180     EventFlags ev;
00181     uint32_t flag, flags, ret;
00182 
00183     flags = NO_FLAGS;
00184     for (int i = 0; i <= MAX_FLAG_POS; i++) {
00185         ret = ev.clear();
00186         TEST_ASSERT_EQUAL(flags, ret);
00187         flags = 1 << i;
00188         ret = ev.set(flags);
00189         TEST_ASSERT_EQUAL(flags, ret);
00190         ret = ev.get();
00191         TEST_ASSERT_EQUAL(flags, ret);
00192     }
00193 
00194     ev.clear();
00195     flags = NO_FLAGS;
00196     for (int i = 0; i <= MAX_FLAG_POS; i++) {
00197         ret = ev.clear(NO_FLAGS);
00198         TEST_ASSERT_EQUAL(flags, ret);
00199         flag = 1 << i;
00200         flags |= flag;
00201         ret = ev.set(flag);
00202         TEST_ASSERT_EQUAL(flags, ret);
00203         ret = ev.get();
00204         TEST_ASSERT_EQUAL(flags, ret);
00205     }
00206 }
00207 
00208 /** Test if multi-threaded flag set cause wait_all to return
00209 
00210     Given a EventFlags object and three threads are started in parallel
00211     When threads set specified flags
00212     Then main thread waits until receive all of them
00213  */
00214 void test_multi_thread_all(void)
00215 {
00216     EventFlags ef;
00217     Thread thread1(osPriorityNormal, THREAD_STACK_SIZE);
00218     Thread thread2(osPriorityNormal, THREAD_STACK_SIZE);
00219     Thread thread3(osPriorityNormal, THREAD_STACK_SIZE);
00220     thread1.start(callback(send_thread<FLAG01, 1>, &ef));
00221     thread2.start(callback(send_thread<FLAG02, 2>, &ef));
00222     thread3.start(callback(send_thread<FLAG03, 3>, &ef));
00223 
00224     uint32_t ret = ef.wait_all(FLAG01 | FLAG02 | FLAG03);
00225     TEST_ASSERT_EQUAL(FLAG01 | FLAG02 | FLAG03, ret);
00226 }
00227 
00228 /** Test if multi-threaded flag set cause wait_any to return
00229 
00230     Given a EventFlags object and three threads are started in parallel
00231     When threads set specified flags
00232     Then main thread waits until receive all of them
00233  */
00234 void test_multi_thread_any(void)
00235 {
00236     EventFlags ef;
00237     uint32_t ret;
00238     Thread thread1(osPriorityNormal, THREAD_STACK_SIZE);
00239     Thread thread2(osPriorityNormal, THREAD_STACK_SIZE);
00240     Thread thread3(osPriorityNormal, THREAD_STACK_SIZE);
00241     thread1.start(callback(send_thread<FLAG01, 1>, &ef));
00242     thread2.start(callback(send_thread<FLAG02, 1>, &ef));
00243     thread3.start(callback(send_thread<FLAG03, 1>, &ef));
00244 
00245     for (int i = 0; i <= MAX_FLAG_POS; i++) {
00246         uint32_t flag = 1 << i;
00247         ret = ef.wait_any(flag);
00248         TEST_ASSERT(flag | ret);
00249     }
00250     ret = ef.get();
00251     TEST_ASSERT_EQUAL(NO_FLAGS, ret);
00252 }
00253 
00254 /** Test if multi-threaded flag set cause wait_any(with timeout) to return
00255 
00256     Given a EventFlags object and thread is running
00257     When main thread call @ wait_any with timeout
00258     Then when timeout expires @ wait_any return status is osFlagsErrorTimeout
00259     When main thread call @ wait_any with timeout and thread set specified flags
00260     Then main thread waits until receive all of them and @ wait_any return status is wait flag
00261  */
00262 void test_multi_thread_any_timeout(void)
00263 {
00264     EventFlags ef;
00265     uint32_t ret;
00266     Thread thread(osPriorityNormal, THREAD_STACK_SIZE);
00267     thread.start(callback(send_thread_sync<FLAG01 | FLAG02 | FLAG03, 1>, &ef));
00268 
00269     for (int i = 0; i <= MAX_FLAG_POS; i++) {
00270         uint32_t flag = 1 << i;
00271 
00272         ret = ef.wait_any(flag, 10);
00273         TEST_ASSERT_EQUAL(osFlagsErrorTimeout, ret);
00274 
00275         sync_sem.release();
00276         ret = ef.wait_any(flag, 10);
00277         TEST_ASSERT_EQUAL(flag, ret);
00278     }
00279     ret = ef.get();
00280     TEST_ASSERT_EQUAL(NO_FLAGS, ret);
00281 }
00282 
00283 /** Test if multi-threaded flag set cause wait_any(without clear) to return
00284 
00285     Given a EventFlags object and three threads are started in parallel
00286     When threads set specified flags
00287     Then main thread waits until receive all of them
00288  */
00289 void test_multi_thread_any_no_clear(void)
00290 {
00291     EventFlags ef;
00292     uint32_t ret;
00293     Thread thread1(osPriorityNormal, THREAD_STACK_SIZE);
00294     Thread thread2(osPriorityNormal, THREAD_STACK_SIZE);
00295     Thread thread3(osPriorityNormal, THREAD_STACK_SIZE);
00296     thread1.start(callback(send_thread<FLAG01, 1>, &ef));
00297     thread2.start(callback(send_thread<FLAG02, 1>, &ef));
00298     thread3.start(callback(send_thread<FLAG03, 1>, &ef));
00299 
00300     for (int i = 0; i <= MAX_FLAG_POS; i++) {
00301         uint32_t flag = 1 << i;
00302         ret = ef.wait_any(flag, osWaitForever, false);
00303         TEST_ASSERT(flag | ret);
00304         ret = ef.clear(flag);
00305         TEST_ASSERT(ret < osFlagsError);
00306     }
00307     ret = ef.get();
00308     TEST_ASSERT_EQUAL(NO_FLAGS, ret);
00309 }
00310 
00311 /** Test multi-threaded wait_any
00312 
00313     Given a EventFlags object and three threads are started in parallel
00314     When flags are set in main thread
00315     Then other threads waits until receive all of them
00316  */
00317 void test_multi_thread_all_many_wait(void)
00318 {
00319     EventFlags ef;
00320     {
00321         Thread thread1(osPriorityNormal, THREAD_STACK_SIZE);
00322         Thread thread2(osPriorityNormal, THREAD_STACK_SIZE);
00323         Thread thread3(osPriorityNormal, THREAD_STACK_SIZE);
00324         thread1.start(callback(wait_thread_all<FLAG01>, &ef));
00325         thread2.start(callback(wait_thread_all<FLAG02>, &ef));
00326         thread3.start(callback(wait_thread_all<FLAG03>, &ef));
00327 
00328         ef.set(FLAG01 | FLAG02 | FLAG03);
00329         thread1.join();
00330         thread2.join();
00331         thread3.join();
00332         TEST_ASSERT_EQUAL(NO_FLAGS, ef.get());
00333     }
00334 
00335     {
00336         Thread thread1(osPriorityNormal, THREAD_STACK_SIZE);
00337         Thread thread2(osPriorityNormal, THREAD_STACK_SIZE);
00338         Thread thread3(osPriorityNormal, THREAD_STACK_SIZE);
00339         thread1.start(callback(wait_thread_all<FLAG01>, &ef));
00340         thread2.start(callback(wait_thread_all<FLAG02>, &ef));
00341         thread3.start(callback(wait_thread_all<FLAG03>, &ef));
00342 
00343         ef.set(FLAG01);
00344         thread1.join();
00345         ef.set(FLAG02);
00346         thread2.join();
00347         ef.set(FLAG03);
00348         thread3.join();
00349         TEST_ASSERT_EQUAL(NO_FLAGS, ef.get());
00350     }
00351 }
00352 
00353 utest::v1::status_t test_setup(const size_t number_of_cases)
00354 {
00355     GREENTEA_SETUP(10, "default_auto");
00356     return utest::v1::verbose_test_setup_handler(number_of_cases);
00357 }
00358 
00359 Case cases[] = {
00360     Case("Test empty clear", test_empty_clear),
00361     Case("Test empty get", test_empty_get),
00362     Case("Test empty set", test_empty_set),
00363     Case("Test clear/set with prohibited flag", test_prohibited),
00364     Case("Test set/get/clear for full flag range", test_set_get_clear_full_flag_range),
00365     Case("Test multi-threaded wait_all", test_multi_thread_all),
00366     Case("Test multi-threaded wait_any", test_multi_thread_any),
00367     Case("Test multi-threaded wait_all many wait", test_multi_thread_all_many_wait),
00368     Case("Test multi-threaded wait_any timeout", test_multi_thread_any_timeout),
00369     Case("Test multi-threaded wait_any no clear", test_multi_thread_any_no_clear)
00370 };
00371 
00372 utest::v1::Specification specification(test_setup, cases);
00373 
00374 int main()
00375 {
00376     return !utest::v1::Harness::run(specification);
00377 }