takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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 "unity.h"
00019 #include "utest.h"
00020 #include "rtos.h"
00021 
00022 #if defined(MBED_RTOS_SINGLE_THREAD)
00023 #error [NOT_SUPPORTED] test not supported
00024 #endif
00025 
00026 #if !DEVICE_USTICKER
00027 #error [NOT_SUPPORTED] test not supported
00028 #endif
00029 
00030 using namespace utest::v1;
00031 
00032 #if defined(__CORTEX_M23) || defined(__CORTEX_M33)
00033 #define TEST_STACK_SIZE 768
00034 #else
00035 #define TEST_STACK_SIZE 512
00036 #endif
00037 
00038 #define TEST_LONG_DELAY 20
00039 #define TEST_DELAY 10
00040 #define SIGNALS_TO_EMIT 100
00041 
00042 Mutex stdio_mutex;
00043 
00044 volatile int change_counter = 0;
00045 volatile bool changing_counter = false;
00046 volatile bool mutex_defect = false;
00047 
00048 bool manipulate_protected_zone(const int thread_delay)
00049 {
00050     bool result = true;
00051     osStatus stat;
00052 
00053     stdio_mutex.lock();
00054 
00055     core_util_critical_section_enter();
00056     if (changing_counter == true) {
00057         result = false;
00058         mutex_defect = true;
00059     }
00060     changing_counter = true;
00061 
00062     change_counter++;
00063     core_util_critical_section_exit();
00064 
00065     Thread::wait(thread_delay);
00066 
00067     core_util_critical_section_enter();
00068     changing_counter = false;
00069     core_util_critical_section_exit();
00070 
00071     stdio_mutex.unlock();
00072 
00073     return result;
00074 }
00075 
00076 void test_thread(int const *thread_delay)
00077 {
00078     while (true) {
00079         manipulate_protected_zone(*thread_delay);
00080     }
00081 }
00082 
00083 /** Test multiple thread
00084 
00085     Given 3 threads started with different delays and a section protected with a mutex
00086     when each thread runs it tries to lock the mutex
00087     then no more than one thread should be able to access protected region
00088 */
00089 void test_multiple_threads(void)
00090 {
00091     const int t1_delay = TEST_DELAY * 1;
00092     const int t2_delay = TEST_DELAY * 2;
00093     const int t3_delay = TEST_DELAY * 3;
00094 
00095     Thread t2(osPriorityNormal, TEST_STACK_SIZE);
00096     Thread t3(osPriorityNormal, TEST_STACK_SIZE);
00097 
00098     t2.start(callback(test_thread, &t2_delay));
00099     t3.start(callback(test_thread, &t3_delay));
00100 
00101     while (true) {
00102         // Thread 1 action
00103         Thread::wait(t1_delay);
00104         manipulate_protected_zone(t1_delay);
00105 
00106         core_util_critical_section_enter();
00107         if (change_counter >= SIGNALS_TO_EMIT or mutex_defect == true) {
00108             core_util_critical_section_exit();
00109             t2.terminate();
00110             t3.terminate();
00111             break;
00112         }
00113         core_util_critical_section_exit();
00114     }
00115 
00116     TEST_ASSERT_EQUAL(false, mutex_defect);
00117 }
00118 
00119 void test_dual_thread_nolock_lock_thread(Mutex *mutex)
00120 {
00121     osStatus stat;
00122     mutex->lock();
00123 
00124     mutex->unlock();
00125 }
00126 
00127 void test_dual_thread_nolock_trylock_thread(Mutex *mutex)
00128 {
00129     bool stat_b = mutex->trylock();
00130     TEST_ASSERT_EQUAL(true, stat_b);
00131 
00132     mutex->unlock();
00133 }
00134 
00135 /** Test dual thread no-lock
00136 
00137     Test dual thread second thread lock
00138     Given two threads A & B and a mutex
00139     When thread A creates a mutex and starts thread B
00140         and thread B calls @a lock and @a unlock
00141     Then @a lock and @a unlock operations are successfully performed.
00142 
00143     Test dual thread second thread trylock
00144     Given two threads A & B and a mutex
00145     When thread A creates a mutex and starts thread B
00146         and thread B calls @a trylock and @a unlock
00147     Then @a trylock and @a unlock operations are successfully performed.
00148 */
00149 template <void (*F)(Mutex *)>
00150 void test_dual_thread_nolock(void)
00151 {
00152     Mutex mutex;
00153     Thread thread(osPriorityNormal, TEST_STACK_SIZE);
00154 
00155     thread.start(callback(F, &mutex));
00156 
00157     wait_ms(TEST_DELAY);
00158 }
00159 
00160 void test_dual_thread_lock_unlock_thread(Mutex *mutex)
00161 {
00162     mutex->lock();
00163 }
00164 
00165 /** Test dual thread lock unlock
00166 
00167     Given two threads and a lock
00168     When thread A locks the lock and starts thread B
00169         and thread B calls @a lock on the mutex
00170     Then thread B waits for thread A to unlock the lock
00171     When thread A calls @a unlock on the mutex
00172     Then thread B acquires the lock
00173 */
00174 void test_dual_thread_lock_unlock(void)
00175 {
00176     Mutex mutex;
00177     osStatus stat;
00178     Thread thread(osPriorityNormal, TEST_STACK_SIZE);
00179 
00180     mutex.lock();
00181 
00182     thread.start(callback(test_dual_thread_lock_unlock_thread, &mutex));
00183 
00184     mutex.unlock();
00185 
00186     wait_ms(TEST_DELAY);
00187 }
00188 
00189 void test_dual_thread_lock_trylock_thread(Mutex *mutex)
00190 {
00191     bool stat = mutex->trylock();
00192     TEST_ASSERT_EQUAL(false, stat);
00193 }
00194 
00195 void test_dual_thread_lock_lock_thread(Mutex *mutex)
00196 {
00197     Timer timer;
00198     timer.start();
00199 
00200     bool stat = mutex->trylock_for(TEST_DELAY);
00201     TEST_ASSERT_EQUAL(false, stat);
00202     TEST_ASSERT_UINT32_WITHIN(5000, TEST_DELAY*1000, timer.read_us());
00203 }
00204 
00205 /** Test dual thread lock
00206 
00207     Test dual thread lock locked
00208     Given a mutex and two threads A & B
00209     When thread A calls @a lock and starts thread B
00210         and thread B calls @a lock with 500ms timeout
00211     Then thread B waits 500ms and timeouts
00212 
00213     Test dual thread trylock locked
00214     Given a mutex and two threads A & B
00215     When thread A calls @a lock and starts thread B
00216     Then thread B calls @a trylock
00217         and thread B fails to acquire the lock
00218 */
00219 template <void (*F)(Mutex *)>
00220 void test_dual_thread_lock(void)
00221 {
00222     Mutex mutex;
00223     osStatus stat;
00224     Thread thread(osPriorityNormal, TEST_STACK_SIZE);
00225 
00226     mutex.lock();
00227 
00228     thread.start(callback(F, &mutex));
00229 
00230     wait_ms(TEST_LONG_DELAY);
00231 
00232     mutex.unlock();
00233 }
00234 
00235 /** Test single thread lock recursive
00236 
00237     Given a mutex and a single running thread
00238     When thread calls @a lock twice and @a unlock twice on the mutex
00239     Then @a lock and @a unlock operations are successfully performed.
00240 */
00241 void test_single_thread_lock_recursive(void)
00242 {
00243     Mutex mutex;
00244     osStatus stat;
00245 
00246     mutex.lock();
00247 
00248     mutex.lock();
00249 
00250     mutex.unlock();
00251 
00252     mutex.unlock();
00253 }
00254 
00255 /** Test single thread trylock
00256 
00257     Given a mutex and a single running thread
00258     When thread calls @a trylock and @a unlock on the mutex
00259     Then @a trylock and @a unlock operations are successfully performed.
00260 */
00261 void test_single_thread_trylock(void)
00262 {
00263     Mutex mutex;
00264 
00265     bool stat_b = mutex.trylock();
00266     TEST_ASSERT_EQUAL(true, stat_b);
00267 
00268     mutex.unlock();
00269 }
00270 
00271 /** Test single thread lock
00272 
00273     Given a mutex and a single running thread
00274     When thread calls @a lock and @a unlock on the mutex
00275     Then @a lock and @a unlock operations are successfully performed.
00276 */
00277 void test_single_thread_lock(void)
00278 {
00279     Mutex mutex;
00280     osStatus stat;
00281 
00282     mutex.lock();
00283 
00284     mutex.unlock();
00285 }
00286 
00287 utest::v1::status_t test_setup(const size_t number_of_cases)
00288 {
00289     GREENTEA_SETUP(10, "default_auto");
00290     return verbose_test_setup_handler(number_of_cases);
00291 }
00292 
00293 Case cases[] = {
00294     Case("Test single thread lock", test_single_thread_lock),
00295     Case("Test single thread trylock", test_single_thread_trylock),
00296     Case("Test single thread lock recursive", test_single_thread_lock_recursive),
00297     Case("Test dual thread lock locked", test_dual_thread_lock<test_dual_thread_lock_lock_thread>),
00298     Case("Test dual thread trylock locked", test_dual_thread_lock<test_dual_thread_lock_trylock_thread>),
00299     Case("Test dual thread lock unlock", test_dual_thread_lock_unlock),
00300     Case("Test dual thread second thread lock", test_dual_thread_nolock<test_dual_thread_nolock_lock_thread>),
00301     Case("Test dual thread second thread trylock", test_dual_thread_nolock<test_dual_thread_nolock_trylock_thread>),
00302     Case("Test multiple thread", test_multiple_threads),
00303 };
00304 
00305 Specification specification(test_setup, cases);
00306 
00307 int main()
00308 {
00309     return !Harness::run(specification);
00310 }