Compare commits
13 Commits
master
...
developmen
| Author | SHA1 | Date |
|---|---|---|
|
|
5f06643d12 | 4 years ago |
|
|
ae72a97e89 | 4 years ago |
|
|
180ccdddd3 | 4 years ago |
|
|
c00bfce360 | 4 years ago |
|
|
b703fdd6f3 | 4 years ago |
|
|
cf428a0b95 | 4 years ago |
|
|
72bef4fbe1 | 4 years ago |
|
|
73e1855b9d | 4 years ago |
|
|
242dffa9dd | 4 years ago |
|
|
6208dc71fc | 4 years ago |
|
|
ff1a4dff8f | 4 years ago |
|
|
1f9be39c77 | 4 years ago |
|
|
1dc788f79f | 4 years ago |
@ -0,0 +1,82 @@
|
||||
#include "MultiTimer.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/* Timer handle list head. */
|
||||
static MultiTimer* timerList = NULL;
|
||||
|
||||
/* Timer tick */
|
||||
static PlatformTicksFunction_t platformTicksFunction = NULL;
|
||||
|
||||
int MultiTimerInstall(PlatformTicksFunction_t ticksFunc)
|
||||
{
|
||||
platformTicksFunction = ticksFunc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MultiTimerStart(MultiTimer* timer, uint64_t timing, MultiTimerCallback_t callback, void* userData)
|
||||
{
|
||||
if (!timer || !callback ) {
|
||||
return -1;
|
||||
}
|
||||
MultiTimer** nextTimer = &timerList;
|
||||
/* Remove the existing target timer. */
|
||||
for (; *nextTimer; nextTimer = &(*nextTimer)->next) {
|
||||
if (timer == *nextTimer) {
|
||||
*nextTimer = timer->next; /* remove from list */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Init timer. */
|
||||
timer->deadline = platformTicksFunction() + timing;
|
||||
timer->callback = callback;
|
||||
timer->userData = userData;
|
||||
|
||||
/* Insert timer. */
|
||||
for (nextTimer = &timerList;; nextTimer = &(*nextTimer)->next) {
|
||||
if (!*nextTimer) {
|
||||
timer->next = NULL;
|
||||
*nextTimer = timer;
|
||||
break;
|
||||
}
|
||||
if (timer->deadline < (*nextTimer)->deadline) {
|
||||
timer->next = *nextTimer;
|
||||
*nextTimer = timer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MultiTimerStop(MultiTimer* timer)
|
||||
{
|
||||
MultiTimer** nextTimer = &timerList;
|
||||
/* Find and remove timer. */
|
||||
for (; *nextTimer; nextTimer = &(*nextTimer)->next) {
|
||||
MultiTimer* entry = *nextTimer;
|
||||
if (entry == timer) {
|
||||
*nextTimer = timer->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MultiTimerYield(void)
|
||||
{
|
||||
MultiTimer* entry = timerList;
|
||||
for (; entry; entry = entry->next) {
|
||||
/* Sorted list, just process with the front part. */
|
||||
if (platformTicksFunction() < entry->deadline) {
|
||||
return (int)(entry->deadline - platformTicksFunction());
|
||||
}
|
||||
/* remove expired timer from list */
|
||||
timerList = entry->next;
|
||||
|
||||
/* call callback */
|
||||
if (entry->callback) {
|
||||
entry->callback(entry, entry->userData);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2021 0x1abin
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _MULTI_TIMER_H_
|
||||
#define _MULTI_TIMER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint64_t (*PlatformTicksFunction_t)(void);
|
||||
|
||||
typedef struct MultiTimerHandle MultiTimer;
|
||||
|
||||
typedef void (*MultiTimerCallback_t)(MultiTimer* timer, void* userData);
|
||||
|
||||
struct MultiTimerHandle {
|
||||
MultiTimer* next;
|
||||
uint64_t deadline;
|
||||
MultiTimerCallback_t callback;
|
||||
void* userData;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Platform ticks function.
|
||||
*
|
||||
* @param ticksFunc ticks function.
|
||||
* @return int 0 on success, -1 on error.
|
||||
*/
|
||||
int MultiTimerInstall(PlatformTicksFunction_t ticksFunc);
|
||||
|
||||
/**
|
||||
* @brief Start the timer work, add the handle into work list.
|
||||
*
|
||||
* @param timer target handle strcut.
|
||||
* @param timing Set the start time.
|
||||
* @param callback deadline callback.
|
||||
* @param userData user data.
|
||||
* @return int 0: success, -1: fail.
|
||||
*/
|
||||
int MultiTimerStart(MultiTimer* timer, uint64_t timing, MultiTimerCallback_t callback, void* userData);
|
||||
|
||||
/**
|
||||
* @brief Stop the timer work, remove the handle off work list.
|
||||
*
|
||||
* @param timer target handle strcut.
|
||||
* @return int 0: success, -1: fail.
|
||||
*/
|
||||
int MultiTimerStop(MultiTimer* timer);
|
||||
|
||||
/**
|
||||
* @brief Check the timer expried and call callback.
|
||||
*
|
||||
* @return int The next timer expires.
|
||||
*/
|
||||
int MultiTimerYield(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -1,34 +0,0 @@
|
||||
#include "multi_timer.h"
|
||||
|
||||
struct Timer timer1;
|
||||
struct Timer timer2;
|
||||
|
||||
void timer1_callback(void *arg)
|
||||
{
|
||||
printf("timer1 timeout! arg: %p\r\n", arg);
|
||||
}
|
||||
|
||||
void timer2_callback(void *arg)
|
||||
{
|
||||
printf("timer2 timeout! arg: %p\r\n", arg);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
timer_init(&timer1, timer1_callback, 1000, 1000, NULL); //1s loop
|
||||
timer_start(&timer1);
|
||||
|
||||
timer_init(&timer2, timer2_callback, 50, 0, NULL); //50ms delay
|
||||
timer_start(&timer2);
|
||||
|
||||
while(1) {
|
||||
timer_loop();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HAL_SYSTICK_Callback(void)
|
||||
{
|
||||
timer_ticks(); //1ms ticks
|
||||
}
|
||||
@ -1,92 +1,45 @@
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "../MultiTimer.h"
|
||||
|
||||
#include "../multi_timer.h"
|
||||
MultiTimer timer1;
|
||||
MultiTimer timer2;
|
||||
MultiTimer timer3;
|
||||
|
||||
#define LOG_TIMESTAMP_FORMAT "[%Y-%m-%d %H:%M:%S]"
|
||||
#define LOG_TIMESTAMP_LEN 21
|
||||
#define MS_TIMESTAMP_LEN 5
|
||||
|
||||
int32_t printf_timestamp(const char *msg, ...)
|
||||
uint64_t PlatformTicksGetFunc(void)
|
||||
{
|
||||
char content[1024] = {0};
|
||||
time_t time_write;
|
||||
struct tm tm_Log;
|
||||
struct timeval t;
|
||||
uint32_t len = 0;
|
||||
va_list vl_list;
|
||||
|
||||
time_write = time(NULL);
|
||||
localtime_r(&time_write, &tm_Log);
|
||||
strftime((char *)&content[len], sizeof(content) - len - 1, LOG_TIMESTAMP_FORMAT, &tm_Log);
|
||||
len = strlen(&content[len]);
|
||||
|
||||
/* .msec] */
|
||||
gettimeofday(&t, NULL);
|
||||
len--; // min a ']' char
|
||||
snprintf((char*)&content[len], sizeof(content) - len, ".%03d]", (int)(t.tv_usec / 1000));
|
||||
len += MS_TIMESTAMP_LEN;
|
||||
|
||||
va_start(vl_list, msg);
|
||||
vsnprintf((char *)&content[len], sizeof(content) - len - 1, (const char *)msg, vl_list);
|
||||
va_end(vl_list);
|
||||
|
||||
printf("%s", content);
|
||||
|
||||
return 0;
|
||||
struct timespec current_time;
|
||||
clock_gettime(CLOCK_MONOTONIC, ¤t_time);
|
||||
return (uint64_t)((current_time.tv_sec * 1000) + (current_time.tv_nsec / 1000000));
|
||||
}
|
||||
|
||||
void signalHandler(int signo)
|
||||
void exampleTimer1Callback(MultiTimer* timer, void *userData)
|
||||
{
|
||||
switch(signo)
|
||||
{
|
||||
case SIGALRM:
|
||||
timer_ticks();
|
||||
//printf_timestamp("Caught the SIGALRM signal every 1ms !\n");
|
||||
break;
|
||||
}
|
||||
printf("[%012ld] Timer:%p callback-> %s.\r\n", PlatformTicksGetFunc(), timer, (char*)userData);
|
||||
MultiTimerStart(timer, 1000, exampleTimer1Callback, userData);
|
||||
}
|
||||
|
||||
struct Timer timer1;
|
||||
struct Timer timer2;
|
||||
|
||||
void timer1_callback(void *arg)
|
||||
void exampleTimer2Callback(MultiTimer* timer, void *userData)
|
||||
{
|
||||
printf_timestamp("timer1 timeout! arg: %p\r\n", arg);
|
||||
printf("[%012ld] Timer:%p callback-> %s.\r\n", PlatformTicksGetFunc(), timer, (char*)userData);
|
||||
}
|
||||
|
||||
void timer2_callback(void *arg)
|
||||
void exampleTimer3Callback(MultiTimer* timer, void *userData)
|
||||
{
|
||||
printf_timestamp("timer2 timeout! arg: %p\r\n", arg);
|
||||
printf("[%012ld] Timer:%p callback-> %s.\r\n", PlatformTicksGetFunc(), timer, (char*)userData);
|
||||
MultiTimerStart(timer, 4567, exampleTimer3Callback, userData);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf_timestamp("%s start ...\r\n", __func__);
|
||||
|
||||
signal(SIGALRM, signalHandler);
|
||||
|
||||
struct itimerval new_value, old_value;
|
||||
new_value.it_value.tv_sec = 0; // should be 0x00 !!!
|
||||
new_value.it_value.tv_usec = 1; // non-zero is OK !!!
|
||||
new_value.it_interval.tv_sec = 0;
|
||||
new_value.it_interval.tv_usec = 1000 * CFG_TIMER_1_TICK_N_MS; // 1ms
|
||||
setitimer(ITIMER_REAL, &new_value, &old_value);
|
||||
MultiTimerInstall(PlatformTicksGetFunc);
|
||||
|
||||
timer_init(&timer1, timer1_callback, 4000, 1000, &timer1); // start timer after 4s
|
||||
timer_start(&timer1);
|
||||
MultiTimerStart(&timer1, 1000, exampleTimer1Callback, "1000ms CYCLE timer");
|
||||
MultiTimerStart(&timer2, 5000, exampleTimer2Callback, "5000ms ONCE timer");
|
||||
MultiTimerStart(&timer3, 3456, exampleTimer3Callback, "3456ms delay start, 4567ms CYCLE timer");
|
||||
|
||||
timer_init(&timer2, timer2_callback, 0, 5000, &timer2); // start timer right now
|
||||
timer_start(&timer2);
|
||||
|
||||
while(1) {
|
||||
/* Maybe some sleep time is needed to avoid running CPU all the time. */
|
||||
timer_loop();
|
||||
while (1) {
|
||||
MultiTimerYield();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Zibin Zheng <znbin@qq.com>
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "multi_timer.h"
|
||||
|
||||
//timer handle list head.
|
||||
static struct Timer* head_handle = NULL;
|
||||
|
||||
//Timer ticks
|
||||
//static uint32_t _timer_ticks = (1 << 32)- 1000; // only for test tick clock overflow
|
||||
static uint32_t _timer_ticks = 0;
|
||||
|
||||
/**
|
||||
* @brief Initializes the timer struct handle.
|
||||
* @param handle: the timer handle strcut.
|
||||
* @param timeout_cb: timeout callback.
|
||||
* @param timeout: delay to start the timer.
|
||||
* @param repeat: repeat interval time.
|
||||
* @param arg: the input argument for timeout_cb fucntion.
|
||||
* @retval None
|
||||
*/
|
||||
void timer_init(struct Timer* handle, void (*timeout_cb)(void *arg), \
|
||||
uint32_t timeout, uint32_t repeat, void *arg)
|
||||
{
|
||||
// memset(handle, sizeof(struct Timer), 0);
|
||||
handle->timeout_cb = timeout_cb;
|
||||
handle->timeout = timeout;
|
||||
handle->repeat = repeat;
|
||||
handle->cur_ticks = _timer_ticks;
|
||||
handle->cur_expired_time = handle->timeout;
|
||||
handle->arg = arg;
|
||||
//printf("cur_ticks: %u, cur_expired_time: %u, _timer_ticks: %u, timeout: %u\r\n",
|
||||
// handle->cur_ticks, handle->cur_expired_time, _timer_ticks, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start the timer work, add the handle into work list.
|
||||
* @param btn: target handle strcut.
|
||||
* @retval 0: succeed. -1: already exist.
|
||||
*/
|
||||
int timer_start(struct Timer* handle)
|
||||
{
|
||||
struct Timer* target = head_handle;
|
||||
|
||||
while(target) {
|
||||
if(target == handle) {
|
||||
return -1; //already exist.
|
||||
}
|
||||
target = target->next;
|
||||
}
|
||||
handle->next = head_handle;
|
||||
head_handle = handle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop the timer work, remove the handle off work list.
|
||||
* @param handle: target handle strcut.
|
||||
* @retval 0: succeed. -1: timer not exist.
|
||||
*/
|
||||
int timer_stop(struct Timer* handle)
|
||||
{
|
||||
struct Timer** curr;
|
||||
|
||||
for(curr = &head_handle; *curr;) {
|
||||
struct Timer* entry = *curr;
|
||||
if(entry == handle) {
|
||||
*curr = entry->next;
|
||||
//free(entry);
|
||||
return 0; // found specified timer
|
||||
} else {
|
||||
curr = &entry->next;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief main loop.
|
||||
* @param None.
|
||||
* @retval None
|
||||
*/
|
||||
void timer_loop(void)
|
||||
{
|
||||
struct Timer* target;
|
||||
|
||||
for(target = head_handle; target; target = target->next) {
|
||||
/*
|
||||
More detail on tick-clock overflow, please see https://blog.csdn.net/szullc/article/details/115332326
|
||||
*/
|
||||
if(_timer_ticks - target->cur_ticks >= target->cur_expired_time) {
|
||||
//printf("cur_ticks: %u, cur_expired_time: %u, _timer_ticks: %u\r\n",
|
||||
// target->cur_ticks, target->cur_expired_time, _timer_ticks);
|
||||
if(target->repeat == 0) {
|
||||
timer_stop(target);
|
||||
} else {
|
||||
target->cur_ticks = _timer_ticks;
|
||||
target->cur_expired_time = target->repeat;
|
||||
}
|
||||
target->timeout_cb(target->arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief background ticks, timer repeat invoking interval nms.
|
||||
* @param None.
|
||||
* @retval None.
|
||||
*/
|
||||
void timer_ticks(void)
|
||||
{
|
||||
_timer_ticks += CFG_TIMER_1_TICK_N_MS;
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Zibin Zheng <znbin@qq.com>
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef _MULTI_TIMER_H_
|
||||
#define _MULTI_TIMER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
It means 1 tick for 1ms.
|
||||
Your can configurate for your tick time such as 5ms/10ms and so on.
|
||||
*/
|
||||
#define CFG_TIMER_1_TICK_N_MS 1
|
||||
|
||||
typedef struct Timer {
|
||||
uint32_t cur_ticks; /* Record current timer start tick */
|
||||
uint32_t cur_expired_time; /* Record current timer expired time */
|
||||
uint32_t timeout; /* Delay (xx ms) time to start tiemr */
|
||||
uint32_t repeat; /* Timer interval expired time (xx ms) */
|
||||
void * arg; /* Input argument for timeout_cb function */
|
||||
void (*timeout_cb)(void *arg); /* Timer expired callback function */
|
||||
struct Timer* next; /* Pointer to next timer */
|
||||
} Timer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initializes the timer struct handle.
|
||||
* @param handle: the timer handle strcut.
|
||||
* @param timeout_cb: timeout callback.
|
||||
* @param timeout: delay to start the timer.
|
||||
* @param repeat: repeat interval time.
|
||||
* @param arg: the input argument for timeout_cb fucntion.
|
||||
* @retval None
|
||||
*/
|
||||
void timer_init(struct Timer* handle, void(*timeout_cb)(void *arg), \
|
||||
uint32_t timeout, uint32_t repeat, void *arg);
|
||||
|
||||
/**
|
||||
* @brief Start the timer work, add the handle into work list.
|
||||
* @param btn: target handle strcut.
|
||||
* @retval 0: succeed. -1: already exist.
|
||||
*/
|
||||
int timer_start(struct Timer* handle);
|
||||
|
||||
/**
|
||||
* @brief Stop the timer work, remove the handle off work list.
|
||||
* @param handle: target handle strcut.
|
||||
* @retval 0: succeed. -1: timer not exist.
|
||||
*/
|
||||
int timer_stop(struct Timer* handle);
|
||||
|
||||
/**
|
||||
* @brief background ticks, timer repeat invoking interval nms.
|
||||
* @param None.
|
||||
* @retval None.
|
||||
*/
|
||||
void timer_ticks(void);
|
||||
|
||||
/**
|
||||
* @brief main loop.
|
||||
* @param None.
|
||||
* @retval None
|
||||
*/
|
||||
void timer_loop(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue