@web-font-path: "roboto-debian.css";
v2.2.0 (RP2040)
Loading...
Searching...
No Matches
time_adapter.h
/*
* Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_TIME_ADAPTER_H
#define _PICO_TIME_ADAPTER_H
#include "hardware/irq.h"
#include "hardware/timer.h"
#include "pico/assert.h"
#define TA_NUM_TIMERS NUM_GENERIC_TIMERS
#define TA_NUM_TIMER_ALARMS NUM_ALARMS
#define timer_hw_from_timer(t) ((timer_hw_t *)(t))
static inline void ta_force_irq(alarm_pool_timer_t *timer, uint alarm_num) {
hw_set_bits(&timer_hw_from_timer(timer)->intf, 1u << alarm_num);
}
static inline void ta_clear_force_irq(alarm_pool_timer_t *timer, uint alarm_num) {
hw_clear_bits(&timer_hw_from_timer(timer)->intf, 1u << alarm_num);
}
static inline void ta_clear_irq(alarm_pool_timer_t *timer, uint alarm_num) {
timer_hw_from_timer(timer)->intr = 1u << alarm_num;
}
static inline alarm_pool_timer_t *ta_from_current_irq(uint *alarm_num) {
uint irq_num = __get_current_exception() - VTABLE_FIRST_IRQ;
alarm_pool_timer_t *timer = timer_get_instance(TIMER_NUM_FROM_IRQ(irq_num));
*alarm_num = TIMER_ALARM_NUM_FROM_IRQ(irq_num);
return timer;
}
static inline void ta_set_timeout(alarm_pool_timer_t *timer, uint alarm_num, int64_t target) {
// We never want to set the timeout to be later than our current one.
uint32_t current = timer_time_us_32(timer_hw_from_timer(timer));
uint32_t time_til_target = (uint32_t) target - current;
uint32_t time_til_alarm = timer_hw_from_timer(timer)->alarm[alarm_num] - current;
// Note: we are only dealing with the low 32 bits of the timer values,
// so there is some opportunity to make wrap-around errors.
//
// 1. If we just passed the alarm time, then time_til_alarm will be high, meaning we will
// likely do the update, but this is OK since the alarm will have just fired
// 2. If we just passed the target time, then time_til_target will be high, meaning we will
// likely not do the update, but this is OK since the caller who has the full 64 bits
// must check if the target time has passed when we return anyway to avoid races.
// 3. We should never leave here without an alarm being armed
if (time_til_target < time_til_alarm || (timer_hw_from_timer(timer)->armed & (1 << alarm_num)) == 0) {
timer_hw_from_timer(timer)->alarm[alarm_num] = (uint32_t) target;
}
}
static inline bool ta_wakes_up_on_or_before(alarm_pool_timer_t *timer, uint alarm_num, int64_t target) {
int64_t current = (int64_t)timer_time_us_64(timer_hw_from_timer(timer));
int64_t time_til_target = target - current;
uint32_t time_til_alarm = timer_hw_from_timer(timer)->alarm[alarm_num] - (uint32_t)current;
return time_til_alarm <= time_til_target;
}
static inline uint64_t ta_time_us_64(alarm_pool_timer_t *timer) {
return timer_time_us_64(timer_hw_from_timer(timer));
}
static inline void ta_enable_irq_handler(alarm_pool_timer_t *timer, uint alarm_num, irq_handler_t irq_handler) {
// disarm the timer
uint irq_num = timer_hardware_alarm_get_irq_num(timer, alarm_num);
timer_hw_from_timer(timer)->armed = 1u << alarm_num;
irq_set_exclusive_handler(irq_num, irq_handler);
irq_set_enabled(irq_num, true);
hw_set_bits(&timer_hw_from_timer(timer)->inte, 1u << alarm_num);
}
static inline void ta_disable_irq_handler(alarm_pool_timer_t *timer, uint alarm_num, irq_handler_t irq_handler) {
uint irq_num = timer_hardware_alarm_get_irq_num(timer, alarm_num);
timer_hw_from_timer(timer)->armed = 1u << alarm_num; // disarm the timer
hw_clear_bits(&timer_hw_from_timer(timer)->inte, 1u << alarm_num);
irq_set_enabled(irq_num, true);
irq_remove_handler(irq_num, irq_handler);
timer_hardware_alarm_unclaim(timer, alarm_num);
}
static inline void ta_hardware_alarm_claim(alarm_pool_timer_t *timer, uint hardware_alaram_num) {
timer_hardware_alarm_claim(timer_hw_from_timer(timer), hardware_alaram_num);
}
static inline int ta_hardware_alarm_claim_unused(alarm_pool_timer_t *timer, bool required) {
return timer_hardware_alarm_claim_unused(timer, required);
}
static inline alarm_pool_timer_t *ta_timer_instance(uint timer_num) {
return timer_get_instance(timer_num);
}
static inline uint ta_timer_num(alarm_pool_timer_t *timer) {
return timer_get_index(timer_hw_from_timer(timer));
}
static inline alarm_pool_timer_t *ta_default_timer_instance(void) {
return PICO_DEFAULT_TIMER_INSTANCE();
}
#endif
hw_set_bits
static __force_inline void hw_set_bits(io_rw_32 *addr, uint32_t mask)
Atomically set the specified bits to 1 in a HW register.
Definition address_mapped.h:135
hw_clear_bits
static __force_inline void hw_clear_bits(io_rw_32 *addr, uint32_t mask)
Atomically clear the specified bits to 0 in a HW register.
Definition address_mapped.h:145
irq_set_enabled
void irq_set_enabled(uint num, bool enabled)
Enable or disable a specific interrupt on the executing core.
Definition irq.c:60
irq_handler_t
void(* irq_handler_t)(void)
Interrupt handler function type.
Definition irq.h:195
irq_remove_handler
void irq_remove_handler(uint num, irq_handler_t handler)
Remove a specific interrupt handler for the given irq number on the executing core.
Definition irq.c:485
irq_set_exclusive_handler
void irq_set_exclusive_handler(uint num, irq_handler_t handler)
Set an exclusive interrupt handler for an interrupt on the executing core.
Definition irq.c:231
timer_get_instance
static timer_hw_t * timer_get_instance(uint timer_num)
Returns the timer instance with the given timer number.
Definition timer.h:590
timer_time_us_32
static uint32_t timer_time_us_32(timer_hw_t *timer)
Return a 32 bit timestamp value in microseconds for a given timer instance.
Definition timer.h:202
timer_hardware_alarm_get_irq_num
static uint timer_hardware_alarm_get_irq_num(timer_hw_t *timer, uint alarm_num)
Returns the irq_num_t for the alarm interrupt from the given alarm on the given timer instance.
Definition timer.h:557
timer_get_index
static uint timer_get_index(timer_hw_t *timer)
Returns the timer number for a timer instance.
Definition timer.h:579
timer_hardware_alarm_claim_unused
int timer_hardware_alarm_claim_unused(timer_hw_t *timer, bool required)
cooperatively claim the use of a hardware alarm_num on the given timer instance
Definition timer.c:48
PICO_DEFAULT_TIMER_INSTANCE
#define PICO_DEFAULT_TIMER_INSTANCE()
Returns the default timer instance on the platform based on the setting of PICO_DEFAULT_TIMER.
Definition timer.h:182
timer_time_us_64
uint64_t timer_time_us_64(timer_hw_t *timer)
Return the current 64 bit timestamp value in microseconds for a given timer instance.
Definition timer.c:57
timer_hardware_alarm_claim
void timer_hardware_alarm_claim(timer_hw_t *timer, uint alarm_num)
cooperatively claim the use of this hardware alarm_num on the given timer instance
Definition timer.c:21
TIMER_NUM_FROM_IRQ
#define TIMER_NUM_FROM_IRQ(irq_num)
Returns the alarm number from an irq_num_t. See TIMER_INSTANCE_NUM_FROM_IRQ to get the alarm number.
Definition timer.h:147
timer_hardware_alarm_unclaim
void timer_hardware_alarm_unclaim(timer_hw_t *timer, uint alarm_num)
cooperatively release the claim on use of this hardware alarm_num on the given timer instance
Definition timer.c:30
TIMER_ALARM_NUM_FROM_IRQ
#define TIMER_ALARM_NUM_FROM_IRQ(irq_num)
Returns the alarm number from an irq_num_t. See TIMER_INSTANCE_NUM_FROM_IRQ to get the timer instance...
Definition timer.h:129
__get_current_exception
static __force_inline uint __get_current_exception(void)
Get the current exception level on this core.
Definition platform.h:131
irq.h
timer.h