system_timer
chre/platform/include/chre/platform/system_timer.h
#include "chre/target_platform/system_timer_base.h"
#include "chre/util/non_copyable.h"
#include "chre/util/time.h"
namespace chre {
/**
* The function signature of a timer callback.
*
* @param The data pointer here is passed in by the entity that requested the
* timer and is used to provided a context in the callback.
*/
typedef void (SystemTimerCallback)(void *data);
/**
* Abstracts a system timer from the underlying platform, which will invoke the
* supplied callback after at least the given amount of time has passed. The
* calling context for the callback is undefined, and may be inside an
* interrupt, or in a different thread, etc. Therefore, the callback is
* responsible for ensuring that it handles this potential concurrency
* appropriately.
*/
class SystemTimer : public SystemTimerBase,
public NonCopyable {
/**
* Initializes the timer. This must be called before other methods in this
* class are called.
*
* @return true on successful, false on failure
*/
bool init();
/**
* Sets the timer to expire after the given delay. If the timer was already
* running, its expiry time is updated to this value.
*
* Note that it is possible for the timer to fire before this function
* returns.
*
* @param callback The callback to invoke when the timer has elapsed.
* @param data The data to pass to the callback when it is invoked.
* @param delay The minimum delay until the first firing of the timer.
* @return true on success, false on failure
*/
bool set(SystemTimerCallback *callback, void *data, Nanoseconds delay);
private:
//! The callback to invoke when the timer has elapsed.
SystemTimerCallback *mCallback;
//! The data to pass to the callback when invoked.
void *mData;
}
SystemTimerBase
//chre/platform/slpi/include/chre/target_platform/system_timer_base.h
class SystemTimerBase {
public:
//! The underlying QURT timer.
SlpiTimerHandle mTimerHandle;
//! Tracks whether the timer has been initialized correctly.
bool mInitialized = false;
//! A static method that is invoked by the underlying QURT timer.
static void systemTimerNotifyCallback(SlpiTimerCallbackDataType data);
};
system_timer的实现
构造函数
SystemTimer::SystemTimer() {}
init
bool SystemTimer::init() {
if (mInitialized) {
LOGW("Tried re-initializing timer");
} else {
SlpiTimerErrorType status = timer_def_osal(
&mTimerHandle, &timer_non_defer_group, TIMER_FUNC1_CB_TYPE,
reinterpret_cast<time_osal_notify_obj_ptr>(systemTimerNotifyCallback),
reinterpret_cast<time_osal_notify_data>(this));
if (status != SLPI_TIMER_SUCCESS) {
LOGE("Error initializing timer %d", status);
} else {
mInitialized = true;
}
}
return mInitialized;
}
// core/services/time/src/timer_client.c
/**
Defines and initializes a timer.
Please refer timer.h
*/
timer_error_type timer_def_osal
(
timer_ptr_type timer,
timer_group_ptr group,
timer_notify_type cb_type,
time_osal_notify_obj_ptr sigs_func_addr,
time_osal_notify_data sigs_mask_data
)
{
//group being NULL is allowed for timer_def, timer_def2
return timer_invoke_def_osal(timer_client_qdi_handle, timer, group, cb_type, sigs_func_addr, sigs_mask_data);
}
//./core/services/time/src/timer_qdi_v.h
static inline timer_error_type timer_invoke_def_osal(
int handle,
timer_ptr_type timer,
timer_group_ptr group,
timer_notify_type cb_type,
time_osal_notify_obj_ptr sigs_func_addr,
time_osal_notify_data sigs_mask_data)
{
return qurt_qdi_handle_invoke(handle, TIMER_QDI_DEF_OSAL, timer, group, cb_type, sigs_func_addr, sigs_mask_data);
}
// int qurt_qdi_handle_invoke();
#define qurt_qdi_handle_invoke(h,m,...) \
_QDMPASTE(_QDMHI,_QDMCNT(QDI_HANDLE_LOCAL_CLIENT,h,m,##__VA_ARGS__))(QDI_HANDLE_LOCAL_CLIENT,h,m,##__VA_ARGS__)
//core/api/kernel/qurt/qurt_qdi.h
/**@ingroup driver_interface
Performs a generic driver operation, which (depending on the specified operation) can be
either be one of the predefined operations listed in Table 2-1, or a driver-specific
operation.
The user provides a QDI handle and an integer
method number, along with 0 to 8 optional 32-bit arguments.
The device driver invocation function is invoked with the
same method number and 0 to 8 optional arguments, and the
return value from the invocation function is passed back to
the user as the return value of qurt_qdi_handle_invoke.
@note1hang For reasons related to the Hexagon standard for varargs functions, the
qurt_qdi_handle_invoke function prototype is not actually defined as a
varargs function (and in fact would break if it were defined this way).
@param h Integer handle to a QDI device driver.
@param m Integer method number passed to the device driver.
@param ... Arguments can be passed as operation-specific parameters: \n
arg1 -- Optional 1st parameter to device driver \n
arg2 Optional 2nd parameter to device driver \n
arg3 Optional 3rd parameter to device driver \n
arg4 Optional 4th parameter to device driver \n
arg5 Optional 5th parameter to device driver \n
arg6 Optional 6th parameter to device driver \n
arg7 Optional 7th parameter to device driver \n
arg8 Optional 8th parameter to device driver
@return
Integer value defined by the device driver itself. \n
-1 -- Error.
@dependencies
None.
*/
set
bool SystemTimer::set(SystemTimerCallback *callback, void *data,
Nanoseconds delay) {
bool wasSet = false;
if (mInitialized) {
mCallback = callback;
mData = data;
SlpiTimerErrorType status = slpiTimerSet64(&mTimerHandle,
Microseconds(delay).getMicroseconds(), 0, SlpiTimerMicroUnit);
if (status != SLPI_TIMER_SUCCESS) {
LOGE("Error setting timer %d", status);
} else {
wasSet = true;
}
}
return wasSet;
}
callback
void SystemTimerBase::systemTimerNotifyCallback(SlpiTimerCallbackDataType data) {
SystemTimer *systemTimer = reinterpret_cast<SystemTimer *>(data);
systemTimer->mCallback(systemTimer->mData);
}