Merge pull request #5028 from c1728p9/ticker_api_changes

Update ticker to map closely to hardware
pull/4955/head
Jimmy Brisson 2017-10-13 09:18:02 -05:00 committed by GitHub
commit fad67559ae
8 changed files with 438 additions and 36 deletions

View File

@ -29,7 +29,8 @@ using namespace utest::v1;
#define MBED_ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
#define TIMESTAMP_MAX_DELTA MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA
#define TIMESTAMP_MAX_DELTA_BITS(bits) ((uint64_t)(0x7 << ((bits) - 4)))
#define TIMESTAMP_MAX_DELTA TIMESTAMP_MAX_DELTA_BITS(32)
struct ticker_interface_stub_t {
ticker_interface_t interface;
@ -43,9 +44,11 @@ struct ticker_interface_stub_t {
unsigned int clear_interrupt_call;
unsigned int set_interrupt_call;
unsigned int fire_interrupt_call;
unsigned int get_info_call;
};
static ticker_interface_stub_t interface_stub = { 0 };
static ticker_info_t interface_info_stub = { 0 };
static void ticker_interface_stub_init()
{
@ -81,6 +84,12 @@ static void ticker_interface_stub_fire_interrupt()
++interface_stub.fire_interrupt_call;
}
static const ticker_info_t *ticker_interface_stub_get_info()
{
++interface_stub.get_info_call;
return &interface_info_stub;
}
static void reset_ticker_interface_stub()
{
interface_stub.interface.init = ticker_interface_stub_init;
@ -91,6 +100,7 @@ static void reset_ticker_interface_stub()
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.interface.get_info = ticker_interface_stub_get_info;
interface_stub.initialized = false;
interface_stub.interrupt_flag = false;
interface_stub.timestamp = 0;
@ -101,6 +111,9 @@ static void reset_ticker_interface_stub()
interface_stub.clear_interrupt_call = 0;
interface_stub.set_interrupt_call = 0;
interface_stub.fire_interrupt_call = 0;
interface_info_stub.frequency = 1000000;
interface_info_stub.bits = 32;
}
// stub of the event queue
@ -115,6 +128,12 @@ static void reset_queue_stub()
{
queue_stub.event_handler = NULL;
queue_stub.head = NULL,
queue_stub.tick_last_read = 0;
queue_stub.tick_remainder = 0;
queue_stub.frequency = 0;
queue_stub.bitmask = 0;
queue_stub.max_delta = 0;
queue_stub.max_delta_us = 0;
queue_stub.present_time = 0;
queue_stub.initialized = false;
}
@ -131,6 +150,34 @@ static void reset_ticker_stub()
reset_ticker_interface_stub();
}
const uint32_t test_frequencies[] = {
1,
32768, // 2^15
1000000,
0xFFFFFFFF // 2^32 - 1
};
const uint32_t test_bitwidths[] = {
32,
31,
16,
8
};
template < void (F)(uint32_t a, uint32_t b)>
static void test_over_frequency_and_width(void)
{
for (unsigned int i = 0; i < MBED_ARRAY_SIZE(test_frequencies); i++) {
for (unsigned int j = 0; j < MBED_ARRAY_SIZE(test_bitwidths); j++) {
reset_ticker_stub();
interface_info_stub.frequency = test_frequencies[i];
interface_info_stub.bits = test_bitwidths[j];
F(test_frequencies[i], test_bitwidths[j]);
}
}
}
static utest::v1::status_t case_setup_handler(
const Case *const source, const size_t index_of_case
) {
@ -175,8 +222,7 @@ static utest::v1::status_t greentea_failure_handler(
* Then:
* - The ticker interface should be initialized
* - The queue handler should be set to the handler provided in parameter
* - The internal ticker timestamp should be synced with the counter in the
* interface counter.
* - The internal ticker timestamp should be zero
* - interrupt should be scheduled in current timestamp +
* TIMESTAMP_MAX_DELTA
* - The queue should not contains any event
@ -192,7 +238,7 @@ static void test_ticker_initialization()
TEST_ASSERT_TRUE(interface_stub.initialized);
TEST_ASSERT_EQUAL_PTR(dummy_handler, queue_stub.event_handler);
TEST_ASSERT_EQUAL_UINT64(interface_stub.timestamp, queue_stub.present_time);
TEST_ASSERT_EQUAL_UINT64(0, queue_stub.present_time);
TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);
TEST_ASSERT_EQUAL_UINT32(
interface_stub.timestamp + TIMESTAMP_MAX_DELTA,
@ -347,7 +393,7 @@ static void test_legacy_insert_event_outside_overflow_range()
// test the beginning of the range
ticker_event_t first_event = { 0 };
const timestamp_t timestamp_first_event = interface_stub.timestamp + 1;
const timestamp_t timestamp_first_event = interface_stub.timestamp + 1;
const uint32_t id_first_event = 0xAAAAAAAA;
ticker_insert_event(
@ -820,6 +866,7 @@ static void test_insert_event_us_outside_overflow_range()
ticker_set_handler(&ticker_stub, NULL);
interface_stub.set_interrupt_call = 0;
interface_stub.timestamp = 0xAAAAAAAA;
queue_stub.tick_last_read = interface_stub.timestamp;
queue_stub.present_time = 10ULL << 32 | interface_stub.timestamp;
// test the end of the range
@ -881,6 +928,7 @@ static void test_insert_event_us_in_overflow_range()
ticker_set_handler(&ticker_stub, NULL);
interface_stub.set_interrupt_call = 0;
interface_stub.timestamp = 0xAAAAAAAA;
queue_stub.tick_last_read = interface_stub.timestamp;
queue_stub.present_time = 10ULL << 32 | interface_stub.timestamp;
// test the end of the range
@ -944,6 +992,7 @@ static void test_insert_event_us_underflow()
interface_stub.set_interrupt_call = 0;
interface_stub.timestamp = 0xAAAAAAAA;
queue_stub.tick_last_read = interface_stub.timestamp;
queue_stub.present_time = 10ULL << 32 | interface_stub.timestamp;
// test the end of the range
@ -979,6 +1028,7 @@ static void test_insert_event_us_head()
ticker_set_handler(&ticker_stub, NULL);
interface_stub.set_interrupt_call = 0;
interface_stub.timestamp = 0xAAAAAAAA;
queue_stub.tick_last_read = interface_stub.timestamp;
queue_stub.present_time = 10ULL << 32 | interface_stub.timestamp;
const us_timestamp_t timestamps[] = {
@ -2003,6 +2053,8 @@ static uint32_t ticker_interface_stub_read_interrupt_time()
*/
static void test_set_interrupt_past_time()
{
ticker_set_handler(&ticker_stub, NULL);
interface_stub.set_interrupt_call = 0;
interface_stub.fire_interrupt_call = 0;
interface_stub.timestamp = 0xFF;
@ -2023,6 +2075,8 @@ static void test_set_interrupt_past_time()
*/
static void test_set_interrupt_past_time_with_delay()
{
ticker_set_handler(&ticker_stub, NULL);
interface_stub.set_interrupt_call = 0;
interface_stub.fire_interrupt_call = 0;
interface_stub.timestamp = 0xFF;
@ -2038,6 +2092,168 @@ static void test_set_interrupt_past_time_with_delay()
TEST_ASSERT_EQUAL(1, interface_stub.fire_interrupt_call);
}
/**
* Convert ticks at a given frequency to time in microseconds
*
* Assert if there is a 64-bit overflow
*/
static uint64_t convert_to_us(uint64_t ticks, uint32_t frequency)
{
uint64_t scaled_ticks = ticks * 1000000;
// Assert that there was not an overflow
TEST_ASSERT_EQUAL(ticks, scaled_ticks / 1000000);
return scaled_ticks / frequency;
}
/**
* Given an uninitialized ticker instance and an interface of a
* certain frequency and bit width.
* Then the time returned the ticker should match the cumulative time.
*/
void test_frequencies_and_masks(uint32_t frequency, uint32_t bits)
{
const uint32_t bitmask = ((uint64_t)1 << bits) - 1;
ticker_set_handler(&ticker_stub, NULL);
uint64_t ticks = 0;
// Single tick
ticks += 1;
interface_stub.timestamp = ticks & bitmask;
TEST_ASSERT_EQUAL_UINT32(convert_to_us(ticks, frequency), ticker_read(&ticker_stub));
TEST_ASSERT_EQUAL_UINT64(convert_to_us(ticks, frequency), ticker_read_us(&ticker_stub));
// Run until the loop before 64-bit overflow (worst case with frequency=1hz, bits=32)
for (unsigned int k = 0; k < 4294; k++) {
// Largest value possible tick
ticks += ((uint64_t)1 << bits) - 1;
interface_stub.timestamp = ticks & bitmask;
TEST_ASSERT_EQUAL_UINT32(convert_to_us(ticks, frequency), ticker_read(&ticker_stub));
TEST_ASSERT_EQUAL_UINT64(convert_to_us(ticks, frequency), ticker_read_us(&ticker_stub));
}
}
/**
* Given an uninitialized ticker_data instance.
* When the ticker is initialized
* Then:
* - The internal ticker timestamp should be zero
* - interrupt should be scheduled in current (timestamp +
* TIMESTAMP_MAX_DELTA_BITS(bitwidth)) % modval
* - The queue should not contains any event
*/
static void test_ticker_max_value()
{
for (int bitwidth = 8; bitwidth <= 32; bitwidth++) {
const uint64_t modval = 1ULL << bitwidth;
// setup of the stub
reset_ticker_stub();
interface_info_stub.bits = bitwidth;
interface_stub.timestamp = 0xBA;
ticker_set_handler(&ticker_stub, NULL);
TEST_ASSERT_EQUAL_UINT64(0, queue_stub.present_time);
TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call);
TEST_ASSERT_EQUAL_UINT32(
(interface_stub.timestamp + TIMESTAMP_MAX_DELTA_BITS(bitwidth)) % modval,
interface_stub.interrupt_timestamp
);
TEST_ASSERT_EQUAL_PTR(NULL, queue_stub.head);
TEST_ASSERT_EQUAL(0, interface_stub.disable_interrupt_call);
}
}
/**
* Check that _ticker_match_interval_passed correctly detects matches
*
* Brute force test that _ticker_match_interval_passed returns the correct match value
* for all cominations of values within a small range.
*/
static void test_match_interval_passed()
{
for (int modval = 1; modval <= 5; modval++) {
for (int prev = 0; prev < modval; prev++) {
for (int cur = 0; cur < modval; cur++) {
for (int match = 0; match < modval; match++) {
uint32_t delta = (cur - prev) % modval;
uint32_t delta_to_match = (match - prev) % modval;
bool match_expected = false;
if (delta_to_match) {
match_expected = delta >= delta_to_match;
}
// Sanity checks
if (prev == cur) {
// No time has passed
TEST_ASSERT_EQUAL(false, match_expected);
} else if (match == prev) {
// Match can't occur without an overflow occurring
TEST_ASSERT_EQUAL(false, match_expected);
} else if (cur == match) {
// All other cases where cur == match a match should be expected
TEST_ASSERT_EQUAL(true, match_expected);
}
// Actual test
TEST_ASSERT_EQUAL(match_expected, _ticker_match_interval_passed(prev, cur, match));
}
}
}
}
}
typedef struct {
timestamp_t prev;
timestamp_t cur;
timestamp_t match;
bool result;
} match_interval_entry_t;
/**
* Check that _ticker_match_interval_passed correctly detects matches
*
* Use a table of pre-computed values to check that _ticker_match_interval_passed
* returns the correct match value.
*/
static void test_match_interval_passed_table()
{
static const match_interval_entry_t test_values[] = {
/* prev, cur, match, result */
{0x00000000, 0x00000000, 0x00000000, false},
{0x00000000, 0x00000000, 0xffffffff, false},
{0x00000000, 0x00000000, 0x00000001, false},
{0x00000000, 0xffffffff, 0x00000000, false},
{0x00000000, 0x00000001, 0x00000000, false},
{0xffffffff, 0x00000000, 0x00000000, true},
{0x00000001, 0x00000000, 0x00000000, true},
{0x00005555, 0x00005555, 0x00005555, false},
{0x00005555, 0x00005555, 0x00005554, false},
{0x00005555, 0x00005555, 0x00005556, false},
{0x00005555, 0x00005554, 0x00005555, false},
{0x00005555, 0x00005556, 0x00005555, false},
{0x00005554, 0x00005555, 0x00005555, true},
{0x00005556, 0x00005555, 0x00005555, true},
{0xffffffff, 0xffffffff, 0xffffffff, false},
{0xffffffff, 0xffffffff, 0xfffffffe, false},
{0xffffffff, 0xffffffff, 0x00000000, false},
{0xffffffff, 0xfffffffe, 0xffffffff, false},
{0xffffffff, 0x00000000, 0xffffffff, false},
{0xfffffffe, 0xffffffff, 0xffffffff, true},
{0x00000000, 0xffffffff, 0xffffffff, true},
};
for (int i = 0; i < MBED_ARRAY_SIZE(test_values); i++) {
const uint32_t prev = test_values[i].prev;
const uint32_t cur = test_values[i].cur;
const uint32_t match = test_values[i].match;
const uint32_t result = test_values[i].result;
TEST_ASSERT_EQUAL(result, _ticker_match_interval_passed(prev, cur, match));
}
}
static const case_t cases[] = {
MAKE_TEST_CASE("ticker initialization", test_ticker_initialization),
MAKE_TEST_CASE(
@ -2130,12 +2346,28 @@ static const case_t cases[] = {
MAKE_TEST_CASE(
"test_set_interrupt_past_time_with_delay",
test_set_interrupt_past_time_with_delay
),
MAKE_TEST_CASE(
"test_frequencies_and_masks",
test_over_frequency_and_width<test_frequencies_and_masks>
),
MAKE_TEST_CASE(
"test_ticker_max_value",
test_ticker_max_value
),
MAKE_TEST_CASE(
"test_match_interval_passed",
test_match_interval_passed
),
MAKE_TEST_CASE(
"test_match_interval_passed_table",
test_match_interval_passed_table
)
};
static utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(30, "default_auto");
GREENTEA_SETUP(60, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}

View File

@ -80,6 +80,11 @@ void lp_ticker_clear_interrupt(void);
*/
void lp_ticker_fire_interrupt(void);
/** Get frequency and counter bits of this ticker.
*
*/
const ticker_info_t* lp_ticker_get_info(void);
/**@}*/
#ifdef __cplusplus

View File

@ -26,6 +26,7 @@ static const ticker_interface_t lp_interface = {
.clear_interrupt = lp_ticker_clear_interrupt,
.set_interrupt = lp_ticker_set_interrupt,
.fire_interrupt = lp_ticker_fire_interrupt,
.get_info = lp_ticker_get_info,
};
static const ticker_data_t lp_data = {

View File

@ -17,6 +17,7 @@
#include <stddef.h>
#include "hal/ticker_api.h"
#include "platform/mbed_critical.h"
#include "mbed_assert.h"
static void schedule_interrupt(const ticker_data_t *const ticker);
static void update_present_time(const ticker_data_t *const ticker);
@ -33,9 +34,31 @@ static void initialize(const ticker_data_t *ticker)
}
ticker->interface->init();
const ticker_info_t *info = ticker->interface->get_info();
uint32_t frequency = info->frequency;
if (info->frequency == 0) {
MBED_ASSERT(0);
frequency = 1000000;
}
uint32_t bits = info->bits;
if ((info->bits > 32) || (info->bits < 4)) {
MBED_ASSERT(0);
bits = 32;
}
uint32_t max_delta = 0x7 << (bits - 4); // 7/16th
uint64_t max_delta_us =
((uint64_t)max_delta * 1000000 + frequency - 1) / frequency;
ticker->queue->event_handler = NULL;
ticker->queue->head = NULL;
ticker->queue->tick_last_read = ticker->interface->read();
ticker->queue->tick_remainder = 0;
ticker->queue->frequency = frequency;
ticker->queue->bitmask = ((uint64_t)1 << bits) - 1;
ticker->queue->max_delta = max_delta;
ticker->queue->max_delta_us = max_delta_us;
ticker->queue->present_time = 0;
ticker->queue->initialized = true;
@ -86,53 +109,143 @@ static us_timestamp_t convert_timestamp(us_timestamp_t ref, timestamp_t timestam
* Update the present timestamp value of a ticker.
*/
static void update_present_time(const ticker_data_t *const ticker)
{
ticker->queue->present_time = convert_timestamp(
ticker->queue->present_time,
ticker->interface->read()
);
{
ticker_event_queue_t *queue = ticker->queue;
uint32_t ticker_time = ticker->interface->read();
if (ticker_time == ticker->queue->tick_last_read) {
// No work to do
return;
}
uint64_t elapsed_ticks = (ticker_time - queue->tick_last_read) & queue->bitmask;
queue->tick_last_read = ticker_time;
uint64_t elapsed_us;
if (1000000 == queue->frequency) {
// Optimized for 1MHz
elapsed_us = elapsed_ticks;
} else if (32768 == queue->frequency) {
// Optimized for 32KHz
uint64_t us_x_ticks = elapsed_ticks * 1000000;
elapsed_us = us_x_ticks >> 15;
// Update remainder
queue->tick_remainder += us_x_ticks - (elapsed_us << 15);
if (queue->tick_remainder >= queue->frequency) {
elapsed_us += 1;
queue->tick_remainder -= queue->frequency;
}
} else {
// General case
uint64_t us_x_ticks = elapsed_ticks * 1000000;
elapsed_us = us_x_ticks / queue->frequency;
// Update remainder
queue->tick_remainder += us_x_ticks - elapsed_us * queue->frequency;
if (queue->tick_remainder >= queue->frequency) {
elapsed_us += 1;
queue->tick_remainder -= queue->frequency;
}
}
// Update current time
queue->present_time += elapsed_us;
}
/**
* Given the absolute timestamp compute the hal tick timestamp.
*/
static timestamp_t compute_tick(const ticker_data_t *const ticker, us_timestamp_t timestamp)
{
ticker_event_queue_t *queue = ticker->queue;
us_timestamp_t delta_us = timestamp - queue->present_time;
timestamp_t delta = ticker->queue->max_delta;
if (delta_us <= ticker->queue->max_delta_us) {
// Checking max_delta_us ensures the operation will not overflow
if (1000000 == queue->frequency) {
// Optimized for 1MHz
delta = delta_us;
if (delta > ticker->queue->max_delta) {
delta = ticker->queue->max_delta;
}
} else if (32768 == queue->frequency) {
// Optimized for 32KHz
delta = (delta_us << 15) / 1000000;
if (delta > ticker->queue->max_delta) {
delta = ticker->queue->max_delta;
}
} else {
// General case
delta = delta_us * queue->frequency / 1000000;
if (delta > ticker->queue->max_delta) {
delta = ticker->queue->max_delta;
}
}
}
return (queue->tick_last_read + delta) & queue->bitmask;
}
/**
* Return 1 if the tick has incremented to or past match_tick, otherwise 0.
*/
int _ticker_match_interval_passed(timestamp_t prev_tick, timestamp_t cur_tick, timestamp_t match_tick)
{
if (match_tick > prev_tick) {
return (cur_tick >= match_tick) || (cur_tick < prev_tick);
} else {
return (cur_tick < prev_tick) && (cur_tick >= match_tick);
}
}
/**
* Compute the time when the interrupt has to be triggered and schedule it.
*
* If there is no event in the queue or the next event to execute is in more
* than MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA us from now then the ticker
* irq will be scheduled in MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA us.
* Otherwise the irq will be scheduled to happen when the running counter reach
* the timestamp of the first event in the queue.
* than ticker.queue.max_delta ticks from now then the ticker irq will be
* scheduled in ticker.queue.max_delta ticks. Otherwise the irq will be
* scheduled to happen when the running counter reach the timestamp of the
* first event in the queue.
*
* @note If there is no event in the queue then the interrupt is scheduled to
* in MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA. This is necessary to keep track
* in ticker.queue.max_delta. This is necessary to keep track
* of the timer overflow.
*/
static void schedule_interrupt(const ticker_data_t *const ticker)
{
ticker_event_queue_t *queue = ticker->queue;
update_present_time(ticker);
uint32_t relative_timeout = MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA;
if (ticker->queue->head) {
us_timestamp_t present = ticker->queue->present_time;
us_timestamp_t next_event_timestamp = ticker->queue->head->timestamp;
us_timestamp_t match_time = ticker->queue->head->timestamp;
// if the event at the head of the queue is in the past then schedule
// it immediately.
if (next_event_timestamp <= present) {
if (match_time <= present) {
ticker->interface->fire_interrupt();
return;
} else if ((next_event_timestamp - present) < MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA) {
relative_timeout = next_event_timestamp - present;
}
}
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();
timestamp_t match_tick = compute_tick(ticker, match_time);
ticker->interface->set_interrupt(match_tick);
timestamp_t cur_tick = ticker->interface->read();
if (_ticker_match_interval_passed(queue->tick_last_read, cur_tick, match_tick)) {
ticker->interface->fire_interrupt();
}
} else {
uint32_t match_tick =
(queue->tick_last_read + queue->max_delta) & queue->bitmask;
ticker->interface->set_interrupt(match_tick);
}
}

View File

@ -24,6 +24,7 @@ static const ticker_interface_t us_interface = {
.clear_interrupt = us_ticker_clear_interrupt,
.set_interrupt = us_ticker_set_interrupt,
.fire_interrupt = us_ticker_fire_interrupt,
.get_info = us_ticker_get_info,
};
static const ticker_data_t us_data = {

View File

@ -23,11 +23,6 @@
#include <stdbool.h>
#include "device.h"
/**
* Maximum delta (in us) between too interrupts.
*/
#define MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA 0x70000000ULL
/**
* Legacy format representing a timestamp in us.
* Given it is modeled as a 32 bit integer, this type can represent timestamp
@ -52,6 +47,14 @@ typedef struct ticker_event_s {
typedef void (*ticker_event_handler)(uint32_t id);
/** Information about the ticker implementation
*/
typedef struct {
uint32_t frequency; /**< Frequency in Hz this ticker runs at */
uint32_t bits; /**< Number of bits this ticker supports */
} ticker_info_t;
/** Ticker's interface structure - required API for a ticker
*/
typedef struct {
@ -61,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 */
const ticker_info_t *(*get_info)(void); /**< Return info about this ticker's implementation */
} ticker_interface_t;
/** Ticker's event queue structure
@ -68,6 +72,12 @@ typedef struct {
typedef struct {
ticker_event_handler event_handler; /**< Event handler */
ticker_event_t *head; /**< A pointer to head */
uint32_t frequency; /**< Frequency of the timer in Hz */
uint32_t bitmask; /**< Mask to be applied to time values read */
uint32_t max_delta; /**< Largest delta in ticks that can be used when scheduling */
uint64_t max_delta_us; /**< Largest delta in us that can be used when scheduling */
uint32_t tick_last_read; /**< Last tick read */
uint64_t tick_remainder; /**< Ticks that have not been added to base_time */
us_timestamp_t present_time; /**< Store the timestamp used for present time */
bool initialized; /**< Indicate if the instance is initialized */
} ticker_event_queue_t;
@ -171,6 +181,19 @@ us_timestamp_t ticker_read_us(const ticker_data_t *const ticker);
*/
int ticker_get_next_timestamp(const ticker_data_t *const ticker, timestamp_t *timestamp);
/* Private functions
*
* @cond PRIVATE
*
*/
int _ticker_match_interval_passed(timestamp_t prev_tick, timestamp_t cur_tick, timestamp_t match_tick);
/*
* @endcond PRIVATE
*
*/
/**@}*/
#ifdef __cplusplus

View File

@ -78,6 +78,11 @@ void us_ticker_clear_interrupt(void);
*/
void us_ticker_fire_interrupt(void);
/** Get frequency and counter bits of this ticker.
*
*/
const ticker_info_t* us_ticker_get_info(void);
/**@}*/
#ifdef __cplusplus

View File

@ -27,6 +27,8 @@
#include "platform/mbed_stats.h"
#include "platform/mbed_critical.h"
#include "platform/PlatformMutex.h"
#include "us_ticker_api.h"
#include "lp_ticker_api.h"
#include <stdlib.h>
#include <string.h>
#include <limits.h>
@ -1063,3 +1065,23 @@ extern "C" clock_t clock()
_mutex->unlock();
return t;
}
// temporary - Default to 1MHz at 32 bits if target does not have us_ticker_get_info
MBED_WEAK const ticker_info_t* us_ticker_get_info()
{
static const ticker_info_t info = {
1000000,
32
};
return &info;
}
// temporary - Default to 1MHz at 32 bits if target does not have lp_ticker_get_info
MBED_WEAK const ticker_info_t* lp_ticker_get_info()
{
static const ticker_info_t info = {
1000000,
32
};
return &info;
}