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 #if defined(MBED_RTOS_SINGLE_THREAD) 00023 #error [NOT_SUPPORTED] test not supported 00024 #endif 00025 00026 using namespace utest::v1; 00027 00028 #define THREAD_STACK_SIZE 320 /* larger stack cause out of heap memory on some 16kB RAM boards in multi thread test*/ 00029 #define QUEUE_SIZE 16 00030 #define THREAD_1_ID 1 00031 #define THREAD_2_ID 2 00032 #define THREAD_3_ID 3 00033 #define QUEUE_PUT_DELAY_1 5 00034 #define QUEUE_PUT_DELAY_2 50 00035 #define QUEUE_PUT_DELAY_3 100 00036 #define DATA_BASE 100 00037 00038 00039 typedef struct { 00040 uint16_t data; 00041 uint8_t thread_id; 00042 } mail_t; 00043 00044 00045 template<uint8_t thread_id, uint32_t wait_ms, uint32_t send_count> 00046 void send_thread(Mail<mail_t, QUEUE_SIZE> *m) 00047 { 00048 uint32_t data = thread_id * DATA_BASE; 00049 00050 for (uint32_t i = 0; i < send_count; i++) { 00051 mail_t *mail = m->alloc(); 00052 mail->thread_id = thread_id; 00053 mail->data = data++; 00054 m->put(mail); 00055 Thread::wait(wait_ms); 00056 } 00057 } 00058 00059 template<uint8_t thread_id, uint32_t queue_size, uint32_t wait_ms> 00060 void receive_thread(Mail<mail_t, queue_size> *m) 00061 { 00062 int result_counter = 0; 00063 uint32_t data = thread_id * DATA_BASE; 00064 00065 Thread::wait(wait_ms); 00066 for (uint32_t i = 0; i < queue_size; i++) { 00067 osEvent evt = m->get(); 00068 if (evt.status == osEventMail) { 00069 mail_t *mail = (mail_t*)evt.value.p; 00070 const uint8_t id = mail->thread_id; 00071 00072 // verify thread id 00073 TEST_ASSERT_TRUE(id == thread_id); 00074 // verify sent data 00075 TEST_ASSERT_TRUE(mail->data == data++); 00076 00077 m->free(mail); 00078 result_counter++; 00079 } 00080 } 00081 TEST_ASSERT_EQUAL(queue_size, result_counter); 00082 } 00083 00084 /** Test single thread Mail usage and order 00085 00086 Given mailbox and one additional thread 00087 When messages are put in to the Mail box by this thread 00088 Then messages are received in main thread in the same order as was sent and the data sent is valid 00089 */ 00090 void test_single_thread_order(void) 00091 { 00092 uint16_t data = DATA_BASE; 00093 int result_counter = 0; 00094 Mail<mail_t, QUEUE_SIZE> mail_box; 00095 00096 // mail send thread creation 00097 Thread thread(osPriorityNormal, THREAD_STACK_SIZE); 00098 thread.start(callback(send_thread<THREAD_1_ID, QUEUE_PUT_DELAY_1, QUEUE_SIZE>, &mail_box)); 00099 00100 // wait for some mail to be collected 00101 Thread::wait(10); 00102 00103 for (uint32_t i = 0; i < QUEUE_SIZE; i++) { 00104 // mail receive (main thread) 00105 osEvent evt = mail_box.get(); 00106 if (evt.status == osEventMail) { 00107 mail_t *mail = (mail_t*)evt.value.p; 00108 const uint8_t id = mail->thread_id; 00109 00110 // verify thread id 00111 TEST_ASSERT_TRUE(id == THREAD_1_ID); 00112 // verify sent data 00113 TEST_ASSERT_TRUE(mail->data == data++); 00114 mail_box.free(mail); 00115 00116 result_counter++; 00117 } 00118 } 00119 TEST_ASSERT_EQUAL(QUEUE_SIZE, result_counter); 00120 } 00121 00122 /** Test multi thread Mail usage and order 00123 00124 Given mailbox and three additional threads 00125 When messages are put in to the Mail box by these threads 00126 Then messages are received in main thread in the same per thread order as was sent and the data sent is valid 00127 */ 00128 void test_multi_thread_order(void) 00129 { 00130 uint16_t data[4] = { 0, DATA_BASE, DATA_BASE * 2, DATA_BASE * 3 }; 00131 int result_counter = 0; 00132 Mail<mail_t, QUEUE_SIZE> mail_box; 00133 00134 // mail send threads creation 00135 Thread thread1(osPriorityNormal, THREAD_STACK_SIZE); 00136 Thread thread2(osPriorityNormal, THREAD_STACK_SIZE); 00137 Thread thread3(osPriorityNormal, THREAD_STACK_SIZE); 00138 thread1.start(callback(send_thread<THREAD_1_ID, QUEUE_PUT_DELAY_1, 7>, &mail_box)); 00139 thread2.start(callback(send_thread<THREAD_2_ID, QUEUE_PUT_DELAY_2, 5>, &mail_box)); 00140 thread3.start(callback(send_thread<THREAD_3_ID, QUEUE_PUT_DELAY_3, 4>, &mail_box)); 00141 00142 // wait for some mail to be collected 00143 Thread::wait(10); 00144 00145 for (uint32_t i = 0; i < QUEUE_SIZE; i++) { 00146 // mail receive (main thread) 00147 osEvent evt = mail_box.get(); 00148 if (evt.status == osEventMail) { 00149 mail_t *mail = (mail_t*)evt.value.p; 00150 const uint8_t id = mail->thread_id; 00151 00152 // verify thread id 00153 TEST_ASSERT_TRUE((id == THREAD_1_ID) || (id == THREAD_2_ID) || (id == THREAD_3_ID)); 00154 // verify sent data 00155 TEST_ASSERT_TRUE(mail->data == data[id]++); 00156 mail_box.free(mail); 00157 00158 result_counter++; 00159 } 00160 } 00161 TEST_ASSERT_EQUAL(QUEUE_SIZE, result_counter); 00162 } 00163 00164 /** Test multi thread multi Mail usage and order 00165 00166 Given 3 mailbox and three additional threads 00167 When messages are put in to the mail boxes by main thread 00168 Then messages are received by threads in the same per mail box order as was sent and the data sent is valid 00169 */ 00170 void test_multi_thread_multi_mail_order(void) 00171 { 00172 Mail<mail_t, 4> mail_box[4]; /* mail_box[0] not used */ 00173 uint16_t data[4] = { 0, DATA_BASE, DATA_BASE * 2, DATA_BASE * 3 }; 00174 mail_t *mail; 00175 uint8_t id; 00176 00177 // mail receive threads creation 00178 Thread thread1(osPriorityNormal, THREAD_STACK_SIZE); 00179 Thread thread2(osPriorityNormal, THREAD_STACK_SIZE); 00180 Thread thread3(osPriorityNormal, THREAD_STACK_SIZE); 00181 thread1.start(callback(receive_thread<THREAD_1_ID, 4, 0>, mail_box + 1)); 00182 thread2.start(callback(receive_thread<THREAD_2_ID, 4, 10>, mail_box + 2)); 00183 thread3.start(callback(receive_thread<THREAD_3_ID, 4, 100>, mail_box + 3)); 00184 00185 for (uint32_t i = 0; i < 4; i++) { 00186 id = THREAD_1_ID; 00187 mail = mail_box[id].alloc(); 00188 mail->thread_id = id; 00189 mail->data = data[id]++; 00190 mail_box[id].put(mail); 00191 00192 id = THREAD_2_ID; 00193 mail = mail_box[id].alloc(); 00194 mail->thread_id = id; 00195 mail->data = data[id]++; 00196 mail_box[id].put(mail); 00197 00198 id = THREAD_3_ID; 00199 mail = mail_box[id].alloc(); 00200 mail->thread_id = id; 00201 mail->data = data[id]++; 00202 mail_box[id].put(mail); 00203 00204 Thread::wait(i * 10); 00205 } 00206 00207 thread1.join(); 00208 thread2.join(); 00209 thread3.join(); 00210 } 00211 00212 /** Test message memory deallocation with block out of the scope 00213 00214 Given an empty mailbox 00215 When try to free out of the scope memory block 00216 Then it return appropriate error code 00217 */ 00218 void test_free_wrong() 00219 { 00220 osStatus status; 00221 Mail<uint32_t, 4> mail_box; 00222 uint32_t *mail, data; 00223 00224 mail = &data; 00225 status = mail_box.free(mail); 00226 TEST_ASSERT_EQUAL(osErrorParameter, status); 00227 00228 mail = mail_box.alloc(); 00229 TEST_ASSERT_NOT_EQUAL(NULL, mail); 00230 00231 mail = &data; 00232 status = mail_box.free(mail); 00233 TEST_ASSERT_EQUAL(osErrorParameter, status); 00234 } 00235 00236 /** Test message memory deallocation with null block 00237 00238 Given an empty mailbox 00239 When try to free null ptr 00240 Then it return appropriate error code 00241 */ 00242 void test_free_null() 00243 { 00244 osStatus status; 00245 Mail<uint32_t, 4> mail_box; 00246 uint32_t *mail; 00247 00248 mail = NULL; 00249 status = mail_box.free(mail); 00250 TEST_ASSERT_EQUAL(osErrorParameter, status); 00251 00252 mail = mail_box.alloc(); 00253 TEST_ASSERT_NOT_EQUAL(NULL, mail); 00254 00255 mail = NULL; 00256 status = mail_box.free(mail); 00257 TEST_ASSERT_EQUAL(osErrorParameter, status); 00258 } 00259 00260 /** Test same message memory deallocation twice 00261 00262 Given an empty mailbox 00263 Then allocate message memory 00264 When try to free it second time 00265 Then it return appropriate error code 00266 */ 00267 void test_free_twice() 00268 { 00269 osStatus status; 00270 Mail<uint32_t, 4> mail_box; 00271 00272 uint32_t *mail = mail_box.alloc(); 00273 TEST_ASSERT_NOT_EQUAL(NULL, mail); 00274 00275 status = mail_box.free(mail); 00276 TEST_ASSERT_EQUAL(osOK, status); 00277 00278 status = mail_box.free(mail); 00279 TEST_ASSERT_EQUAL(osErrorResource, status); 00280 } 00281 00282 /** Test get from empty mailbox with timeout set 00283 00284 Given an empty mailbox 00285 When @a get is called on the mailbox with timeout of 50 00286 Then mailbox returns status of osOK, but no data after specified amount of time 00287 */ 00288 void test_get_empty_timeout() 00289 { 00290 Mail<uint32_t, 4> mail_box; 00291 Timer timer; 00292 00293 timer.start(); 00294 osEvent evt = mail_box.get(50); 00295 TEST_ASSERT_UINT32_WITHIN(5000, 50000, timer.read_us()); 00296 TEST_ASSERT_EQUAL(osEventTimeout, evt.status); 00297 } 00298 00299 /** Test get from empty mailbox with 0 timeout 00300 00301 Given an empty mailbox 00302 When @a get is called on the mailbox with timeout of 0 00303 Then mailbox returns status of osOK, but no data 00304 */ 00305 void test_get_empty_no_timeout() 00306 { 00307 Mail<uint32_t, 4> mail_box; 00308 00309 osEvent evt = mail_box.get(0); 00310 TEST_ASSERT_EQUAL(osOK, evt.status); 00311 } 00312 00313 /** Test mail order 00314 00315 Given an mailbox for uint32_t values 00316 Then allocate two mails and put them in to mailbox 00317 When call @a get it returns previously put mails 00318 Then mails should be in the same order as put 00319 */ 00320 void test_order(void) 00321 { 00322 osStatus status; 00323 osEvent evt; 00324 Mail<int32_t, 4> mail_box; 00325 const int32_t TEST_VAL1 = 123; 00326 const int32_t TEST_VAL2 = 456; 00327 00328 int32_t *mail1 = mail_box.alloc(); 00329 TEST_ASSERT_NOT_EQUAL(NULL, mail1); 00330 00331 *mail1 = TEST_VAL1; 00332 status = mail_box.put(mail1); 00333 TEST_ASSERT_EQUAL(osOK, status); 00334 00335 int32_t *mail2 = mail_box.alloc(); 00336 TEST_ASSERT_NOT_EQUAL(NULL, mail2); 00337 00338 *mail2 = TEST_VAL2; 00339 status = mail_box.put(mail2); 00340 TEST_ASSERT_EQUAL(osOK, status); 00341 00342 00343 evt = mail_box.get(); 00344 TEST_ASSERT_EQUAL(evt.status, osEventMail); 00345 00346 mail1 = (int32_t*)evt.value.p; 00347 TEST_ASSERT_EQUAL(TEST_VAL1, *mail1); 00348 00349 evt = mail_box.get(); 00350 TEST_ASSERT_EQUAL(evt.status, osEventMail); 00351 00352 mail2 = (int32_t*)evt.value.p; 00353 TEST_ASSERT_EQUAL(TEST_VAL2, *mail2); 00354 00355 00356 status = mail_box.free(mail1); 00357 TEST_ASSERT_EQUAL(osOK, status); 00358 00359 status = mail_box.free(mail2); 00360 TEST_ASSERT_EQUAL(osOK, status); 00361 } 00362 00363 /** Test Mail box max size limit 00364 00365 Given an Mail box with max size of 4 elements 00366 When call @a alloc four times it returns memory blocks 00367 Then the memory blocks should be valid 00368 When call @a alloc one more time it returns memory blocks 00369 Then the memory blocks should be not valid (NULL - no memory available) 00370 */ 00371 void test_max_size() 00372 { 00373 osStatus status; 00374 Mail<uint32_t, 4> mail_box; 00375 const uint32_t TEST_VAL = 123; 00376 00377 // 1 OK 00378 uint32_t *mail1 = mail_box.alloc(); 00379 TEST_ASSERT_NOT_EQUAL(NULL, mail1); 00380 00381 // 2 OK 00382 uint32_t *mail2 = mail_box.alloc(); 00383 TEST_ASSERT_NOT_EQUAL(NULL, mail2); 00384 00385 // 3 OK 00386 uint32_t *mail3 = mail_box.alloc(); 00387 TEST_ASSERT_NOT_EQUAL(NULL, mail3); 00388 00389 // 4 OK 00390 uint32_t *mail4 = mail_box.alloc(); 00391 TEST_ASSERT_NOT_EQUAL(NULL, mail4); 00392 00393 // 5 KO 00394 uint32_t *mail5 = mail_box.alloc(); 00395 TEST_ASSERT_EQUAL(NULL, mail5); 00396 00397 00398 status = mail_box.free(mail1); 00399 TEST_ASSERT_EQUAL(osOK, status); 00400 00401 status = mail_box.free(mail2); 00402 TEST_ASSERT_EQUAL(osOK, status); 00403 00404 status = mail_box.free(mail3); 00405 TEST_ASSERT_EQUAL(osOK, status); 00406 00407 status = mail_box.free(mail4); 00408 TEST_ASSERT_EQUAL(osOK, status); 00409 } 00410 00411 /** Test mailbox of T type data 00412 00413 Given an mailbox with T memory block type 00414 When allocate/put/get/free memory block 00415 Then all operations should succeed 00416 */ 00417 template<typename T> 00418 void test_data_type(void) 00419 { 00420 osStatus status; 00421 Mail<T, 4> mail_box; 00422 const T TEST_VAL = 123; 00423 00424 T *mail = mail_box.alloc(); 00425 TEST_ASSERT_NOT_EQUAL(NULL, mail); 00426 00427 *mail = TEST_VAL; 00428 status = mail_box.put(mail); 00429 TEST_ASSERT_EQUAL(osOK, status); 00430 00431 osEvent evt = mail_box.get(); 00432 TEST_ASSERT_EQUAL(evt.status, osEventMail); 00433 00434 mail = (T*)evt.value.p; 00435 TEST_ASSERT_EQUAL(TEST_VAL, *mail); 00436 00437 00438 status = mail_box.free(mail); 00439 TEST_ASSERT_EQUAL(osOK, status); 00440 } 00441 00442 /** Test calloc - memory block allocation with resetting 00443 00444 Given an empty Mail box 00445 When call @a calloc it returns allocated memory block 00446 Then the memory block should be valid and filled with zeros 00447 */ 00448 void test_calloc() 00449 { 00450 Mail<uint32_t, 1> mail_box; 00451 00452 uint32_t *mail = mail_box.calloc(); 00453 TEST_ASSERT_NOT_EQUAL(NULL, mail); 00454 TEST_ASSERT_EQUAL(0, *mail); 00455 } 00456 00457 /** Test mail empty 00458 00459 Given a mail of uint32_t data 00460 before data is inserted the mail should be empty 00461 after data is inserted the mail shouldn't be empty 00462 */ 00463 void test_mail_empty() 00464 { 00465 Mail<mail_t, 1> m; 00466 00467 mail_t *mail = m.alloc(); 00468 00469 TEST_ASSERT_EQUAL(true, m.empty()); 00470 00471 m.put(mail); 00472 00473 TEST_ASSERT_EQUAL(false, m.empty()); 00474 } 00475 00476 /** Test mail empty 00477 00478 Given a mail of uint32_t data with size of 1 00479 before data is inserted the mail shouldn't be full 00480 after data is inserted the mail should be full 00481 */ 00482 void test_mail_full() 00483 { 00484 Mail<mail_t, 1> m; 00485 00486 mail_t *mail = m.alloc(); 00487 00488 TEST_ASSERT_EQUAL(false, m.full()); 00489 00490 m.put(mail); 00491 00492 TEST_ASSERT_EQUAL(true, m.full()); 00493 } 00494 00495 utest::v1::status_t test_setup(const size_t number_of_cases) 00496 { 00497 GREENTEA_SETUP(10, "default_auto"); 00498 return verbose_test_setup_handler(number_of_cases); 00499 } 00500 00501 Case cases[] = { 00502 Case("Test calloc", test_calloc), 00503 Case("Test message type uint8", test_data_type<uint8_t>), 00504 Case("Test message type uint16", test_data_type<uint16_t>), 00505 Case("Test message type uint32", test_data_type<uint32_t>), 00506 Case("Test mailbox max size", test_max_size), 00507 Case("Test message send order", test_order), 00508 Case("Test get with timeout on empty mailbox", test_get_empty_timeout), 00509 Case("Test get without timeout on empty mailbox", test_get_empty_no_timeout), 00510 Case("Test message free twice", test_free_twice), 00511 Case("Test null message free", test_free_null), 00512 Case("Test invalid message free", test_free_wrong), 00513 Case("Test message send/receive single thread and order", test_single_thread_order), 00514 Case("Test message send/receive multi-thread and per thread order", test_multi_thread_order), 00515 Case("Test message send/receive multi-thread, multi-Mail and per thread order", test_multi_thread_multi_mail_order), 00516 Case("Test mail empty", test_mail_empty), 00517 Case("Test mail full", test_mail_full) 00518 }; 00519 00520 Specification specification(test_setup, cases); 00521 00522 int main() 00523 { 00524 return !Harness::run(specification); 00525 }
Generated on Sun Jul 17 2022 08:25:27 by 1.7.2