diff --git a/TESTS/mbed_hal/ticker/main.cpp b/TESTS/mbed_hal/ticker/main.cpp index a4964a17db..334a1ae404 100644 --- a/TESTS/mbed_hal/ticker/main.cpp +++ b/TESTS/mbed_hal/ticker/main.cpp @@ -42,6 +42,7 @@ struct ticker_interface_stub_t { unsigned int disable_interrupt_call; unsigned int clear_interrupt_call; unsigned int set_interrupt_call; + unsigned int fire_interrupt_call; }; static ticker_interface_stub_t interface_stub = { 0 }; @@ -75,6 +76,11 @@ static void ticker_interface_stub_set_interrupt(timestamp_t timestamp) interface_stub.interrupt_timestamp = timestamp; } +static void ticker_interface_stub_fire_interrupt() +{ + ++interface_stub.fire_interrupt_call; +} + static void reset_ticker_interface_stub() { interface_stub.interface.init = ticker_interface_stub_init; @@ -84,6 +90,7 @@ static void reset_ticker_interface_stub() interface_stub.interface.clear_interrupt = ticker_interface_stub_clear_interrupt; interface_stub.interface.set_interrupt =ticker_interface_stub_set_interrupt; + interface_stub.interface.fire_interrupt = ticker_interface_stub_fire_interrupt; interface_stub.initialized = false; interface_stub.interrupt_flag = false; interface_stub.timestamp = 0; @@ -93,6 +100,7 @@ static void reset_ticker_interface_stub() interface_stub.disable_interrupt_call = 0; interface_stub.clear_interrupt_call = 0; interface_stub.set_interrupt_call = 0; + interface_stub.fire_interrupt_call = 0; } // stub of the event queue @@ -949,11 +957,7 @@ static void test_insert_event_us_underflow() ); TEST_ASSERT_EQUAL_PTR(&event, queue_stub.head); - TEST_ASSERT_EQUAL_UINT32( - interface_stub.timestamp, - interface_stub.interrupt_timestamp - ); - TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call); + TEST_ASSERT_EQUAL(1, interface_stub.fire_interrupt_call); TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call); } @@ -1982,6 +1986,58 @@ static void test_irq_handler_insert_non_immediate_in_irq() TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call); } +static uint32_t ticker_interface_stub_read_interrupt_time() +{ + ++interface_stub.read_call; + // only if set interrupt call, to test the condition afterwards + if (interface_stub.set_interrupt_call) { + return interface_stub.interrupt_timestamp; + } else { + return interface_stub.timestamp; + } +} + +/** + * Test to insert an event that is already in the past, the fire_interrupt should + * be invoked, instead of set_interrupt + */ +static void test_set_interrupt_past_time() +{ + interface_stub.set_interrupt_call = 0; + interface_stub.fire_interrupt_call = 0; + interface_stub.timestamp = 0xFF; + + + // This tests fire now functinality when next_event_timestamp <= present + ticker_event_t event = { 0 }; + const timestamp_t event_timestamp = interface_stub.timestamp; + const uint32_t id_last_event = 0xDEADDEAF; + + ticker_insert_event(&ticker_stub, &event, event_timestamp, id_last_event); + TEST_ASSERT_EQUAL(0, interface_stub.set_interrupt_call); + TEST_ASSERT_EQUAL(1, interface_stub.fire_interrupt_call); +} +/** + * Test to insert an event that is being delayed, set_interrupt is set + * but then event is already in the past, thus fire_interrupt should be invoked right-away + */ +static void test_set_interrupt_past_time_with_delay() +{ + interface_stub.set_interrupt_call = 0; + interface_stub.fire_interrupt_call = 0; + interface_stub.timestamp = 0xFF; + + // This tests fire now functionality when present time >= new_match_time + interface_stub.interface.read = ticker_interface_stub_read_interrupt_time; + ticker_event_t event = { 0 }; + const timestamp_t event_timestamp = interface_stub.timestamp + 5; + const uint32_t id_last_event = 0xDEADDEAF; + + ticker_insert_event(&ticker_stub, &event, event_timestamp, id_last_event); + TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call); + TEST_ASSERT_EQUAL(1, interface_stub.fire_interrupt_call); +} + static const case_t cases[] = { MAKE_TEST_CASE("ticker initialization", test_ticker_initialization), MAKE_TEST_CASE( @@ -2066,6 +2122,14 @@ static const case_t cases[] = { MAKE_TEST_CASE( "test_irq_handler_insert_non_immediate_in_irq", test_irq_handler_insert_non_immediate_in_irq + ), + MAKE_TEST_CASE( + "test_set_interrupt_past_time", + test_set_interrupt_past_time + ), + MAKE_TEST_CASE( + "test_set_interrupt_past_time_with_delay", + test_set_interrupt_past_time_with_delay ) }; @@ -2079,4 +2143,4 @@ int main() { Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); return !Harness::run(specification); -} \ No newline at end of file +} diff --git a/hal/lp_ticker_api.h b/hal/lp_ticker_api.h index 58b91ba52c..73d8eb5a07 100644 --- a/hal/lp_ticker_api.h +++ b/hal/lp_ticker_api.h @@ -74,6 +74,12 @@ void lp_ticker_disable_interrupt(void); */ void lp_ticker_clear_interrupt(void); +/** Set pending interrupt that should be fired right away. + * + * The ticker should be initialized prior calling this function. + */ +void lp_ticker_fire_interrupt(void); + /**@}*/ #ifdef __cplusplus diff --git a/hal/mbed_lp_ticker_api.c b/hal/mbed_lp_ticker_api.c index 6a90b153f6..501f7f9487 100644 --- a/hal/mbed_lp_ticker_api.c +++ b/hal/mbed_lp_ticker_api.c @@ -25,6 +25,7 @@ static const ticker_interface_t lp_interface = { .disable_interrupt = lp_ticker_disable_interrupt, .clear_interrupt = lp_ticker_clear_interrupt, .set_interrupt = lp_ticker_set_interrupt, + .fire_interrupt = lp_ticker_fire_interrupt, }; static const ticker_data_t lp_data = { diff --git a/hal/mbed_ticker_api.c b/hal/mbed_ticker_api.c index 0eb52622fd..f4f8cfe7cc 100644 --- a/hal/mbed_ticker_api.c +++ b/hal/mbed_ticker_api.c @@ -117,14 +117,23 @@ static void schedule_interrupt(const ticker_data_t *const ticker) // if the event at the head of the queue is in the past then schedule // it immediately. - if (next_event_timestamp < present) { - relative_timeout = 0; + if (next_event_timestamp <= present) { + ticker->interface->fire_interrupt(); + return; } else if ((next_event_timestamp - present) < MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA) { relative_timeout = next_event_timestamp - present; } } - ticker->interface->set_interrupt(ticker->queue->present_time + relative_timeout); + us_timestamp_t new_match_time = ticker->queue->present_time + relative_timeout; + ticker->interface->set_interrupt(new_match_time); + // there could be a delay, reread the time, check if it was set in the past + // As result, if it is already in the past, we fire it immediately + update_present_time(ticker); + us_timestamp_t present = ticker->queue->present_time; + if (present >= new_match_time) { + ticker->interface->fire_interrupt(); + } } void ticker_set_handler(const ticker_data_t *const ticker, ticker_event_handler handler) diff --git a/hal/mbed_us_ticker_api.c b/hal/mbed_us_ticker_api.c index 2f2cf2cb25..fb1663a5d3 100644 --- a/hal/mbed_us_ticker_api.c +++ b/hal/mbed_us_ticker_api.c @@ -23,6 +23,7 @@ static const ticker_interface_t us_interface = { .disable_interrupt = us_ticker_disable_interrupt, .clear_interrupt = us_ticker_clear_interrupt, .set_interrupt = us_ticker_set_interrupt, + .fire_interrupt = us_ticker_fire_interrupt, }; static const ticker_data_t us_data = { diff --git a/hal/ticker_api.h b/hal/ticker_api.h index 36cb58f8e4..fceba2db87 100644 --- a/hal/ticker_api.h +++ b/hal/ticker_api.h @@ -60,6 +60,7 @@ typedef struct { void (*disable_interrupt)(void); /**< Disable interrupt function */ void (*clear_interrupt)(void); /**< Clear interrupt function */ void (*set_interrupt)(timestamp_t timestamp); /**< Set interrupt function */ + void (*fire_interrupt)(void); /**< Fire interrupt right-away */ } ticker_interface_t; /** Ticker's event queue structure diff --git a/hal/us_ticker_api.h b/hal/us_ticker_api.h index 82f556dd0b..b22fcc1d7b 100644 --- a/hal/us_ticker_api.h +++ b/hal/us_ticker_api.h @@ -72,6 +72,12 @@ void us_ticker_disable_interrupt(void); */ void us_ticker_clear_interrupt(void); +/** Set pending interrupt that should be fired right away. + * + * The ticker should be initialized prior calling this function. + */ +void us_ticker_fire_interrupt(void); + /**@}*/ #ifdef __cplusplus diff --git a/targets/TARGET_ARM_SSG/TARGET_BEETLE/lp_ticker.c b/targets/TARGET_ARM_SSG/TARGET_BEETLE/lp_ticker.c index 13fa7ae715..50d3039029 100644 --- a/targets/TARGET_ARM_SSG/TARGET_BEETLE/lp_ticker.c +++ b/targets/TARGET_ARM_SSG/TARGET_BEETLE/lp_ticker.c @@ -115,27 +115,24 @@ uint32_t lp_ticker_read(void) */ void lp_ticker_set_interrupt(timestamp_t timestamp) { - int32_t delta = 0; - /* Verify if lp_ticker has been not Initialized */ if (lp_ticker_initialized == 0) lp_ticker_init(); /* Calculate the delta */ - delta = (int32_t)(timestamp - lp_ticker_read()); - /* Check if the event was in the past */ - if (delta <= 0) { - /* This event was in the past */ - DualTimer_SetInterrupt_1(DUALTIMER0, 0, - DUALTIMER_COUNT_32 | DUALTIMER_ONESHOT); - return; - } + uint32_t delta = timestamp - lp_ticker_read(); /* Enable interrupt on SingleTimer1 */ DualTimer_SetInterrupt_1(DUALTIMER0, delta, DUALTIMER_COUNT_32 | DUALTIMER_ONESHOT); } +void lp_ticker_fire_interrupt(void) +{ + uint32_t lp_ticker_irqn = DualTimer_GetIRQn(DUALTIMER0); + NVIC_SetPendingIRQ((IRQn_Type)lp_ticker_irqn); +} + /** * Disable low power ticker interrupt */ diff --git a/targets/TARGET_ARM_SSG/TARGET_BEETLE/us_ticker.c b/targets/TARGET_ARM_SSG/TARGET_BEETLE/us_ticker.c index 809961f98d..68c51dbc24 100644 --- a/targets/TARGET_ARM_SSG/TARGET_BEETLE/us_ticker.c +++ b/targets/TARGET_ARM_SSG/TARGET_BEETLE/us_ticker.c @@ -91,22 +91,19 @@ uint32_t us_ticker_read() { } void us_ticker_set_interrupt(timestamp_t timestamp) { - int32_t delta = 0; - if (!us_ticker_inited) us_ticker_init(); - delta = (int32_t)(timestamp - us_ticker_read()); - /* Check if the event was in the past */ - if (delta <= 0) { - /* This event was in the past */ - Timer_SetInterrupt(TIMER0, 0); - return; - } - /* If the event was not in the past enable interrupt */ + uint32_t delta = timestamp - us_ticker_read(); Timer_SetInterrupt(TIMER0, delta); } +void us_ticker_fire_interrupt(void) +{ + uint32_t us_ticker_irqn1 = Timer_GetIRQn(TIMER1); + NVIC_SetPendingIRQ((IRQn_Type)us_ticker_irqn1); +} + void us_ticker_disable_interrupt(void) { Timer_DisableInterrupt(TIMER0); } diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/us_ticker.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/us_ticker.c index 156742567b..dffd8d3b2f 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/us_ticker.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/us_ticker.c @@ -108,22 +108,23 @@ uint32_t us_ticker_read() void us_ticker_set_interrupt(timestamp_t timestamp) { - int32_t delta = 0; + uint32_t delta = 0; if (!us_ticker_drv_data.inited) { us_ticker_init(); } - delta = (int32_t)(timestamp - us_ticker_read()); + delta = timestamp - us_ticker_read(); - /* Check if the event was in the past */ - if (delta <= 0) { - /* This event was in the past */ - Timer_SetInterrupt(TIMER0, 0); - } else { - /* If the event was not in the past enable interrupt */ - Timer_SetInterrupt(TIMER0, delta); - } + /* If the event was not in the past enable interrupt */ + Timer_SetInterrupt(TIMER0, delta); + +} + +void us_ticker_fire_interrupt(void) +{ + uint32_t us_ticker_irqn1 = Timer_GetIRQn(TIMER1); + NVIC_SetPendingIRQ((IRQn_Type)us_ticker_irqn1); } void us_ticker_disable_interrupt(void) diff --git a/targets/TARGET_ARM_SSG/TARGET_IOTSS/us_ticker.c b/targets/TARGET_ARM_SSG/TARGET_IOTSS/us_ticker.c index 4197d3eb39..3c933462c6 100644 --- a/targets/TARGET_ARM_SSG/TARGET_IOTSS/us_ticker.c +++ b/targets/TARGET_ARM_SSG/TARGET_IOTSS/us_ticker.c @@ -69,6 +69,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { US_TICKER_TIMER1->TimerControl |= 0x80; //enable timer } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +} + void us_ticker_disable_interrupt(void) { US_TICKER_TIMER1->TimerControl &= 0xDF; diff --git a/targets/TARGET_ARM_SSG/TARGET_MPS2/us_ticker.c b/targets/TARGET_ARM_SSG/TARGET_MPS2/us_ticker.c index 66fd616d8d..5adf19e39c 100644 --- a/targets/TARGET_ARM_SSG/TARGET_MPS2/us_ticker.c +++ b/targets/TARGET_ARM_SSG/TARGET_MPS2/us_ticker.c @@ -51,15 +51,10 @@ uint32_t return_value = 0; } void us_ticker_set_interrupt(timestamp_t timestamp) { -int delta = 0; if (!us_ticker_inited) us_ticker_init(); - delta = (int)(timestamp - us_ticker_read()); - if (delta <= 0) { - // This event was in the past: - us_ticker_irq_handler(); - return; - } + + uint32_t delta = timestamp - us_ticker_read(); // enable interrupt US_TICKER_TIMER1->TimerControl = 0x0; // disable timer US_TICKER_TIMER1->TimerControl = 0x62; // enable interrupt and set to 32 bit counter and set to periodic mode @@ -67,6 +62,12 @@ int delta = 0; US_TICKER_TIMER1->TimerControl |= 0x80; //enable timer } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +} + + void us_ticker_disable_interrupt(void) { US_TICKER_TIMER1->TimerControl &= 0xDF; diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM4/lp_ticker.c b/targets/TARGET_Atmel/TARGET_SAM_CortexM4/lp_ticker.c index b2d91f72c3..1524b90cb7 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM4/lp_ticker.c +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM4/lp_ticker.c @@ -86,15 +86,10 @@ uint32_t lp_ticker_read() void lp_ticker_set_interrupt(timestamp_t timestamp) { uint32_t cur_time; - int32_t delta; + uint32_t delta; cur_time = lp_ticker_read(); - delta = (int32_t)((uint32_t)timestamp - cur_time); - if (delta < 0) { - /* Event already occurred in past */ - lp_ticker_irq_handler(); - return; - } + delta = timestamp - cur_time; uint16_t interruptat=0; @@ -120,6 +115,11 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) tc_start(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2); } +void lp_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(TICKER_COUNTER_IRQn2); +} + void lp_ticker_disable_interrupt(void) { tc_stop(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2); diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM4/us_ticker.c b/targets/TARGET_Atmel/TARGET_SAM_CortexM4/us_ticker.c index 815299c37e..dad8e9dd6e 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM4/us_ticker.c +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM4/us_ticker.c @@ -170,6 +170,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) tc_start(TICKER_COUNTER_uS, TICKER_COUNTER_CHANNEL1); } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(TICKER_COUNTER_IRQn1); +} + void us_ticker_disable_interrupt(void) { tc_stop(TICKER_COUNTER_uS, TICKER_COUNTER_CHANNEL1); diff --git a/targets/TARGET_Freescale/TARGET_K20XX/TARGET_K20D50M/us_ticker.c b/targets/TARGET_Freescale/TARGET_K20XX/TARGET_K20D50M/us_ticker.c index cc2d9b29b8..4ea164b136 100644 --- a/targets/TARGET_Freescale/TARGET_K20XX/TARGET_K20D50M/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_K20XX/TARGET_K20D50M/us_ticker.c @@ -138,13 +138,7 @@ static void ticker_isr(void) { } void us_ticker_set_interrupt(timestamp_t timestamp) { - int delta = (int)((uint32_t)timestamp - us_ticker_read()); - if (delta <= 0) { - // This event was in the past: - us_ticker_irq_handler(); - return; - } - + uint32_t delta = timestamp - us_ticker_read(); //Calculate how much falls outside the 32-bit after multiplying with clk_mhz //We shift twice 16-bit to keep everything within the 32-bit variable us_ticker_int_counter = (uint32_t)(delta >> 16); @@ -159,3 +153,8 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { ticker_set(us_ticker_int_remainder); } } + +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(PIT_TICKER_IRQ); +} diff --git a/targets/TARGET_Freescale/TARGET_K20XX/TARGET_TEENSY3_1/us_ticker.c b/targets/TARGET_Freescale/TARGET_K20XX/TARGET_TEENSY3_1/us_ticker.c index a41d0bd7aa..143e1383fc 100644 --- a/targets/TARGET_Freescale/TARGET_K20XX/TARGET_TEENSY3_1/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_K20XX/TARGET_TEENSY3_1/us_ticker.c @@ -70,15 +70,14 @@ void us_ticker_clear_interrupt(void) { } void us_ticker_set_interrupt(timestamp_t timestamp) { - int delta = (int)((uint32_t)timestamp - us_ticker_read()); - if (delta <= 0) { - // This event was in the past: - us_ticker_irq_handler(); - return; - } - + uint32_t delta = timestamp - us_ticker_read(); PIT->CHANNEL[3].TCTRL = 0; PIT->CHANNEL[3].LDVAL = delta; PIT->CHANNEL[3].TCTRL = PIT_TCTRL_TIE_MASK | PIT_TCTRL_TEN_MASK | PIT_TCTRL_CHN_MASK; } + +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(PIT3_IRQn); +} diff --git a/targets/TARGET_Freescale/TARGET_KLXX/us_ticker.c b/targets/TARGET_Freescale/TARGET_KLXX/us_ticker.c index 8aee691985..96cb66f2fd 100644 --- a/targets/TARGET_Freescale/TARGET_KLXX/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_KLXX/us_ticker.c @@ -185,13 +185,7 @@ static void lptmr_isr(void) { } void us_ticker_set_interrupt(timestamp_t timestamp) { - int delta = (int)((uint32_t)timestamp - us_ticker_read()); - if (delta <= 0) { - // This event was in the past. Force it into the very near - // future instead. - delta = 1; - } - + uint32_t delta = timestamp - us_ticker_read(); us_ticker_int_counter = (uint32_t)(delta >> 16); us_ticker_int_remainder = (uint16_t)(0xFFFF & delta); if (us_ticker_int_counter > 0) { @@ -202,3 +196,13 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { us_ticker_int_remainder = 0; } } + +void us_ticker_fire_interrupt(void) +{ +#if defined(TARGET_KL43Z) + NVIC_SetPendingIRQ(LPTMR0_IRQn); +#else + NVIC_SetPendingIRQ(LPTimer_IRQn); + +#endif +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/us_ticker.c index fe485e9039..1be03651e4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/us_ticker.c @@ -73,16 +73,7 @@ void us_ticker_clear_interrupt(void) void us_ticker_set_interrupt(timestamp_t timestamp) { - int delta = (int)(timestamp - us_ticker_read()); - if (delta <= 0) { - // This event was in the past. - // Set the interrupt as pending, but don't process it here. - // This prevents a recurive loop under heavy load - // which can lead to a stack overflow. - NVIC_SetPendingIRQ(PIT3_IRQn); - return; - } - + uint32_t delta = timestamp - us_ticker_read(); PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta); @@ -90,3 +81,8 @@ void us_ticker_set_interrupt(timestamp_t timestamp) PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } + +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(PIT3_IRQn); +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/us_ticker.c index fe485e9039..1be03651e4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/us_ticker.c @@ -73,16 +73,7 @@ void us_ticker_clear_interrupt(void) void us_ticker_set_interrupt(timestamp_t timestamp) { - int delta = (int)(timestamp - us_ticker_read()); - if (delta <= 0) { - // This event was in the past. - // Set the interrupt as pending, but don't process it here. - // This prevents a recurive loop under heavy load - // which can lead to a stack overflow. - NVIC_SetPendingIRQ(PIT3_IRQn); - return; - } - + uint32_t delta = timestamp - us_ticker_read(); PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta); @@ -90,3 +81,8 @@ void us_ticker_set_interrupt(timestamp_t timestamp) PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } + +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(PIT3_IRQn); +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/us_ticker.c index 728ea8f448..6af039a5a3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/us_ticker.c @@ -82,18 +82,14 @@ void us_ticker_clear_interrupt(void) void us_ticker_set_interrupt(timestamp_t timestamp) { - int delta = (int)(timestamp - us_ticker_read()); - if (delta <= 0) { - // This event was in the past. - // Set the interrupt as pending, but don't process it here. - // This prevents a recurive loop under heavy load - // which can lead to a stack overflow. - NVIC_SetPendingIRQ(LPTMR0_IRQn); - return; - } - + uint32_t delta = timestamp - us_ticker_read(); LPTMR_StopTimer(LPTMR0); LPTMR_SetTimerPeriod(LPTMR0, (uint32_t)delta); LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); LPTMR_StartTimer(LPTMR0); } + +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(LPTMR0_IRQn); +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/us_ticker.c index 728ea8f448..6af039a5a3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/us_ticker.c @@ -82,18 +82,14 @@ void us_ticker_clear_interrupt(void) void us_ticker_set_interrupt(timestamp_t timestamp) { - int delta = (int)(timestamp - us_ticker_read()); - if (delta <= 0) { - // This event was in the past. - // Set the interrupt as pending, but don't process it here. - // This prevents a recurive loop under heavy load - // which can lead to a stack overflow. - NVIC_SetPendingIRQ(LPTMR0_IRQn); - return; - } - + uint32_t delta = timestamp - us_ticker_read(); LPTMR_StopTimer(LPTMR0); LPTMR_SetTimerPeriod(LPTMR0, (uint32_t)delta); LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); LPTMR_StartTimer(LPTMR0); } + +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(LPTMR0_IRQn); +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/us_ticker.c index 3bd89fe997..613483583e 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/us_ticker.c @@ -73,16 +73,7 @@ void us_ticker_clear_interrupt(void) void us_ticker_set_interrupt(timestamp_t timestamp) { - int delta = (int)(timestamp - us_ticker_read()); - if (delta <= 0) { - // This event was in the past. - // Set the interrupt as pending, but don't process it here. - // This prevents a recurive loop under heavy load - // which can lead to a stack overflow. - NVIC_SetPendingIRQ(PIT0_IRQn); - return; - } - + uint32_t delta = timestamp - us_ticker_read(); PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta); @@ -90,3 +81,9 @@ void us_ticker_set_interrupt(timestamp_t timestamp) PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } + +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(PIT0_IRQn); +} + diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/us_ticker.c index fe485e9039..1be03651e4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/us_ticker.c @@ -73,16 +73,7 @@ void us_ticker_clear_interrupt(void) void us_ticker_set_interrupt(timestamp_t timestamp) { - int delta = (int)(timestamp - us_ticker_read()); - if (delta <= 0) { - // This event was in the past. - // Set the interrupt as pending, but don't process it here. - // This prevents a recurive loop under heavy load - // which can lead to a stack overflow. - NVIC_SetPendingIRQ(PIT3_IRQn); - return; - } - + uint32_t delta = timestamp - us_ticker_read(); PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta); @@ -90,3 +81,8 @@ void us_ticker_set_interrupt(timestamp_t timestamp) PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } + +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(PIT3_IRQn); +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/us_ticker.c index 2a2138041c..b376ce0d26 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/us_ticker.c @@ -77,18 +77,14 @@ void us_ticker_clear_interrupt(void) { } void us_ticker_set_interrupt(timestamp_t timestamp) { - int delta = (int)(timestamp - us_ticker_read()); - if (delta <= 0) { - // This event was in the past. - // Set the interrupt as pending, but don't process it here. - // This prevents a recurive loop under heavy load - // which can lead to a stack overflow. - NVIC_SetPendingIRQ(LPTMR0_IRQn); - return; - } - + uint32_t delta = timestamp - us_ticker_read(); LPTMR_StopTimer(LPTMR0); LPTMR_SetTimerPeriod(LPTMR0, (uint32_t)delta); LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); LPTMR_StartTimer(LPTMR0); } + +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(LPTMR0_IRQn); +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/us_ticker.c index fe485e9039..1be03651e4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/us_ticker.c @@ -73,16 +73,7 @@ void us_ticker_clear_interrupt(void) void us_ticker_set_interrupt(timestamp_t timestamp) { - int delta = (int)(timestamp - us_ticker_read()); - if (delta <= 0) { - // This event was in the past. - // Set the interrupt as pending, but don't process it here. - // This prevents a recurive loop under heavy load - // which can lead to a stack overflow. - NVIC_SetPendingIRQ(PIT3_IRQn); - return; - } - + uint32_t delta = timestamp - us_ticker_read(); PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta); @@ -90,3 +81,8 @@ void us_ticker_set_interrupt(timestamp_t timestamp) PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } + +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(PIT3_IRQn); +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/us_ticker.c index 2c7d394587..9594b3dd48 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/us_ticker.c @@ -73,16 +73,7 @@ void us_ticker_clear_interrupt(void) void us_ticker_set_interrupt(timestamp_t timestamp) { - int delta = (int)(timestamp - us_ticker_read()); - if (delta <= 0) { - // This event was in the past. - // Set the interrupt as pending, but don't process it here. - // This prevents a recurive loop under heavy load - // which can lead to a stack overflow. - NVIC_SetPendingIRQ(PIT3_IRQn); - return; - } - + uint32_t delta = timestamp - us_ticker_read(); PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta); @@ -90,3 +81,8 @@ void us_ticker_set_interrupt(timestamp_t timestamp) PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } + +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(PIT3_IRQn); +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/us_ticker.c index fe485e9039..1be03651e4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/us_ticker.c @@ -73,16 +73,7 @@ void us_ticker_clear_interrupt(void) void us_ticker_set_interrupt(timestamp_t timestamp) { - int delta = (int)(timestamp - us_ticker_read()); - if (delta <= 0) { - // This event was in the past. - // Set the interrupt as pending, but don't process it here. - // This prevents a recurive loop under heavy load - // which can lead to a stack overflow. - NVIC_SetPendingIRQ(PIT3_IRQn); - return; - } - + uint32_t delta = timestamp - us_ticker_read(); PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta); @@ -90,3 +81,8 @@ void us_ticker_set_interrupt(timestamp_t timestamp) PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } + +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(PIT3_IRQn); +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/lp_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/lp_ticker.c index 312b81f1c5..18fc6e1dfe 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/lp_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/lp_ticker.c @@ -163,6 +163,11 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) } } +void lp_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(LPTMR0_IRQn); +} + /** Disable low power ticker interrupt * */ @@ -180,4 +185,5 @@ void lp_ticker_clear_interrupt(void) RTC->TAR = 0; /* Write clears the IRQ flag */ LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag); } + #endif /* DEVICE_LOWPOWERTIMER */ diff --git a/targets/TARGET_Maxim/TARGET_MAX32600/rtc_api.c b/targets/TARGET_Maxim/TARGET_MAX32600/rtc_api.c index ded6e9ec2a..67bd74ce3c 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32600/rtc_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32600/rtc_api.c @@ -229,6 +229,11 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) MXC_PWRSEQ->msk_flags &= ~MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0; } +void lp_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(RTC0_IRQn); +} + //****************************************************************************** inline void lp_ticker_disable_interrupt(void) { diff --git a/targets/TARGET_Maxim/TARGET_MAX32600/us_ticker.c b/targets/TARGET_Maxim/TARGET_MAX32600/us_ticker.c index 05381a43cf..f0ff494b2f 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32600/us_ticker.c +++ b/targets/TARGET_Maxim/TARGET_MAX32600/us_ticker.c @@ -234,6 +234,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) US_TIMER->ctrl |= MXC_F_TMR_CTRL_ENABLE0; // enable timer } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TIMER_IRQn); +} + //****************************************************************************** void us_ticker_disable_interrupt(void) { diff --git a/targets/TARGET_Maxim/TARGET_MAX32610/rtc_api.c b/targets/TARGET_Maxim/TARGET_MAX32610/rtc_api.c index ded6e9ec2a..67bd74ce3c 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32610/rtc_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32610/rtc_api.c @@ -229,6 +229,11 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) MXC_PWRSEQ->msk_flags &= ~MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0; } +void lp_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(RTC0_IRQn); +} + //****************************************************************************** inline void lp_ticker_disable_interrupt(void) { diff --git a/targets/TARGET_Maxim/TARGET_MAX32610/us_ticker.c b/targets/TARGET_Maxim/TARGET_MAX32610/us_ticker.c index 05381a43cf..f0ff494b2f 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32610/us_ticker.c +++ b/targets/TARGET_Maxim/TARGET_MAX32610/us_ticker.c @@ -234,6 +234,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) US_TIMER->ctrl |= MXC_F_TMR_CTRL_ENABLE0; // enable timer } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TIMER_IRQn); +} + //****************************************************************************** void us_ticker_disable_interrupt(void) { diff --git a/targets/TARGET_Maxim/TARGET_MAX32620/rtc_api.c b/targets/TARGET_Maxim/TARGET_MAX32620/rtc_api.c index bf50d87b7f..d4e15e567c 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32620/rtc_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32620/rtc_api.c @@ -281,6 +281,11 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) while(MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING); } +void lp_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(RTC0_IRQn); +} + //****************************************************************************** inline void lp_ticker_disable_interrupt(void) { diff --git a/targets/TARGET_Maxim/TARGET_MAX32620/us_ticker.c b/targets/TARGET_Maxim/TARGET_MAX32620/us_ticker.c index 3cd72785bf..e219e30d90 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32620/us_ticker.c +++ b/targets/TARGET_Maxim/TARGET_MAX32620/us_ticker.c @@ -265,6 +265,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) US_TIMER->ctrl |= MXC_F_TMR_CTRL_ENABLE0; // enable timer } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TIMER_IRQn); +} + //****************************************************************************** void us_ticker_disable_interrupt(void) { diff --git a/targets/TARGET_Maxim/TARGET_MAX32625/rtc_api.c b/targets/TARGET_Maxim/TARGET_MAX32625/rtc_api.c index 703ea7954c..4abb1a5abe 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32625/rtc_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32625/rtc_api.c @@ -234,6 +234,11 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING); } +void lp_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(RTC0_IRQn); +} + //****************************************************************************** inline void lp_ticker_disable_interrupt(void) { diff --git a/targets/TARGET_Maxim/TARGET_MAX32625/us_ticker.c b/targets/TARGET_Maxim/TARGET_MAX32625/us_ticker.c index 5da2417d89..8bd5f111c3 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32625/us_ticker.c +++ b/targets/TARGET_Maxim/TARGET_MAX32625/us_ticker.c @@ -228,6 +228,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) TMR32_Start(US_TIMER); } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TIMER_IRQn); +} + //****************************************************************************** void us_ticker_disable_interrupt(void) { diff --git a/targets/TARGET_Maxim/TARGET_MAX32630/rtc_api.c b/targets/TARGET_Maxim/TARGET_MAX32630/rtc_api.c index 703ea7954c..4abb1a5abe 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32630/rtc_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32630/rtc_api.c @@ -234,6 +234,11 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING); } +void lp_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(RTC0_IRQn); +} + //****************************************************************************** inline void lp_ticker_disable_interrupt(void) { diff --git a/targets/TARGET_Maxim/TARGET_MAX32630/us_ticker.c b/targets/TARGET_Maxim/TARGET_MAX32630/us_ticker.c index 5da2417d89..8bd5f111c3 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32630/us_ticker.c +++ b/targets/TARGET_Maxim/TARGET_MAX32630/us_ticker.c @@ -228,6 +228,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) TMR32_Start(US_TIMER); } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TIMER_IRQn); +} + //****************************************************************************** void us_ticker_disable_interrupt(void) { diff --git a/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/us_ticker.c b/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/us_ticker.c index 39fe4472b3..251ec50aa0 100644 --- a/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/us_ticker.c +++ b/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/us_ticker.c @@ -285,6 +285,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) } } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(RTC1_IRQn); +} + void us_ticker_disable_interrupt(void) { if (us_ticker_callbackPending) { diff --git a/targets/TARGET_NORDIC/TARGET_NRF5/lp_ticker.c b/targets/TARGET_NORDIC/TARGET_NRF5/lp_ticker.c index ae63c2a1e1..41f4b8ea2b 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5/lp_ticker.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5/lp_ticker.c @@ -35,6 +35,14 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) LP_TICKER_CC_CHANNEL, LP_TICKER_INT_MASK); } +void lp_ticker_fire_interrupt(void) +{ + uint32_t closest_safe_compare = common_rtc_32bit_ticks_get() + 2; + + nrf_rtc_cc_set(COMMON_RTC_INSTANCE, LP_TICKER_CC_CHANNEL, RTC_WRAP(closest_safe_compare)); + nrf_rtc_event_enable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK); +} + void lp_ticker_disable_interrupt(void) { nrf_rtc_event_disable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK); diff --git a/targets/TARGET_NORDIC/TARGET_NRF5/us_ticker.c b/targets/TARGET_NORDIC/TARGET_NRF5/us_ticker.c index f3964c6b73..97f1504162 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5/us_ticker.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5/us_ticker.c @@ -271,6 +271,14 @@ void us_ticker_set_interrupt(timestamp_t timestamp) US_TICKER_CC_CHANNEL, US_TICKER_INT_MASK); } +void us_ticker_fire_interrupt(void) +{ + uint32_t closest_safe_compare = common_rtc_32bit_ticks_get() + 2; + + nrf_rtc_cc_set(COMMON_RTC_INSTANCE, US_TICKER_CC_CHANNEL, RTC_WRAP(closest_safe_compare)); + nrf_rtc_event_enable(COMMON_RTC_INSTANCE, US_TICKER_INT_MASK); +} + void us_ticker_disable_interrupt(void) { nrf_rtc_event_disable(COMMON_RTC_INSTANCE, US_TICKER_INT_MASK); diff --git a/targets/TARGET_NUVOTON/TARGET_M451/lp_ticker.c b/targets/TARGET_NUVOTON/TARGET_M451/lp_ticker.c index cdfb07887b..ae0bde4453 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/lp_ticker.c +++ b/targets/TARGET_NUVOTON/TARGET_M451/lp_ticker.c @@ -145,31 +145,23 @@ timestamp_t lp_ticker_read() void lp_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now = lp_ticker_read(); + uint32_t delta = timestamp - lp_ticker_read(); wakeup_tick = timestamp; TIMER_Stop((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); + cd_major_minor_clks = (uint64_t) delta * US_PER_TICK * TMR3_CLK_PER_SEC / US_PER_SEC; + lp_ticker_arm_cd(); +} + +void lp_ticker_fire_interrupt(void) +{ + cd_major_minor_clks = cd_minor_clks = 0; /** - * FIXME: Scheduled alarm may go off incorrectly due to wrap around. - * Conditions in which delta is negative: - * 1. Wrap around - * 2. Newly scheduled alarm is behind now - */ - //int delta = (timestamp > now) ? (timestamp - now) : (uint32_t) ((uint64_t) timestamp + 0xFFFFFFFFu - now); - int delta = (int) (timestamp - now); - if (delta > 0) { - cd_major_minor_clks = (uint64_t) delta * US_PER_TICK * TMR3_CLK_PER_SEC / US_PER_SEC; - lp_ticker_arm_cd(); - } - else { - cd_major_minor_clks = cd_minor_clks = 0; - /** - * This event was in the past. Set the interrupt as pending, but don't process it here. - * This prevents a recurive loop under heavy load which can lead to a stack overflow. - */ - NVIC_SetPendingIRQ(timer3_modinit.irq_n); - } + * This event was in the past. Set the interrupt as pending, but don't process it here. + * This prevents a recurive loop under heavy load which can lead to a stack overflow. + */ + NVIC_SetPendingIRQ(timer3_modinit.irq_n); } void lp_ticker_disable_interrupt(void) diff --git a/targets/TARGET_NUVOTON/TARGET_M451/us_ticker.c b/targets/TARGET_NUVOTON/TARGET_M451/us_ticker.c index c82ea1364b..4c0676b864 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/us_ticker.c +++ b/targets/TARGET_NUVOTON/TARGET_M451/us_ticker.c @@ -150,19 +150,19 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { TIMER_Stop((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname)); - int delta = (int) (timestamp - us_ticker_read()); - if (delta > 0) { - cd_major_minor_us = delta * US_PER_TICK; - us_ticker_arm_cd(); - } - else { - cd_major_minor_us = cd_minor_us = 0; - /** - * This event was in the past. Set the interrupt as pending, but don't process it here. - * This prevents a recurive loop under heavy load which can lead to a stack overflow. - */ - NVIC_SetPendingIRQ(timer1hires_modinit.irq_n); - } + uint32_t delta = timestamp - us_ticker_read(); + cd_major_minor_us = delta * US_PER_TICK; + us_ticker_arm_cd(); +} + +void us_ticker_fire_interrupt(void) +{ + cd_major_minor_us = cd_minor_us = 0; + /** + * This event was in the past. Set the interrupt as pending, but don't process it here. + * This prevents a recurive loop under heavy load which can lead to a stack overflow. + */ + NVIC_SetPendingIRQ(timer1hires_modinit.irq_n); } static void tmr0_vec(void) diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/lp_ticker.c b/targets/TARGET_NUVOTON/TARGET_NUC472/lp_ticker.c index 232d230bcc..f5dc4a673a 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/lp_ticker.c +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/lp_ticker.c @@ -144,31 +144,23 @@ timestamp_t lp_ticker_read() void lp_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now = lp_ticker_read(); + uint32_t delta = timestamp - lp_ticker_read(); wakeup_tick = timestamp; TIMER_Stop((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); - + cd_major_minor_clks = (uint64_t) delta * US_PER_TICK * TMR3_CLK_PER_SEC / US_PER_SEC; + lp_ticker_arm_cd(); + +} + +void lp_ticker_fire_interrupt(void) +{ + cd_major_minor_clks = cd_minor_clks = 0; /** - * FIXME: Scheduled alarm may go off incorrectly due to wrap around. - * Conditions in which delta is negative: - * 1. Wrap around - * 2. Newly scheduled alarm is behind now - */ - //int delta = (timestamp > now) ? (timestamp - now) : (uint32_t) ((uint64_t) timestamp + 0xFFFFFFFFu - now); - int delta = (int) (timestamp - now); - if (delta > 0) { - cd_major_minor_clks = (uint64_t) delta * US_PER_TICK * TMR3_CLK_PER_SEC / US_PER_SEC; - lp_ticker_arm_cd(); - } - else { - cd_major_minor_clks = cd_minor_clks = 0; - /** - * This event was in the past. Set the interrupt as pending, but don't process it here. - * This prevents a recurive loop under heavy load which can lead to a stack overflow. - */ - NVIC_SetPendingIRQ(timer3_modinit.irq_n); - } + * This event was in the past. Set the interrupt as pending, but don't process it here. + * This prevents a recurive loop under heavy load which can lead to a stack overflow. + */ + NVIC_SetPendingIRQ(timer3_modinit.irq_n); } void lp_ticker_disable_interrupt(void) diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/us_ticker.c b/targets/TARGET_NUVOTON/TARGET_NUC472/us_ticker.c index c83164ab92..667422df69 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/us_ticker.c +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/us_ticker.c @@ -149,19 +149,15 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { TIMER_Stop((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname)); - int delta = (int) (timestamp - us_ticker_read()); - if (delta > 0) { - cd_major_minor_us = delta * US_PER_TICK; - us_ticker_arm_cd(); - } - else { - cd_major_minor_us = cd_minor_us = 0; - /** - * This event was in the past. Set the interrupt as pending, but don't process it here. - * This prevents a recurive loop under heavy load which can lead to a stack overflow. - */ - NVIC_SetPendingIRQ(timer1hires_modinit.irq_n); - } + uint32_t delta = timestamp - us_ticker_read(); + cd_major_minor_us = delta * US_PER_TICK; + us_ticker_arm_cd(); +} + +void us_ticker_fire_interrupt(void) +{ + cd_major_minor_us = cd_minor_us = 0; + NVIC_SetPendingIRQ(timer1hires_modinit.irq_n); } static void tmr0_vec(void) diff --git a/targets/TARGET_NXP/TARGET_LPC11U6X/us_ticker.c b/targets/TARGET_NXP/TARGET_LPC11U6X/us_ticker.c index a38df4d5ce..726386b3a0 100644 --- a/targets/TARGET_NXP/TARGET_LPC11U6X/us_ticker.c +++ b/targets/TARGET_NXP/TARGET_LPC11U6X/us_ticker.c @@ -53,6 +53,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { US_TICKER_TIMER->MCR |= 1; } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +} + void us_ticker_disable_interrupt(void) { US_TICKER_TIMER->MCR &= ~1; } diff --git a/targets/TARGET_NXP/TARGET_LPC11UXX/us_ticker.c b/targets/TARGET_NXP/TARGET_LPC11UXX/us_ticker.c index 059b272233..074b3edfbf 100644 --- a/targets/TARGET_NXP/TARGET_LPC11UXX/us_ticker.c +++ b/targets/TARGET_NXP/TARGET_LPC11UXX/us_ticker.c @@ -53,6 +53,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { US_TICKER_TIMER->MCR |= 1; } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +} + void us_ticker_disable_interrupt(void) { US_TICKER_TIMER->MCR &= ~1; } diff --git a/targets/TARGET_NXP/TARGET_LPC11XX_11CXX/us_ticker.c b/targets/TARGET_NXP/TARGET_LPC11XX_11CXX/us_ticker.c index 909263782b..a3fcf32ed5 100644 --- a/targets/TARGET_NXP/TARGET_LPC11XX_11CXX/us_ticker.c +++ b/targets/TARGET_NXP/TARGET_LPC11XX_11CXX/us_ticker.c @@ -53,6 +53,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { US_TICKER_TIMER->MCR |= 1; } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +} + void us_ticker_disable_interrupt(void) { US_TICKER_TIMER->MCR &= ~1; } diff --git a/targets/TARGET_NXP/TARGET_LPC13XX/us_ticker.c b/targets/TARGET_NXP/TARGET_LPC13XX/us_ticker.c index d77495d03c..dd321198a6 100644 --- a/targets/TARGET_NXP/TARGET_LPC13XX/us_ticker.c +++ b/targets/TARGET_NXP/TARGET_LPC13XX/us_ticker.c @@ -53,6 +53,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { US_TICKER_TIMER->MCR |= 1; } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +} + void us_ticker_disable_interrupt(void) { US_TICKER_TIMER->MCR &= ~1; } diff --git a/targets/TARGET_NXP/TARGET_LPC15XX/us_ticker.c b/targets/TARGET_NXP/TARGET_LPC15XX/us_ticker.c index 8d049ffb78..120a559346 100644 --- a/targets/TARGET_NXP/TARGET_LPC15XX/us_ticker.c +++ b/targets/TARGET_NXP/TARGET_LPC15XX/us_ticker.c @@ -72,6 +72,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { LPC_SCT3->EVEN = (1 << 0); } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +} + void us_ticker_disable_interrupt(void) { // Disable interrupt on SCT3 event 0 LPC_SCT3->EVEN = 0; diff --git a/targets/TARGET_NXP/TARGET_LPC176X/us_ticker.c b/targets/TARGET_NXP/TARGET_LPC176X/us_ticker.c index b46d75e6bc..5b79d4223c 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/us_ticker.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/us_ticker.c @@ -55,6 +55,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { US_TICKER_TIMER->MCR |= 1; } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +} + void us_ticker_disable_interrupt(void) { US_TICKER_TIMER->MCR &= ~1; } diff --git a/targets/TARGET_NXP/TARGET_LPC408X/us_ticker.c b/targets/TARGET_NXP/TARGET_LPC408X/us_ticker.c index c7075b3c88..e9bd036ff1 100644 --- a/targets/TARGET_NXP/TARGET_LPC408X/us_ticker.c +++ b/targets/TARGET_NXP/TARGET_LPC408X/us_ticker.c @@ -55,6 +55,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { US_TICKER_TIMER->MCR |= 1; } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +} + void us_ticker_disable_interrupt(void) { US_TICKER_TIMER->MCR &= ~1; } diff --git a/targets/TARGET_NXP/TARGET_LPC43XX/us_ticker.c b/targets/TARGET_NXP/TARGET_LPC43XX/us_ticker.c index 417bc4ebe1..f509324fa3 100644 --- a/targets/TARGET_NXP/TARGET_LPC43XX/us_ticker.c +++ b/targets/TARGET_NXP/TARGET_LPC43XX/us_ticker.c @@ -55,6 +55,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { US_TICKER_TIMER->MCR |= 1; } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +} + void us_ticker_disable_interrupt(void) { US_TICKER_TIMER->MCR &= ~1; } diff --git a/targets/TARGET_NXP/TARGET_LPC81X/us_ticker.c b/targets/TARGET_NXP/TARGET_LPC81X/us_ticker.c index 0330fdc728..075505fc46 100644 --- a/targets/TARGET_NXP/TARGET_LPC81X/us_ticker.c +++ b/targets/TARGET_NXP/TARGET_LPC81X/us_ticker.c @@ -110,6 +110,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { LPC_MRT->CTRL1 |= 1; } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +} + //Disable Timestamped interrupts triggered by TIMER1 void us_ticker_disable_interrupt() { //Timer1 for Timestamped interrupts (31 bits downcounter @ SystemCoreClock) diff --git a/targets/TARGET_NXP/TARGET_LPC82X/us_ticker.c b/targets/TARGET_NXP/TARGET_LPC82X/us_ticker.c index dfb8debe52..4c44168291 100644 --- a/targets/TARGET_NXP/TARGET_LPC82X/us_ticker.c +++ b/targets/TARGET_NXP/TARGET_LPC82X/us_ticker.c @@ -86,6 +86,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { LPC_MRT->CTRL1 |= 1; } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +} + //Disable Timestamped interrupts triggered by TIMER1 void us_ticker_disable_interrupt() { //Timer1 for Timestamped interrupts (31 bits downcounter @ SystemCoreClock) diff --git a/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_lp_ticker_api.c b/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_lp_ticker_api.c index 324dbb32f3..fec4c07246 100644 --- a/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_lp_ticker_api.c +++ b/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_lp_ticker_api.c @@ -58,6 +58,11 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) fRtcSetInterrupt(timestamp); } +void lp_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(Rtc_IRQn); +} + /** Disable low power ticker interrupt * */ diff --git a/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_us_ticker_api.c b/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_us_ticker_api.c index d47e2e87d5..75fa1b398b 100644 --- a/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_us_ticker_api.c +++ b/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_us_ticker_api.c @@ -128,6 +128,11 @@ uint32_t us_ticker_read() return retval; } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(Tim0_IRQn); +} + /******************************************************************************* * Event Timer * diff --git a/targets/TARGET_ONSEMI/TARGET_NCS36510/rtc.c b/targets/TARGET_ONSEMI/TARGET_NCS36510/rtc.c index f8cef1cfbd..de035dc3fa 100644 --- a/targets/TARGET_ONSEMI/TARGET_NCS36510/rtc.c +++ b/targets/TARGET_ONSEMI/TARGET_NCS36510/rtc.c @@ -125,17 +125,6 @@ void fRtcSetInterrupt(uint32_t timestamp) { uint64_t current_time = fRtcRead(); - /* compute delta between current time and timestamp. - * Note: the current time used to compute the delta is relative (truncated - * to 32 bits). - */ - int32_t delta = timestamp - (uint32_t) current_time; - if (delta <= 0) { - // event considered in the past, set the interrupt as pending. - NVIC_SetPendingIRQ(Rtc_IRQn); - return; - } - uint64_t full_timestamp = (current_time & ~UINT32_MAX) | timestamp; if ( (uint32_t)current_time > timestamp) { full_timestamp += ((uint64_t) UINT32_MAX) + 1; diff --git a/targets/TARGET_RENESAS/TARGET_RZ_A1H/us_ticker.c b/targets/TARGET_RENESAS/TARGET_RZ_A1H/us_ticker.c index 10ffe2a62c..7bd1ab24cc 100644 --- a/targets/TARGET_RENESAS/TARGET_RZ_A1H/us_ticker.c +++ b/targets/TARGET_RENESAS/TARGET_RZ_A1H/us_ticker.c @@ -144,6 +144,10 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { GIC_EnableIRQ(US_TICKER_TIMER_IRQn); } +void us_ticker_fire_interrupt(void) { + GIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +} + void us_ticker_disable_interrupt(void) { GIC_DisableIRQ(US_TICKER_TIMER_IRQn); } diff --git a/targets/TARGET_RENESAS/TARGET_VK_RZ_A1H/us_ticker.c b/targets/TARGET_RENESAS/TARGET_VK_RZ_A1H/us_ticker.c index 060f5e03f5..6bcaea41d6 100644 --- a/targets/TARGET_RENESAS/TARGET_VK_RZ_A1H/us_ticker.c +++ b/targets/TARGET_RENESAS/TARGET_VK_RZ_A1H/us_ticker.c @@ -130,6 +130,10 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { GIC_EnableIRQ(US_TICKER_TIMER_IRQn); } +void us_ticker_fire_interrupt(void) { + GIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +} + void us_ticker_disable_interrupt(void) { GIC_DisableIRQ(US_TICKER_TIMER_IRQn); } diff --git a/targets/TARGET_Realtek/TARGET_AMEBA/us_ticker.c b/targets/TARGET_Realtek/TARGET_AMEBA/us_ticker.c index 060ffccfb8..0efdca5d45 100644 --- a/targets/TARGET_Realtek/TARGET_AMEBA/us_ticker.c +++ b/targets/TARGET_Realtek/TARGET_AMEBA/us_ticker.c @@ -97,6 +97,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(TIMER2_7_IRQ); +} + void us_ticker_disable_interrupt(void) { HalTimerOp.HalTimerDis((u32)TimerAdapter.TimerId); diff --git a/targets/TARGET_STM/lp_ticker.c b/targets/TARGET_STM/lp_ticker.c index c123793247..689833ffcd 100644 --- a/targets/TARGET_STM/lp_ticker.c +++ b/targets/TARGET_STM/lp_ticker.c @@ -70,6 +70,11 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) rtc_set_wake_up_timer(delta); } +void lp_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(RTC_WKUP_IRQn); +} + void lp_ticker_disable_interrupt(void) { rtc_deactivate_wake_up_timer(); diff --git a/targets/TARGET_STM/us_ticker_16b.c b/targets/TARGET_STM/us_ticker_16b.c index cea80ff99b..7b703555fc 100644 --- a/targets/TARGET_STM/us_ticker_16b.c +++ b/targets/TARGET_STM/us_ticker_16b.c @@ -81,109 +81,105 @@ void us_ticker_set_interrupt(timestamp_t timestamp) // Enable IT __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC1); - int current_time = us_ticker_read(); - int delta = (int)(timestamp - current_time); - - if (delta <= 0) { // This event was in the past - /* Immediately set the compare event to cause the event to be handled in - * the next interrupt context. This prevents calling interrupt handlers - * recursively as us_ticker_set_interrupt might be called again from the - * application handler + /* Set the number of timer wrap-around loops before the actual timestamp + * is reached. If the calculated delta time is more than halfway to the + * next compare event, check to see if a compare event has already been + * set, and if so, add one to the wrap-around count. This is done to + * ensure the correct wrap count is used in the corner cases where the + * 16 bit counter passes the compare value during the process of + * configuring this interrupt. + * + * Assumption: The time to execute this function is less than 32ms + * (otherwise incorrect behaviour could result) + * + * Consider the following corner cases: + * 1) timestamp is 1 us in the future: + * oc_int_part = 0 initially + * oc_int_part left at 0 because ((delta - 1) & 0xFFFF) < 0x8000 + * Compare event should happen in 1 us and us_ticker_irq_handler() + * called + * 2) timestamp is 0x8000 us in the future: + * oc_int_part = 0 initially + * oc_int_part left at 0 because ((delta - 1) & 0xFFFF) < 0x8000 + * There should be no possibility of the CC1 flag being set yet + * (see assumption above). When the compare event does occur in + * 32768 us, us_ticker_irq_handler() will be called + * 3) timestamp is 0x8001 us in the future: + * oc_int_part = 0 initially + * ((delta - 1) & 0xFFFF) >= 0x8000 but there should be no + * possibility of the CC1 flag being set yet (see assumption above), + * so oc_int_part will be left at 0, and when the compare event + * does occur in 32769 us, us_ticker_irq_handler() will be called + * 4) timestamp is 0x10000 us in the future: + * oc_int_part = 0 initially + * ((delta - 1) & 0xFFFF) >= 0x8000 + * There are two subcases: + * a) The timer counter has not incremented past the compare + * value while setting up the interrupt. In this case, the + * CC1 flag will not be set, so oc_int_part will be + * left at 0, and when the compare event occurs in 65536 us, + * us_ticker_irq_handler() will be called + * b) The timer counter has JUST incremented past the compare + * value. In this case, the CC1 flag will be set, so + * oc_int_part will be incremented to 1, and the interrupt will + * occur immediately after this function returns, where + * oc_int_part will decrement to 0 without calling + * us_ticker_irq_handler(). Then about 65536 us later, the + * compare event will occur again, and us_ticker_irq_handler() + * will be called + * 5) timestamp is 0x10001 us in the future: + * oc_int_part = 1 initially + * oc_int_part left at 1 because ((delta - 1) & 0xFFFF) < 0x8000 + * CC1 flag will not be set (see assumption above). In 1 us the + * compare event will cause an interrupt, where oc_int_part will be + * decremented to 0 without calling us_ticker_irq_handler(). Then + * about 65536 us later, the compare event will occur again, and + * us_ticker_irq_handler() will be called + * 6) timestamp is 0x18000 us in the future: + * oc_int_part = 1 initially + * oc_int_part left at 1 because ((delta - 1) & 0xFFFF) < 0x8000 + * There should be no possibility of the CC1 flag being set yet + * (see assumption above). When the compare event does occur in + * 32768 us, oc_int_part will be decremented to 0 without calling + * us_ticker_irq_handler(). Then about 65536 us later, the + * compare event will occur again, and us_ticker_irq_handler() will + * be called + * 7) timestamp is 0x18001 us in the future: + * oc_int_part = 1 initially + * ((delta - 1) & 0xFFFF) >= 0x8000 but there should be no + * possibility of the CC1 flag being set yet (see assumption above), + * so oc_int_part will be left at 1, and when the compare event + * does occur in 32769 us, oc_int_part will be decremented to 0 + * without calling us_ticker_irq_handler(). Then about 65536 us + * later, the compare event will occur again, and + * us_ticker_irq_handler() will be called + * + * delta - 1 is used because the timer compare event happens on the + * counter incrementing to match the compare value, and it won't occur + * immediately when the compare value is set to the current counter + * value. + */ + uint32_t current_time = us_ticker_read(); + uint32_t delta = timestamp - current_time; + oc_int_part = (delta - 1) >> 16; + if ( ((delta - 1) & 0xFFFF) >= 0x8000 && + __HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1) == SET ) { + ++oc_int_part; + /* NOTE: Instead of incrementing oc_int_part here, we could clear + * the CC1 flag, but then you'd have to wait to ensure the + * interrupt is knocked down before returning and reenabling + * interrupts. Since this is a rare case, it's not worth it + * to try and optimize it, and it keeps the code simpler and + * safer to just do this increment instead. */ - oc_int_part = 0; - HAL_TIM_GenerateEvent(&TimMasterHandle, TIM_EVENTSOURCE_CC1); - } else { - /* Set the number of timer wrap-around loops before the actual timestamp - * is reached. If the calculated delta time is more than halfway to the - * next compare event, check to see if a compare event has already been - * set, and if so, add one to the wrap-around count. This is done to - * ensure the correct wrap count is used in the corner cases where the - * 16 bit counter passes the compare value during the process of - * configuring this interrupt. - * - * Assumption: The time to execute this function is less than 32ms - * (otherwise incorrect behaviour could result) - * - * Consider the following corner cases: - * 1) timestamp is 1 us in the future: - * oc_int_part = 0 initially - * oc_int_part left at 0 because ((delta - 1) & 0xFFFF) < 0x8000 - * Compare event should happen in 1 us and us_ticker_irq_handler() - * called - * 2) timestamp is 0x8000 us in the future: - * oc_int_part = 0 initially - * oc_int_part left at 0 because ((delta - 1) & 0xFFFF) < 0x8000 - * There should be no possibility of the CC1 flag being set yet - * (see assumption above). When the compare event does occur in - * 32768 us, us_ticker_irq_handler() will be called - * 3) timestamp is 0x8001 us in the future: - * oc_int_part = 0 initially - * ((delta - 1) & 0xFFFF) >= 0x8000 but there should be no - * possibility of the CC1 flag being set yet (see assumption above), - * so oc_int_part will be left at 0, and when the compare event - * does occur in 32769 us, us_ticker_irq_handler() will be called - * 4) timestamp is 0x10000 us in the future: - * oc_int_part = 0 initially - * ((delta - 1) & 0xFFFF) >= 0x8000 - * There are two subcases: - * a) The timer counter has not incremented past the compare - * value while setting up the interrupt. In this case, the - * CC1 flag will not be set, so oc_int_part will be - * left at 0, and when the compare event occurs in 65536 us, - * us_ticker_irq_handler() will be called - * b) The timer counter has JUST incremented past the compare - * value. In this case, the CC1 flag will be set, so - * oc_int_part will be incremented to 1, and the interrupt will - * occur immediately after this function returns, where - * oc_int_part will decrement to 0 without calling - * us_ticker_irq_handler(). Then about 65536 us later, the - * compare event will occur again, and us_ticker_irq_handler() - * will be called - * 5) timestamp is 0x10001 us in the future: - * oc_int_part = 1 initially - * oc_int_part left at 1 because ((delta - 1) & 0xFFFF) < 0x8000 - * CC1 flag will not be set (see assumption above). In 1 us the - * compare event will cause an interrupt, where oc_int_part will be - * decremented to 0 without calling us_ticker_irq_handler(). Then - * about 65536 us later, the compare event will occur again, and - * us_ticker_irq_handler() will be called - * 6) timestamp is 0x18000 us in the future: - * oc_int_part = 1 initially - * oc_int_part left at 1 because ((delta - 1) & 0xFFFF) < 0x8000 - * There should be no possibility of the CC1 flag being set yet - * (see assumption above). When the compare event does occur in - * 32768 us, oc_int_part will be decremented to 0 without calling - * us_ticker_irq_handler(). Then about 65536 us later, the - * compare event will occur again, and us_ticker_irq_handler() will - * be called - * 7) timestamp is 0x18001 us in the future: - * oc_int_part = 1 initially - * ((delta - 1) & 0xFFFF) >= 0x8000 but there should be no - * possibility of the CC1 flag being set yet (see assumption above), - * so oc_int_part will be left at 1, and when the compare event - * does occur in 32769 us, oc_int_part will be decremented to 0 - * without calling us_ticker_irq_handler(). Then about 65536 us - * later, the compare event will occur again, and - * us_ticker_irq_handler() will be called - * - * delta - 1 is used because the timer compare event happens on the - * counter incrementing to match the compare value, and it won't occur - * immediately when the compare value is set to the current counter - * value. - */ - oc_int_part = ((uint32_t)delta - 1) >> 16; - if ( ((delta - 1) & 0xFFFF) >= 0x8000 && - __HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1) == SET ) { - ++oc_int_part; - /* NOTE: Instead of incrementing oc_int_part here, we could clear - * the CC1 flag, but then you'd have to wait to ensure the - * interrupt is knocked down before returning and reenabling - * interrupts. Since this is a rare case, it's not worth it - * to try and optimize it, and it keeps the code simpler and - * safer to just do this increment instead. - */ - } } + +} + +void us_ticker_fire_interrupt(void) +{ + TimMasterHandle.Instance = TIM_MST; + HAL_TIM_GenerateEvent(&TimMasterHandle, TIM_EVENTSOURCE_CC1); } void us_ticker_disable_interrupt(void) diff --git a/targets/TARGET_STM/us_ticker_32b.c b/targets/TARGET_STM/us_ticker_32b.c index f00705234a..c157c2f04b 100644 --- a/targets/TARGET_STM/us_ticker_32b.c +++ b/targets/TARGET_STM/us_ticker_32b.c @@ -48,14 +48,15 @@ void us_ticker_set_interrupt(timestamp_t timestamp) __HAL_TIM_DISABLE_IT(&TimMasterHandle, TIM_IT_CC1); // Set new output compare value __HAL_TIM_SET_COMPARE(&TimMasterHandle, TIM_CHANNEL_1, (uint32_t)timestamp); - // Check if timestamp has already passed, and if so, set the event immediately - if ((int32_t)(timestamp - TIM_MST->CNT) <= 0) { - LL_TIM_GenerateEvent_CC1(TimMasterHandle.Instance); - } // Enable IT __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC1); } +void us_ticker_fire_interrupt(void) +{ + LL_TIM_GenerateEvent_CC1(TimMasterHandle.Instance); +} + void us_ticker_disable_interrupt(void) { TimMasterHandle.Instance = TIM_MST; diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c index 1af40902a4..684ed188c9 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c @@ -92,6 +92,11 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) RTC_FreezeEnable(false); } +void lp_ticker_fire_interrupt(void) +{ + RTC_IntSet(RTC_IFS_COMP0); +} + inline void lp_ticker_disable_interrupt() { RTC_IntDisable(RTC_IF_COMP0); @@ -160,6 +165,11 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) RTCC_IntEnable(RTCC_IF_CC0); } +void lp_ticker_fire_interrupt(void) +{ + RTCC_IntSet(RTCC_IFS_CC0); +} + inline void lp_ticker_disable_interrupt() { RTCC_IntDisable(RTCC_IF_CC0); diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/us_ticker.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/us_ticker.c index 33f055324d..514d7ba6b5 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/us_ticker.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/us_ticker.c @@ -211,6 +211,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) TIMER_IntEnable(US_TICKER_TIMER, TIMER_IEN_CC0); } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQ); +} + void us_ticker_disable_interrupt(void) { if((US_TICKER_TIMER->IEN & TIMER_IEN_CC0) != 0) { diff --git a/targets/TARGET_WIZNET/TARGET_W7500x/us_ticker.c b/targets/TARGET_WIZNET/TARGET_W7500x/us_ticker.c index cd4e3071c6..a479a58cb9 100644 --- a/targets/TARGET_WIZNET/TARGET_W7500x/us_ticker.c +++ b/targets/TARGET_WIZNET/TARGET_W7500x/us_ticker.c @@ -96,12 +96,6 @@ void us_ticker_set_interrupt(timestamp_t timestamp) dev = (int32_t)(timestamp - us_ticker_read()); dev = dev * ((GetSystemClock() / 1000000) / 16); - if(dev <= 0) - { - us_ticker_irq_handler(); - return; - } - DUALTIMER_ClockEnable(TIMER_0); DUALTIMER_Stop(TIMER_0); @@ -123,6 +117,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) } +void us_ticker_fire_interrupt(void) +{ + NVIC_SetPendingIRQ(TIMER_IRQn); +} + void us_ticker_disable_interrupt(void) { NVIC_DisableIRQ(TIMER_IRQn); diff --git a/targets/TARGET_ublox/TARGET_HI2110/lp_ticker.c b/targets/TARGET_ublox/TARGET_HI2110/lp_ticker.c index 4ac5763fb3..1aa98ab220 100644 --- a/targets/TARGET_ublox/TARGET_HI2110/lp_ticker.c +++ b/targets/TARGET_ublox/TARGET_HI2110/lp_ticker.c @@ -323,6 +323,14 @@ void lp_ticker_set_interrupt(timestamp_t time) core_util_critical_section_exit(); } +void lp_ticker_fire_interrupt(void) +{ + // user interrupt only set, this will invoke from ISR routine directly lp handler + g_user_interrupt_pending = false; + g_user_interrupt_set = true; + NVIC_SetPendingIRQ(RTC_IRQn); +} + void lp_ticker_disable_interrupt(void) { /* Can't disable interrupts as we need them to manage diff --git a/targets/TARGET_ublox/TARGET_HI2110/us_ticker.c b/targets/TARGET_ublox/TARGET_HI2110/us_ticker.c index 053045c2b5..86decef269 100644 --- a/targets/TARGET_ublox/TARGET_HI2110/us_ticker.c +++ b/targets/TARGET_ublox/TARGET_HI2110/us_ticker.c @@ -226,6 +226,12 @@ void us_ticker_set_interrupt(timestamp_t timestamp) core_util_critical_section_exit(); } +void us_ticker_fire_interrupt(void) +{ + g_user_interrupt = true; + NVIC_SetPendingIRQ(Timer_IRQn); +} + void us_ticker_disable_interrupt(void) { /* Can't actually disable the interrupt here