Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
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 #if defined(MBED_RTOS_SINGLE_THREAD) 00025 #error [NOT_SUPPORTED] test not supported 00026 #endif 00027 00028 #define THREAD_DELAY 30 00029 #define SEMAPHORE_SLOTS 2 00030 #define SEM_CHANGES 100 00031 #define SHORT_WAIT 5 00032 00033 #define THREAD_STACK_SIZE 320 /* larger stack cause out of heap memory on some 16kB RAM boards in multi thread test*/ 00034 00035 Semaphore two_slots(SEMAPHORE_SLOTS); 00036 00037 volatile int change_counter = 0; 00038 volatile int sem_counter = 0; 00039 volatile bool sem_defect = false; 00040 00041 void test_thread(int const *delay) 00042 { 00043 const int thread_delay = *delay; 00044 while (true) { 00045 two_slots.wait(); 00046 sem_counter++; 00047 const bool sem_lock_failed = sem_counter > SEMAPHORE_SLOTS; 00048 if (sem_lock_failed) { 00049 sem_defect = true; 00050 } 00051 Thread::wait(thread_delay); 00052 sem_counter--; 00053 change_counter++; 00054 two_slots.release(); 00055 } 00056 } 00057 00058 /* Test multiple threads 00059 00060 Given 3 threads started with different delays and a semaphore with 2 tokens 00061 when each thread runs it tries to acquire a token 00062 then no more than two threads should be able to access protected region 00063 */ 00064 void test_multi() 00065 { 00066 const int t1_delay = THREAD_DELAY * 1; 00067 const int t2_delay = THREAD_DELAY * 2; 00068 const int t3_delay = THREAD_DELAY * 3; 00069 00070 Thread t1(osPriorityNormal, THREAD_STACK_SIZE); 00071 Thread t2(osPriorityNormal, THREAD_STACK_SIZE); 00072 Thread t3(osPriorityNormal, THREAD_STACK_SIZE); 00073 00074 t1.start(callback(test_thread, &t1_delay)); 00075 t2.start(callback(test_thread, &t2_delay)); 00076 t3.start(callback(test_thread, &t3_delay)); 00077 00078 while (true) { 00079 if (change_counter >= SEM_CHANGES or sem_defect == true) { 00080 t1.terminate(); 00081 t2.terminate(); 00082 t3.terminate(); 00083 break; 00084 } 00085 } 00086 } 00087 00088 struct thread_data { 00089 Semaphore *sem; 00090 uint32_t data; 00091 }; 00092 00093 void single_thread(struct thread_data *data) 00094 { 00095 int32_t cnt = data->sem->wait(); 00096 TEST_ASSERT_EQUAL(1, cnt); 00097 data->data++; 00098 } 00099 00100 /** Test single thread 00101 00102 Given a two threads A & B and a semaphore (with count of 0) and a counter (equals to 0) 00103 when thread B calls @a wait 00104 then thread B waits for a token to become available 00105 then the counter is equal to 0 00106 when thread A calls @a release on the semaphore 00107 then thread B acquires a token and increments the counter 00108 then the counter equals to 1 00109 */ 00110 void test_single_thread() 00111 { 00112 Thread t(osPriorityNormal, THREAD_STACK_SIZE); 00113 Semaphore sem(0); 00114 struct thread_data data; 00115 osStatus res; 00116 00117 data.sem = &sem; 00118 data.data = 0; 00119 00120 res = t.start(callback(single_thread, &data)); 00121 TEST_ASSERT_EQUAL(osOK, res); 00122 Thread::wait(SHORT_WAIT); 00123 00124 TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state()); 00125 TEST_ASSERT_EQUAL(0, data.data); 00126 00127 res = sem.release(); 00128 TEST_ASSERT_EQUAL(osOK, res); 00129 00130 Thread::wait(SHORT_WAIT); 00131 00132 TEST_ASSERT_EQUAL(1, data.data); 00133 00134 t.join(); 00135 } 00136 00137 void timeout_thread(Semaphore *sem) 00138 { 00139 int32_t cnt = sem->wait(30); 00140 TEST_ASSERT_EQUAL(0, cnt); 00141 } 00142 00143 /** Test timeout 00144 00145 Given thread and a semaphore with no tokens available 00146 when thread calls @a wait on the semaphore with timeout of 10ms 00147 then the thread waits for 10ms and timeouts after 00148 */ 00149 void test_timeout() 00150 { 00151 Thread t(osPriorityNormal, THREAD_STACK_SIZE); 00152 Semaphore sem(0); 00153 osStatus res; 00154 00155 Timer timer; 00156 timer.start(); 00157 res = t.start(callback(timeout_thread, &sem)); 00158 TEST_ASSERT_EQUAL(osOK, res); 00159 Thread::wait(SHORT_WAIT); 00160 00161 TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state()); 00162 00163 t.join(); 00164 TEST_ASSERT_UINT32_WITHIN(5000, 30000, timer.read_us()); 00165 } 00166 00167 /** Test no timeouts 00168 00169 Test 1 token no timeout 00170 Given thread and a semaphore with one token available 00171 when thread calls @a wait on the semaphore with timeout of 0ms 00172 then the thread acquires the token immediately 00173 00174 Test 0 tokens no timeout 00175 Given thread and a semaphore with no tokens available 00176 when thread calls @a wait on the semaphore with timeout of 0ms 00177 then the thread returns immediately without acquiring a token 00178 */ 00179 template<int T> 00180 void test_no_timeout() 00181 { 00182 Semaphore sem(T); 00183 00184 Timer timer; 00185 timer.start(); 00186 00187 int32_t cnt = sem.wait(0); 00188 TEST_ASSERT_EQUAL(T, cnt); 00189 00190 TEST_ASSERT_UINT32_WITHIN(5000, 0, timer.read_us()); 00191 } 00192 00193 /** Test multiple tokens wait 00194 00195 Given a thread and a semaphore initialized with 5 tokens 00196 when thread calls @a wait 6 times on the semaphore 00197 then the token counts goes to zero 00198 */ 00199 void test_multiple_tokens_wait() 00200 { 00201 Semaphore sem(5); 00202 00203 for(int i = 5; i >= 0; i--) { 00204 int32_t cnt = sem.wait(0); 00205 TEST_ASSERT_EQUAL(i, cnt); 00206 } 00207 } 00208 00209 /** Test multiple tokens release 00210 00211 Given a thread and a semaphore initialized with zero tokens and max of 5 00212 when thread calls @a release 6 times on the semaphore 00213 then the token count should be equal to 5 and last release call should fail 00214 */ 00215 void test_multiple_tokens_release() 00216 { 00217 Semaphore sem(0, 5); 00218 00219 for(int i = 5; i > 0; i--) { 00220 osStatus stat = sem.release(); 00221 TEST_ASSERT_EQUAL(osOK, stat); 00222 } 00223 osStatus stat = sem.release(); 00224 TEST_ASSERT_EQUAL(osErrorResource, stat); 00225 } 00226 00227 utest::v1::status_t test_setup(const size_t number_of_cases) 00228 { 00229 GREENTEA_SETUP(10, "default_auto"); 00230 return verbose_test_setup_handler(number_of_cases); 00231 } 00232 00233 Case cases[] = { 00234 Case("Test single thread", test_single_thread), 00235 Case("Test timeout", test_timeout), 00236 Case("Test 1 token no timeout", test_no_timeout<1>), 00237 Case("Test 0 tokens no timeout", test_no_timeout<0>), 00238 Case("Test multiple tokens wait", test_multiple_tokens_wait), 00239 Case("Test multiple tokens release", test_multiple_tokens_release), 00240 Case("Test multiple threads", test_multi) 00241 }; 00242 00243 Specification specification(test_setup, cases); 00244 00245 int main() 00246 { 00247 return !Harness::run(specification); 00248 }
Generated on Sun Jul 17 2022 08:25:27 by 1.7.2