mirror of https://github.com/ARMmbed/mbed-os.git
256 lines
8.4 KiB
C
256 lines
8.4 KiB
C
|
/*
|
||
|
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
|
||
|
* SPDX-License-Identifier: Apache-2.0
|
||
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||
|
* not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
#ifndef EVENTOS_EVENT_TIMER_H_
|
||
|
#define EVENTOS_EVENT_TIMER_H_
|
||
|
#ifdef __cplusplus
|
||
|
extern "C" {
|
||
|
#endif
|
||
|
#include "ns_types.h"
|
||
|
#include "eventOS_event.h"
|
||
|
|
||
|
struct arm_event_s;
|
||
|
typedef struct sys_timer_struct_s sys_timer_struct_t;
|
||
|
|
||
|
/* 100 Hz ticker, so 10 milliseconds per tick */
|
||
|
#define EVENTOS_EVENT_TIMER_HZ 100
|
||
|
|
||
|
static inline uint32_t eventOS_event_timer_ticks_to_ms(uint32_t ticks)
|
||
|
{
|
||
|
NS_STATIC_ASSERT(1000 % EVENTOS_EVENT_TIMER_HZ == 0, "Assuming whole number of ms per tick")
|
||
|
return ticks * (1000 / EVENTOS_EVENT_TIMER_HZ);
|
||
|
}
|
||
|
|
||
|
/* Convert ms to ticks, rounding up (so 9ms = 1 tick, 10ms = 1 tick, 11ms = 2 ticks) */
|
||
|
static inline uint32_t eventOS_event_timer_ms_to_ticks(uint32_t ms)
|
||
|
{
|
||
|
NS_STATIC_ASSERT(1000 % EVENTOS_EVENT_TIMER_HZ == 0, "Assuming whole number of ms per tick")
|
||
|
return (ms + (1000 / EVENTOS_EVENT_TIMER_HZ) - 1) / (1000 / EVENTOS_EVENT_TIMER_HZ);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Read current timer tick count.
|
||
|
*
|
||
|
* Can be used as a monotonic time source, and to schedule events with
|
||
|
* eventOS_event_timer_send.
|
||
|
*
|
||
|
* Note that the value will wrap, so take care on comparisons.
|
||
|
*
|
||
|
* \return tick count.
|
||
|
*/
|
||
|
extern uint32_t eventOS_event_timer_ticks(void);
|
||
|
|
||
|
/* Comparison macros handling wrap efficiently (assuming a conventional compiler
|
||
|
* which converts 0x80000000 to 0xFFFFFFFF to negative when casting to int32_t).
|
||
|
*/
|
||
|
#define TICKS_AFTER(a, b) ((int32_t) ((a)-(b)) > 0)
|
||
|
#define TICKS_BEFORE(a, b) ((int32_t) ((a)-(b)) < 0)
|
||
|
#define TICKS_AFTER_OR_AT(a, b) ((int32_t) ((a)-(b)) >= 0)
|
||
|
#define TICKS_BEFORE_OR_AT(a, b) ((int32_t) ((a)-(b)) <= 0)
|
||
|
|
||
|
/**
|
||
|
* Send an event after time expired (in milliseconds)
|
||
|
*
|
||
|
* Note that the current implementation has the "feature" that rounding
|
||
|
* varies depending on the precise timing requested:
|
||
|
* 0-20 ms => 2 x 10ms tick
|
||
|
* 21-29 ms => 3 x 10ms tick
|
||
|
* 30-39 ms => 4 x 10ms tick
|
||
|
* 40-49 ms => 5 x 10ms tick
|
||
|
* ... etc
|
||
|
*
|
||
|
* For improved flexibility on the event, and for more control of time,
|
||
|
* you should use eventOS_event_timer_request_at().
|
||
|
*
|
||
|
* \param event_id event_id for event
|
||
|
* \param event_type event_type for event
|
||
|
* \param tasklet_id receiver for event
|
||
|
* \param time time to sleep in milliseconds
|
||
|
*
|
||
|
* \return 0 on success
|
||
|
* \return -1 on error (invalid tasklet_id or allocation failure)
|
||
|
*
|
||
|
* */
|
||
|
extern int8_t eventOS_event_timer_request(uint8_t event_id, uint8_t event_type, int8_t tasklet_id, uint32_t time);
|
||
|
|
||
|
/**
|
||
|
* Send an event at specified time
|
||
|
*
|
||
|
* The event will be sent when eventOS_event_timer_ticks() reaches the
|
||
|
* specified value.
|
||
|
*
|
||
|
* If the specified time is in the past (ie "at" is before or at the current
|
||
|
* tick value), the event will be sent immediately.
|
||
|
*
|
||
|
* Can also be invoked using the eventOS_event_send_at() macro in eventOS_event.h
|
||
|
*
|
||
|
* \param event event to send
|
||
|
* \param at absolute tick time to run event at
|
||
|
*
|
||
|
* \return pointer to timer structure on success
|
||
|
* \return NULL on error (invalid tasklet_id or allocation failure)
|
||
|
*
|
||
|
*/
|
||
|
extern arm_event_storage_t *eventOS_event_timer_request_at(const struct arm_event_s *event, uint32_t at);
|
||
|
|
||
|
/**
|
||
|
* Send an event in a specified time
|
||
|
*
|
||
|
* The event will be sent in the specified number of ticks - to
|
||
|
* be precise, it is equivalent to requesting an event at
|
||
|
*
|
||
|
* eventOS_event_timer_ticks() + ticks
|
||
|
*
|
||
|
* Because of timer granularity, the elapsed time between issuing the request
|
||
|
* and it running may be up to 1 tick less than the specified time.
|
||
|
*
|
||
|
* eg requesting 2 ticks will cause the event to be sent on the second tick from
|
||
|
* now. If requested just after a tick, the delay will be nearly 2 ticks, but if
|
||
|
* requested just before a tick, the delay will be just over 1 tick.
|
||
|
*
|
||
|
* If `in` is <= 0, the event will be sent immediately.
|
||
|
*
|
||
|
* Can also be invoked using the eventOS_event_send_in() macro in eventOS_event.h
|
||
|
*
|
||
|
* \param event event to send
|
||
|
* \param in tick delay for event
|
||
|
*
|
||
|
* \return pointer to timer structure on success
|
||
|
* \return NULL on error (invalid tasklet_id or allocation failure)
|
||
|
*
|
||
|
*/
|
||
|
extern arm_event_storage_t *eventOS_event_timer_request_in(const struct arm_event_s *event, int32_t in);
|
||
|
|
||
|
/**
|
||
|
* Send an event after a specified time
|
||
|
*
|
||
|
* The event will be sent after the specified number of ticks - to
|
||
|
* be precise, it is equivalent to requesting an event at
|
||
|
*
|
||
|
* eventOS_event_timer_ticks() + ticks + 1
|
||
|
*
|
||
|
* Because of timer granularity, the elapsed time between issuing the request
|
||
|
* and it running may be up to 1 tick more than the specified time.
|
||
|
*
|
||
|
* eg requesting 2 ticks will cause the event to be sent on the third tick from
|
||
|
* now. If requested just after a tick, the delay will be nearly 3 ticks, but if
|
||
|
* requested just before a tick, the delay will be just over 2 ticks.
|
||
|
*
|
||
|
* If `after` is < 0, the event will be sent immediately. If it is 0, the event
|
||
|
* is sent on the next tick.
|
||
|
*
|
||
|
* Can also be invoked using the eventOS_event_send_after() macro in eventOS_event.h
|
||
|
*
|
||
|
* \param event event to send
|
||
|
* \param after tick delay for event
|
||
|
*
|
||
|
* \return pointer to timer structure on success
|
||
|
* \return NULL on error (invalid tasklet_id or allocation failure)
|
||
|
*
|
||
|
*/
|
||
|
#define eventOS_event_timer_request_after(event, after) \
|
||
|
eventOS_event_timer_request_in(event, (after) + 1)
|
||
|
|
||
|
/**
|
||
|
* Send an event periodically
|
||
|
*
|
||
|
* The event will be sent repeatedly using the specified ticks period.
|
||
|
*
|
||
|
* The first call is sent at
|
||
|
*
|
||
|
* eventOS_event_timer_ticks() + ticks
|
||
|
*
|
||
|
* Subsequent events will be sent at N*ticks from the initial time.
|
||
|
*
|
||
|
* Period will be maintained while the device is awake, regardless of delays to
|
||
|
* event scheduling. If an event has not been delivered and completed by the
|
||
|
* next scheduled time, the next event will be sent immediately when it
|
||
|
* finishes. This could cause a continuous stream of events if unable to keep
|
||
|
* up with the period.
|
||
|
*
|
||
|
* Can also be invoked using the eventOS_event_send_every() macro in eventOS_event.h
|
||
|
*
|
||
|
* \param event event to send
|
||
|
* \param period period for event
|
||
|
*
|
||
|
* \return pointer to timer structure on success
|
||
|
* \return NULL on error (invalid tasklet_id or allocation failure)
|
||
|
*
|
||
|
*/
|
||
|
extern arm_event_storage_t *eventOS_event_timer_request_every(const struct arm_event_s *event, int32_t period);
|
||
|
|
||
|
/**
|
||
|
* Cancel an event timer
|
||
|
*
|
||
|
* This cancels a pending timed event, matched by event_id and tasklet_id.
|
||
|
*
|
||
|
* \param event_id event_id for event
|
||
|
* \param tasklet_id receiver for event
|
||
|
*
|
||
|
* \return 0 on success
|
||
|
* \return -1 on error (event not found)
|
||
|
*
|
||
|
* */
|
||
|
extern int8_t eventOS_event_timer_cancel(uint8_t event_id, int8_t tasklet_id);
|
||
|
|
||
|
/**
|
||
|
* System Timer shortest time in milli seconds
|
||
|
*
|
||
|
* \param ticks Time in 10 ms resolution
|
||
|
*
|
||
|
* \return none
|
||
|
*
|
||
|
* */
|
||
|
extern uint32_t eventOS_event_timer_shortest_active_timer(void);
|
||
|
|
||
|
|
||
|
/** Timeout structure. Not to be modified by user */
|
||
|
typedef struct timeout_entry_t timeout_t;
|
||
|
|
||
|
/** Request timeout callback.
|
||
|
*
|
||
|
* Create timeout request for specific callback.
|
||
|
*
|
||
|
* \param ms timeout in milliseconds. Maximum range is same as for eventOS_event_timer_request().
|
||
|
* \param callback function to call after timeout
|
||
|
* \param arg arquement to pass to callback
|
||
|
* \return pointer to timeout structure or NULL on errors
|
||
|
*/
|
||
|
timeout_t *eventOS_timeout_ms(void (*callback)(void *), uint32_t ms, void *arg);
|
||
|
|
||
|
/** Request periodic callback.
|
||
|
*
|
||
|
* Create timeout request for specific callback. Called periodically until eventOS_timeout_cancel() is called.
|
||
|
*
|
||
|
* \param every period in milliseconds. Maximum range is same as for eventOS_event_timer_request().
|
||
|
* \param callback function to call after timeout
|
||
|
* \param arg arquement to pass to callback
|
||
|
* \return pointer to timeout structure or NULL on errors
|
||
|
*/
|
||
|
timeout_t *eventOS_timeout_every_ms(void (*callback)(void *), uint32_t every, void *arg);
|
||
|
|
||
|
/** Cancell timeout request.
|
||
|
*
|
||
|
* \param t timeout request id.
|
||
|
*/
|
||
|
void eventOS_timeout_cancel(timeout_t *t);
|
||
|
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#endif /* EVENTOS_EVENT_TIMER_H_ */
|