-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from ZhuLingQing/os-timer
Os timer
- Loading branch information
Showing
13 changed files
with
447 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
build/ | ||
.vscode/ | ||
*.bak |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
include(FetchContent) | ||
|
||
fetchcontent_declare( | ||
etl | ||
GIT_REPOSITORY https://github.com/ETLCPP/etl.git | ||
GIT_TAG 20.38.10 | ||
) | ||
|
||
FetchContent_MakeAvailable(etl) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#ifndef _OS_TIMER_PORT_H_ | ||
#define _OS_TIMER_PORT_H_ | ||
|
||
#if __linux__ | ||
|
||
void portTimerInit( void (*callback)()); | ||
|
||
void portTimerStop(); | ||
|
||
long portTimerGetUs(); | ||
|
||
void portTimerStart(long end_us); | ||
|
||
#elif __riscv__ | ||
|
||
#include "hal/timer/mtime.h" | ||
#include "hal/timer/riscv_mtime_csr.h" | ||
|
||
#define portTimerInit(cb) \ | ||
do \ | ||
{ \ | ||
MtimeSetPeriod(0); \ | ||
MtimeRegister(cb); \ | ||
} while (0) | ||
|
||
#define portTimerStop() __mtime_set_compare(~0ULL) | ||
|
||
#define portTimerTicksPerUs() ((MtimeGetPeriod() + 1) * 1000) | ||
|
||
#define portTimerGetUs() __mtime_get_count() | ||
|
||
#define portTimerStart(end) __mtime_set_compare(end) | ||
|
||
#endif | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
#include "os-timer.h" | ||
#include "pt-os.h" | ||
#include "os-timer-port.h" | ||
#include <etl/set.h> | ||
|
||
constexpr int kMaxTimerItem = 16; | ||
|
||
typedef struct | ||
{ | ||
OsTimerCallback_t callback; | ||
void *param; | ||
uint64_t period_tick; | ||
uint64_t end_tick; | ||
int id; | ||
bool repeatable; | ||
} OsTimer_t; | ||
|
||
volatile int kOsTimerTrigged_ = 0; | ||
int kOsTimerHandled_ = 0; | ||
int kOsTimerIdSeed_ = 0; | ||
|
||
struct tick_cmp | ||
{ | ||
bool operator()(const OsTimer_t &a, const OsTimer_t &b) const { return a.end_tick < b.end_tick; } | ||
}; | ||
etl::set<OsTimer_t, kMaxTimerItem, tick_cmp> gOsTimerObj_; | ||
|
||
static void OsTimerIsrHandler_() | ||
{ | ||
kOsTimerTrigged_ += 1; | ||
portTimerStop(); | ||
} | ||
|
||
TASK_DECLARE(OsTimerTask_(OsTaskId taskId, void *)) | ||
{ | ||
TASK_BEGIN(taskId); | ||
while (1) | ||
{ | ||
TASK_WAIT_UNTIL(taskId, kOsTimerTrigged_ > kOsTimerHandled_); | ||
kOsTimerHandled_++; | ||
// find the first timer. Which happened most recently. | ||
auto tim = gOsTimerObj_.begin(); | ||
OS_ASSERT(tim != gOsTimerObj_.end()); // Shouldn't be empty. | ||
if (tim->callback) tim->callback(tim->id, tim->param); | ||
// update the repeatable timer. | ||
if (tim->repeatable) | ||
{ | ||
gOsTimerObj_.insert( | ||
{tim->callback, tim->param, tim->period_tick, tim->end_tick + tim->period_tick, tim->id, true}); | ||
} | ||
// remove the current timer. | ||
gOsTimerObj_.erase(tim); | ||
// if has one or more timer enable it. | ||
tim = gOsTimerObj_.begin(); | ||
if (tim != gOsTimerObj_.end()) | ||
portTimerStart(tim->end_tick); | ||
} | ||
TASK_END(taskId); | ||
} | ||
|
||
void OsTimerInit() | ||
{ | ||
gOsTimerObj_.clear(); | ||
portTimerInit(OsTimerIsrHandler_); | ||
portTimerStop(); | ||
RegisterTask("thrTmr", OsTimerTask_, nullptr); | ||
} | ||
|
||
int OsTimerRegister(OsTimerCallback_t callback, void *param, uint64_t period_us, bool repeatable, int *id) | ||
{ | ||
if (gOsTimerObj_.full()) return NO_RESOURCE; | ||
portTimerStop(); | ||
gOsTimerObj_.insert({callback, param, period_us, | ||
portTimerGetUs() + period_us, ++kOsTimerIdSeed_, repeatable}); | ||
portTimerStart(gOsTimerObj_.begin()->end_tick); | ||
if (id) *id = kOsTimerIdSeed_; | ||
return TASK_OP_SUCCESS; | ||
} | ||
|
||
int OsTimerCount() { return gOsTimerObj_.size(); } | ||
|
||
int OsTimerKill(int id) | ||
{ | ||
for (auto it = gOsTimerObj_.begin(); it != gOsTimerObj_.end(); it++) | ||
{ | ||
if (it->id == id) | ||
{ | ||
gOsTimerObj_.erase(it); | ||
return TASK_OP_SUCCESS; | ||
} | ||
} | ||
return INVALID_TASK_ID; | ||
} | ||
|
||
static void timerDelayCallback_(int id, void *param) | ||
{ | ||
bool *triggerred = (bool *)param; | ||
// HAL_UartPrint("[TIM]: to %llu\n", portTimerGetUs()); | ||
*triggerred = true; | ||
} | ||
|
||
int OsTimerDelayUs(uint64_t delay_us) | ||
{ | ||
bool timerTriggered = false; | ||
// HAL_UartPrint("[TIM]: from %llu - %lluUs\n", portTimerGetUs(), delay_us); | ||
int rc = OsTimerRegister(timerDelayCallback_, &timerTriggered, delay_us, false, 0); | ||
if (rc != TASK_OP_SUCCESS) return rc; | ||
while (timerTriggered == false) TaskYield(); | ||
return TASK_OP_SUCCESS; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#ifndef _OS_TIMER_H_ | ||
#define _OS_TIMER_H_ | ||
|
||
#include <stdint.h> | ||
#include <stdbool.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" | ||
{ | ||
#endif | ||
typedef void (*OsTimerCallback_t)(int id, void *param); | ||
/*****************************************************************************\ | ||
* @description : Initialize the OsTimer module. | ||
* @return {*} | ||
\*****************************************************************************/ | ||
void OsTimerInit(); | ||
|
||
/*****************************************************************************\ | ||
* @description : Register a timer | ||
* ------------ | ||
* @callback [I]: timer triggered callback function. | ||
* @param [I]: input parameter for callback function. | ||
* @period_us [I]: micro second delay to trigger the timer. | ||
* @repeatable [I]: true=auto reload period_us. | ||
* @id [O]: output the timer id for Kill. (Will be auto killed after | ||
* triggered, if not repeatable timer) | ||
* @return error or success | ||
\*****************************************************************************/ | ||
int OsTimerRegister(OsTimerCallback_t callback, void *param, uint64_t period_us, bool repeatable, int *id); | ||
|
||
/*****************************************************************************\ | ||
* @description : return number of active timer | ||
* @return number of active timer | ||
\*****************************************************************************/ | ||
int OsTimerCount(); | ||
|
||
/*****************************************************************************\ | ||
* @description : Kill a timer | ||
* @id [I]: timer id, which given by OsTimerRegister(...,&id) | ||
* @return error or success | ||
\*****************************************************************************/ | ||
int OsTimerKill(int id); | ||
|
||
int OsTimerDelayUs(uint64_t delay_us); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,4 +11,6 @@ | |
#include <cassert> | ||
#define OS_ASSERT assert | ||
|
||
#define OS_PRINT printf | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#include "os-timer-port.h" | ||
#include "os-timer.h" | ||
#include "pt-os.h" | ||
#include <stdio.h> | ||
|
||
#if __linux__ | ||
|
||
#include <signal.h> | ||
#include <time.h> | ||
#include <sys/time.h> | ||
|
||
static void (*TimerCallback_)(); | ||
static long TimerBaseUs_ = 0; | ||
|
||
static void TimerRoutine(int signo) | ||
{ | ||
struct itimerval value, ovalue; | ||
switch (signo){ | ||
case SIGALRM: | ||
portTimerStop(); | ||
TimerCallback_(); | ||
break; | ||
} | ||
} | ||
|
||
void portTimerInit( void (*callback)()) | ||
{ | ||
struct timeval tv; | ||
gettimeofday(&tv,NULL); | ||
TimerBaseUs_ = tv.tv_sec*1000000 + tv.tv_usec; | ||
TimerCallback_ = callback; | ||
signal(SIGALRM, TimerRoutine); | ||
} | ||
|
||
void portTimerStop() | ||
{ | ||
struct itimerval value, ovalue; | ||
value.it_value.tv_sec = 0; | ||
value.it_value.tv_usec = 0; | ||
value.it_interval.tv_sec = 0; | ||
value.it_interval.tv_usec = 0; | ||
setitimer(ITIMER_REAL, &value, &ovalue); | ||
} | ||
|
||
long portTimerGetUs() | ||
{ | ||
struct timeval tv; | ||
gettimeofday(&tv,NULL); | ||
return (tv.tv_sec*1000000 + tv.tv_usec - TimerBaseUs_); | ||
} | ||
|
||
void portTimerStart(long end_us) | ||
{ | ||
struct itimerval value, ovalue; | ||
long offset = end_us - portTimerGetUs(); | ||
if (offset < 10) offset = 100; | ||
value.it_value.tv_sec = offset/1000000; | ||
value.it_value.tv_usec = offset%1000000; | ||
value.it_interval.tv_sec = value.it_value.tv_sec; | ||
value.it_interval.tv_usec = value.it_value.tv_usec; | ||
setitimer(ITIMER_REAL, &value, &ovalue); | ||
} | ||
|
||
#endif |
Oops, something went wrong.