Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2013-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 00022 using utest::v1::Case; 00023 00024 #define ONE_MILLI_SEC 1000 00025 #define TICKER_COUNT 16 00026 #define MULTI_TICKER_TIME_MS 100 00027 volatile uint32_t callback_trigger_count = 0; 00028 static const int test_timeout = 240; 00029 static const int total_ticks = 10; 00030 00031 00032 /* Tolerance is quite arbitrary due to large number of boards with varying level of accuracy */ 00033 #define TOLERANCE_US 1000 00034 00035 volatile uint32_t ticker_callback_flag; 00036 volatile uint32_t multi_counter; 00037 00038 DigitalOut led1(LED1); 00039 DigitalOut led2(LED2); 00040 00041 Ticker *volatile ticker1; 00042 Ticker *volatile ticker2; 00043 Timer gtimer; 00044 00045 volatile int ticker_count = 0; 00046 volatile bool print_tick = false; 00047 00048 void ticker_callback_1_switch_to_2(void); 00049 void ticker_callback_2_switch_to_1(void); 00050 00051 void increment_ticker_counter(void) 00052 { 00053 ++callback_trigger_count; 00054 } 00055 00056 void switch_led1_state(void) 00057 { 00058 led1 = !led1; 00059 } 00060 00061 void switch_led2_state(void) 00062 { 00063 led2 = !led2; 00064 } 00065 00066 void ticker_callback_1_switch_to_2(void) 00067 { 00068 ++callback_trigger_count; 00069 // If ticker is NULL then it is being or has been deleted 00070 if (ticker1) { 00071 ticker1->detach(); 00072 ticker1->attach_us(ticker_callback_2_switch_to_1, ONE_MILLI_SEC); 00073 } 00074 switch_led1_state(); 00075 } 00076 00077 void ticker_callback_2_switch_to_1(void) 00078 { 00079 ++callback_trigger_count; 00080 // If ticker is NULL then it is being or has been deleted 00081 if (ticker2) { 00082 ticker2->detach(); 00083 ticker2->attach_us(ticker_callback_1_switch_to_2, ONE_MILLI_SEC); 00084 } 00085 switch_led2_state(); 00086 } 00087 00088 00089 void sem_release(Semaphore *sem) 00090 { 00091 sem->release(); 00092 } 00093 00094 00095 void stop_gtimer_set_flag(void) 00096 { 00097 gtimer.stop(); 00098 core_util_atomic_incr_u32((uint32_t*)&ticker_callback_flag, 1); 00099 } 00100 00101 void increment_multi_counter(void) 00102 { 00103 core_util_atomic_incr_u32((uint32_t*)&multi_counter, 1); 00104 } 00105 00106 00107 /* Tests is to measure the accuracy of Ticker over a period of time 00108 * 00109 * 1) DUT would start to update callback_trigger_count every milli sec, in 2x callback we use 2 tickers 00110 * to update the count alternatively. 00111 * 2) Host would query what is current count base_time, Device responds by the callback_trigger_count 00112 * 3) Host after waiting for measurement stretch. It will query for device time again final_time. 00113 * 4) Host computes the drift considering base_time, final_time, transport delay and measurement stretch 00114 * 5) Finally host send the results back to device pass/fail based on tolerance. 00115 * 6) More details on tests can be found in timing_drift_auto.py 00116 */ 00117 void test_case_1x_ticker() 00118 { 00119 char _key[11] = { }; 00120 char _value[128] = { }; 00121 int expected_key = 1; 00122 00123 greentea_send_kv("timing_drift_check_start", 0); 00124 ticker1->attach_us(&increment_ticker_counter, ONE_MILLI_SEC); 00125 00126 // wait for 1st signal from host 00127 do { 00128 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00129 expected_key = strcmp(_key, "base_time"); 00130 } while (expected_key); 00131 greentea_send_kv(_key, callback_trigger_count * ONE_MILLI_SEC); 00132 00133 // wait for 2nd signal from host 00134 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00135 greentea_send_kv(_key, callback_trigger_count * ONE_MILLI_SEC); 00136 00137 //get the results from host 00138 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00139 00140 TEST_ASSERT_EQUAL_STRING_MESSAGE("pass", _key,"Host side script reported a fail..."); 00141 } 00142 00143 void test_case_2x_callbacks() 00144 { 00145 char _key[11] = { }; 00146 char _value[128] = { }; 00147 int expected_key = 1; 00148 00149 led1 = 0; 00150 led2 = 0; 00151 callback_trigger_count = 0; 00152 00153 greentea_send_kv("timing_drift_check_start", 0); 00154 ticker1->attach_us(ticker_callback_1_switch_to_2, ONE_MILLI_SEC); 00155 00156 // wait for 1st signal from host 00157 do { 00158 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00159 expected_key = strcmp(_key, "base_time"); 00160 } while (expected_key); 00161 greentea_send_kv(_key, callback_trigger_count * ONE_MILLI_SEC); 00162 00163 // wait for 2nd signal from host 00164 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00165 greentea_send_kv(_key, callback_trigger_count * ONE_MILLI_SEC); 00166 00167 //get the results from host 00168 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00169 00170 TEST_ASSERT_EQUAL_STRING_MESSAGE("pass", _key,"Host side script reported a fail..."); 00171 } 00172 00173 /** Test many tickers run one after the other 00174 00175 Given many Tickers 00176 When schedule them one after the other with the same time intervals 00177 Then tickers properly execute callbacks 00178 When schedule them one after the other with the different time intervals 00179 Then tickers properly execute callbacks 00180 */ 00181 void test_multi_ticker(void) 00182 { 00183 Ticker ticker[TICKER_COUNT]; 00184 const uint32_t extra_wait = 5; // extra 5ms wait time 00185 00186 multi_counter = 0; 00187 for (int i = 0; i < TICKER_COUNT; i++) { 00188 ticker[i].attach_us(callback(increment_multi_counter), MULTI_TICKER_TIME_MS * 1000); 00189 } 00190 00191 Thread::wait(MULTI_TICKER_TIME_MS + extra_wait); 00192 for (int i = 0; i < TICKER_COUNT; i++) { 00193 ticker[i].detach(); 00194 } 00195 TEST_ASSERT_EQUAL(TICKER_COUNT, multi_counter); 00196 00197 multi_counter = 0; 00198 for (int i = 0; i < TICKER_COUNT; i++) { 00199 ticker[i].attach_us(callback(increment_multi_counter), (MULTI_TICKER_TIME_MS + i) * 1000); 00200 } 00201 00202 Thread::wait(MULTI_TICKER_TIME_MS + TICKER_COUNT + extra_wait); 00203 for (int i = 0; i < TICKER_COUNT; i++) { 00204 ticker[i].detach(); 00205 } 00206 TEST_ASSERT_EQUAL(TICKER_COUNT, multi_counter); 00207 } 00208 00209 /** Test multi callback time 00210 00211 Given a Ticker 00212 When the callback is attached multiple times 00213 Then ticker properly execute callback multiple times 00214 */ 00215 void test_multi_call_time(void) 00216 { 00217 Ticker ticker; 00218 int time_diff; 00219 const int attach_count = 10; 00220 00221 for (int i = 0; i < attach_count; i++) { 00222 ticker_callback_flag = 0; 00223 gtimer.reset(); 00224 00225 gtimer.start(); 00226 ticker.attach_us(callback(stop_gtimer_set_flag), MULTI_TICKER_TIME_MS * 1000); 00227 while(!ticker_callback_flag); 00228 time_diff = gtimer.read_us(); 00229 00230 TEST_ASSERT_UINT32_WITHIN(TOLERANCE_US, MULTI_TICKER_TIME_MS * 1000, time_diff); 00231 } 00232 } 00233 00234 /** Test if detach cancel scheduled callback event 00235 00236 Given a Ticker with callback attached 00237 When the callback is detached 00238 Then the callback is not being called 00239 */ 00240 void test_detach(void) 00241 { 00242 Ticker ticker; 00243 int32_t ret; 00244 const float ticker_time_s = 0.1f; 00245 const uint32_t wait_time_ms = 500; 00246 Semaphore sem(0, 1); 00247 00248 ticker.attach(callback(sem_release, &sem), ticker_time_s); 00249 00250 ret = sem.wait(); 00251 TEST_ASSERT_TRUE(ret > 0); 00252 00253 ret = sem.wait(); 00254 ticker.detach(); /* cancel */ 00255 TEST_ASSERT_TRUE(ret > 0); 00256 00257 ret = sem.wait(wait_time_ms); 00258 TEST_ASSERT_EQUAL(0, ret); 00259 } 00260 00261 /** Test single callback time via attach 00262 00263 Given a Ticker 00264 When callback attached with time interval specified 00265 Then ticker properly executes callback within a specified time interval 00266 */ 00267 template<us_timestamp_t DELAY_US> 00268 void test_attach_time(void) 00269 { 00270 Ticker ticker; 00271 ticker_callback_flag = 0; 00272 00273 gtimer.reset(); 00274 gtimer.start(); 00275 ticker.attach(callback(stop_gtimer_set_flag), ((float)DELAY_US) / 1000000.0f); 00276 while(!ticker_callback_flag); 00277 ticker.detach(); 00278 const int time_diff = gtimer.read_us(); 00279 00280 TEST_ASSERT_UINT64_WITHIN(TOLERANCE_US, DELAY_US, time_diff); 00281 } 00282 00283 /** Test single callback time via attach_us 00284 00285 Given a Ticker 00286 When callback attached with time interval specified 00287 Then ticker properly executes callback within a specified time interval 00288 */ 00289 template<us_timestamp_t DELAY_US> 00290 void test_attach_us_time(void) 00291 { 00292 Ticker ticker; 00293 ticker_callback_flag = 0; 00294 00295 gtimer.reset(); 00296 gtimer.start(); 00297 ticker.attach_us(callback(stop_gtimer_set_flag), DELAY_US); 00298 while(!ticker_callback_flag); 00299 ticker.detach(); 00300 const int time_diff = gtimer.read_us(); 00301 00302 TEST_ASSERT_UINT64_WITHIN(TOLERANCE_US, DELAY_US, time_diff); 00303 } 00304 00305 00306 utest::v1::status_t one_ticker_case_setup_handler_t(const Case *const source, const size_t index_of_case) 00307 { 00308 ticker1 = new Ticker(); 00309 return greentea_case_setup_handler(source, index_of_case); 00310 } 00311 00312 utest::v1::status_t two_ticker_case_setup_handler_t(const Case *const source, const size_t index_of_case) 00313 { 00314 ticker1 = new Ticker(); 00315 ticker2 = new Ticker(); 00316 return utest::v1::greentea_case_setup_handler(source, index_of_case); 00317 } 00318 00319 utest::v1::status_t one_ticker_case_teardown_handler_t(const Case *const source, const size_t passed, const size_t failed, const utest::v1::failure_t reason) 00320 { 00321 Ticker *temp1 = ticker1; 00322 ticker1 = NULL; 00323 delete temp1; 00324 return utest::v1::greentea_case_teardown_handler(source, passed, failed, reason); 00325 } 00326 00327 utest::v1::status_t two_ticker_case_teardown_handler_t(const Case *const source, const size_t passed, const size_t failed, const utest::v1::failure_t reason) 00328 { 00329 Ticker *temp1 = ticker1; 00330 Ticker *temp2 = ticker2; 00331 ticker1 = NULL; 00332 ticker2 = NULL; 00333 delete temp1; 00334 delete temp2; 00335 return utest::v1::greentea_case_teardown_handler(source, passed, failed, reason); 00336 } 00337 00338 00339 // Test cases 00340 Case cases[] = { 00341 Case("Test attach for 0.01s and time measure", test_attach_time<10000>), 00342 Case("Test attach_us for 10ms and time measure", test_attach_us_time<10000>), 00343 Case("Test attach for 0.1s and time measure", test_attach_time<100000>), 00344 Case("Test attach_us for 100ms and time measure", test_attach_us_time<100000>), 00345 Case("Test attach for 0.5s and time measure", test_attach_time<500000>), 00346 Case("Test attach_us for 500ms and time measure", test_attach_us_time<500000>), 00347 Case("Test detach", test_detach), 00348 Case("Test multi call and time measure", test_multi_call_time), 00349 Case("Test multi ticker", test_multi_ticker), 00350 Case("Test timers: 1x ticker", one_ticker_case_setup_handler_t,test_case_1x_ticker, one_ticker_case_teardown_handler_t), 00351 Case("Test timers: 2x callbacks", two_ticker_case_setup_handler_t,test_case_2x_callbacks, two_ticker_case_teardown_handler_t) 00352 }; 00353 00354 utest::v1::status_t greentea_test_setup(const size_t number_of_cases) 00355 { 00356 GREENTEA_SETUP(test_timeout, "timing_drift_auto"); 00357 return utest::v1::greentea_test_setup_handler(number_of_cases); 00358 } 00359 00360 utest::v1::Specification specification(greentea_test_setup, cases, utest::v1::greentea_test_teardown_handler); 00361 00362 int main() 00363 { 00364 utest::v1::Harness::run(specification); 00365 }
Generated on Sun Jul 17 2022 08:25:27 by 1.7.2