diff --git a/.gitignore b/.gitignore index 567609b..8341083 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ build/ +.vscode/ +*.bak \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index e4c9eb9..4a625b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ include_directories(${PROJECT_SOURCE_DIR}) target_include_directories(${LIB_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_link_libraries(${LIB_NAME} protothreads) +target_link_libraries(${LIB_NAME} protothreads etl) set( OS_LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}" PARENT_SCOPE ) diff --git a/bash_build.sh b/bash_build.sh index 4429194..bc1141b 100644 --- a/bash_build.sh +++ b/bash_build.sh @@ -21,9 +21,15 @@ pushd ${build_dir} #clone the dependency repo git clone https://github.com/ZhuLingQing/protothreads.git +git clone https://github.com/ETLCPP/etl.git +pushd etl +git checkout 20.38.10 +popd #build the os static library -g++ -g -o ${lib_name}.o -c ../pt-os.cpp -I./protothreads -ar -rv lib${lib_name}.a ${lib_name}.o +g++ -g -o ${pt-os}.o -c ../pt-os.cpp -I./protothreads -I./etl +g++ -g -o ${os-timer}.o -c ../os-timer.cpp -I./protothreads -I./etl +g++ -g -o ${os-timer-port}.o -c ../os-timer-port.cpp -I./protothreads -I./etl +ar -rv lib${lib_name}.a ${pt-os}.o ${os-timer}.o ${os-timer-port}.o #build the test g++ -g -o test_pt_os ../tests/*.cpp -I./protothreads -I.. -I../tests -L. -l${lib_name} #run the test diff --git a/os-timer-port.cpp b/os-timer-port.cpp new file mode 100644 index 0000000..e5fb408 --- /dev/null +++ b/os-timer-port.cpp @@ -0,0 +1,67 @@ +#include "os-timer-port.h" +#include "os-timer.h" +#include "pt-os.h" +#include + +#if __linux__ + +#include +#include +#include + +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 > 5) + { + 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); + } + else TimerCallback_(); +} + +#endif \ No newline at end of file diff --git a/os-timer-port.h b/os-timer-port.h index 47a0130..c8c54a8 100644 --- a/os-timer-port.h +++ b/os-timer-port.h @@ -1,6 +1,18 @@ #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" @@ -15,10 +27,10 @@ #define portTimerTicksPerUs() ((MtimeGetPeriod() + 1) * 1000) -#define portTimerGetTick() __mtime_get_count() - -#define portTimerComputeEndTick(tick) (portTimerGetTick() + (tick)) +#define portTimerGetUs() __mtime_get_count() #define portTimerStart(end) __mtime_set_compare(end) #endif + +#endif diff --git a/os-timer.cpp b/os-timer.cpp index c098f76..be712c5 100644 --- a/os-timer.cpp +++ b/os-timer.cpp @@ -1,6 +1,6 @@ -#include "os_timer.h" +#include "os-timer.h" #include "pt-os.h" -#include "os_timer_port.h" +#include "os-timer-port.h" #include constexpr int kMaxTimerItem = 16; @@ -18,7 +18,6 @@ typedef struct volatile int kOsTimerTrigged_ = 0; int kOsTimerHandled_ = 0; int kOsTimerIdSeed_ = 0; -uint64_t kOsTimerTicksPerUs_ = 0; struct tick_cmp { @@ -52,11 +51,9 @@ TASK_DECLARE(OsTimerTask_(OsTaskId taskId, void *)) // remove the current timer. gOsTimerObj_.erase(tim); // if has one or more timer enable it. - if (gOsTimerObj_.size()) - { - tim = gOsTimerObj_.begin(); + tim = gOsTimerObj_.begin(); + if (tim != gOsTimerObj_.end()) portTimerStart(tim->end_tick); - } } TASK_END(taskId); } @@ -65,16 +62,15 @@ void OsTimerInit() { portTimerInit(OsTimerIsrHandler_); portTimerStop(); - kOsTimerTicksPerUs_ = portTimerTicksPerUs(); RegisterTask("thrTmr", OsTimerTask_, nullptr); } int OsTimerRegister(OsTimerCallback_t callback, void *param, uint64_t period_us, bool repeatable, int *id) { - if (gOsTimerObj_.full()) return kLtMallocFail; + if (gOsTimerObj_.full()) return NO_RESOURCE; portTimerStop(); - gOsTimerObj_.insert({callback, param, period_us * kOsTimerTicksPerUs_, - portTimerComputeEndTick(period_us * kOsTimerTicksPerUs_), ++kOsTimerIdSeed_, repeatable}); + gOsTimerObj_.insert({callback, param, period_us, + portTimerGetUs() + period_us, ++kOsTimerIdSeed_, repeatable}); portTimerStart(gOsTimerObj_.begin()->end_tick); if (id) *id = kOsTimerIdSeed_; return TASK_OP_SUCCESS; @@ -92,19 +88,20 @@ int OsTimerKill(int id) 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", portTimerGetTick()); + // 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", portTimerGetTick(), delay_us); + // 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(); diff --git a/os-timer.h b/os-timer.h index f802592..9ec6335 100644 --- a/os-timer.h +++ b/os-timer.h @@ -1,6 +1,9 @@ #ifndef _OS_TIMER_H_ #define _OS_TIMER_H_ +#include +#include + #ifdef __cplusplus extern "C" { diff --git a/pt-os.h b/pt-os.h index a053e2a..94eaac7 100644 --- a/pt-os.h +++ b/pt-os.h @@ -30,6 +30,7 @@ extern "C" #define TASK_OP_SUCCESS (0) #define INVALID_TASK_ID (-1) #define INVALID_TASK_STATUS (-2) +#define NO_RESOURCE (-3) typedef enum { diff --git a/pt-osConfig.h b/pt-osConfig.h index d1ef6ca..9ae2126 100644 --- a/pt-osConfig.h +++ b/pt-osConfig.h @@ -11,4 +11,6 @@ #include #define OS_ASSERT assert +#define OS_PRINT printf + #endif diff --git a/tests/timer.cpp b/tests/timer.cpp index 3f6e2fd..7085044 100644 --- a/tests/timer.cpp +++ b/tests/timer.cpp @@ -1,58 +1,59 @@ -#include +#include "os_test.h" #include +constexpr long testTimerGain_ = 10000; constexpr int kMaxTestNum_ = 10; -volatile int testCount = 0; -uint64_t tickStart; +volatile int kSignalTriggered_ = 0; +uint64_t kStartUs_; static long testTimerParam[kMaxTestNum_]; constexpr long testTimerGolden[kMaxTestNum_] = {11, 33, 50, 51, 33, 99, 33, 33, 33, 33}; -static uint64_t testTickCounter[kMaxTestNum_]; -constexpr uint64_t testTickGolden[kMaxTestNum_] = {100, 300, 500, 500, 600, 900, 900, 1200, 1500, 1800}; +static uint64_t testUsCounter[kMaxTestNum_]; +constexpr uint64_t testUsGolden[kMaxTestNum_] = {100, 300, 500, 500, 600, 900, 900, 1200, 1500, 1800}; void testTimerCallback_(int id, void *param) { - testTickCounter[testCount] = portTimerGetTick() / 1000 - tickStart; - testTimerParam[testCount] = (long)param; - OS_TRACE("Timer%d: %lld happened at %llu\n", id, testTimerParam[testCount], testTickCounter[testCount]); - testCount++; + testUsCounter[kSignalTriggered_] = portTimerGetUs(); + testTimerParam[kSignalTriggered_] = (long)param; + OS_TRACE("Timer%d: %lld happened at %llu\n", id, testTimerParam[kSignalTriggered_], testUsCounter[kSignalTriggered_]/1000); + kSignalTriggered_++; } constexpr long kTimerTaskSeconds_ = 3; -long tCount1Ms = 0; -long tCount100Us = 0; +long tCount1s = 0; +long tCount100Ms = 0; long tCountIdle = 0; static void timerDelayCallback_(int id, void *param) { bool *triggerred = (bool *)param; - // OS_TRACE("[TIM]: to %llu\n", portTimerGetTick()); + // OS_TRACE("[TIM]: to %llu\n", portTimerGetUs()); *triggerred = true; } -PT_THREAD(testTimerThread1Ms_(OsTaskId taskId, void *param)) +PT_THREAD(testTimerThread1s_(OsTaskId taskId, void *param)) { static bool timerTriggered; TASK_BEGIN(taskId); while (1) { - OsTimerDelayUs(1000); + OsTimerDelayUs(1000 * 1000); TASK_YIELD(taskId); // force Yield - tCount1Ms++; - // OS_TRACE("1Ms hit %ld, idleYield %ld\n", tCount1Ms, tCountIdle); + tCount1s++; + // OS_TRACE("1s hit %ld, idleYield %ld\n", tCount1s, tCountIdle); } TASK_END(taskId); } -PT_THREAD(testTimerThread100Us_(OsTaskId taskId, void *param)) +PT_THREAD(testTimerThread100Ms_(OsTaskId taskId, void *param)) { static bool timerTriggered; TASK_BEGIN(taskId); while (1) { - OsTimerDelayUs(100); + OsTimerDelayUs(100 * 1000); TASK_YIELD(taskId); // force Yield - tCount100Us++; - // OS_TRACE("100Us hit %ld, idleYield %ld\n", tCount100Us, tCountIdle); + tCount100Ms++; + // OS_TRACE("100Ms hit %ld, idleYield %ld\n", tCount100Ms, tCountIdle); } TASK_END(taskId); } @@ -71,24 +72,27 @@ PT_THREAD(testIdleThread_(OsTaskId taskId, void *param)) int TestTimer() { int repeat_timer_id; + OS_TRACE("======== %s ========\n", __FUNCTION__); OsInit(); OsTimerInit(); + kStartUs_ = portTimerGetUs(); + OS_TRACE("Timer Init\n", __FUNCTION__); - tickStart = portTimerGetTick() / 1000; - LT_ASSERT(kLtSc == OsTimerRegister(testTimerCallback_, (void *)(11), 100, false, nullptr)); - LT_ASSERT(kLtSc == OsTimerRegister(testTimerCallback_, (void *)(50), 500, false, nullptr)); - LT_ASSERT(kLtSc == OsTimerRegister(testTimerCallback_, (void *)(99), 900, false, nullptr)); - LT_ASSERT(kLtSc == OsTimerRegister(testTimerCallback_, (void *)(33), 300, true, &repeat_timer_id)); - LT_ASSERT(kLtSc == OsTimerRegister(testTimerCallback_, (void *)(51), 500, false, nullptr)); + OsTimerRegister(testTimerCallback_, (void *)(11), 100 * testTimerGain_, false, nullptr); + OsTimerRegister(testTimerCallback_, (void *)(50), 500 * testTimerGain_, false, nullptr); + OsTimerRegister(testTimerCallback_, (void *)(99), 900 * testTimerGain_, false, nullptr); + OsTimerRegister(testTimerCallback_, (void *)(33), 300 * testTimerGain_, true, &repeat_timer_id); + OsTimerRegister(testTimerCallback_, (void *)(51), 500 * testTimerGain_, false, nullptr); - while (testCount < kMaxTestNum_) TaskYield(); + OS_TRACE("Timer Yield\n", __FUNCTION__); + while (kSignalTriggered_ < kMaxTestNum_) TaskYield(); for (int i = 0; i < kMaxTestNum_; i++) { - if (testTimerParam[i] != testTimerGolden[i] || testTickCounter[i] / 10 != testTickGolden[i] / 10) + if (testTimerParam[i] != testTimerGolden[i] || testUsCounter[i] / 1000 != testUsGolden[i] * testTimerGain_ / 1000) { OS_TRACE("Test%d Failed\n", i); OS_TRACE("Timer [%lld : %lld]. Tick [%llu : %llu]\n", testTimerParam[i], testTimerGolden[i], - testTickCounter[i], testTickGolden[i]); + testUsCounter[i], testUsGolden[i] * testTimerGain_); return 1; } } @@ -97,7 +101,7 @@ int TestTimer() OS_TRACE("Timer count error 1 - %d\n", OsTimerCount()); return 2; } - LT_ASSERT(OsTimerKill(repeat_timer_id) == kLtSc); + OsTimerKill(repeat_timer_id); if (OsTimerCount() != 0) { OS_TRACE("Timer count error 0 - %d\n", OsTimerCount()); @@ -105,17 +109,17 @@ int TestTimer() } OS_TRACE("Test Timer in task\n"); - RegisterTask("thr1Ms", &testTimerThread1Ms_, nullptr); - RegisterTask("thr100Us", &testTimerThread100Us_, nullptr); + RegisterTask("thr1s", &testTimerThread1s_, nullptr); + RegisterTask("thr100Ms", &testTimerThread100Ms_, nullptr); RegisterTask("thrIdle", &testIdleThread_, nullptr); OS_TRACE("Test Timer start\n"); - while (tCount1Ms < kTimerTaskSeconds_) + while (tCount1s < kTimerTaskSeconds_) { TaskYield(); } - if ((tCount1Ms * 10 - tCount100Us) <= 2) + if ((tCount1s * 10 - tCount100Ms) <= 2) { - OS_TRACE("Timer task error %ld - %ld\n", tCount1Ms, tCount100Us); + OS_TRACE("Timer task error %ld - %ld\n", tCount1s, tCount100Ms); return 4; } OS_TRACE("Idle task yield %ld\n", tCountIdle);