Marco Mayer / Mbed OS Queue
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 
00017 #define __STDC_LIMIT_MACROS
00018 #include <stdint.h>
00019 #include <algorithm>
00020 
00021 #include "utest/utest.h"
00022 #include "unity/unity.h"
00023 #include "greentea-client/test_env.h"
00024 
00025 #include "mbed.h"
00026 #include "ticker_api.h"
00027 
00028 using namespace utest::v1;
00029 
00030 #define MBED_ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
00031 
00032 #define TIMESTAMP_MAX_DELTA_BITS(bits)  ((uint64_t)(0x7 << ((bits) - 4)))
00033 #define TIMESTAMP_MAX_DELTA TIMESTAMP_MAX_DELTA_BITS(32)
00034 
00035 struct ticker_interface_stub_t { 
00036     ticker_interface_t interface;
00037     bool initialized; 
00038     bool interrupt_flag;
00039     timestamp_t timestamp ;
00040     timestamp_t interrupt_timestamp; 
00041     unsigned int init_call;
00042     unsigned int read_call;
00043     unsigned int disable_interrupt_call;
00044     unsigned int clear_interrupt_call;
00045     unsigned int set_interrupt_call;
00046     unsigned int fire_interrupt_call;
00047     unsigned int get_info_call;
00048 };
00049 
00050 static ticker_interface_stub_t interface_stub = { 0 };
00051 static ticker_info_t interface_info_stub = { 0 };
00052 
00053 static void ticker_interface_stub_init()
00054 {
00055     ++interface_stub.init_call;
00056     interface_stub.initialized = true;
00057 }
00058 
00059 static uint32_t ticker_interface_stub_read()
00060 {
00061     ++interface_stub.read_call;
00062     return interface_stub.timestamp;
00063 } 
00064 
00065 static void ticker_interface_stub_disable_interrupt()
00066 { 
00067     ++interface_stub.disable_interrupt_call;
00068 }
00069 
00070 static void ticker_interface_stub_clear_interrupt()
00071 {
00072     ++interface_stub.clear_interrupt_call;
00073     interface_stub.interrupt_flag = false;
00074 }
00075 
00076 static void ticker_interface_stub_set_interrupt(timestamp_t timestamp)
00077 {
00078     ++interface_stub.set_interrupt_call;
00079     interface_stub.interrupt_timestamp = timestamp; 
00080 }
00081 
00082 static void ticker_interface_stub_fire_interrupt()
00083 {
00084     ++interface_stub.fire_interrupt_call;
00085 }
00086 
00087 static const ticker_info_t *ticker_interface_stub_get_info()
00088 {
00089     ++interface_stub.get_info_call;
00090     return &interface_info_stub;
00091 }
00092 
00093 static void reset_ticker_interface_stub()
00094 {
00095     interface_stub.interface.init = ticker_interface_stub_init;
00096     interface_stub.interface.read = ticker_interface_stub_read;
00097     interface_stub.interface.disable_interrupt = 
00098         ticker_interface_stub_disable_interrupt;
00099     interface_stub.interface.clear_interrupt = 
00100         ticker_interface_stub_clear_interrupt;
00101     interface_stub.interface.set_interrupt =ticker_interface_stub_set_interrupt;
00102     interface_stub.interface.fire_interrupt = ticker_interface_stub_fire_interrupt;
00103     interface_stub.interface.get_info = ticker_interface_stub_get_info;
00104     interface_stub.initialized = false;
00105     interface_stub.interrupt_flag = false;
00106     interface_stub.timestamp = 0;
00107     interface_stub.interrupt_timestamp = 0;
00108     interface_stub.init_call = 0;
00109     interface_stub.read_call = 0;
00110     interface_stub.disable_interrupt_call = 0;
00111     interface_stub.clear_interrupt_call = 0;
00112     interface_stub.set_interrupt_call = 0;
00113     interface_stub.fire_interrupt_call = 0;
00114 
00115     interface_info_stub.frequency = 1000000;
00116     interface_info_stub.bits = 32;
00117 }
00118 
00119 // stub of the event queue 
00120 static ticker_event_queue_t queue_stub = {
00121     /* event handler */ NULL,
00122     /* head */ NULL,
00123     /* timestamp */ 0,
00124     /* initialized */ false
00125 };
00126 
00127 static void reset_queue_stub()
00128 {
00129     queue_stub.event_handler = NULL;
00130     queue_stub.head = NULL,
00131     queue_stub.tick_last_read = 0;
00132     queue_stub.tick_remainder = 0;
00133     queue_stub.frequency = 0;
00134     queue_stub.bitmask = 0;
00135     queue_stub.max_delta = 0;
00136     queue_stub.max_delta_us = 0;
00137     queue_stub.present_time = 0;
00138     queue_stub.initialized = false;
00139 }
00140 
00141 // stub of the ticker
00142 static ticker_data_t ticker_stub = {
00143     /* interface */ &interface_stub.interface,
00144     /* queue */ &queue_stub
00145 };
00146 
00147 static void reset_ticker_stub()
00148 {
00149     reset_queue_stub();
00150     reset_ticker_interface_stub();
00151 }
00152 
00153 const uint32_t test_frequencies[] = {
00154     1,
00155     32768,      // 2^15
00156     1000000,
00157     0xFFFFFFFF  // 2^32 - 1
00158 };
00159 
00160 const uint32_t test_bitwidths[] = {
00161     32,
00162     31,
00163     16,
00164     8
00165 };
00166 
00167 template < void (F)(uint32_t a, uint32_t b)>
00168 static void test_over_frequency_and_width(void)
00169 {
00170     for (unsigned int i = 0; i < MBED_ARRAY_SIZE(test_frequencies); i++) {
00171         for (unsigned int j = 0; j < MBED_ARRAY_SIZE(test_bitwidths); j++) {
00172             reset_ticker_stub();
00173             interface_info_stub.frequency = test_frequencies[i];
00174             interface_info_stub.bits = test_bitwidths[j];
00175 
00176             F(test_frequencies[i], test_bitwidths[j]);
00177         }
00178     }
00179 }
00180 
00181 static utest::v1::status_t case_setup_handler(
00182     const Case *const source, const size_t index_of_case
00183 ) { 
00184     utest::v1::status_t status = greentea_case_setup_handler(source, index_of_case);
00185     reset_ticker_stub();
00186     return status;
00187 }
00188 
00189 static utest::v1::status_t case_teardown_handler(
00190     const Case *const source, const size_t passed, const size_t failed, const failure_t reason
00191 ) { 
00192     reset_ticker_stub();
00193     utest::v1::status_t status = greentea_case_teardown_handler(
00194         source, passed, failed, reason
00195     );
00196     return status;
00197 }
00198 
00199 static utest::v1::status_t greentea_failure_handler(
00200     const Case *const source, const failure_t reason
00201 ) {
00202     utest::v1::status_t status = greentea_case_failure_abort_handler(
00203         source, reason
00204     );
00205     return status;
00206 }
00207 
00208 #define MAKE_TEST_CASE(description, handler) \
00209     { \
00210         description, \
00211         handler, \
00212         NULL, \
00213         NULL, \
00214         case_setup_handler, \
00215         case_teardown_handler, \
00216         greentea_failure_handler \
00217     }
00218 
00219 /**
00220  * Given an unitialized ticker_data instance. 
00221  * When the ticker is initialized 
00222  * Then: 
00223  *   - The ticker interface should be initialized 
00224  *   - The queue handler should be set to the handler provided in parameter
00225  *   - The internal ticker timestamp should be zero
00226  *   - interrupt should be scheduled in current timestamp + 
00227  *     TIMESTAMP_MAX_DELTA
00228  *   - The queue should not contains any event
00229  */
00230 static void test_ticker_initialization()
00231 {
00232     ticker_event_handler dummy_handler = (ticker_event_handler)0xDEADBEEF;
00233 
00234     // setup of the stub 
00235     interface_stub.timestamp = 0xFEEDBABE;
00236 
00237     ticker_set_handler(&ticker_stub, dummy_handler);
00238 
00239     TEST_ASSERT_TRUE(interface_stub.initialized);
00240     TEST_ASSERT_EQUAL_PTR(dummy_handler, queue_stub.event_handler);
00241     TEST_ASSERT_EQUAL_UINT64(0, queue_stub.present_time);
00242     TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);
00243     TEST_ASSERT_EQUAL_UINT32(
00244         interface_stub.timestamp + TIMESTAMP_MAX_DELTA,
00245         interface_stub.interrupt_timestamp
00246     );
00247     TEST_ASSERT_EQUAL_PTR(NULL, queue_stub.head);
00248     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
00249 }
00250 
00251 /**
00252  * Given an initialized ticker_data instance. 
00253  * When the ticker handler is set to a new value    
00254  * Then: 
00255  *   - The ticker interface initialization function should not be called.
00256  *   - The queue handler should be set to the new handler.
00257  *   - The events in the queue should remains the same.
00258  */
00259 static void test_ticker_re_initialization()
00260 {
00261     ticker_event_handler dummy_handler = (ticker_event_handler) 0xDEADBEEF;
00262     ticker_event_handler expected_handler = (ticker_event_handler) 0xFEEDDEAF;
00263     
00264     ticker_event_t first_event = { 0 }; 
00265     ticker_event_t second_event  = { 0 }; 
00266     ticker_event_t third_event  = { 0 }; 
00267 
00268     first_event.next = &second_event;
00269     second_event.next = &third_event;
00270 
00271     // initialize the ticker and put few events in the queue.
00272     ticker_set_handler(&ticker_stub, dummy_handler);
00273     // simulate insertion, it shouldn't affect the queue behaviour for this test
00274     queue_stub.head = &first_event;
00275     interface_stub.init_call = 0;
00276 
00277     ticker_set_handler(&ticker_stub, expected_handler);
00278 
00279     TEST_ASSERT_TRUE(interface_stub.initialized);
00280     TEST_ASSERT_EQUAL(0, interface_stub.init_call);
00281     TEST_ASSERT_EQUAL(expected_handler, queue_stub.event_handler);
00282     TEST_ASSERT_EQUAL(&first_event, queue_stub.head);
00283     TEST_ASSERT_EQUAL(&second_event, queue_stub.head->next);
00284     TEST_ASSERT_EQUAL(&third_event, queue_stub.head->next->next);
00285     TEST_ASSERT_EQUAL(NULL, queue_stub.head->next->next->next);
00286     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
00287 }
00288 
00289 /**
00290  * Given an initialized ticker_data instance. 
00291  * When the ticker is read 
00292  * Then it should return the value present in the ticker interface
00293  */
00294 static void test_ticker_read()
00295 {
00296     ticker_set_handler(&ticker_stub, NULL);
00297 
00298     timestamp_t timestamps[] = { 
00299         0xA,
00300         0xAA,
00301         0xAAA,
00302         0xAAAA,
00303         0xAAAAA,
00304         0xAAAAAA,
00305         0xAAAAAAA,
00306         0xAAAAAAAA
00307     };
00308 
00309     for (size_t i = 0; i < MBED_ARRAY_SIZE(timestamps); ++i) {
00310         interface_stub.timestamp = timestamps[i];
00311         TEST_ASSERT_EQUAL_UINT32(timestamps[i], ticker_read(&ticker_stub));
00312         TEST_ASSERT_EQUAL_UINT64(timestamps[i], ticker_read_us(&ticker_stub));
00313     }
00314 
00315     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
00316 }
00317 
00318 /**
00319  * Given an initialized ticker_data instance. 
00320  * When the ticker is read and the value read is less than the previous 
00321  * value read.
00322  * Then:
00323  *   - ticker_read should return the value read in the ticker interface 
00324  *   - ticker_read_us should return a value where: 
00325  *     + lower 8 bytes should be equal to the value in the ticker interface
00326  *     + upper 8 bytes should be equal to the previous value of upper 8 bytes
00327  *       plus one.
00328  */
00329 static void test_ticker_read_overflow()
00330 {
00331     const timestamp_t timestamps[] = { 
00332         0xAAAAAAAA,
00333         0xAAAAAAA,
00334         0xAAAAAA,
00335         0xAAAAA,
00336         0xAAAA,
00337         0xAAA,
00338         0xAA,
00339         0xA
00340     };
00341 
00342     ticker_set_handler(&ticker_stub, NULL);
00343 
00344     uint32_t upper_bytes_begin = ticker_read_us(&ticker_stub) >> 32;
00345 
00346     for (size_t i = 0; i < MBED_ARRAY_SIZE(timestamps); ++i) {
00347         interface_stub.timestamp = timestamps[i];
00348         TEST_ASSERT_EQUAL_UINT32(timestamps[i], ticker_read(&ticker_stub));
00349         TEST_ASSERT_EQUAL_UINT32(timestamps[i], ticker_read_us(&ticker_stub));
00350         TEST_ASSERT_EQUAL_UINT64(
00351             upper_bytes_begin + i, ticker_read_us(&ticker_stub) >> 32
00352         );
00353     }
00354 
00355     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
00356 }
00357 
00358 /**
00359  * Given an initialized ticker without user registered events.  
00360  * When an event is inserted with ticker_insert_event and the timestamp passed 
00361  * in parameter is in range [ticker_timestamp : ticker_timestamp + 
00362  * TIMESTAMP_MAX_DELTA[.
00363  * Then 
00364  *   - The event should be in the queue
00365  *   - The interrupt timestamp should be equal to the timestamp of the event 
00366  *   - The timestamp of the event should reflect the timestamp requested. 
00367  *   - The id of the event should be equal to the id passed in parameter. 
00368  */
00369 static void test_legacy_insert_event_outside_overflow_range()
00370 {
00371     ticker_set_handler(&ticker_stub, NULL);
00372     interface_stub.set_interrupt_call = 0;
00373 
00374     // test the end of the range
00375     ticker_event_t last_event = { 0 };
00376     const timestamp_t timestamp_last_event = 
00377         interface_stub.timestamp + TIMESTAMP_MAX_DELTA; 
00378     const uint32_t id_last_event = 0xDEADDEAF;
00379 
00380     ticker_insert_event(
00381         &ticker_stub, 
00382         &last_event, timestamp_last_event, id_last_event
00383     );
00384 
00385     TEST_ASSERT_EQUAL_PTR(&last_event, queue_stub.head);
00386     TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);    
00387     TEST_ASSERT_EQUAL_UINT32(
00388         timestamp_last_event, interface_stub.interrupt_timestamp
00389     );
00390     TEST_ASSERT_EQUAL_PTR(NULL, queue_stub.head->next);
00391     TEST_ASSERT_EQUAL_UINT32(timestamp_last_event, last_event.timestamp);
00392     TEST_ASSERT_EQUAL_UINT32(id_last_event, last_event.id);
00393 
00394     // test the beginning of the range
00395     ticker_event_t first_event = { 0 };
00396     const timestamp_t timestamp_first_event = interface_stub.timestamp + 1;
00397     const uint32_t id_first_event = 0xAAAAAAAA;
00398 
00399     ticker_insert_event(
00400         &ticker_stub, 
00401         &first_event, timestamp_first_event, id_first_event
00402     );
00403 
00404     TEST_ASSERT_EQUAL_PTR(&first_event, queue_stub.head);
00405     TEST_ASSERT_EQUAL(2, interface_stub.set_interrupt_call);    
00406     TEST_ASSERT_EQUAL_UINT32(
00407         timestamp_first_event, interface_stub.interrupt_timestamp
00408     );
00409     TEST_ASSERT_EQUAL_PTR(&last_event, queue_stub.head->next);
00410     TEST_ASSERT_EQUAL_UINT32(
00411         timestamp_first_event, first_event.timestamp
00412     );
00413     TEST_ASSERT_EQUAL_UINT32(id_first_event, first_event.id);
00414 
00415     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
00416 }  
00417 
00418 /**
00419  * Given an initialized ticker without user registered events.  
00420  * When an event is inserted with ticker_insert_event and a timestamp in the 
00421  * range [ticker_timestamp + TIMESTAMP_MAX_DELTA + 1 : 
00422  * ticker_timestamp + UINT32MAX [
00423  * Then 
00424  *   - The event should be in the queue
00425  *   - The interrupt timestamp should be equal to 
00426  *     TIMESTAMP_MAX_DELTA 
00427  *   - The timestamp of the event should reflect the timestamp requested. 
00428  *   - The id of the event should be equal to the id passed in parameter. 
00429  */
00430 static void test_legacy_insert_event_in_overflow_range()
00431 {
00432     ticker_set_handler(&ticker_stub, NULL);
00433     interface_stub.set_interrupt_call = 0;
00434 
00435     // test the end of the range
00436     ticker_event_t last_event = { 0 };
00437     const timestamp_t timestamp_last_event = 
00438         interface_stub.timestamp + UINT32_MAX; 
00439     const uint32_t id_last_event = 0xDEADDEAF;
00440 
00441     ticker_insert_event(
00442         &ticker_stub, 
00443         &last_event, timestamp_last_event, id_last_event
00444     );
00445 
00446     TEST_ASSERT_EQUAL_PTR(&last_event, queue_stub.head);
00447     TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);    
00448     TEST_ASSERT_EQUAL_UINT32(
00449         interface_stub.timestamp + TIMESTAMP_MAX_DELTA, 
00450         interface_stub.interrupt_timestamp
00451     );
00452     TEST_ASSERT_EQUAL_PTR(NULL, queue_stub.head->next);
00453     TEST_ASSERT_EQUAL_UINT32(timestamp_last_event, last_event.timestamp);
00454     TEST_ASSERT_EQUAL_UINT32(id_last_event, last_event.id);
00455 
00456     // test the beginning of the range
00457     ++interface_stub.timestamp;
00458 
00459     ticker_event_t first_event = { 0 };
00460     const timestamp_t timestamp_first_event = 
00461         interface_stub.timestamp + TIMESTAMP_MAX_DELTA + 1; 
00462     const uint32_t id_first_event = 0xAAAAAAAA;
00463 
00464     ticker_insert_event(
00465         &ticker_stub, 
00466         &first_event, timestamp_first_event, id_first_event
00467     );
00468 
00469     TEST_ASSERT_EQUAL_PTR(&first_event, queue_stub.head);
00470     TEST_ASSERT_EQUAL(2, interface_stub.set_interrupt_call);    
00471     TEST_ASSERT_EQUAL_UINT32(
00472         interface_stub.timestamp + TIMESTAMP_MAX_DELTA, 
00473         interface_stub.interrupt_timestamp
00474     );
00475     TEST_ASSERT_EQUAL_PTR(&last_event, queue_stub.head->next);
00476     TEST_ASSERT_EQUAL_UINT32(
00477         timestamp_first_event, first_event.timestamp
00478     );
00479     TEST_ASSERT_EQUAL_UINT32(id_first_event, first_event.id);
00480 
00481     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
00482 }  
00483 
00484 /**
00485  * Given an initialized ticker without user registered events.  
00486  * When an event is inserted with ticker_insert_event and the timestamp in 
00487  * parameter is less than the current timestamp value.
00488  * Then 
00489  *   - The event should be in the queue
00490  *   - The timestamp of the event should reflect the timestamp requested:
00491  *     + lower 8 bytes should be equal to the timestamp in input. 
00492  *     + upper 8 bytes should be equal to the upper of the upper 8 bytes of the
00493  *       timestamp state stored in the queue plus one.
00494  *   - The id of the event should be equal to the id passed in parameter. 
00495  */
00496 static void test_legacy_insert_event_overflow(){
00497     ticker_set_handler(&ticker_stub, NULL);
00498     interface_stub.set_interrupt_call = 0;
00499 
00500     interface_stub.timestamp = 0x20000000;
00501     ticker_read(&ticker_stub);
00502 
00503     ticker_event_t event = { 0 };
00504     const timestamp_t expected_timestamp = 
00505         interface_stub.timestamp + 
00506         TIMESTAMP_MAX_DELTA + 
00507         1; 
00508     const us_timestamp_t expected_us_timestamp = 
00509         (((queue_stub.present_time >> 32) + 1) << 32) | expected_timestamp;
00510     const uint32_t expected_id = 0xDEADDEAF;
00511 
00512     ticker_insert_event(
00513         &ticker_stub, 
00514         &event, expected_timestamp, expected_id
00515     );
00516 
00517     TEST_ASSERT_EQUAL_PTR(&event, queue_stub.head);
00518     TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);    
00519     TEST_ASSERT_EQUAL_UINT32(
00520         interface_stub.timestamp + TIMESTAMP_MAX_DELTA, 
00521         interface_stub.interrupt_timestamp
00522     );
00523     TEST_ASSERT_EQUAL_PTR(NULL, queue_stub.head->next);
00524     TEST_ASSERT_EQUAL_UINT32(expected_us_timestamp, event.timestamp);
00525     TEST_ASSERT_EQUAL_UINT32(expected_id, event.id);
00526 
00527     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
00528 }  
00529 
00530 /**
00531  * Given an initialized ticker.
00532  * When an event is inserted with ticker_insert_event and a timestamp less than 
00533  * the one for the next scheduled timestamp.
00534  * Then 
00535  *   - The event inserted should be the first in the queue
00536  *   - The interrupt timestamp should be equal to the timestamp of the event or 
00537  *     TIMESTAMP_MAX_DELTA if in the overflow range.
00538  *   - The timestamp of the event should reflect the timestamp requested.
00539  *   - The id of the event should be equal to the id passed in parameter. 
00540  *   - Events in the queue should remained ordered by timestamp.
00541  */
00542 static void test_legacy_insert_event_head()
00543 {
00544     ticker_set_handler(&ticker_stub, NULL);
00545     interface_stub.set_interrupt_call = 0;
00546 
00547     const timestamp_t timestamps[] = { 
00548         UINT32_MAX,
00549         TIMESTAMP_MAX_DELTA + 1,
00550         TIMESTAMP_MAX_DELTA,
00551         TIMESTAMP_MAX_DELTA / 2,
00552         TIMESTAMP_MAX_DELTA / 4,
00553         TIMESTAMP_MAX_DELTA / 8,
00554         TIMESTAMP_MAX_DELTA / 16,
00555     };
00556     ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 };
00557 
00558     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
00559         ticker_insert_event(
00560             &ticker_stub, 
00561             &events[i], timestamps[i], i
00562         );
00563 
00564         TEST_ASSERT_EQUAL_PTR(&events[i], queue_stub.head);
00565         TEST_ASSERT_EQUAL(i + 1, interface_stub.set_interrupt_call);  
00566         if (timestamps[i] < TIMESTAMP_MAX_DELTA) { 
00567             TEST_ASSERT_EQUAL_UINT32(
00568                 timestamps[i], 
00569                 interface_stub.interrupt_timestamp
00570             );
00571         } else { 
00572             TEST_ASSERT_EQUAL_UINT32(
00573                 TIMESTAMP_MAX_DELTA, 
00574                 interface_stub.interrupt_timestamp
00575             );
00576         }
00577 
00578         TEST_ASSERT_EQUAL_UINT32(
00579             timestamps[i], events[i].timestamp
00580         );
00581         TEST_ASSERT_EQUAL_UINT32(i, events[i].id);
00582 
00583         ticker_event_t* e = &events[i];
00584         while (e) { 
00585             TEST_ASSERT_EQUAL_UINT32(timestamps[e->id], e->timestamp);
00586             if (e->next) { 
00587                 TEST_ASSERT_TRUE(e->id > e->next->id);
00588                 TEST_ASSERT_TRUE(e->timestamp < e->next->timestamp);
00589             } else { 
00590                 TEST_ASSERT_EQUAL_UINT32(0, e->id);
00591             }
00592             e = e->next;
00593         }
00594     }
00595 
00596     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
00597 }  
00598 
00599 /** 
00600  * Given an initialized ticker.
00601  * When an event is inserted with ticker_insert_event and its timestamp is bigger 
00602  * than the one of the last event in the queue.
00603  * Then 
00604  *   - The event inserted should be the last in the queue
00605  *   - The interrupt timestamp should remains equal to the interrupt timestamp 
00606  *     of the head event .
00607  *   - The timestamp of the event should reflect the timestamp requested.
00608  *   - The id of the event should be equal to the id passed in parameter. 
00609  *   - Events in the queue should remained ordered by timestamp.
00610  */
00611 static void test_legacy_insert_event_tail()
00612 {
00613     ticker_set_handler(&ticker_stub, NULL);
00614     interface_stub.set_interrupt_call = 0;
00615 
00616     const timestamp_t timestamps[] = { 
00617         0xA,
00618         0xAA,
00619         0xAAA,
00620         0xAAAA,
00621         0xAAAAA,
00622         0xAAAAAA,
00623         0xAAAAAAA,
00624         0xAAAAAAAA,
00625     };
00626     ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 };
00627 
00628     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
00629         ticker_insert_event(
00630             &ticker_stub, 
00631             &events[i], timestamps[i], i
00632         );
00633 
00634         TEST_ASSERT_EQUAL_PTR(&events[0], queue_stub.head);
00635         TEST_ASSERT_EQUAL_UINT32(
00636             timestamps[0], interface_stub.interrupt_timestamp
00637         );
00638 
00639         TEST_ASSERT_EQUAL_UINT32(timestamps[i], events[i].timestamp);
00640         TEST_ASSERT_EQUAL_UINT32(i, events[i].id);
00641 
00642         ticker_event_t* e = queue_stub.head;
00643         while (e) { 
00644             TEST_ASSERT_EQUAL_UINT32(timestamps[e->id], e->timestamp);
00645             if (e->next) { 
00646                 TEST_ASSERT_TRUE(e->id < e->next->id);
00647                 TEST_ASSERT_TRUE(e->timestamp < e->next->timestamp);
00648             } else { 
00649                 TEST_ASSERT_EQUAL_UINT32(&events[i], e);
00650             }
00651             e = e->next;
00652         }
00653     }
00654 
00655     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
00656 } 
00657 
00658 /**
00659  * Given an initialized ticker.
00660  * When an event is inserted with ticker_insert_event and a timestamp less 
00661  * than the current timestamp in the interface and less than the relative 
00662  * timestamp of the next event to execute.
00663  * Then 
00664  *   - The event inserted should be after the head
00665  *   - The interrupt timestamp should remains equal to the interrupt timestamp 
00666  *     of the head event .
00667  *   - The timestamp of the event should reflect the timestamp requested (overflow)
00668  *   - The id of the event should be equal to the id passed in parameter. 
00669  *   - Events in the queue should remained ordered by timestamp.
00670  */
00671 static void test_legacy_insert_event_multiple_overflow()
00672 {
00673     ticker_set_handler(&ticker_stub, NULL);
00674     interface_stub.set_interrupt_call = 0;
00675 
00676     const timestamp_t timestamps[] = { 
00677         0xA,
00678         0xAA,
00679         0xAAA,
00680         0xAAAA,
00681         0xAAAAA,
00682         0xAAAAAA,
00683         0xAAAAAAA,
00684         0xAAAAAAAA
00685     };
00686     ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 };
00687 
00688     ticker_event_t ref_event;
00689     timestamp_t ref_event_timestamp = 0xCCCCCCCC;
00690     ticker_insert_event(
00691         &ticker_stub, 
00692         &ref_event, ref_event_timestamp, 0xDEADBEEF
00693     );
00694 
00695     timestamp_t last_timestamp_to_insert = 
00696         timestamps[MBED_ARRAY_SIZE(timestamps) - 1];
00697     interface_stub.timestamp = 
00698         last_timestamp_to_insert + 
00699         ((ref_event_timestamp - last_timestamp_to_insert) / 2);
00700 
00701     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
00702         ticker_insert_event(
00703             &ticker_stub, 
00704             &events[i], timestamps[i], i
00705         );
00706 
00707         TEST_ASSERT_EQUAL_PTR(&ref_event, queue_stub.head);
00708         TEST_ASSERT_EQUAL_PTR(&events[0], queue_stub.head->next);
00709         TEST_ASSERT_EQUAL_UINT32(
00710             ref_event_timestamp, interface_stub.interrupt_timestamp
00711         );
00712 
00713         TEST_ASSERT_EQUAL_UINT32(timestamps[i], events[i].timestamp);
00714         TEST_ASSERT_EQUAL_UINT32(i, events[i].id);
00715 
00716         ticker_event_t* e = queue_stub.head->next;
00717         while (e) { 
00718             TEST_ASSERT_EQUAL_UINT32(timestamps[e->id], e->timestamp);
00719             if (e->next) { 
00720                 TEST_ASSERT_TRUE(e->id < e->next->id);
00721                 TEST_ASSERT_TRUE(e->timestamp < e->next->timestamp);
00722             } else { 
00723                 TEST_ASSERT_EQUAL_UINT32(&events[i], e);
00724             }
00725             e = e->next;
00726         }
00727     }
00728 
00729     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
00730 }
00731 
00732 /**
00733  * Given an initialized ticker.
00734  * When an event is inserted with ticker_insert_event.
00735  * Then 
00736  *   - The event inserted should be at the correct position in the queue
00737  *   - The event queue should remain ordered by timestamp
00738  *   - The interrupt timestamp should be equal to the interrupt timestamp 
00739  *     of the head event or TIMESTAMP_MAX_DELTA if the 
00740  *     timestamp is in the overflow range.
00741  *   - The timestamp of the event should reflect the timestamp requested (overflow)
00742  *   - The id of the event should be equal to the id passed in parameter. 
00743  *   - Events in the queue should remained ordered by timestamp.
00744  */
00745 static void test_legacy_insert_event_multiple_random()
00746 {
00747     ticker_set_handler(&ticker_stub, NULL);
00748     interface_stub.set_interrupt_call = 0;
00749 
00750     const timestamp_t ref_timestamp = UINT32_MAX / 2;
00751     interface_stub.timestamp = ref_timestamp;
00752 
00753     // insert first event at the head of the queue 
00754     ticker_event_t first_event;
00755     const timestamp_t first_event_timestamp = 
00756         ref_timestamp + TIMESTAMP_MAX_DELTA + 100;
00757 
00758     ticker_insert_event(
00759         &ticker_stub,
00760         &first_event, first_event_timestamp, (uint32_t) &first_event
00761     );
00762 
00763     TEST_ASSERT_EQUAL_PTR(&first_event, queue_stub.head);
00764     TEST_ASSERT_EQUAL_PTR(NULL, first_event.next);
00765     TEST_ASSERT_EQUAL_UINT32(
00766         ref_timestamp + TIMESTAMP_MAX_DELTA, interface_stub.interrupt_timestamp
00767     );
00768     TEST_ASSERT_EQUAL_UINT32(first_event_timestamp, first_event.timestamp);
00769     TEST_ASSERT_EQUAL_UINT64(
00770         first_event.timestamp,
00771         first_event_timestamp + 
00772         ((first_event_timestamp < ref_timestamp) ? (1ULL << 32) : 0)
00773     );
00774     TEST_ASSERT_EQUAL_UINT32((uint32_t) &first_event, first_event.id);
00775 
00776     // insert second event at the tail of the queue
00777     ticker_event_t second_event;
00778     const timestamp_t second_event_timestamp = first_event_timestamp + 1;
00779 
00780     ticker_insert_event(
00781         &ticker_stub,
00782         &second_event, second_event_timestamp, (uint32_t) &second_event
00783     );
00784 
00785     TEST_ASSERT_EQUAL_PTR(&first_event, queue_stub.head);
00786     TEST_ASSERT_EQUAL_PTR(&second_event, first_event.next);
00787     TEST_ASSERT_EQUAL_PTR(NULL, second_event.next);
00788     TEST_ASSERT_EQUAL_UINT32(
00789         ref_timestamp + TIMESTAMP_MAX_DELTA, interface_stub.interrupt_timestamp
00790     );
00791     TEST_ASSERT_EQUAL_UINT32(second_event_timestamp, second_event.timestamp);
00792     TEST_ASSERT_EQUAL_UINT64(
00793         second_event.timestamp,
00794         second_event_timestamp + 
00795         ((second_event_timestamp < ref_timestamp) ? (1ULL << 32) : 0)
00796     );
00797     TEST_ASSERT_EQUAL_UINT32((uint32_t) &second_event, second_event.id);
00798 
00799 
00800     // insert third event at the head of the queue out the overflow zone
00801     ticker_event_t third_event;
00802     const timestamp_t third_event_timestamp = 
00803         ref_timestamp + TIMESTAMP_MAX_DELTA - 100;
00804 
00805     ticker_insert_event(
00806         &ticker_stub,
00807         &third_event, third_event_timestamp, (uint32_t) &third_event
00808     );
00809 
00810     TEST_ASSERT_EQUAL_PTR(&third_event, queue_stub.head);
00811     TEST_ASSERT_EQUAL_PTR(&first_event, third_event.next);
00812     TEST_ASSERT_EQUAL_PTR(&second_event, first_event.next);
00813     TEST_ASSERT_EQUAL_PTR(NULL, second_event.next);
00814     TEST_ASSERT_EQUAL_UINT32(
00815         third_event_timestamp, interface_stub.interrupt_timestamp
00816     );
00817     TEST_ASSERT_EQUAL_UINT32(third_event_timestamp, third_event.timestamp);
00818     TEST_ASSERT_EQUAL_UINT64(
00819         third_event.timestamp,
00820         third_event_timestamp + 
00821         ((third_event_timestamp < ref_timestamp) ? (1ULL << 32) : 0)
00822     );
00823     TEST_ASSERT_EQUAL_UINT32((uint32_t) &third_event, third_event.id);
00824 
00825     // insert fourth event right after the third event
00826     ticker_event_t fourth_event;
00827     const timestamp_t fourth_event_timestamp = third_event_timestamp + 50;
00828 
00829     ticker_insert_event(
00830         &ticker_stub,
00831         &fourth_event, fourth_event_timestamp, (uint32_t) &fourth_event
00832     );
00833 
00834     TEST_ASSERT_EQUAL_PTR(&third_event, queue_stub.head);
00835     TEST_ASSERT_EQUAL_PTR(&fourth_event, third_event.next);
00836     TEST_ASSERT_EQUAL_PTR(&first_event, fourth_event.next);
00837     TEST_ASSERT_EQUAL_PTR(&second_event, first_event.next);
00838     TEST_ASSERT_EQUAL_PTR(NULL, second_event.next);
00839     TEST_ASSERT_EQUAL_UINT32(
00840         third_event_timestamp, interface_stub.interrupt_timestamp
00841     );
00842     TEST_ASSERT_EQUAL_UINT32(fourth_event_timestamp, fourth_event.timestamp);
00843     TEST_ASSERT_EQUAL_UINT64(
00844         fourth_event.timestamp,
00845         fourth_event_timestamp + 
00846         ((fourth_event_timestamp < ref_timestamp) ? (1ULL << 32) : 0)
00847     );
00848     TEST_ASSERT_EQUAL_UINT32((uint32_t) &fourth_event, fourth_event.id);
00849 
00850     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
00851 }
00852 
00853 /**
00854  * Given an initialized ticker without user registered events.  
00855  * When an event is inserted with ticker_insert_event_us and the timestamp passed 
00856  * in parameter is in range [ticker_timestamp : ticker_timestamp + 
00857  * TIMESTAMP_MAX_DELTA[.
00858  * Then 
00859  *   - The event should be in the queue
00860  *   - The interrupt timestamp should be equal to the lower 8 bytes of the event. 
00861  *   - The timestamp of the event should be equal to the timestamp requested. 
00862  *   - The id of the event should be equal to the id passed in parameter. 
00863  */
00864 static void test_insert_event_us_outside_overflow_range()
00865 {
00866     ticker_set_handler(&ticker_stub, NULL);
00867     interface_stub.set_interrupt_call = 0;
00868     interface_stub.timestamp = 0xAAAAAAAA;
00869     queue_stub.tick_last_read = interface_stub.timestamp;
00870     queue_stub.present_time = 10ULL << 32 | interface_stub.timestamp;
00871 
00872     // test the end of the range
00873     ticker_event_t last_event = { 0 };
00874     const us_timestamp_t timestamp_last_event = 
00875         queue_stub.present_time + TIMESTAMP_MAX_DELTA;
00876     const uint32_t id_last_event = 0xDEADDEAF;
00877 
00878     ticker_insert_event_us(
00879         &ticker_stub, 
00880         &last_event, timestamp_last_event, id_last_event
00881     );
00882 
00883     TEST_ASSERT_EQUAL_PTR(&last_event, queue_stub.head);
00884     TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);    
00885     TEST_ASSERT_EQUAL_UINT32(
00886         timestamp_last_event, interface_stub.interrupt_timestamp
00887     );
00888     TEST_ASSERT_EQUAL_PTR(NULL, queue_stub.head->next);
00889     TEST_ASSERT_EQUAL_UINT64(timestamp_last_event, last_event.timestamp);
00890     TEST_ASSERT_EQUAL_UINT32(id_last_event, last_event.id);
00891 
00892     // test the beginning of the range
00893     ticker_event_t first_event = { 0 };
00894     const us_timestamp_t timestamp_first_event = queue_stub.present_time + 1;
00895     const uint32_t id_first_event = 0xAAAAAAAA;
00896 
00897     ticker_insert_event_us(
00898         &ticker_stub, 
00899         &first_event, timestamp_first_event, id_first_event
00900     );
00901 
00902     TEST_ASSERT_EQUAL_PTR(&first_event, queue_stub.head);
00903     TEST_ASSERT_EQUAL(2, interface_stub.set_interrupt_call);    
00904     TEST_ASSERT_EQUAL_UINT32(
00905         timestamp_first_event, interface_stub.interrupt_timestamp
00906     );
00907     TEST_ASSERT_EQUAL_PTR(&last_event, queue_stub.head->next);
00908     TEST_ASSERT_EQUAL_UINT64(
00909         timestamp_first_event, first_event.timestamp
00910     );
00911     TEST_ASSERT_EQUAL_UINT32(id_first_event, first_event.id);
00912 
00913     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
00914 }  
00915 
00916 /**
00917  * Given an initialized ticker without user registered events.  
00918  * When an event is inserted with ticker_insert_event_us and a timestamp in the 
00919  * range [ticker_timestamp + TIMESTAMP_MAX_DELTA + 1 : UINT64_MAX [ 
00920  * Then 
00921  *   - The event should be in the queue
00922  *   - The interrupt timestamp should be equal to TIMESTAMP_MAX_DELTA 
00923  *   - The timestamp of the event should be equal to the timestamp in parameter. 
00924  *   - The id of the event should be equal to the id passed in parameter. 
00925  */
00926 static void test_insert_event_us_in_overflow_range()
00927 {
00928     ticker_set_handler(&ticker_stub, NULL);
00929     interface_stub.set_interrupt_call = 0;
00930     interface_stub.timestamp = 0xAAAAAAAA;
00931     queue_stub.tick_last_read = interface_stub.timestamp;
00932     queue_stub.present_time = 10ULL << 32 | interface_stub.timestamp;
00933 
00934     // test the end of the range
00935     ticker_event_t last_event = { 0 };
00936     const us_timestamp_t timestamp_last_event = UINT64_MAX; 
00937     const uint32_t id_last_event = 0xDEADDEAF;
00938 
00939     ticker_insert_event_us(
00940         &ticker_stub, 
00941         &last_event, timestamp_last_event, id_last_event
00942     );
00943 
00944     TEST_ASSERT_EQUAL_PTR(&last_event, queue_stub.head);
00945     TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);    
00946     TEST_ASSERT_EQUAL_UINT32(
00947         interface_stub.timestamp + TIMESTAMP_MAX_DELTA, 
00948         interface_stub.interrupt_timestamp
00949     );
00950     TEST_ASSERT_EQUAL_PTR(NULL, queue_stub.head->next);
00951     TEST_ASSERT_EQUAL_UINT64(timestamp_last_event, last_event.timestamp);
00952     TEST_ASSERT_EQUAL_UINT32(id_last_event, last_event.id);
00953 
00954     // test the beginning of the range
00955     ++interface_stub.timestamp;
00956     ++queue_stub.present_time;
00957 
00958     ticker_event_t first_event = { 0 };
00959     const us_timestamp_t timestamp_first_event = 
00960         queue_stub.present_time + TIMESTAMP_MAX_DELTA + 1;
00961     uint32_t id_first_event = 0xAAAAAAAA;
00962 
00963     ticker_insert_event_us(&ticker_stub, 
00964         &first_event, timestamp_first_event, id_first_event
00965     );
00966 
00967     TEST_ASSERT_EQUAL_PTR(&first_event, queue_stub.head);
00968     TEST_ASSERT_EQUAL(2, interface_stub.set_interrupt_call);    
00969     TEST_ASSERT_EQUAL_UINT32(
00970         interface_stub.timestamp + TIMESTAMP_MAX_DELTA, 
00971         interface_stub.interrupt_timestamp
00972     );
00973     TEST_ASSERT_EQUAL_PTR(&last_event, queue_stub.head->next);
00974     TEST_ASSERT_EQUAL_UINT64(timestamp_first_event, first_event.timestamp);
00975     TEST_ASSERT_EQUAL_UINT32(id_first_event, first_event.id);
00976 
00977     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
00978 } 
00979 
00980 /**
00981  * Given an initialized ticker without user registered events.  
00982  * When an event is inserted with ticker_insert_event_us and a timestamp less 
00983  * than timestamp value in the ticker interface.
00984  * Then 
00985  *   - The event should be in the queue
00986  *   - The interrupt timestamp should be set to interface_stub.timestamp so it
00987  *     is scheduled immediately.
00988  */
00989 static void test_insert_event_us_underflow()
00990 {
00991     ticker_set_handler(&ticker_stub, NULL);
00992     interface_stub.set_interrupt_call = 0;
00993 
00994     interface_stub.timestamp = 0xAAAAAAAA;
00995     queue_stub.tick_last_read = interface_stub.timestamp;
00996     queue_stub.present_time = 10ULL << 32 | interface_stub.timestamp;
00997 
00998     // test the end of the range
00999     ticker_event_t event = { 0 };
01000     const timestamp_t expected_timestamp = queue_stub.present_time - 1;
01001     const uint32_t expected_id = 0xDEADDEAF;
01002 
01003     ticker_insert_event_us(
01004         &ticker_stub,
01005         &event, expected_timestamp, expected_id
01006     );
01007 
01008     TEST_ASSERT_EQUAL_PTR(&event, queue_stub.head);
01009     TEST_ASSERT_EQUAL(1, interface_stub.fire_interrupt_call);
01010 
01011     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01012 }  
01013 
01014 /**
01015  * Given an initialized ticker.
01016  * When an event is inserted with ticker_insert_event_us and a timestamp less 
01017  * than the one for the next scheduled timestamp.
01018  * Then 
01019  *   - The event inserted should be the first in the queue
01020  *   - The interrupt timestamp should be equal to the timestamp of the event or 
01021  *     TIMESTAMP_MAX_DELTA if in the overflow range.
01022  *   - The timestamp of the event should be equal to the timestamp in parameter. 
01023  *   - The id of the event should be equal to the id passed in parameter. 
01024  *   - Events in the queue should remained ordered by timestamp.
01025  */
01026 static void test_insert_event_us_head()
01027 {
01028     ticker_set_handler(&ticker_stub, NULL);
01029     interface_stub.set_interrupt_call = 0;
01030     interface_stub.timestamp = 0xAAAAAAAA;
01031     queue_stub.tick_last_read = interface_stub.timestamp;
01032     queue_stub.present_time = 10ULL << 32 | interface_stub.timestamp;
01033 
01034     const us_timestamp_t timestamps[] = { 
01035         UINT64_MAX,
01036         queue_stub.present_time + TIMESTAMP_MAX_DELTA + 1,
01037         queue_stub.present_time + TIMESTAMP_MAX_DELTA,
01038         queue_stub.present_time + (TIMESTAMP_MAX_DELTA / 2),
01039         queue_stub.present_time + (TIMESTAMP_MAX_DELTA / 4),
01040         queue_stub.present_time + (TIMESTAMP_MAX_DELTA / 8),
01041         queue_stub.present_time + (TIMESTAMP_MAX_DELTA / 16),
01042     };
01043     ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 };
01044 
01045     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
01046         ticker_insert_event_us(
01047             &ticker_stub, 
01048             &events[i], timestamps[i], i
01049         );
01050 
01051         TEST_ASSERT_EQUAL_PTR(&events[i], queue_stub.head);
01052         if ((timestamps[i] - queue_stub.present_time) < TIMESTAMP_MAX_DELTA) {
01053             TEST_ASSERT_EQUAL_UINT32(
01054                 timestamps[i], 
01055                 interface_stub.interrupt_timestamp
01056             );
01057         } else { 
01058             TEST_ASSERT_EQUAL_UINT32(
01059                 queue_stub.present_time + TIMESTAMP_MAX_DELTA,
01060                 interface_stub.interrupt_timestamp
01061             );
01062         }
01063 
01064         TEST_ASSERT_EQUAL_UINT64(timestamps[i], events[i].timestamp);
01065         TEST_ASSERT_EQUAL_UINT32(i, events[i].id);
01066 
01067         ticker_event_t* e = &events[i];
01068         while (e) { 
01069             TEST_ASSERT_EQUAL_UINT32(timestamps[e->id], e->timestamp);
01070             if (e->next) { 
01071                 TEST_ASSERT_TRUE(e->id > e->next->id);
01072                 TEST_ASSERT_TRUE(e->timestamp < e->next->timestamp);
01073             } else { 
01074                 TEST_ASSERT_EQUAL_UINT32(0, e->id);
01075             }
01076             e = e->next;
01077         }
01078     }
01079 
01080     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01081 }  
01082 
01083 /** 
01084  * Given an initialized ticker.
01085  * When an event is inserted with ticker_insert_event_us and its timestamp is 
01086  * bigger than the one of the last event in the queue.
01087  * Then 
01088  *   - The event inserted should be the last in the queue
01089  *   - The interrupt timestamp should remains equal to the interrupt timestamp 
01090  *     of the head event .
01091  *   - The timestamp of the event should reflect the timestamp requested.
01092  *   - The id of the event should be equal to the id passed in parameter. 
01093  *   - Events in the queue should remained ordered by timestamp.
01094  */
01095 static void test_insert_event_us_tail()
01096 {
01097     ticker_set_handler(&ticker_stub, NULL);
01098     interface_stub.set_interrupt_call = 0;
01099 
01100     const us_timestamp_t timestamps[] = { 
01101         0xA,
01102         (1ULL << 32),
01103         (2ULL << 32),
01104         (4ULL << 32),
01105         (8ULL << 32),
01106         (16ULL << 32),
01107         (32ULL << 32),
01108         (64ULL << 32),
01109     };
01110     ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 };
01111 
01112     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
01113         ticker_insert_event_us(
01114             &ticker_stub, 
01115             &events[i], timestamps[i], i
01116         );
01117 
01118         TEST_ASSERT_EQUAL_PTR(&events[0], queue_stub.head); 
01119         TEST_ASSERT_EQUAL_UINT32(
01120             timestamps[0], interface_stub.interrupt_timestamp
01121         );
01122         TEST_ASSERT_EQUAL_UINT64(timestamps[i], events[i].timestamp);
01123         TEST_ASSERT_EQUAL_UINT32(i, events[i].id);
01124 
01125         ticker_event_t* e = queue_stub.head;
01126         while (e) { 
01127             TEST_ASSERT_EQUAL_UINT32(timestamps[e->id], e->timestamp);
01128             if (e->next) { 
01129                 TEST_ASSERT_TRUE(e->id < e->next->id);
01130                 TEST_ASSERT_TRUE(e->timestamp < e->next->timestamp);
01131             } else { 
01132                 TEST_ASSERT_EQUAL_UINT32(&events[i], e);
01133             }
01134             e = e->next;
01135         }
01136     }
01137 
01138     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01139 } 
01140 
01141 /**
01142  * Given an initialized ticker.
01143  * When an event is inserted with ticker_insert_event_us.
01144  * Then 
01145  *   - The event inserted should be at the correct position in the queue
01146  *   - The event queue should remain ordered by timestamp
01147  *   - The interrupt timestamp should be equal to the interrupt timestamp 
01148  *     of the head event or TIMESTAMP_MAX_DELTA if the 
01149  *     timestamp is in the overflow range.
01150  *   - The timestamp of the event should be equal to the timestamp parameter.
01151  *   - The id of the event should be equal to the id passed in parameter. 
01152  *   - Events in the queue should remained ordered by timestamp.
01153  */
01154 static void test_insert_event_us_multiple_random()
01155 {
01156     ticker_set_handler(&ticker_stub, NULL);
01157     interface_stub.set_interrupt_call = 0;
01158 
01159     const timestamp_t ref_timestamp = UINT32_MAX / 2;
01160     interface_stub.timestamp = ref_timestamp;
01161 
01162     // insert first event at the head of the queue 
01163     ticker_event_t first_event;
01164     const us_timestamp_t first_event_timestamp = 
01165         ref_timestamp + TIMESTAMP_MAX_DELTA + 100;
01166 
01167     ticker_insert_event_us(
01168         &ticker_stub,
01169         &first_event, first_event_timestamp, (uint32_t) &first_event
01170     );
01171 
01172     TEST_ASSERT_EQUAL_PTR(&first_event, queue_stub.head);
01173     TEST_ASSERT_EQUAL_PTR(NULL, first_event.next);
01174     TEST_ASSERT_EQUAL_UINT32(
01175         ref_timestamp + TIMESTAMP_MAX_DELTA, interface_stub.interrupt_timestamp
01176     );
01177     TEST_ASSERT_EQUAL_UINT64(first_event.timestamp, first_event_timestamp);
01178     TEST_ASSERT_EQUAL_UINT32((uint32_t) &first_event, first_event.id);
01179 
01180     // insert second event at the tail of the queue
01181     ticker_event_t second_event;
01182     const us_timestamp_t second_event_timestamp = first_event_timestamp + 1;
01183 
01184     ticker_insert_event_us(
01185         &ticker_stub,
01186         &second_event, second_event_timestamp, (uint32_t) &second_event
01187     );
01188 
01189     TEST_ASSERT_EQUAL_PTR(&first_event, queue_stub.head);
01190     TEST_ASSERT_EQUAL_PTR(&second_event, first_event.next);
01191     TEST_ASSERT_EQUAL_PTR(NULL, second_event.next);
01192     TEST_ASSERT_EQUAL_UINT32(
01193         ref_timestamp + TIMESTAMP_MAX_DELTA, interface_stub.interrupt_timestamp
01194     );
01195     TEST_ASSERT_EQUAL_UINT64(second_event_timestamp, second_event.timestamp);
01196     TEST_ASSERT_EQUAL_UINT32((uint32_t) &second_event, second_event.id);
01197 
01198 
01199     // insert third event at the head of the queue out the overflow zone
01200     ticker_event_t third_event;
01201     const us_timestamp_t third_event_timestamp = 
01202         ref_timestamp + TIMESTAMP_MAX_DELTA - 100;
01203 
01204     ticker_insert_event_us(
01205         &ticker_stub,
01206         &third_event, third_event_timestamp, (uint32_t) &third_event
01207     );
01208 
01209     TEST_ASSERT_EQUAL_PTR(&third_event, queue_stub.head);
01210     TEST_ASSERT_EQUAL_PTR(&first_event, third_event.next);
01211     TEST_ASSERT_EQUAL_PTR(&second_event, first_event.next);
01212     TEST_ASSERT_EQUAL_PTR(NULL, second_event.next);
01213     TEST_ASSERT_EQUAL_UINT32(
01214         third_event_timestamp, interface_stub.interrupt_timestamp
01215     );
01216     TEST_ASSERT_EQUAL_UINT64(third_event_timestamp, third_event.timestamp);
01217     TEST_ASSERT_EQUAL_UINT32((uint32_t) &third_event, third_event.id);
01218 
01219     // insert fourth event right after the third event
01220     ticker_event_t fourth_event;
01221     const us_timestamp_t fourth_event_timestamp = third_event_timestamp + 50;
01222 
01223     ticker_insert_event_us(
01224         &ticker_stub,
01225         &fourth_event, fourth_event_timestamp, (uint32_t) &fourth_event
01226     );
01227 
01228     TEST_ASSERT_EQUAL_PTR(&third_event, queue_stub.head);
01229     TEST_ASSERT_EQUAL_PTR(&fourth_event, third_event.next);
01230     TEST_ASSERT_EQUAL_PTR(&first_event, fourth_event.next);
01231     TEST_ASSERT_EQUAL_PTR(&second_event, first_event.next);
01232     TEST_ASSERT_EQUAL_PTR(NULL, second_event.next);
01233     TEST_ASSERT_EQUAL_UINT32(
01234         third_event_timestamp, interface_stub.interrupt_timestamp
01235     );
01236     TEST_ASSERT_EQUAL_UINT64(fourth_event_timestamp, fourth_event.timestamp);
01237     TEST_ASSERT_EQUAL_UINT32((uint32_t) &fourth_event, fourth_event.id);
01238 
01239     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01240 }
01241 
01242 /**
01243  * Given an initialized ticker with multiple events registered. 
01244  * When the event at the tail of the queue is removed from the queue.
01245  * Then: 
01246  *    - The event should not be in the queue.
01247  *    - The events in the queue should remain ordered
01248  *    - The interrupt timestamp should be unchanged. 
01249  */
01250 static void test_remove_event_tail()
01251 {
01252     ticker_set_handler(&ticker_stub, NULL);
01253     const us_timestamp_t timestamps[] = { 
01254         0xA,
01255         (1ULL << 32),
01256         (2ULL << 32),
01257         (4ULL << 32),
01258         (8ULL << 32),
01259         (16ULL << 32),
01260         (32ULL << 32),
01261         (64ULL << 32),
01262     };
01263     ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 };
01264 
01265     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
01266         ticker_insert_event_us(
01267             &ticker_stub, 
01268             &events[i], timestamps[i], i
01269         );
01270     }
01271 
01272     for (ssize_t i = MBED_ARRAY_SIZE(events) - 1; i >= 0; --i) { 
01273         ticker_remove_event(&ticker_stub, &events[i]);
01274 
01275         ticker_event_t* e = queue_stub.head;
01276         size_t event_count = 0;
01277         while (e) { 
01278             TEST_ASSERT_NOT_EQUAL(e, &events[i]);
01279             if (e->next) { 
01280                 TEST_ASSERT_TRUE(e->timestamp <= e->next->timestamp);
01281             }
01282             e = e->next;
01283             ++event_count;
01284         }
01285 
01286         TEST_ASSERT_EQUAL(i, event_count);
01287 
01288         if (i != 0 ) { 
01289             TEST_ASSERT_EQUAL(
01290                 timestamps[0],
01291                 interface_stub.interrupt_timestamp
01292             );
01293         } else { 
01294             TEST_ASSERT_EQUAL(
01295                 interface_stub.timestamp + TIMESTAMP_MAX_DELTA,
01296                 interface_stub.interrupt_timestamp
01297             );
01298         }
01299     }
01300 
01301     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01302 }
01303 
01304 /**
01305  * Given an initialized ticker with multiple events registered. 
01306  * When the event at the head of the queue is removed from the queue.
01307  * Then: 
01308  *    - The event should not be in the queue.
01309  *    - The event at the head of the queue should be the equal to the one 
01310  *      after the event removed.
01311  *    - The interrupt timestamp should be equal to the interrupt timestamp 
01312  *      of the head event or TIMESTAMP_MAX_DELTA if the 
01313  *      timestamp is in the overflow range.
01314  */
01315 static void test_remove_event_head()
01316 {
01317     ticker_set_handler(&ticker_stub, NULL);
01318     const us_timestamp_t timestamps[] = { 
01319         TIMESTAMP_MAX_DELTA / 8,
01320         TIMESTAMP_MAX_DELTA / 4,
01321         TIMESTAMP_MAX_DELTA / 2,
01322         TIMESTAMP_MAX_DELTA - 1,
01323         TIMESTAMP_MAX_DELTA,
01324         TIMESTAMP_MAX_DELTA + 1,
01325         (1ULL << 32) | TIMESTAMP_MAX_DELTA,
01326         UINT64_MAX
01327     };
01328     ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 };
01329 
01330     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
01331         ticker_insert_event_us(&ticker_stub, 
01332             &events[i], timestamps[i], i
01333         );
01334     }
01335 
01336     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
01337         ticker_remove_event(&ticker_stub, &events[i]);
01338 
01339         ticker_event_t* e = queue_stub.head;
01340         size_t event_count = 0;
01341         while (e) { 
01342             TEST_ASSERT_NOT_EQUAL(e, &events[i]);
01343             if (e->next) { 
01344                 TEST_ASSERT_TRUE(e->timestamp <= e->next->timestamp);
01345             }
01346             e = e->next;
01347             ++event_count;
01348         }
01349 
01350         TEST_ASSERT_EQUAL(MBED_ARRAY_SIZE(events) - i - 1, event_count);
01351 
01352         if (event_count) { 
01353             TEST_ASSERT_EQUAL(
01354                 std::min(
01355                     timestamps[i + 1], 
01356                     interface_stub.timestamp + TIMESTAMP_MAX_DELTA
01357                 ),
01358                 interface_stub.interrupt_timestamp
01359             );
01360         } else { 
01361             TEST_ASSERT_EQUAL(
01362                 interface_stub.timestamp + TIMESTAMP_MAX_DELTA,
01363                 interface_stub.interrupt_timestamp
01364             );
01365         }
01366 
01367     }
01368 
01369     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01370 }
01371 
01372 /**
01373  * Given an initialized ticker with multiple events registered. 
01374  * When an event not in the queue is attempted to be removed.
01375  * Then the queue should remains identical as before.
01376  */
01377 static void test_remove_event_invalid()
01378 {
01379     ticker_set_handler(&ticker_stub, NULL);
01380     const us_timestamp_t timestamps[] = { 
01381         TIMESTAMP_MAX_DELTA / 8,
01382         TIMESTAMP_MAX_DELTA / 4,
01383         TIMESTAMP_MAX_DELTA / 2,
01384         TIMESTAMP_MAX_DELTA - 1,
01385         TIMESTAMP_MAX_DELTA,
01386         TIMESTAMP_MAX_DELTA + 1,
01387         (1ULL << 32) | TIMESTAMP_MAX_DELTA,
01388         UINT64_MAX
01389     };
01390     ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 };
01391 
01392     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
01393         ticker_insert_event_us(
01394             &ticker_stub, 
01395             &events[i], timestamps[i], i
01396         );
01397     }
01398 
01399     ticker_event_t invalid_event;
01400     ticker_remove_event(&ticker_stub, &invalid_event);
01401 
01402     TEST_ASSERT_EQUAL(&events[0], queue_stub.head);
01403 
01404     ticker_event_t* e = queue_stub.head;
01405     size_t event_count = 0;
01406     while (e) { 
01407         TEST_ASSERT_EQUAL(e, &events[event_count]);
01408         e = e->next;
01409         ++event_count;
01410     }
01411     TEST_ASSERT_EQUAL(MBED_ARRAY_SIZE(events), event_count);
01412 }
01413 
01414 /**
01415  * Given an initialized ticker with multiple events inserted.
01416  * When an event is remoced
01417  * Then:
01418  *   - the event should not be in the queue
01419  *   - the queue should remain ordered
01420  *   - the interrupt timestamp should be set to either head->timestamp or 
01421  *     TIMESTAMP_MAX_DELTA depending on the distance between the current time 
01422  *     ans the timestamp of the event at the head of the queue.
01423  */
01424 static void test_remove_random()
01425 {
01426     ticker_set_handler(&ticker_stub, NULL);
01427     interface_stub.set_interrupt_call = 0;
01428 
01429     const timestamp_t ref_timestamp = UINT32_MAX / 2;
01430     interface_stub.timestamp = ref_timestamp;
01431 
01432     // insert all events 
01433     ticker_event_t first_event;
01434     const us_timestamp_t first_event_timestamp = 
01435         ref_timestamp + TIMESTAMP_MAX_DELTA + 100;
01436 
01437     ticker_insert_event_us(
01438         &ticker_stub,
01439         &first_event, first_event_timestamp, (uint32_t) &first_event
01440     );
01441 
01442 
01443     ticker_event_t second_event;
01444     const us_timestamp_t second_event_timestamp = first_event_timestamp + 1;
01445 
01446     ticker_insert_event_us(
01447         &ticker_stub,
01448         &second_event, second_event_timestamp, (uint32_t) &second_event
01449     );
01450 
01451     ticker_event_t third_event;
01452     const us_timestamp_t third_event_timestamp = 
01453         ref_timestamp + TIMESTAMP_MAX_DELTA - 100;
01454 
01455     ticker_insert_event_us(
01456         &ticker_stub,
01457         &third_event, third_event_timestamp, (uint32_t) &third_event
01458     );
01459 
01460     ticker_event_t fourth_event;
01461     const us_timestamp_t fourth_event_timestamp = third_event_timestamp + 50;
01462 
01463     ticker_insert_event_us(
01464         &ticker_stub,
01465         &fourth_event, fourth_event_timestamp, (uint32_t) &fourth_event
01466     );
01467 
01468     // test that the queue is in the correct state 
01469     TEST_ASSERT_EQUAL_PTR(&third_event, queue_stub.head);
01470     TEST_ASSERT_EQUAL_PTR(&fourth_event, third_event.next);
01471     TEST_ASSERT_EQUAL_PTR(&first_event, fourth_event.next);
01472     TEST_ASSERT_EQUAL_PTR(&second_event, first_event.next);
01473     TEST_ASSERT_EQUAL_PTR(NULL, second_event.next);
01474     TEST_ASSERT_EQUAL_UINT32(
01475         third_event_timestamp, interface_stub.interrupt_timestamp
01476     );
01477     TEST_ASSERT_EQUAL_UINT64(fourth_event_timestamp, fourth_event.timestamp);
01478     TEST_ASSERT_EQUAL_UINT32((uint32_t) &fourth_event, fourth_event.id);
01479 
01480     // remove fourth event 
01481     ticker_remove_event(&ticker_stub, &fourth_event);
01482 
01483     TEST_ASSERT_EQUAL_PTR(&third_event, queue_stub.head);
01484     TEST_ASSERT_EQUAL_PTR(&first_event, third_event.next);
01485     TEST_ASSERT_EQUAL_PTR(&second_event, first_event.next);
01486     TEST_ASSERT_EQUAL_PTR(NULL, second_event.next);
01487     TEST_ASSERT_EQUAL_UINT32(
01488         third_event_timestamp, interface_stub.interrupt_timestamp
01489     );
01490     TEST_ASSERT_EQUAL_UINT64(third_event_timestamp, third_event.timestamp);
01491     TEST_ASSERT_EQUAL_UINT32((uint32_t) &third_event, third_event.id);
01492 
01493     // remove third event 
01494     ticker_remove_event(&ticker_stub, &third_event);
01495 
01496     TEST_ASSERT_EQUAL_PTR(&first_event, queue_stub.head);
01497     TEST_ASSERT_EQUAL_PTR(&second_event, first_event.next);
01498     TEST_ASSERT_EQUAL_PTR(NULL, second_event.next);
01499     TEST_ASSERT_EQUAL_UINT32(
01500         ref_timestamp + TIMESTAMP_MAX_DELTA, interface_stub.interrupt_timestamp
01501     );
01502     TEST_ASSERT_EQUAL_UINT64(second_event_timestamp, second_event.timestamp);
01503     TEST_ASSERT_EQUAL_UINT32((uint32_t) &second_event, second_event.id);
01504 
01505     // remove second event 
01506     ticker_remove_event(&ticker_stub, &second_event);
01507 
01508     TEST_ASSERT_EQUAL_PTR(&first_event, queue_stub.head);
01509     TEST_ASSERT_EQUAL_PTR(NULL, first_event.next);
01510     TEST_ASSERT_EQUAL_UINT32(
01511         ref_timestamp + TIMESTAMP_MAX_DELTA, interface_stub.interrupt_timestamp
01512     );
01513     TEST_ASSERT_EQUAL_UINT64(first_event.timestamp, first_event_timestamp);
01514     TEST_ASSERT_EQUAL_UINT32((uint32_t) &first_event, first_event.id);
01515 
01516     // remove first event 
01517     ticker_remove_event(&ticker_stub, &first_event);
01518 
01519     TEST_ASSERT_EQUAL_PTR(NULL, queue_stub.head);
01520     TEST_ASSERT_EQUAL_PTR(NULL, first_event.next);
01521     TEST_ASSERT_EQUAL_UINT32(
01522         ref_timestamp + TIMESTAMP_MAX_DELTA, interface_stub.interrupt_timestamp
01523     );
01524 
01525     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01526 }
01527 
01528 /** 
01529  * Given an initialized ticker without user registered events and a ticker 
01530  * interface timestamp equal or bigger than the one registered by the overflow 
01531  * event.
01532  * When the interrupt handler is called.
01533  * Then:
01534  *   - The interrupt timestamp should be updated to the timestamp of the ticker 
01535  *     interface plus TIMESTAMP_MAX_DELTA. 
01536  *   - The irq handler registered should not be called.
01537  */
01538 static void test_overflow_event_update()
01539 {
01540     static uint32_t handler_call = 0;
01541     struct irq_handler_stub_t { 
01542         static void event_handler(uint32_t id) { 
01543             ++handler_call;
01544         }
01545     };
01546     handler_call = 0;
01547 
01548     ticker_set_handler(&ticker_stub, irq_handler_stub_t::event_handler);
01549     interface_stub.set_interrupt_call = 0;
01550 
01551     for (size_t i = 0; i < 8; ++i) {
01552         us_timestamp_t previous_timestamp = queue_stub.present_time;
01553         timestamp_t interface_timestamp = 
01554             previous_timestamp + (TIMESTAMP_MAX_DELTA + i * 100);
01555         interface_stub.timestamp = interface_timestamp;
01556             
01557         ticker_irq_handler(&ticker_stub);
01558         TEST_ASSERT_EQUAL(i + 1, interface_stub.clear_interrupt_call);
01559 
01560         TEST_ASSERT_EQUAL(i + 1, interface_stub.set_interrupt_call);
01561         TEST_ASSERT_EQUAL_UINT32(
01562             interface_timestamp + TIMESTAMP_MAX_DELTA,
01563             interface_stub.interrupt_timestamp
01564         );
01565         TEST_ASSERT_EQUAL(0, handler_call);
01566     }
01567 
01568     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01569 }  
01570 
01571 /** 
01572  * Given an initialized ticker without user registered events and a ticker 
01573  * interface timestamp less than the one registered to handle overflow.
01574  * When the interrupt handler is called.
01575  * Then:
01576  *   - The interrupt timestamp should be updated to the timestamp of the ticker 
01577  *     interface plus TIMESTAMP_MAX_DELTA. 
01578  *   - The irq handler registered should not be called.
01579  */
01580 static void test_overflow_event_update_when_spurious_interrupt()
01581 {
01582     static uint32_t handler_call = 0;
01583     struct irq_handler_stub_t { 
01584         static void event_handler(uint32_t id) { 
01585             ++handler_call;
01586         }
01587     };
01588     handler_call = 0;
01589 
01590     ticker_set_handler(&ticker_stub, irq_handler_stub_t::event_handler);
01591     interface_stub.set_interrupt_call = 0;
01592 
01593     for (size_t i = 0; i < 8; ++i) {
01594         us_timestamp_t previous_timestamp = queue_stub.present_time;
01595         timestamp_t interface_timestamp = 
01596             previous_timestamp + (TIMESTAMP_MAX_DELTA / (2 + i));
01597         interface_stub.timestamp = interface_timestamp;
01598             
01599         ticker_irq_handler(&ticker_stub);
01600 
01601         TEST_ASSERT_EQUAL(i + 1, interface_stub.clear_interrupt_call);
01602         TEST_ASSERT_EQUAL(i + 1, interface_stub.set_interrupt_call);
01603         TEST_ASSERT_EQUAL_UINT32(
01604             interface_timestamp + TIMESTAMP_MAX_DELTA,
01605             interface_stub.interrupt_timestamp
01606         );
01607         TEST_ASSERT_EQUAL(0, handler_call);
01608     }
01609 
01610     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01611 }  
01612 
01613 /**
01614  * Given an initialized ticker with a single ticker event inserted and a ticker 
01615  * interface timestamp bigger than the one set for interrupt. 
01616  * When ticker_irq_handler is called.
01617  * Then: 
01618  *   - The IRQ handler should be called with the id of the event at the head of 
01619  *     the queue.
01620  *   - The event at the head of the queue should be replaced by the next event.
01621  *   - The interrupt timestamp in the ticker interface should be set to the 
01622  *     value of the interface timestamp + TIMESTAMP_MAX_DELTA  
01623  */
01624 static void test_irq_handler_single_event()
01625 {
01626     static const timestamp_t event_timestamp = 0xAAAAAAAA;
01627     static const timestamp_t interface_timestamp_after_irq = event_timestamp + 100;
01628 
01629     uint32_t handler_call = 0;
01630     struct irq_handler_stub_t { 
01631         static void event_handler(uint32_t id) { 
01632             ++ (*((uint32_t*) id));
01633             interface_stub.timestamp = interface_timestamp_after_irq;
01634         }
01635     };
01636 
01637     ticker_set_handler(&ticker_stub, irq_handler_stub_t::event_handler);
01638     interface_stub.set_interrupt_call = 0;
01639 
01640     ticker_event_t e; 
01641     ticker_insert_event(&ticker_stub, &e, event_timestamp, (uint32_t) &handler_call);
01642 
01643     interface_stub.timestamp = event_timestamp;
01644     interface_stub.set_interrupt_call = 0;
01645 
01646     ticker_irq_handler(&ticker_stub);
01647 
01648     TEST_ASSERT_EQUAL(1, interface_stub.clear_interrupt_call);
01649     TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);
01650     TEST_ASSERT_EQUAL(1, handler_call);
01651     TEST_ASSERT_EQUAL_UINT32(
01652         interface_timestamp_after_irq + TIMESTAMP_MAX_DELTA,
01653         interface_stub.interrupt_timestamp
01654     );
01655 
01656     TEST_ASSERT_NULL(queue_stub.head);
01657 
01658     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01659 }
01660 
01661 /**
01662  * Given an initialized ticker with at least a ticker event inserted and a ticker 
01663  * interface timestamp less than the one set for interrupt. 
01664  * When ticker_irq_handler is called.
01665  * Then: 
01666  *   - The IRQ handler should not be called.
01667  *   - The event at the head of the queue should remains the same.
01668  *   - The interrupt timestamp in the ticker interface should be set to the 
01669  *     value of the event timestamp  
01670  */
01671 static void test_irq_handler_single_event_spurious()
01672 {
01673     struct irq_handler_stub_t { 
01674         static void event_handler(uint32_t id) { 
01675             TEST_FAIL();
01676         }
01677     };
01678 
01679     ticker_set_handler(&ticker_stub, irq_handler_stub_t::event_handler);
01680     interface_stub.set_interrupt_call = 0;
01681 
01682     const us_timestamp_t timestamps [] = {
01683         UINT32_MAX, 
01684         TIMESTAMP_MAX_DELTA + 1, 
01685         TIMESTAMP_MAX_DELTA,
01686         TIMESTAMP_MAX_DELTA - 1
01687     };
01688 
01689     ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 };
01690 
01691     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
01692         ticker_insert_event_us(
01693             &ticker_stub, 
01694             &events[i], timestamps[i], timestamps[i]
01695         );
01696         interface_stub.set_interrupt_call = 0;
01697         interface_stub.clear_interrupt_call = 0;
01698 
01699         ticker_irq_handler(&ticker_stub);
01700 
01701         TEST_ASSERT_EQUAL(1, interface_stub.clear_interrupt_call);
01702         TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);
01703         TEST_ASSERT_EQUAL_UINT32(
01704             std::min(timestamps[i], TIMESTAMP_MAX_DELTA),
01705             interface_stub.interrupt_timestamp
01706         );
01707     }
01708 
01709     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01710 }
01711 
01712 /**
01713  * Given an initialized ticker with multiple ticker event inserted, its 
01714  * interface timestamp at greater than the timestamp of the next schedule event 
01715  * and all event execution time taking at least the time befor ethe next event.
01716  * When ticker_irq_handler is called.
01717  * Then: 
01718  *   - The IRQ handler should have been called for every event.
01719  *   - The head of the queue should be set to NULL.
01720  *   - The interrupt timestamp in the ticker interface should be scheduled in
01721  *     TIMESTAMP_MAX_DELTAs
01722  */
01723 static void test_irq_handler_multiple_event_multiple_dequeue()
01724 {
01725     const us_timestamp_t timestamps [] = {
01726         10, 
01727         10 + TIMESTAMP_MAX_DELTA - 1,
01728         10 + TIMESTAMP_MAX_DELTA,
01729         10 + TIMESTAMP_MAX_DELTA + 1, 
01730         UINT32_MAX
01731     };
01732 
01733     static size_t handler_called = 0;
01734     struct irq_handler_stub_t { 
01735         static void event_handler(uint32_t id) { 
01736             ++handler_called;
01737             ticker_event_t* e = (ticker_event_t*) id;
01738             if (e->next) { 
01739                 interface_stub.timestamp = e->next->timestamp;
01740             }
01741         }
01742     };
01743     handler_called = 0;
01744 
01745     ticker_set_handler(&ticker_stub, irq_handler_stub_t::event_handler);
01746     interface_stub.set_interrupt_call = 0;
01747 
01748     ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 };
01749 
01750     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
01751         ticker_insert_event_us(
01752             &ticker_stub, 
01753             &events[i], timestamps[i], (uint32_t) &events[i]
01754         );
01755     }
01756 
01757     interface_stub.set_interrupt_call = 0;
01758     interface_stub.clear_interrupt_call = 0;
01759     interface_stub.timestamp = timestamps[0];
01760     
01761     ticker_irq_handler(&ticker_stub);
01762 
01763     TEST_ASSERT_EQUAL(1, interface_stub.clear_interrupt_call);
01764     TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);
01765     TEST_ASSERT_EQUAL_UINT32(MBED_ARRAY_SIZE(timestamps), handler_called);
01766     TEST_ASSERT_EQUAL_UINT32(
01767         timestamps[MBED_ARRAY_SIZE(timestamps) - 1] + TIMESTAMP_MAX_DELTA,
01768         interface_stub.interrupt_timestamp
01769     );
01770     TEST_ASSERT_NULL(queue_stub.head);
01771 
01772     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01773 }
01774 
01775 /**
01776  * Given an initialized ticker with two ticker event inserted scheduled from more 
01777  * than TIMESTAMP_MAX_DELTA from one another. The interface 
01778  * timestamp is equal to the timestamp of the first event. 
01779  * When ticker_irq_handler is called.
01780  * Then: 
01781  *   - The IRQ handler should have been called for the first event.
01782  *   - The head of the queue should be set to the event after the first event.
01783  *   - The interrupt timestamp in the ticker interface should be scheduled in
01784  *     TIMESTAMP_MAX_DELTA.
01785  */
01786 static void test_irq_handler_multiple_event_single_dequeue_overflow()
01787 {
01788     const us_timestamp_t timestamps [] = {
01789         10, 
01790         10 + TIMESTAMP_MAX_DELTA + 1
01791     };
01792 
01793     size_t handler_called = 0;
01794     struct irq_handler_stub_t { 
01795         static void event_handler(uint32_t id) { 
01796             ++ (*((size_t*) id));
01797         }
01798     };
01799 
01800     ticker_set_handler(&ticker_stub, irq_handler_stub_t::event_handler);
01801     interface_stub.set_interrupt_call = 0;
01802 
01803     ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 };
01804 
01805     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
01806         ticker_insert_event_us(
01807             &ticker_stub, 
01808             &events[i], timestamps[i], (uint32_t) &handler_called
01809         );
01810     }
01811 
01812     interface_stub.set_interrupt_call = 0;
01813     interface_stub.clear_interrupt_call = 0;
01814     interface_stub.timestamp = timestamps[0];
01815     
01816     ticker_irq_handler(&ticker_stub);
01817 
01818     TEST_ASSERT_EQUAL(1, interface_stub.clear_interrupt_call);
01819     TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);
01820     TEST_ASSERT_EQUAL_UINT32(1, handler_called);
01821     TEST_ASSERT_EQUAL_UINT32(
01822         timestamps[0] + TIMESTAMP_MAX_DELTA,
01823         interface_stub.interrupt_timestamp
01824     );
01825     TEST_ASSERT_EQUAL_PTR(&events[1], queue_stub.head);
01826 
01827     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01828 }
01829 
01830 /**
01831  * Given an initialized ticker with two ticker event inserted scheduled from less 
01832  * than TIMESTAMP_MAX_DELTA from one another. The interface 
01833  * timestamp is equal to the timestamp of the first event. 
01834  * When ticker_irq_handler is called.
01835  * Then: 
01836  *   - The IRQ handler should have been called for the first event.
01837  *   - The head of the queue should be set to second event.
01838  *   - The interrupt timestamp in the ticker interface should be equal to the 
01839  *     timestamp of the second event.
01840  */
01841 static void test_irq_handler_multiple_event_single_dequeue()
01842 {
01843     const us_timestamp_t timestamps [] = {
01844         10, 
01845         10 + TIMESTAMP_MAX_DELTA - 1
01846     };
01847 
01848     size_t handler_called = 0;
01849     struct irq_handler_stub_t { 
01850         static void event_handler(uint32_t id) { 
01851             ++ (*((size_t*) id));
01852         }
01853     };
01854 
01855     ticker_set_handler(&ticker_stub, irq_handler_stub_t::event_handler);
01856     interface_stub.set_interrupt_call = 0;
01857 
01858     ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 };
01859 
01860     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
01861         ticker_insert_event_us(
01862             &ticker_stub, 
01863             &events[i], timestamps[i], (uint32_t) &handler_called
01864         );
01865     }
01866 
01867     interface_stub.set_interrupt_call = 0;
01868     interface_stub.clear_interrupt_call = 0;
01869     interface_stub.timestamp = timestamps[0];
01870     
01871     ticker_irq_handler(&ticker_stub);
01872 
01873     TEST_ASSERT_EQUAL(1, interface_stub.clear_interrupt_call);
01874     TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);
01875     TEST_ASSERT_EQUAL_UINT32(1, handler_called);
01876     TEST_ASSERT_EQUAL_UINT32(
01877         timestamps[1],
01878         interface_stub.interrupt_timestamp
01879     );
01880     TEST_ASSERT_EQUAL_PTR(&events[1], queue_stub.head);
01881 
01882     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01883 }
01884 
01885 /**
01886  * Given an initialized ticker with multiple ticker event inserted and the 
01887  * interface timestamp is equal to the timestamp of the first event. The first
01888  * event to execute will insert an events in the ticker which have to be executed 
01889  * immediately.
01890  * When ticker_irq_handler is called.
01891  * Then: 
01892  *   - The IRQ handler should have been called for the first event and the event 
01893  *     inserted during irq.
01894  *   - The head of the queue should be set correctly.
01895  *   - The interrupt timestamp in the ticker interface should be equal to 
01896  *     timestamp of the head event.
01897  */
01898 static void test_irq_handler_insert_immediate_in_irq()
01899 {
01900     static const us_timestamp_t timestamps [] = {
01901         10, 
01902         10 + TIMESTAMP_MAX_DELTA - 1
01903     };
01904 
01905     static const us_timestamp_t expected_timestamp = 
01906         ((timestamps[1] - timestamps[0]) / 2) + timestamps[0];
01907 
01908     struct ctrl_block_t { 
01909         bool irq_event_called;
01910         ticker_event_t immediate_event; 
01911         size_t handler_called;
01912     };
01913 
01914     ctrl_block_t ctrl_block = { 0 };
01915 
01916     struct irq_handler_stub_t { 
01917         static void event_handler(uint32_t id) { 
01918             ctrl_block_t*  ctrl_block = (ctrl_block_t*) id;
01919 
01920             if (ctrl_block->handler_called == 0) {
01921                 ticker_insert_event(
01922                     &ticker_stub, 
01923                     &ctrl_block->immediate_event, expected_timestamp, id
01924                 );
01925                 interface_stub.timestamp = expected_timestamp;
01926             } else if (ctrl_block->handler_called > 1) { 
01927                 TEST_FAIL();
01928             }
01929             ++ctrl_block->handler_called;
01930         }
01931     };
01932 
01933     ticker_set_handler(&ticker_stub, irq_handler_stub_t::event_handler);
01934     interface_stub.set_interrupt_call = 0;
01935 
01936     ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 };
01937 
01938     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
01939         ticker_insert_event_us(
01940             &ticker_stub, 
01941             &events[i], timestamps[i], (uint32_t) &ctrl_block
01942         );
01943     }
01944 
01945     interface_stub.set_interrupt_call = 0;
01946     interface_stub.clear_interrupt_call = 0;
01947     interface_stub.timestamp = timestamps[0];
01948     
01949     ticker_irq_handler(&ticker_stub);
01950 
01951     TEST_ASSERT_EQUAL(1, interface_stub.clear_interrupt_call);
01952     TEST_ASSERT_EQUAL_UINT32(2, ctrl_block.handler_called);
01953     TEST_ASSERT_EQUAL_UINT32(
01954         timestamps[1],
01955         interface_stub.interrupt_timestamp
01956     );
01957     TEST_ASSERT_EQUAL_PTR(&events[1], queue_stub.head);
01958 
01959     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
01960 }
01961 
01962 /**
01963  * Given an initialized ticker with multiple ticker event inserted and the 
01964  * interface timestamp is equal to the timestamp of the first event. The first
01965  * event to execute will insert an events in the ticker which does not have to 
01966  * be executed  immediately.
01967  * When ticker_irq_handler is called.
01968  * Then: 
01969  *   - The IRQ handler should have been called for the first event.
01970  *   - The head of the queue should be set to the event inserted in IRQ.
01971  *   - The interrupt timestamp in the ticker interface should be equal to 
01972  *     timestamp of the head event.
01973  */
01974 static void test_irq_handler_insert_non_immediate_in_irq()
01975 {
01976     static const us_timestamp_t timestamps [] = {
01977         10, 
01978         10 + TIMESTAMP_MAX_DELTA - 1
01979     };
01980 
01981     static const us_timestamp_t expected_timestamp = 
01982         ((timestamps[1] - timestamps[0]) / 2) + timestamps[0];
01983 
01984     struct ctrl_block_t { 
01985         bool irq_event_called;
01986         ticker_event_t non_immediate_event; 
01987         size_t handler_called;
01988     };
01989 
01990     ctrl_block_t ctrl_block = { 0 };
01991 
01992     struct irq_handler_stub_t { 
01993         static void event_handler(uint32_t id) { 
01994             ctrl_block_t*  ctrl_block = (ctrl_block_t*) id;
01995 
01996             if (ctrl_block->handler_called == 0) {
01997                 ticker_insert_event(
01998                     &ticker_stub, 
01999                     &ctrl_block->non_immediate_event, expected_timestamp, id
02000                 );
02001             } else { 
02002                 TEST_FAIL();
02003             }
02004             ++ctrl_block->handler_called;
02005         }
02006     };
02007 
02008 
02009     ticker_set_handler(&ticker_stub, irq_handler_stub_t::event_handler);
02010     interface_stub.set_interrupt_call = 0;
02011 
02012     ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 };
02013 
02014     for (size_t i = 0; i < MBED_ARRAY_SIZE(events); ++i) { 
02015         ticker_insert_event_us(
02016             &ticker_stub, 
02017             &events[i], timestamps[i], (uint32_t) &ctrl_block
02018         );
02019     }
02020 
02021     interface_stub.set_interrupt_call = 0;
02022     interface_stub.clear_interrupt_call = 0;
02023     interface_stub.timestamp = timestamps[0];
02024     
02025     ticker_irq_handler(&ticker_stub);
02026 
02027     TEST_ASSERT_EQUAL(1, interface_stub.clear_interrupt_call);
02028     TEST_ASSERT_EQUAL_UINT32(1, ctrl_block.handler_called);
02029     TEST_ASSERT_EQUAL_UINT32(
02030         expected_timestamp,
02031         interface_stub.interrupt_timestamp
02032     );
02033     TEST_ASSERT_EQUAL_PTR(&ctrl_block.non_immediate_event, queue_stub.head);
02034     TEST_ASSERT_EQUAL_PTR(&events[1], queue_stub.head->next);
02035 
02036     TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
02037 }
02038 
02039 static uint32_t ticker_interface_stub_read_interrupt_time()
02040 {
02041     ++interface_stub.read_call;
02042     // only if set interrupt call, to test the condition afterwards
02043     if (interface_stub.set_interrupt_call) {
02044         return interface_stub.interrupt_timestamp;
02045     } else {
02046         return interface_stub.timestamp;
02047     }
02048 } 
02049 
02050 /**
02051  * Test to insert an event that is already in the past, the fire_interrupt should
02052  * be invoked, instead of set_interrupt
02053  */
02054 static void test_set_interrupt_past_time()
02055 {
02056     ticker_set_handler(&ticker_stub, NULL);
02057 
02058     interface_stub.set_interrupt_call = 0;
02059     interface_stub.fire_interrupt_call = 0;
02060     interface_stub.timestamp = 0xFF;
02061 
02062 
02063     // This tests fire now functinality when next_event_timestamp <= present
02064     ticker_event_t event = { 0 };
02065     const timestamp_t event_timestamp = interface_stub.timestamp;
02066     const uint32_t id_last_event = 0xDEADDEAF;
02067 
02068     ticker_insert_event(&ticker_stub, &event, event_timestamp, id_last_event);
02069     TEST_ASSERT_EQUAL(0, interface_stub.set_interrupt_call);
02070     TEST_ASSERT_EQUAL(1, interface_stub.fire_interrupt_call);
02071 }
02072 /**
02073  * Test to insert an event that is being delayed, set_interrupt is set
02074  * but then event is already in the past, thus fire_interrupt should be invoked right-away
02075  */
02076 static void test_set_interrupt_past_time_with_delay()
02077 {
02078     ticker_set_handler(&ticker_stub, NULL);
02079 
02080     interface_stub.set_interrupt_call = 0;
02081     interface_stub.fire_interrupt_call = 0;
02082     interface_stub.timestamp = 0xFF;
02083 
02084     // This tests fire now functionality when present time >= new_match_time
02085     interface_stub.interface.read = ticker_interface_stub_read_interrupt_time;
02086     ticker_event_t event = { 0 };
02087     const timestamp_t event_timestamp = interface_stub.timestamp + 5;
02088     const uint32_t id_last_event = 0xDEADDEAF;
02089 
02090     ticker_insert_event(&ticker_stub, &event, event_timestamp, id_last_event);
02091     TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);
02092     TEST_ASSERT_EQUAL(1, interface_stub.fire_interrupt_call);
02093 }
02094 
02095 /**
02096  * Convert ticks at a given frequency to time in microseconds
02097  *
02098  * Assert if there is a 64-bit overflow
02099  */
02100 static uint64_t convert_to_us(uint64_t ticks, uint32_t frequency)
02101 {
02102     uint64_t scaled_ticks = ticks * 1000000;
02103     // Assert that there was not an overflow
02104     TEST_ASSERT_EQUAL(ticks, scaled_ticks / 1000000);
02105     return scaled_ticks / frequency;
02106 }
02107 
02108 /**
02109  * Given an uninitialized ticker instance and an interface of a
02110  * certain frequency and bit width.
02111  * Then the time returned the ticker should match the cumulative time.
02112  */
02113 void test_frequencies_and_masks(uint32_t frequency, uint32_t bits)
02114 {
02115     const uint32_t bitmask = ((uint64_t)1 << bits) - 1;
02116 
02117     ticker_set_handler(&ticker_stub, NULL);
02118     uint64_t ticks = 0;
02119 
02120     // Single tick
02121     ticks += 1;
02122     interface_stub.timestamp = ticks & bitmask;
02123     TEST_ASSERT_EQUAL_UINT32(convert_to_us(ticks, frequency), ticker_read(&ticker_stub));
02124     TEST_ASSERT_EQUAL_UINT64(convert_to_us(ticks, frequency), ticker_read_us(&ticker_stub));
02125 
02126     // Run until the loop before 64-bit overflow (worst case with frequency=1hz, bits=32)
02127     for (unsigned int k = 0; k < 4294; k++) {
02128 
02129         // Largest value possible tick
02130         ticks += ((uint64_t)1 << bits) - 1;
02131         interface_stub.timestamp = ticks & bitmask;
02132         TEST_ASSERT_EQUAL_UINT32(convert_to_us(ticks, frequency), ticker_read(&ticker_stub));
02133         TEST_ASSERT_EQUAL_UINT64(convert_to_us(ticks, frequency), ticker_read_us(&ticker_stub));
02134     }
02135 }
02136 
02137 /**
02138  * Given an uninitialized ticker_data instance.
02139  * When the ticker is initialized
02140  * Then:
02141  *   - The internal ticker timestamp should be zero
02142  *   - interrupt should be scheduled in current (timestamp +
02143  *          TIMESTAMP_MAX_DELTA_BITS(bitwidth)) % modval
02144  *   - The queue should not contains any event
02145  */
02146 static void test_ticker_max_value()
02147 {
02148     for (int bitwidth = 8; bitwidth <= 32; bitwidth++) {
02149         const uint64_t modval = 1ULL << bitwidth;
02150 
02151         // setup of the stub
02152         reset_ticker_stub();
02153         interface_info_stub.bits = bitwidth;
02154         interface_stub.timestamp = 0xBA;
02155 
02156         ticker_set_handler(&ticker_stub, NULL);
02157 
02158         TEST_ASSERT_EQUAL_UINT64(0, queue_stub.present_time);
02159         TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);
02160         TEST_ASSERT_EQUAL_UINT32(
02161             (interface_stub.timestamp + TIMESTAMP_MAX_DELTA_BITS(bitwidth)) % modval,
02162             interface_stub.interrupt_timestamp
02163         );
02164         TEST_ASSERT_EQUAL_PTR(NULL, queue_stub.head);
02165         TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
02166     }
02167 }
02168 
02169 /**
02170  * Check that _ticker_match_interval_passed correctly detects matches
02171  *
02172  * Brute force test that _ticker_match_interval_passed returns the correct match value
02173  * for all cominations of values within a small range.
02174  */
02175 static void test_match_interval_passed()
02176 {
02177 
02178     for (int modval = 1; modval <= 5; modval++) {
02179         for (int prev = 0; prev < modval; prev++) {
02180             for (int cur = 0; cur < modval; cur++) {
02181                 for (int match = 0; match < modval; match++) {
02182                     uint32_t delta = (cur - prev) % modval;
02183                     uint32_t delta_to_match = (match - prev) % modval;
02184                     bool match_expected = false;
02185                     if (delta_to_match) {
02186                         match_expected = delta >= delta_to_match;
02187                     }
02188 
02189                     // Sanity checks
02190                     if (prev == cur) {
02191                         // No time has passed
02192                         TEST_ASSERT_EQUAL(false, match_expected);
02193                     } else if (match == prev) {
02194                         // Match can't occur without an overflow occurring
02195                         TEST_ASSERT_EQUAL(false, match_expected);
02196                     } else if (cur == match) {
02197                         // All other cases where cur == match a match should be expected
02198                         TEST_ASSERT_EQUAL(true, match_expected);
02199                     }
02200 
02201                     // Actual test
02202                     TEST_ASSERT_EQUAL(match_expected, _ticker_match_interval_passed(prev, cur, match));
02203                 }
02204             }
02205         }
02206     }
02207 }
02208 
02209 typedef struct  {
02210     timestamp_t prev;
02211     timestamp_t cur;
02212     timestamp_t match;
02213     bool result;
02214 } match_interval_entry_t;
02215 
02216 /**
02217  * Check that _ticker_match_interval_passed correctly detects matches
02218  *
02219  * Use a table of pre-computed values to check that _ticker_match_interval_passed
02220  * returns the correct match value.
02221  */
02222 static void test_match_interval_passed_table()
02223 {
02224     static const match_interval_entry_t test_values[] = {
02225           /* prev,       cur,        match,      result */
02226             {0x00000000, 0x00000000, 0x00000000, false},
02227             {0x00000000, 0x00000000, 0xffffffff, false},
02228             {0x00000000, 0x00000000, 0x00000001, false},
02229             {0x00000000, 0xffffffff, 0x00000000, false},
02230             {0x00000000, 0x00000001, 0x00000000, false},
02231             {0xffffffff, 0x00000000, 0x00000000, true},
02232             {0x00000001, 0x00000000, 0x00000000, true},
02233             {0x00005555, 0x00005555, 0x00005555, false},
02234             {0x00005555, 0x00005555, 0x00005554, false},
02235             {0x00005555, 0x00005555, 0x00005556, false},
02236             {0x00005555, 0x00005554, 0x00005555, false},
02237             {0x00005555, 0x00005556, 0x00005555, false},
02238             {0x00005554, 0x00005555, 0x00005555, true},
02239             {0x00005556, 0x00005555, 0x00005555, true},
02240             {0xffffffff, 0xffffffff, 0xffffffff, false},
02241             {0xffffffff, 0xffffffff, 0xfffffffe, false},
02242             {0xffffffff, 0xffffffff, 0x00000000, false},
02243             {0xffffffff, 0xfffffffe, 0xffffffff, false},
02244             {0xffffffff, 0x00000000, 0xffffffff, false},
02245             {0xfffffffe, 0xffffffff, 0xffffffff, true},
02246             {0x00000000, 0xffffffff, 0xffffffff, true},
02247     };
02248     for (int i = 0; i < MBED_ARRAY_SIZE(test_values); i++) {
02249         const uint32_t prev = test_values[i].prev;
02250         const uint32_t cur = test_values[i].cur;
02251         const uint32_t match = test_values[i].match;
02252         const uint32_t result = test_values[i].result;
02253         TEST_ASSERT_EQUAL(result, _ticker_match_interval_passed(prev, cur, match));
02254     }
02255 }
02256 
02257 static const case_t cases[] = {
02258     MAKE_TEST_CASE("ticker initialization", test_ticker_initialization),
02259     MAKE_TEST_CASE(
02260         "ticker multiple initialization",  test_ticker_re_initialization
02261     ),
02262     MAKE_TEST_CASE("ticker read", test_ticker_read),
02263     MAKE_TEST_CASE("ticker read overflow", test_ticker_read_overflow),
02264     MAKE_TEST_CASE(
02265         "legacy insert event outside overflow range", 
02266         test_legacy_insert_event_outside_overflow_range
02267     ),
02268     MAKE_TEST_CASE(
02269         "legacy insert event in overflow range", 
02270         test_legacy_insert_event_in_overflow_range
02271     ),
02272     MAKE_TEST_CASE(
02273         "legacy insert event overflow", test_legacy_insert_event_overflow
02274     ),
02275     MAKE_TEST_CASE(
02276         "legacy insert event head", test_legacy_insert_event_head
02277     ),
02278     MAKE_TEST_CASE(
02279         "legacy insert event tail", test_legacy_insert_event_tail
02280     ),
02281     MAKE_TEST_CASE(
02282         "legacy insert event multiple overflow", 
02283         test_legacy_insert_event_multiple_overflow
02284     ),
02285     MAKE_TEST_CASE(
02286         "test_legacy_insert_event_multiple_random", 
02287         test_legacy_insert_event_multiple_random
02288     ),
02289     MAKE_TEST_CASE(
02290         "test_insert_event_us_outside_overflow_range", 
02291         test_insert_event_us_outside_overflow_range
02292     ),
02293     MAKE_TEST_CASE(
02294         "test_insert_event_us_in_overflow_range", 
02295         test_insert_event_us_in_overflow_range
02296     ),
02297     MAKE_TEST_CASE(
02298         "test_insert_event_us_underflow", test_insert_event_us_underflow
02299     ),
02300     MAKE_TEST_CASE("test_insert_event_us_head", test_insert_event_us_head),
02301     MAKE_TEST_CASE("test_insert_event_us_tail", test_insert_event_us_tail),
02302     MAKE_TEST_CASE(
02303         "test_insert_event_us_multiple_random", 
02304         test_insert_event_us_multiple_random
02305     ),
02306     MAKE_TEST_CASE("test_remove_event_tail", test_remove_event_tail),
02307     MAKE_TEST_CASE("test_remove_event_head", test_remove_event_head),
02308     MAKE_TEST_CASE("test_remove_event_invalid", test_remove_event_invalid),
02309     MAKE_TEST_CASE("test_remove_random", test_remove_random),
02310     MAKE_TEST_CASE("update overflow guard", test_overflow_event_update),
02311     MAKE_TEST_CASE(
02312         "update overflow guard in case of spurious interrupt", 
02313         test_overflow_event_update_when_spurious_interrupt
02314     ),
02315     MAKE_TEST_CASE(
02316         "test_irq_handler_single_event", test_irq_handler_single_event
02317     ),
02318     MAKE_TEST_CASE(
02319         "test_irq_handler_single_event_spurious", 
02320         test_irq_handler_single_event_spurious
02321     ),
02322     MAKE_TEST_CASE(
02323         "test_irq_handler_multiple_event_multiple_dequeue", 
02324         test_irq_handler_multiple_event_multiple_dequeue
02325     ),
02326     MAKE_TEST_CASE(
02327         "test_irq_handler_multiple_event_single_dequeue_overflow", 
02328         test_irq_handler_multiple_event_single_dequeue_overflow
02329     ),
02330     MAKE_TEST_CASE(
02331         "test_irq_handler_multiple_event_single_dequeue", 
02332         test_irq_handler_multiple_event_single_dequeue
02333     ),
02334     MAKE_TEST_CASE(
02335         "test_irq_handler_insert_immediate_in_irq", 
02336         test_irq_handler_insert_immediate_in_irq
02337     ),
02338     MAKE_TEST_CASE(
02339         "test_irq_handler_insert_non_immediate_in_irq", 
02340         test_irq_handler_insert_non_immediate_in_irq
02341     ),
02342     MAKE_TEST_CASE(
02343         "test_set_interrupt_past_time", 
02344         test_set_interrupt_past_time
02345     ),
02346     MAKE_TEST_CASE(
02347         "test_set_interrupt_past_time_with_delay", 
02348         test_set_interrupt_past_time_with_delay
02349     ),
02350     MAKE_TEST_CASE(
02351         "test_frequencies_and_masks",
02352         test_over_frequency_and_width<test_frequencies_and_masks>
02353     ),
02354     MAKE_TEST_CASE(
02355         "test_ticker_max_value",
02356         test_ticker_max_value
02357     ),
02358     MAKE_TEST_CASE(
02359         "test_match_interval_passed",
02360         test_match_interval_passed
02361     ),
02362     MAKE_TEST_CASE(
02363         "test_match_interval_passed_table",
02364         test_match_interval_passed_table
02365     )
02366 };
02367 
02368 static utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
02369 {
02370     GREENTEA_SETUP(60, "default_auto");
02371     return verbose_test_setup_handler(number_of_cases);
02372 }
02373 
02374 int main()
02375 {
02376     Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
02377     return !Harness::run(specification);
02378 }