11#include "pico/runtime_init.h"
45#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
50 .entries = default_alarm_pool_entries,
53static inline bool default_alarm_pool_initialized(
void) {
54 return default_alarm_pool.lock !=
NULL;
60#include "pico/time_adapter.h"
66static inline int16_t alarm_index(
alarm_id_t id) {
67 return (int16_t)(
id >> 16);
70static inline uint16_t alarm_sequence(
alarm_id_t id) {
74static alarm_id_t make_alarm_id(
int index, uint16_t counter) {
75 return index << 16 | counter;
78#if !PICO_RUNTIME_NO_INIT_DEFAULT_ALARM_POOL
80#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
82 if (!default_alarm_pool_initialized()) {
85 alarm_pool_post_alloc_init(&default_alarm_pool,
99#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
101 assert(default_alarm_pool_initialized());
102 return &default_alarm_pool;
105#if defined(PICO_RUNTIME_INIT_DEFAULT_ALARM_POOL) && !PICO_RUNTIME_SKIP_INIT_DEFAULT_ALARM_POOL
116 alarm_pool_post_alloc_init(pool,
timer, hardware_alarm_num, max_timers);
130static void alarm_pool_irq_handler(
void);
134#define repeating_timer_marker ((alarm_callback_t)alarm_pool_irq_handler)
135#include "hardware/gpio.h"
136static void alarm_pool_irq_handler(
void) {
142 uint timer_alarm_num;
147 int64_t earliest_target;
160 if (earliest_index >= 0) {
162 earliest_target = earliest_entry->
target;
163 if (((int64_t)ta_time_us_64(
timer) - earliest_target) >= 0) {
169 if (earliest_target >= 0) {
186 next_time = earliest_target - delta;
189 next_time = (int64_t) ta_time_us_64(
timer) + delta;
191 earliest_entry->
target = next_time;
202 *
prev = earliest_index;
224 while (new_index >= 0) {
226 int64_t new_entry_time = new_entry->
target;
232 int16_t next = *
prev;
234 new_index = new_entry->
next;
235 new_entry->
next = next;
242 __compiler_memory_barrier();
245 for(int16_t index = pool->
ordered_head; index != -1; ) {
247 int16_t next = entry->
next;
264 if (earliest_index < 0)
break;
267 earliest_target = earliest_entry->
target;
271 if (earliest_target != -1) {
275 }
while ((earliest_target - (int64_t)ta_time_us_64(
timer)) <= 0);
289 pool->
free_head = (int16_t)(max_timers - 1);
290 for(
uint i=0;
i<max_timers;
i++) {
299#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
300 if (pool == &default_alarm_pool) {
313 void *user_data,
bool fire_if_past) {
316 if (absolute_time_diff_us(
t, time) < 0)
return 0;
337 entry->
target = (int64_t)to_us_since_boot(time);
338 uint16_t next_sequence = (entry->
sequence + 1) & 0x7fff;
339 if (!next_sequence) next_sequence = 1;
341 alarm_id_t id = make_alarm_id(index, next_sequence);
355 int16_t index = alarm_index(alarm_id);
357 uint16_t sequence = alarm_sequence(alarm_id);
358 bool canceled =
false;
364 if (sequence == current_sequence) {
365 entry->
sequence = (uint16_t)(current_sequence | 0x8000);
366 __compiler_memory_barrier();
384#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
393#if PICO_ON_DEVICE && !defined(NDEBUG)
394 if (__get_current_exception()) {
395 panic(
"Attempted to sleep inside of an exception handler; use busy_wait if you must");
398#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
399 uint64_t t_us = to_us_since_boot(
t);
402 if (t_before_us > t_us) t_before_us = 0;
404 update_us_since_boot(&t_before, t_before_us);
405 if (absolute_time_diff_us(get_absolute_time(), t_before) > 0) {
406 if (add_alarm_at(t_before, sleep_until_callback,
NULL,
false) >= 0) {
423#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
444#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
445 if (__get_current_exception()) {
470 (int64_t)to_us_since_boot(timeout_timestamp))) {
477 id = add_alarm_at(timeout_timestamp, sleep_until_callback,
NULL,
false);
503 out->callback = callback;
505 out->user_data = user_data;
508 return out->alarm_id > 0;
513 if (
timer->alarm_id) {
533 int16_t index = alarm_index(alarm_id);
534 if ((uint16_t)index < pool->num_entries) {
535 uint16_t sequence = alarm_sequence(alarm_id);
540 while (search_index >= 0) {
541 entry = &pool->
entries[search_index];
542 if (index == search_index) {
544 rc = entry->
target - (int64_t) ta_time_us_64(pool->
timer);
548 search_index = entry->
next;
558 if (rc >= 0) rc /= 1000;
559 return rc >= INT32_MAX ? INT32_MAX : (int32_t) rc;
562#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
#define invalid_params_if(x, test)
bool alarm_pool_cancel_alarm(alarm_pool_t *pool, alarm_id_t alarm_id)
Cancel an alarm.
int64_t alarm_pool_remaining_alarm_time_us(alarm_pool_t *pool, alarm_id_t alarm_id)
Return the time remaining before the next trigger of an alarm.
int32_t alarm_pool_remaining_alarm_time_ms(alarm_pool_t *pool, alarm_id_t alarm_id)
Return the time remaining before the next trigger of an alarm.
#define PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM
Selects which timer_alarm is used for the default alarm pool.
uint alarm_pool_core_num(alarm_pool_t *pool)
Return the core number the alarm pool was initialized on (and hence callbacks are called on)
#define PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS
Selects the maximum number of concurrent timers in the default alarm pool.
alarm_pool_t * alarm_pool_get_default(void)
The default alarm pool used when alarms are added without specifying an alarm pool,...
int64_t remaining_alarm_time_us(alarm_id_t alarm_id)
Return the time remaining before the next trigger of an alarm.
int32_t remaining_alarm_time_ms(alarm_id_t alarm_id)
Return the time remaining before the next trigger of an alarm.
alarm_id_t alarm_pool_add_alarm_at_force_in_context(alarm_pool_t *pool, absolute_time_t time, alarm_callback_t callback, void *user_data)
Add an alarm callback to be called at or after a specific time.
int32_t alarm_id_t
The identifier for an alarm.
void alarm_pool_init_default(void)
Create the default alarm pool (if not already created or disabled)
alarm_id_t alarm_pool_add_alarm_at(alarm_pool_t *pool, absolute_time_t time, alarm_callback_t callback, void *user_data, bool fire_if_past)
Add an alarm callback to be called at a specific time.
int64_t(* alarm_callback_t)(alarm_id_t id, void *user_data)
User alarm callback.
void alarm_pool_destroy(alarm_pool_t *pool)
Destroy the alarm pool, cancelling all alarms and freeing up the underlying timer_alarm.
uint alarm_pool_timer_alarm_num(alarm_pool_t *pool)
Return the timer alarm used by an alarm pool.
#define delay_us(delay)
Delay in microseconds.
#define sync_internal_yield_until_before(until)
yield to other processing until some time before the requested time
#define lock_internal_spin_unlock_with_notify(lock, save)
Atomically unlock the lock's spin lock, and send a notification.
#define lock_internal_spin_unlock_with_wait(lock, save)
Atomically unlock the lock's spin lock, and wait for a notification.
void lock_init(lock_core_t *core, uint lock_num)
Initialise a lock structure.
@ PICO_ERROR_GENERIC
An unspecified error occurred.
bool(* repeating_timer_callback_t)(repeating_timer_t *rt)
Callback for a repeating timer.
bool alarm_pool_add_repeating_timer_us(alarm_pool_t *pool, int64_t delay_us, repeating_timer_callback_t callback, void *user_data, repeating_timer_t *out)
Add a repeating timer that is called repeatedly at the specified interval in microseconds.
bool cancel_repeating_timer(repeating_timer_t *timer)
Cancel a repeating timer.
void sleep_until(absolute_time_t t)
Wait until after the given timestamp to return.
void sleep_ms(uint32_t ms)
Wait for the given number of milliseconds before returning.
bool best_effort_wfe_or_timeout(absolute_time_t timeout_timestamp)
Helper method for blocking on a timeout.
void sleep_us(uint64_t us)
Wait for the given number of microseconds before returning.
const absolute_time_t nil_time
The timestamp representing a null timestamp.
const absolute_time_t at_the_end_of_time
The timestamp representing the end of time; this is actually not the maximum possible timestamp,...
uint64_t absolute_time_t
An opaque 64 bit timestamp in microseconds.
spin_lock_t * spin_lock_instance(uint lock_num)
#define PICO_SPINLOCK_ID_TIMER
uint32_t spin_lock_blocking(spin_lock_t *lock)
struct _spin_lock_t spin_lock_t
uint next_striped_spin_lock_num()
void spin_unlock(spin_lock_t *lock, uint32_t saved_irq)
void busy_wait_until(absolute_time_t t)
bool time_reached(absolute_time_t t)
void busy_wait_us(uint64_t delay_us)
#define PICO_RUNTIME_INIT_FUNC_RUNTIME(func, priority_string1, priority_string2)
void ta_enable_irq_handler(alarm_pool_timer_t *timer, uint hardware_alarm_num, void(*irq_handler)(void))
void ta_set_timeout(alarm_pool_timer_t *timer, uint hardware_alarm_num, int64_t target)
void ta_force_irq(alarm_pool_timer_t *timer, uint hardware_alarm_num)
void ta_clear_force_irq(alarm_pool_timer_t *timer, uint hardware_alarm_num)
int ta_hardware_alarm_claim_unused(alarm_pool_timer_t *timer, bool required)
uint ta_timer_num(alarm_pool_timer_t *timer)
alarm_pool_timer_t * ta_default_timer_instance(void)
void ta_hardware_alarm_claim(alarm_pool_timer_t *timer, uint hardware_alarm_num)
void ta_clear_irq(alarm_pool_timer_t *timer, uint hardware_alarm_num)
alarm_pool_timer_t * ta_from_current_irq(uint *alarm_num)
void ta_disable_irq_handler(alarm_pool_timer_t *timer, uint hardware_alarm_num, void(*irq_handler)(void))
#define TA_NUM_TIMER_ALARMS
alarm_pool_timer_t * ta_timer_instance(uint instance_num)
bool ta_wakes_up_on_or_before(alarm_pool_timer_t *timer, uint alarm_num, int64_t target)
btstack_timer_source_t timer
struct lock_core lock_core_t
void *REAL_FUNC malloc(size_t size)
void *REAL_FUNC calloc(size_t count, size_t size)
void REAL_FUNC free(void *mem)
#define PICO_RUNTIME_INIT_DEFAULT_ALARM_POOL
struct repeating_timer repeating_timer_t
void runtime_init_default_alarm_pool(void)
#define PICO_TIME_SLEEP_OVERHEAD_ADJUST_US
struct alarm_pool alarm_pool_t
struct alarm_pool_entry alarm_pool_entry_t
alarm_pool_t * alarm_pool_create_on_timer_with_unused_hardware_alarm(alarm_pool_timer_t *timer, uint max_timers)
alarm_pool_timer_t * alarm_pool_timer_for_timer_num(uint timer_num)
alarm_pool_t * alarm_pool_create_on_timer(alarm_pool_timer_t *timer, uint hardware_alarm_num, uint max_timers)
alarm_pool_timer_t * alarm_pool_get_default_timer(void)
#define repeating_timer_marker
void __weak runtime_init_default_alarm_pool(void)
alarm_callback_t callback
volatile uint16_t sequence
volatile int16_t new_head
alarm_pool_timer_t * timer
alarm_pool_entry_t * entries
volatile bool has_pending_cancellations
repeating_timer_callback_t callback