Skip to content
7 changes: 7 additions & 0 deletions TESTS/mbed_drivers/timer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ static void stub_fire_interrupt(void)
/* do nothing. */
}

/* User ticker interface function. */
static void stub_free(void)
{
/* do nothing. */
}

ticker_info_t info =
{ TICKER_FREQ_1MHZ, TICKER_BITS };

Expand All @@ -122,6 +128,7 @@ static const ticker_interface_t us_interface = {
.clear_interrupt = stub_clear_interrupt,
.set_interrupt = stub_set_interrupt,
.fire_interrupt = stub_fire_interrupt,
.free = stub_free,
.get_info = stub_get_info,
};

Expand Down
134 changes: 112 additions & 22 deletions TESTS/mbed_hal/common_tickers/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ extern "C" {
#error [NOT_SUPPORTED] test not supported
#endif

#define US_PER_S 1000000

#define FORCE_OVERFLOW_TEST (false)
#define TICKER_INT_VAL 500
#define TICKER_DELTA 10
Expand All @@ -43,10 +45,11 @@ extern "C" {
#define US_TICKER_OVERFLOW_DELTA2 60

#define TICKER_100_TICKS 100
#define TICKER_500_TICKS 500

#define MAX_FUNC_EXEC_TIME_US 20
#define DELTA_FUNC_EXEC_TIME_US 5
#define NUM_OF_CALLS 1000
#define NUM_OF_CALLS 100

#define NUM_OF_CYCLES 100000

Expand Down Expand Up @@ -149,6 +152,19 @@ void wait_cycles(volatile unsigned int cycles)
while (cycles--);
}

/* Auxiliary function to determine how long ticker function are executed.
* This function returns number of us between <start_ticks> and <stop_ticks>
* taking into account counter roll-over, counter size and frequency.
*/
uint32_t diff_us(uint32_t start_ticks, uint32_t stop_ticks, const ticker_info_t * info)
{
uint32_t counter_mask = ((1 << info->bits) - 1);

uint32_t diff_ticks = ((stop_ticks - start_ticks) & counter_mask);

return (uint32_t) ((uint64_t) diff_ticks * US_PER_S / info->frequency);
}

/* Test that ticker_init can be called multiple times and
* ticker_init allows the ticker to keep counting and disables the ticker interrupt.
*/
Expand Down Expand Up @@ -419,64 +435,134 @@ void ticker_increment_test(void)
/* Test that common ticker functions complete with the required amount of time. */
void ticker_speed_test(void)
{
Timer timer;
int counter = NUM_OF_CALLS;
uint32_t start;
uint32_t stop;

const ticker_info_t * us_ticker_info = get_us_ticker_data()->interface->get_info();

/* Free function will disable the ticker. For time measurement
* we need to use other one if available.
*/
#if DEVICE_LPTICKER
const ticker_info_t * lp_ticker_info = get_lp_ticker_data()->interface->get_info();
bool us_ticker_test = (intf == get_us_ticker_data()->interface);
#endif

/* ---- Test ticker_read function. ---- */
timer.reset();
timer.start();
start = us_ticker_read();
while (counter--) {
intf->read();
}
timer.stop();
stop = us_ticker_read();

TEST_ASSERT(timer.read_us() < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US)));
TEST_ASSERT(diff_us(start, stop, us_ticker_info) < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US)));

/* ---- Test ticker_clear_interrupt function. ---- */
counter = NUM_OF_CALLS;
timer.reset();
timer.start();
start = us_ticker_read();
while (counter--) {
intf->clear_interrupt();
}
timer.stop();
stop = us_ticker_read();

TEST_ASSERT(timer.read_us() < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US)));
TEST_ASSERT(diff_us(start, stop, us_ticker_info) < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US)));

/* ---- Test ticker_set_interrupt function. ---- */
counter = NUM_OF_CALLS;
timer.reset();
timer.start();
start = us_ticker_read();
while (counter--) {
intf->set_interrupt(0);
}
timer.stop();
stop = us_ticker_read();

TEST_ASSERT(timer.read_us() < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US)));
TEST_ASSERT(diff_us(start, stop, us_ticker_info) < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US)));

/* ---- Test fire_interrupt function. ---- */
counter = NUM_OF_CALLS;
timer.reset();
timer.start();
start = us_ticker_read();
while (counter--) {
intf->fire_interrupt();
}
timer.stop();
stop = us_ticker_read();

TEST_ASSERT(timer.read_us() < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US)));
TEST_ASSERT(diff_us(start, stop, us_ticker_info) < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US)));

/* ---- Test disable_interrupt function. ---- */
counter = NUM_OF_CALLS;
timer.reset();
timer.start();
start = us_ticker_read();
while (counter--) {
intf->disable_interrupt();
}
timer.stop();
stop = us_ticker_read();

TEST_ASSERT(diff_us(start, stop, us_ticker_info) < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US)));

/* ---- Test free function. ---- */
#if DEVICE_LPTICKER
counter = NUM_OF_CALLS;
if (us_ticker_test) {
lp_ticker_init();
}
start = us_ticker_test ? lp_ticker_read() : us_ticker_read();
while (counter--) {
intf->free();
}
stop = us_ticker_test ? lp_ticker_read() : us_ticker_read();

TEST_ASSERT(diff_us(start, stop, us_ticker_info) < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US)));
#endif
}

/* Test that ticker_free disables ticker interrupt. */
void ticker_free_interrupt_test(void)
{
overflow_protect();

uint32_t cycles_500_ticks = 50;
uint32_t reference_ticks_count = 0;

while(reference_ticks_count < TICKER_500_TICKS) {
cycles_500_ticks *= 2;
const uint32_t start = intf->read();
wait_cycles(cycles_500_ticks);
reference_ticks_count = intf->read() - start;
}

intFlag = 0;

intf->set_interrupt(intf->read() + (TICKER_500_TICKS / 2));
intf->free();
wait_cycles(cycles_500_ticks);
intf->init();
TEST_ASSERT_EQUAL(0, intFlag);
}

/* Test that ticker can be successfully re-initialized after free(). */
void ticker_init_free_test(void)
{
intf->free();
intf->init();

overflow_protect();

intFlag = 0;

const uint32_t tick_count = intf->read();

intf->set_interrupt(intf->read() + TICKER_INT_VAL);

while (intf->read() < (tick_count + TICKER_INT_VAL - TICKER_DELTA)) {
TEST_ASSERT_EQUAL_INT_MESSAGE(0, intFlag, "Interrupt fired too early");
}

while (intf->read() < (tick_count + TICKER_INT_VAL + TICKER_DELTA)) {
}

TEST_ASSERT(timer.read_us() < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US)));
TEST_ASSERT_EQUAL(1, intFlag);
}


utest::v1::status_t us_ticker_setup(const Case *const source, const size_t index_of_case)
{
intf = get_us_ticker_data()->interface;
Expand Down Expand Up @@ -551,6 +637,8 @@ Case cases[] = {
Case("Microsecond ticker overflow test", us_ticker_setup, ticker_overflow_test, us_ticker_teardown),
Case("Microsecond ticker increment test", us_ticker_setup, ticker_increment_test, us_ticker_teardown),
Case("Microsecond ticker speed test", us_ticker_setup, ticker_speed_test, us_ticker_teardown),
Case("Microsecond ticker free interrupt test", us_ticker_setup, ticker_free_interrupt_test, us_ticker_teardown),
Case("Microsecond re-init after free test", us_ticker_setup, ticker_init_free_test, us_ticker_teardown),
#if DEVICE_LPTICKER
Case("lp ticker init is safe to call repeatedly", lp_ticker_setup, ticker_init_test, lp_ticker_teardown),
Case("lp ticker info test", lp_ticker_setup, ticker_info_test, lp_ticker_teardown),
Expand All @@ -561,6 +649,8 @@ Case cases[] = {
Case("lp ticker overflow test", lp_ticker_setup, ticker_overflow_test, lp_ticker_teardown),
Case("lp ticker increment test", lp_ticker_setup, ticker_increment_test, lp_ticker_teardown),
Case("lp ticker speed test", lp_ticker_setup, ticker_speed_test, lp_ticker_teardown),
Case("lp ticker free interrupt test", lp_ticker_setup, ticker_free_interrupt_test, lp_ticker_teardown),
Case("lp ticker re-init after free test", lp_ticker_setup, ticker_init_free_test, lp_ticker_teardown),
#endif
};

Expand Down
15 changes: 15 additions & 0 deletions TESTS/mbed_hal/common_tickers/ticker_api_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,21 @@ void ticker_speed_test(void);
*/
void ticker_overflow_test(void);

/** Test ticker_free disables ticker interrupt.
*
* Given ticker is available.
* When ticker interrupt is set and then ticker_free is called.
* Then ticker interrupt is not triggered.
*/
void ticker_free_interrupt_test(void);

/** Test that ticker can be successfully re-initialized after free().
*
* Given ticker is available.
* When ticker has been re-initialized after free().
* Then ticker counts and generates interrupts.
*/
void ticker_init_free_test(void);
/**@}*/

#ifdef __cplusplus
Expand Down
5 changes: 5 additions & 0 deletions TESTS/mbedmicro-rtos-mbed/systimer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ void mock_ticker_fire_interrupt()
{
}

void mock_ticker_free()
{
}

const ticker_info_t *mock_ticker_get_info()
{
static const ticker_info_t mock_ticker_info = {
Expand All @@ -115,6 +119,7 @@ ticker_interface_t mock_ticker_interface = {
.clear_interrupt = mock_ticker_clear_interrupt,
.set_interrupt = mock_ticker_set_interrupt,
.fire_interrupt = mock_ticker_fire_interrupt,
.free = mock_ticker_free,
.get_info = mock_ticker_get_info,
};

Expand Down
1 change: 1 addition & 0 deletions hal/mbed_lp_ticker_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ static const ticker_interface_t lp_interface = {
#endif
.fire_interrupt = lp_ticker_fire_interrupt,
.get_info = lp_ticker_get_info,
.free = lp_ticker_free,
};

static const ticker_data_t lp_data = {
Expand Down
1 change: 1 addition & 0 deletions hal/mbed_us_ticker_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ static const ticker_interface_t us_interface = {
.set_interrupt = us_ticker_set_interrupt,
.fire_interrupt = us_ticker_fire_interrupt,
.get_info = us_ticker_get_info,
.free = us_ticker_free,
};

static const ticker_data_t us_data = {
Expand Down
1 change: 1 addition & 0 deletions hal/ticker_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ typedef struct {
void (*clear_interrupt)(void); /**< Clear interrupt function */
void (*set_interrupt)(timestamp_t timestamp); /**< Set interrupt function */
void (*fire_interrupt)(void); /**< Fire interrupt right-away */
void (*free)(void); /**< Disable function */
const ticker_info_t *(*get_info)(void); /**< Return info about this ticker's implementation */
} ticker_interface_t;

Expand Down
21 changes: 21 additions & 0 deletions hal/us_ticker_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ extern "C" {
* Verified by ::ticker_fire_now_test
* * The ticker operations ticker_read, ticker_clear_interrupt, ticker_set_interrupt and ticker_fire_interrupt
* take less than 20us to complete - Verified by ::ticker_speed_test
* * The function ticker_free disables the ticker interrupt - ::ticker_free_interrupt_test
* * The function ticker_init re-initializes ticker after has been disabled by means of ticker_free - Verified by ::ticker_init_free_test
*
* # Undefined behavior
* * Calling any function other than ticker_init before the initialization of the ticker
Expand Down Expand Up @@ -170,6 +172,25 @@ void us_ticker_init(void);
* except us_ticker_init(), calling any function other than init is undefined.
*
* @note This function stops the ticker from counting.
*
* Pseudo Code:
* @code
* uint32_t us_ticker_free()
* {
* // Disable timer
* TIMER_CTRL &= ~TIMER_CTRL_ENABLE_Msk;
*
* // Disable the compare interrupt
* TIMER_CTRL &= ~TIMER_CTRL_COMPARE_ENABLE_Msk;
*
* // Disable timer interrupt
* NVIC_DisableIRQ(TIMER_IRQn);
*
* // Disable clock gate so processor cannot read TIMER registers
* POWER_CTRL &= ~POWER_CTRL_TIMER_Msk;
* }
* @endcode
*
*/
void us_ticker_free(void);

Expand Down
5 changes: 5 additions & 0 deletions targets/TARGET_ARM_SSG/TARGET_BEETLE/lp_ticker.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,9 @@ void lp_ticker_clear_interrupt(void)
DualTimer_ClearInterrupt(DUALTIMER0);
}

void lp_ticker_free(void)
{

}

#endif
5 changes: 5 additions & 0 deletions targets/TARGET_ARM_SSG/TARGET_BEETLE/us_ticker.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,8 @@ void us_ticker_disable_interrupt(void) {
void us_ticker_clear_interrupt(void) {
Timer_ClearInterrupt(TIMER0);
}

void us_ticker_free(void)
{

}
5 changes: 5 additions & 0 deletions targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/lp_ticker.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ void lp_ticker_fire_interrupt(void)
cmsdk_ticker_fire_interrupt(&timer_data);
}

void lp_ticker_free(void)
{

}

void TIMER1_IRQHandler(void)
{
cmsdk_ticker_irq_handler(&timer_data);
Expand Down
5 changes: 5 additions & 0 deletions targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/us_ticker.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ void us_ticker_fire_interrupt(void)
cmsdk_ticker_fire_interrupt(&timer_data);
}

void us_ticker_free(void)
{

}

void TIMER0_IRQHandler(void)
{
cmsdk_ticker_irq_handler(&timer_data);
Expand Down
5 changes: 5 additions & 0 deletions targets/TARGET_ARM_SSG/TARGET_IOTSS/us_ticker.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,8 @@ void us_ticker_clear_interrupt(void) {
US_TICKER_TIMER2->TimerIntClr = 0x1;

}

void us_ticker_free(void)
{

}
5 changes: 5 additions & 0 deletions targets/TARGET_ARM_SSG/TARGET_MPS2/us_ticker.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,8 @@ void us_ticker_clear_interrupt(void) {
US_TICKER_TIMER2->TimerIntClr = 0x1;

}

void us_ticker_free(void)
{

}
Loading