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