Skip to content

Commit adfed0f

Browse files
Merge pull request #4644 from 0xc0170/fix_ticker_delta_negative
Ticker: add fire interrupt now function
2 parents 6593d5b + 56cb158 commit adfed0f

File tree

69 files changed

+569
-363
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+569
-363
lines changed

TESTS/mbed_hal/ticker/main.cpp

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct ticker_interface_stub_t {
4242
unsigned int disable_interrupt_call;
4343
unsigned int clear_interrupt_call;
4444
unsigned int set_interrupt_call;
45+
unsigned int fire_interrupt_call;
4546
};
4647

4748
static ticker_interface_stub_t interface_stub = { 0 };
@@ -75,6 +76,11 @@ static void ticker_interface_stub_set_interrupt(timestamp_t timestamp)
7576
interface_stub.interrupt_timestamp = timestamp;
7677
}
7778

79+
static void ticker_interface_stub_fire_interrupt()
80+
{
81+
++interface_stub.fire_interrupt_call;
82+
}
83+
7884
static void reset_ticker_interface_stub()
7985
{
8086
interface_stub.interface.init = ticker_interface_stub_init;
@@ -84,6 +90,7 @@ static void reset_ticker_interface_stub()
8490
interface_stub.interface.clear_interrupt =
8591
ticker_interface_stub_clear_interrupt;
8692
interface_stub.interface.set_interrupt =ticker_interface_stub_set_interrupt;
93+
interface_stub.interface.fire_interrupt = ticker_interface_stub_fire_interrupt;
8794
interface_stub.initialized = false;
8895
interface_stub.interrupt_flag = false;
8996
interface_stub.timestamp = 0;
@@ -93,6 +100,7 @@ static void reset_ticker_interface_stub()
93100
interface_stub.disable_interrupt_call = 0;
94101
interface_stub.clear_interrupt_call = 0;
95102
interface_stub.set_interrupt_call = 0;
103+
interface_stub.fire_interrupt_call = 0;
96104
}
97105

98106
// stub of the event queue
@@ -949,11 +957,7 @@ static void test_insert_event_us_underflow()
949957
);
950958

951959
TEST_ASSERT_EQUAL_PTR(&event, queue_stub.head);
952-
TEST_ASSERT_EQUAL_UINT32(
953-
interface_stub.timestamp,
954-
interface_stub.interrupt_timestamp
955-
);
956-
TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);
960+
TEST_ASSERT_EQUAL(1, interface_stub.fire_interrupt_call);
957961

958962
TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
959963
}
@@ -1982,6 +1986,58 @@ static void test_irq_handler_insert_non_immediate_in_irq()
19821986
TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
19831987
}
19841988

1989+
static uint32_t ticker_interface_stub_read_interrupt_time()
1990+
{
1991+
++interface_stub.read_call;
1992+
// only if set interrupt call, to test the condition afterwards
1993+
if (interface_stub.set_interrupt_call) {
1994+
return interface_stub.interrupt_timestamp;
1995+
} else {
1996+
return interface_stub.timestamp;
1997+
}
1998+
}
1999+
2000+
/**
2001+
* Test to insert an event that is already in the past, the fire_interrupt should
2002+
* be invoked, instead of set_interrupt
2003+
*/
2004+
static void test_set_interrupt_past_time()
2005+
{
2006+
interface_stub.set_interrupt_call = 0;
2007+
interface_stub.fire_interrupt_call = 0;
2008+
interface_stub.timestamp = 0xFF;
2009+
2010+
2011+
// This tests fire now functinality when next_event_timestamp <= present
2012+
ticker_event_t event = { 0 };
2013+
const timestamp_t event_timestamp = interface_stub.timestamp;
2014+
const uint32_t id_last_event = 0xDEADDEAF;
2015+
2016+
ticker_insert_event(&ticker_stub, &event, event_timestamp, id_last_event);
2017+
TEST_ASSERT_EQUAL(0, interface_stub.set_interrupt_call);
2018+
TEST_ASSERT_EQUAL(1, interface_stub.fire_interrupt_call);
2019+
}
2020+
/**
2021+
* Test to insert an event that is being delayed, set_interrupt is set
2022+
* but then event is already in the past, thus fire_interrupt should be invoked right-away
2023+
*/
2024+
static void test_set_interrupt_past_time_with_delay()
2025+
{
2026+
interface_stub.set_interrupt_call = 0;
2027+
interface_stub.fire_interrupt_call = 0;
2028+
interface_stub.timestamp = 0xFF;
2029+
2030+
// This tests fire now functionality when present time >= new_match_time
2031+
interface_stub.interface.read = ticker_interface_stub_read_interrupt_time;
2032+
ticker_event_t event = { 0 };
2033+
const timestamp_t event_timestamp = interface_stub.timestamp + 5;
2034+
const uint32_t id_last_event = 0xDEADDEAF;
2035+
2036+
ticker_insert_event(&ticker_stub, &event, event_timestamp, id_last_event);
2037+
TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);
2038+
TEST_ASSERT_EQUAL(1, interface_stub.fire_interrupt_call);
2039+
}
2040+
19852041
static const case_t cases[] = {
19862042
MAKE_TEST_CASE("ticker initialization", test_ticker_initialization),
19872043
MAKE_TEST_CASE(
@@ -2066,6 +2122,14 @@ static const case_t cases[] = {
20662122
MAKE_TEST_CASE(
20672123
"test_irq_handler_insert_non_immediate_in_irq",
20682124
test_irq_handler_insert_non_immediate_in_irq
2125+
),
2126+
MAKE_TEST_CASE(
2127+
"test_set_interrupt_past_time",
2128+
test_set_interrupt_past_time
2129+
),
2130+
MAKE_TEST_CASE(
2131+
"test_set_interrupt_past_time_with_delay",
2132+
test_set_interrupt_past_time_with_delay
20692133
)
20702134
};
20712135

@@ -2079,4 +2143,4 @@ int main()
20792143
{
20802144
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
20812145
return !Harness::run(specification);
2082-
}
2146+
}

hal/lp_ticker_api.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ void lp_ticker_disable_interrupt(void);
7474
*/
7575
void lp_ticker_clear_interrupt(void);
7676

77+
/** Set pending interrupt that should be fired right away.
78+
*
79+
* The ticker should be initialized prior calling this function.
80+
*/
81+
void lp_ticker_fire_interrupt(void);
82+
7783
/**@}*/
7884

7985
#ifdef __cplusplus

hal/mbed_lp_ticker_api.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ static const ticker_interface_t lp_interface = {
2525
.disable_interrupt = lp_ticker_disable_interrupt,
2626
.clear_interrupt = lp_ticker_clear_interrupt,
2727
.set_interrupt = lp_ticker_set_interrupt,
28+
.fire_interrupt = lp_ticker_fire_interrupt,
2829
};
2930

3031
static const ticker_data_t lp_data = {

hal/mbed_ticker_api.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,23 @@ static void schedule_interrupt(const ticker_data_t *const ticker)
117117

118118
// if the event at the head of the queue is in the past then schedule
119119
// it immediately.
120-
if (next_event_timestamp < present) {
121-
relative_timeout = 0;
120+
if (next_event_timestamp <= present) {
121+
ticker->interface->fire_interrupt();
122+
return;
122123
} else if ((next_event_timestamp - present) < MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA) {
123124
relative_timeout = next_event_timestamp - present;
124125
}
125126
}
126127

127-
ticker->interface->set_interrupt(ticker->queue->present_time + relative_timeout);
128+
us_timestamp_t new_match_time = ticker->queue->present_time + relative_timeout;
129+
ticker->interface->set_interrupt(new_match_time);
130+
// there could be a delay, reread the time, check if it was set in the past
131+
// As result, if it is already in the past, we fire it immediately
132+
update_present_time(ticker);
133+
us_timestamp_t present = ticker->queue->present_time;
134+
if (present >= new_match_time) {
135+
ticker->interface->fire_interrupt();
136+
}
128137
}
129138

130139
void ticker_set_handler(const ticker_data_t *const ticker, ticker_event_handler handler)

hal/mbed_us_ticker_api.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ static const ticker_interface_t us_interface = {
2323
.disable_interrupt = us_ticker_disable_interrupt,
2424
.clear_interrupt = us_ticker_clear_interrupt,
2525
.set_interrupt = us_ticker_set_interrupt,
26+
.fire_interrupt = us_ticker_fire_interrupt,
2627
};
2728

2829
static const ticker_data_t us_data = {

hal/ticker_api.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ typedef struct {
6060
void (*disable_interrupt)(void); /**< Disable interrupt function */
6161
void (*clear_interrupt)(void); /**< Clear interrupt function */
6262
void (*set_interrupt)(timestamp_t timestamp); /**< Set interrupt function */
63+
void (*fire_interrupt)(void); /**< Fire interrupt right-away */
6364
} ticker_interface_t;
6465

6566
/** Ticker's event queue structure

hal/us_ticker_api.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ void us_ticker_disable_interrupt(void);
7272
*/
7373
void us_ticker_clear_interrupt(void);
7474

75+
/** Set pending interrupt that should be fired right away.
76+
*
77+
* The ticker should be initialized prior calling this function.
78+
*/
79+
void us_ticker_fire_interrupt(void);
80+
7581
/**@}*/
7682

7783
#ifdef __cplusplus

targets/TARGET_ARM_SSG/TARGET_BEETLE/lp_ticker.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -115,27 +115,24 @@ uint32_t lp_ticker_read(void)
115115
*/
116116
void lp_ticker_set_interrupt(timestamp_t timestamp)
117117
{
118-
int32_t delta = 0;
119-
120118
/* Verify if lp_ticker has been not Initialized */
121119
if (lp_ticker_initialized == 0)
122120
lp_ticker_init();
123121

124122
/* Calculate the delta */
125-
delta = (int32_t)(timestamp - lp_ticker_read());
126-
/* Check if the event was in the past */
127-
if (delta <= 0) {
128-
/* This event was in the past */
129-
DualTimer_SetInterrupt_1(DUALTIMER0, 0,
130-
DUALTIMER_COUNT_32 | DUALTIMER_ONESHOT);
131-
return;
132-
}
123+
uint32_t delta = timestamp - lp_ticker_read();
133124

134125
/* Enable interrupt on SingleTimer1 */
135126
DualTimer_SetInterrupt_1(DUALTIMER0, delta,
136127
DUALTIMER_COUNT_32 | DUALTIMER_ONESHOT);
137128
}
138129

130+
void lp_ticker_fire_interrupt(void)
131+
{
132+
uint32_t lp_ticker_irqn = DualTimer_GetIRQn(DUALTIMER0);
133+
NVIC_SetPendingIRQ((IRQn_Type)lp_ticker_irqn);
134+
}
135+
139136
/**
140137
* Disable low power ticker interrupt
141138
*/

targets/TARGET_ARM_SSG/TARGET_BEETLE/us_ticker.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,22 +91,19 @@ uint32_t us_ticker_read() {
9191
}
9292

9393
void us_ticker_set_interrupt(timestamp_t timestamp) {
94-
int32_t delta = 0;
95-
9694
if (!us_ticker_inited)
9795
us_ticker_init();
98-
delta = (int32_t)(timestamp - us_ticker_read());
99-
/* Check if the event was in the past */
100-
if (delta <= 0) {
101-
/* This event was in the past */
102-
Timer_SetInterrupt(TIMER0, 0);
103-
return;
104-
}
10596

106-
/* If the event was not in the past enable interrupt */
97+
uint32_t delta = timestamp - us_ticker_read();
10798
Timer_SetInterrupt(TIMER0, delta);
10899
}
109100

101+
void us_ticker_fire_interrupt(void)
102+
{
103+
uint32_t us_ticker_irqn1 = Timer_GetIRQn(TIMER1);
104+
NVIC_SetPendingIRQ((IRQn_Type)us_ticker_irqn1);
105+
}
106+
110107
void us_ticker_disable_interrupt(void) {
111108
Timer_DisableInterrupt(TIMER0);
112109
}

targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/us_ticker.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -108,22 +108,23 @@ uint32_t us_ticker_read()
108108

109109
void us_ticker_set_interrupt(timestamp_t timestamp)
110110
{
111-
int32_t delta = 0;
111+
uint32_t delta = 0;
112112

113113
if (!us_ticker_drv_data.inited) {
114114
us_ticker_init();
115115
}
116116

117-
delta = (int32_t)(timestamp - us_ticker_read());
117+
delta = timestamp - us_ticker_read();
118118

119-
/* Check if the event was in the past */
120-
if (delta <= 0) {
121-
/* This event was in the past */
122-
Timer_SetInterrupt(TIMER0, 0);
123-
} else {
124-
/* If the event was not in the past enable interrupt */
125-
Timer_SetInterrupt(TIMER0, delta);
126-
}
119+
/* If the event was not in the past enable interrupt */
120+
Timer_SetInterrupt(TIMER0, delta);
121+
122+
}
123+
124+
void us_ticker_fire_interrupt(void)
125+
{
126+
uint32_t us_ticker_irqn1 = Timer_GetIRQn(TIMER1);
127+
NVIC_SetPendingIRQ((IRQn_Type)us_ticker_irqn1);
127128
}
128129

129130
void us_ticker_disable_interrupt(void)

targets/TARGET_ARM_SSG/TARGET_IOTSS/us_ticker.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp) {
6969
US_TICKER_TIMER1->TimerControl |= 0x80; //enable timer
7070
}
7171

72+
void us_ticker_fire_interrupt(void)
73+
{
74+
NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQn);
75+
}
76+
7277
void us_ticker_disable_interrupt(void) {
7378

7479
US_TICKER_TIMER1->TimerControl &= 0xDF;

targets/TARGET_ARM_SSG/TARGET_MPS2/us_ticker.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,22 +51,23 @@ uint32_t return_value = 0;
5151
}
5252

5353
void us_ticker_set_interrupt(timestamp_t timestamp) {
54-
int delta = 0;
5554
if (!us_ticker_inited)
5655
us_ticker_init();
57-
delta = (int)(timestamp - us_ticker_read());
58-
if (delta <= 0) {
59-
// This event was in the past:
60-
us_ticker_irq_handler();
61-
return;
62-
}
56+
57+
uint32_t delta = timestamp - us_ticker_read();
6358
// enable interrupt
6459
US_TICKER_TIMER1->TimerControl = 0x0; // disable timer
6560
US_TICKER_TIMER1->TimerControl = 0x62; // enable interrupt and set to 32 bit counter and set to periodic mode
6661
US_TICKER_TIMER1->TimerLoad = (delta)*25; //initialise the timer value
6762
US_TICKER_TIMER1->TimerControl |= 0x80; //enable timer
6863
}
6964

65+
void us_ticker_fire_interrupt(void)
66+
{
67+
NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQn);
68+
}
69+
70+
7071
void us_ticker_disable_interrupt(void) {
7172

7273
US_TICKER_TIMER1->TimerControl &= 0xDF;

targets/TARGET_Atmel/TARGET_SAM_CortexM4/lp_ticker.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,10 @@ uint32_t lp_ticker_read()
8686
void lp_ticker_set_interrupt(timestamp_t timestamp)
8787
{
8888
uint32_t cur_time;
89-
int32_t delta;
89+
uint32_t delta;
9090

9191
cur_time = lp_ticker_read();
92-
delta = (int32_t)((uint32_t)timestamp - cur_time);
93-
if (delta < 0) {
94-
/* Event already occurred in past */
95-
lp_ticker_irq_handler();
96-
return;
97-
}
92+
delta = timestamp - cur_time;
9893

9994
uint16_t interruptat=0;
10095

@@ -120,6 +115,11 @@ void lp_ticker_set_interrupt(timestamp_t timestamp)
120115
tc_start(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2);
121116
}
122117

118+
void lp_ticker_fire_interrupt(void)
119+
{
120+
NVIC_SetPendingIRQ(TICKER_COUNTER_IRQn2);
121+
}
122+
123123
void lp_ticker_disable_interrupt(void)
124124
{
125125
tc_stop(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2);

targets/TARGET_Atmel/TARGET_SAM_CortexM4/us_ticker.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
170170
tc_start(TICKER_COUNTER_uS, TICKER_COUNTER_CHANNEL1);
171171
}
172172

173+
void us_ticker_fire_interrupt(void)
174+
{
175+
NVIC_SetPendingIRQ(TICKER_COUNTER_IRQn1);
176+
}
177+
173178
void us_ticker_disable_interrupt(void)
174179
{
175180
tc_stop(TICKER_COUNTER_uS, TICKER_COUNTER_CHANNEL1);

0 commit comments

Comments
 (0)