BA
/
BaBoRo1
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 Timer gtimer; 00042 volatile int ticker_count = 0; 00043 00044 00045 void switch_led1_state(void) 00046 { 00047 // blink 3 times per second 00048 if((callback_trigger_count % 333) == 0) { 00049 led1 = !led1; 00050 } 00051 } 00052 00053 void switch_led2_state(void) 00054 { 00055 // blink 3 times per second 00056 // make led2 blink at the same callback_trigger_count value as led1 00057 if(((callback_trigger_count - 1) % 333) == 0) { 00058 led2 = !led2; 00059 } 00060 } 00061 00062 void ticker_callback_1(void) 00063 { 00064 ++callback_trigger_count; 00065 switch_led1_state(); 00066 } 00067 00068 void ticker_callback_2(void) 00069 { 00070 ++callback_trigger_count; 00071 switch_led2_state(); 00072 } 00073 00074 00075 void sem_release(Semaphore *sem) 00076 { 00077 sem->release(); 00078 } 00079 00080 00081 void stop_gtimer_set_flag(void) 00082 { 00083 gtimer.stop(); 00084 core_util_atomic_incr_u32((uint32_t*)&ticker_callback_flag, 1); 00085 } 00086 00087 void increment_multi_counter(void) 00088 { 00089 core_util_atomic_incr_u32((uint32_t*)&multi_counter, 1); 00090 } 00091 00092 00093 /* Tests is to measure the accuracy of Ticker over a period of time 00094 * 00095 * 1) DUT would start to update callback_trigger_count every milli sec 00096 * 2) Host would query what is current count base_time, Device responds by the callback_trigger_count. 00097 * 3) Host after waiting for measurement stretch. It will query for device time again final_time. 00098 * 4) Host computes the drift considering base_time, final_time, transport delay and measurement stretch 00099 * 5) Finally host send the results back to device pass/fail based on tolerance. 00100 * 6) More details on tests can be found in timing_drift_auto.py 00101 */ 00102 void test_case_1x_ticker() 00103 { 00104 char _key[11] = { }; 00105 char _value[128] = { }; 00106 int expected_key = 1; 00107 Ticker ticker; 00108 00109 led1 = 1; 00110 led2 = 1; 00111 callback_trigger_count = 0; 00112 00113 greentea_send_kv("timing_drift_check_start", 0); 00114 ticker.attach_us(&ticker_callback_1, ONE_MILLI_SEC); 00115 00116 // wait for 1st signal from host 00117 do { 00118 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00119 expected_key = strcmp(_key, "base_time"); 00120 } while (expected_key); 00121 greentea_send_kv(_key, callback_trigger_count * ONE_MILLI_SEC); 00122 00123 // wait for 2nd signal from host 00124 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00125 greentea_send_kv(_key, callback_trigger_count * ONE_MILLI_SEC); 00126 00127 //get the results from host 00128 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00129 00130 TEST_ASSERT_EQUAL_STRING_MESSAGE("pass", _key,"Host side script reported a fail..."); 00131 } 00132 00133 /* Tests is to measure the accuracy of Ticker over a period of time 00134 * 00135 * 1) DUT would start to update callback_trigger_count every milli sec, we use 2 tickers 00136 * to update the count alternatively. 00137 * 2) Host would query what is current count base_time, Device responds by the callback_trigger_count 00138 * 3) Host after waiting for measurement stretch. It will query for device time again final_time. 00139 * 4) Host computes the drift considering base_time, final_time, transport delay and measurement stretch 00140 * 5) Finally host send the results back to device pass/fail based on tolerance. 00141 * 6) More details on tests can be found in timing_drift_auto.py 00142 */ 00143 void test_case_2x_ticker() 00144 { 00145 char _key[11] = { }; 00146 char _value[128] = { }; 00147 int expected_key = 1; 00148 Ticker ticker1, ticker2; 00149 00150 led1 = 0; 00151 led2 = 1; 00152 callback_trigger_count = 0; 00153 00154 ticker1.attach_us(ticker_callback_1, 2 * ONE_MILLI_SEC); 00155 // delay second ticker to have a pair of tickers tick every one millisecond 00156 wait_us(ONE_MILLI_SEC); 00157 greentea_send_kv("timing_drift_check_start", 0); 00158 ticker2.attach_us(ticker_callback_2, 2 * ONE_MILLI_SEC); 00159 00160 // wait for 1st signal from host 00161 do { 00162 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00163 expected_key = strcmp(_key, "base_time"); 00164 } while (expected_key); 00165 greentea_send_kv(_key, callback_trigger_count * ONE_MILLI_SEC); 00166 00167 // wait for 2nd signal from host 00168 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00169 greentea_send_kv(_key, callback_trigger_count * ONE_MILLI_SEC); 00170 00171 //get the results from host 00172 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00173 00174 TEST_ASSERT_EQUAL_STRING_MESSAGE("pass", _key,"Host side script reported a fail..."); 00175 } 00176 00177 /** Test many tickers run one after the other 00178 00179 Given many Tickers 00180 When schedule them one after the other with the same time intervals 00181 Then tickers properly execute callbacks 00182 When schedule them one after the other with the different time intervals 00183 Then tickers properly execute callbacks 00184 */ 00185 void test_multi_ticker(void) 00186 { 00187 Ticker ticker[TICKER_COUNT]; 00188 const uint32_t extra_wait = 5; // extra 5ms wait time 00189 00190 multi_counter = 0; 00191 for (int i = 0; i < TICKER_COUNT; i++) { 00192 ticker[i].attach_us(callback(increment_multi_counter), MULTI_TICKER_TIME_MS * 1000); 00193 } 00194 00195 Thread::wait(MULTI_TICKER_TIME_MS + extra_wait); 00196 for (int i = 0; i < TICKER_COUNT; i++) { 00197 ticker[i].detach(); 00198 } 00199 TEST_ASSERT_EQUAL(TICKER_COUNT, multi_counter); 00200 00201 multi_counter = 0; 00202 for (int i = 0; i < TICKER_COUNT; i++) { 00203 ticker[i].attach_us(callback(increment_multi_counter), (MULTI_TICKER_TIME_MS + i) * 1000); 00204 } 00205 00206 Thread::wait(MULTI_TICKER_TIME_MS + TICKER_COUNT + extra_wait); 00207 for (int i = 0; i < TICKER_COUNT; i++) { 00208 ticker[i].detach(); 00209 } 00210 TEST_ASSERT_EQUAL(TICKER_COUNT, multi_counter); 00211 } 00212 00213 /** Test multi callback time 00214 00215 Given a Ticker 00216 When the callback is attached multiple times 00217 Then ticker properly execute callback multiple times 00218 */ 00219 void test_multi_call_time(void) 00220 { 00221 Ticker ticker; 00222 int time_diff; 00223 const int attach_count = 10; 00224 00225 for (int i = 0; i < attach_count; i++) { 00226 ticker_callback_flag = 0; 00227 gtimer.reset(); 00228 00229 gtimer.start(); 00230 ticker.attach_us(callback(stop_gtimer_set_flag), MULTI_TICKER_TIME_MS * 1000); 00231 while(!ticker_callback_flag); 00232 time_diff = gtimer.read_us(); 00233 00234 TEST_ASSERT_UINT32_WITHIN(TOLERANCE_US, MULTI_TICKER_TIME_MS * 1000, time_diff); 00235 } 00236 } 00237 00238 /** Test if detach cancel scheduled callback event 00239 00240 Given a Ticker with callback attached 00241 When the callback is detached 00242 Then the callback is not being called 00243 */ 00244 void test_detach(void) 00245 { 00246 Ticker ticker; 00247 int32_t ret; 00248 const float ticker_time_s = 0.1f; 00249 const uint32_t wait_time_ms = 500; 00250 Semaphore sem(0, 1); 00251 00252 ticker.attach(callback(sem_release, &sem), ticker_time_s); 00253 00254 ret = sem.wait(); 00255 TEST_ASSERT_TRUE(ret > 0); 00256 00257 ret = sem.wait(); 00258 ticker.detach(); /* cancel */ 00259 TEST_ASSERT_TRUE(ret > 0); 00260 00261 ret = sem.wait(wait_time_ms); 00262 TEST_ASSERT_EQUAL(0, ret); 00263 } 00264 00265 /** Test single callback time via attach 00266 00267 Given a Ticker 00268 When callback attached with time interval specified 00269 Then ticker properly executes callback within a specified time interval 00270 */ 00271 template<us_timestamp_t DELAY_US> 00272 void test_attach_time(void) 00273 { 00274 Ticker ticker; 00275 ticker_callback_flag = 0; 00276 00277 gtimer.reset(); 00278 gtimer.start(); 00279 ticker.attach(callback(stop_gtimer_set_flag), ((float)DELAY_US) / 1000000.0f); 00280 while(!ticker_callback_flag); 00281 ticker.detach(); 00282 const int time_diff = gtimer.read_us(); 00283 00284 TEST_ASSERT_UINT64_WITHIN(TOLERANCE_US, DELAY_US, time_diff); 00285 } 00286 00287 /** Test single callback time via attach_us 00288 00289 Given a Ticker 00290 When callback attached with time interval specified 00291 Then ticker properly executes callback within a specified time interval 00292 */ 00293 template<us_timestamp_t DELAY_US> 00294 void test_attach_us_time(void) 00295 { 00296 Ticker ticker; 00297 ticker_callback_flag = 0; 00298 00299 gtimer.reset(); 00300 gtimer.start(); 00301 ticker.attach_us(callback(stop_gtimer_set_flag), DELAY_US); 00302 while(!ticker_callback_flag); 00303 ticker.detach(); 00304 const int time_diff = gtimer.read_us(); 00305 00306 TEST_ASSERT_UINT64_WITHIN(TOLERANCE_US, DELAY_US, time_diff); 00307 } 00308 00309 00310 // Test cases 00311 Case cases[] = { 00312 Case("Test attach for 0.01s and time measure", test_attach_time<10000>), 00313 Case("Test attach_us for 10ms and time measure", test_attach_us_time<10000>), 00314 Case("Test attach for 0.1s and time measure", test_attach_time<100000>), 00315 Case("Test attach_us for 100ms and time measure", test_attach_us_time<100000>), 00316 Case("Test attach for 0.5s and time measure", test_attach_time<500000>), 00317 Case("Test attach_us for 500ms and time measure", test_attach_us_time<500000>), 00318 Case("Test detach", test_detach), 00319 Case("Test multi call and time measure", test_multi_call_time), 00320 Case("Test multi ticker", test_multi_ticker), 00321 Case("Test timers: 1x ticker", test_case_1x_ticker), 00322 Case("Test timers: 2x ticker", test_case_2x_ticker) 00323 }; 00324 00325 utest::v1::status_t greentea_test_setup(const size_t number_of_cases) 00326 { 00327 GREENTEA_SETUP(test_timeout, "timing_drift_auto"); 00328 return utest::v1::greentea_test_setup_handler(number_of_cases); 00329 } 00330 00331 utest::v1::Specification specification(greentea_test_setup, cases, utest::v1::greentea_test_teardown_handler); 00332 00333 int main() 00334 { 00335 utest::v1::Harness::run(specification); 00336 }
Generated on Tue Jul 12 2022 12:22:06 by
