diff --git a/library.json b/library.json index 29a6a46e..097d2330 100644 --- a/library.json +++ b/library.json @@ -18,7 +18,10 @@ "srcFilter": [ "+", "+", - "+" + "+", + "+", + "+", + "+" ], "extraScript": "platformio_pre.py", "flags": "-DPIP_FREERTOS" diff --git a/libs/main/core/piobject.cpp b/libs/main/core/piobject.cpp index 1ec4714e..ab051a78 100644 --- a/libs/main/core/piobject.cpp +++ b/libs/main/core/piobject.cpp @@ -18,10 +18,10 @@ */ #include "piobject.h" -#include "pisysteminfo.h" #include "pithread.h" #include "piconditionvar.h" #ifndef MICRO_PIP +# include "pisysteminfo.h" # include "pifile.h" #endif @@ -589,6 +589,7 @@ void PIObject::dump(const PIString & line_prefix) const { } +#ifndef MICRO_PIP void dumpApplication() { PIMutexLocker _ml(PIObject::mutexObjects()); //printf("dump application ...\n"); @@ -615,7 +616,6 @@ void dumpApplication() { } -#ifndef MICRO_PIP bool dumpApplicationToFile(const PIString & path) { PIFile f(path + "_tmp"); f.setName("__S__DumpFile"); diff --git a/libs/main/core/piobject.h b/libs/main/core/piobject.h index b7955006..c6c6451a 100644 --- a/libs/main/core/piobject.h +++ b/libs/main/core/piobject.h @@ -37,11 +37,13 @@ typedef void (*Handler)(void * ); class PIP_EXPORT PIObject { +#ifndef MICRO_PIP friend class PIObjectManager; friend void dumpApplication(); + friend class PIIntrospection; +#endif typedef PIObject __PIObject__; typedef void __Parent__; - friend class PIIntrospection; public: NO_COPY_CLASS(PIObject) @@ -539,8 +541,9 @@ private: }; - +#ifndef MICRO_PIP PIP_EXPORT void dumpApplication(); PIP_EXPORT bool dumpApplicationToFile(const PIString & path); +#endif #endif // PIOBJECT_H diff --git a/libs/main/core/pivarianttypes.cpp b/libs/main/core/pivarianttypes.cpp index 13c556fa..de21989e 100644 --- a/libs/main/core/pivarianttypes.cpp +++ b/libs/main/core/pivarianttypes.cpp @@ -19,8 +19,9 @@ #include "pivarianttypes.h" #include "pipropertystorage.h" -#include "piiodevice.h" - +#ifndef MICRO_PIP +# include "piiodevice.h" +#endif int PIVariantTypes::Enum::selectedValue() const { piForeachC (Enumerator & e, enum_list) @@ -83,7 +84,7 @@ PIStringList PIVariantTypes::Enum::names() const { - +#ifndef MICRO_PIP PIVariantTypes::IODevice::IODevice() { mode = PIIODevice::ReadWrite; options = 0; @@ -125,7 +126,7 @@ PIString PIVariantTypes::IODevice::toPICout() const { s << ")"; return s; } - +#endif // MICRO_PIP diff --git a/libs/main/thread/piconditionvar.cpp b/libs/main/thread/piconditionvar.cpp index 908199c9..2143ac24 100644 --- a/libs/main/thread/piconditionvar.cpp +++ b/libs/main/thread/piconditionvar.cpp @@ -20,7 +20,7 @@ #include "piconditionvar.h" #include "pithread.h" #include "pitime.h" - +#include "piincludes_p.h" #ifdef WINDOWS # undef _WIN32_WINNT # define _WIN32_WINNT 0x0600 @@ -28,25 +28,32 @@ # include # include #endif +#ifdef FREERTOS +# include +#endif PRIVATE_DEFINITION_START(PIConditionVariable) -#ifdef WINDOWS - CONDITION_VARIABLE nativeHandle; +#if defined(WINDOWS) + CONDITION_VARIABLE +#elif defined(FREERTOS) + EventGroupHandle_t #else - pthread_cond_t nativeHandle; + pthread_cond_t #endif + nativeHandle; PRIVATE_DEFINITION_END(PIConditionVariable) PIConditionVariable::PIConditionVariable() { -#ifdef WINDOWS +#if defined(WINDOWS) InitializeConditionVariable(&PRIVATE->nativeHandle); +#elif defined(FREERTOS) + PRIVATE->nativeHandle = xEventGroupCreate(); #else - pthread_condattr_t condattr; pthread_condattr_init(&condattr); -# if !defined(MAC_OS) && !defined(FREERTOS) +# if !defined(MAC_OS) pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC); # endif memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle)); @@ -56,7 +63,9 @@ PIConditionVariable::PIConditionVariable() { PIConditionVariable::~PIConditionVariable() { -#ifdef WINDOWS +#if defined(WINDOWS) +#elif defined(FREERTOS) + vEventGroupDelete(PRIVATE->nativeHandle); #else pthread_cond_destroy(&PRIVATE->nativeHandle); #endif @@ -64,8 +73,11 @@ PIConditionVariable::~PIConditionVariable() { void PIConditionVariable::wait(PIMutex& lk) { -#ifdef WINDOWS +#if defined(WINDOWS) SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE); +#elif defined(FREERTOS) + xEventGroupClearBits(PRIVATE->nativeHandle, 1); + xEventGroupWaitBits(PRIVATE->nativeHandle, 1, pdTRUE, pdTRUE, portMAX_DELAY); #else pthread_cond_wait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle()); #endif @@ -77,8 +89,11 @@ void PIConditionVariable::wait(PIMutex& lk, const std::function& conditi while (true) { isCondition = condition(); if (isCondition) break; -#ifdef WINDOWS +#if defined(WINDOWS) SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE); +#elif defined(FREERTOS) + xEventGroupClearBits(PRIVATE->nativeHandle, 1); + xEventGroupWaitBits(PRIVATE->nativeHandle, 1, pdTRUE, pdTRUE, portMAX_DELAY); #else pthread_cond_wait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle()); #endif @@ -88,8 +103,13 @@ void PIConditionVariable::wait(PIMutex& lk, const std::function& conditi bool PIConditionVariable::waitFor(PIMutex &lk, int timeoutMs) { bool isNotTimeout; -#ifdef WINDOWS +#if defined(WINDOWS) isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs) != 0; +#elif defined(FREERTOS) + xEventGroupClearBits(PRIVATE->nativeHandle, 1); + EventBits_t uxBits; + uxBits = xEventGroupWaitBits(PRIVATE->nativeHandle, 1, pdTRUE, pdTRUE, timeoutMs / portTICK_PERIOD_MS); + isNotTimeout = (uxBits & 1) != 0; #else timespec expire_ts; PISystemTime st = PISystemTime::current(true); @@ -103,24 +123,32 @@ bool PIConditionVariable::waitFor(PIMutex &lk, int timeoutMs) { bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::function &condition) { bool isCondition; -#ifdef WINDOWS +#if defined(WINDOWS) || defined(FREERTOS) PITimeMeasurer measurer; #else timespec expire_ts; PISystemTime st = PISystemTime::current(true); st.addMilliseconds(timeoutMs); st.toTimespec(&expire_ts); +#endif +#ifdef FREERTOS + xEventGroupClearBits(PRIVATE->nativeHandle, 1); #endif while (true) { isCondition = condition(); if (isCondition) break; -#ifdef WINDOWS - bool isTimeout = SleepConditionVariableCS( + bool isTimeout; +#if defined(WINDOWS) + isTimeout = SleepConditionVariableCS( &PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs - (int)measurer.elapsed_m()) == 0; +#elif defined(FREERTOS) + EventBits_t uxBits; + uxBits = xEventGroupWaitBits(PRIVATE->nativeHandle, 1, pdTRUE, pdTRUE, (timeoutMs - (int)measurer.elapsed_m()) / portTICK_PERIOD_MS); + isTimeout = (uxBits & 1) == 0; #else - bool isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) != 0; + isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) != 0; #endif if (isTimeout) return false; } @@ -129,8 +157,10 @@ bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::functio void PIConditionVariable::notifyOne() { -#ifdef WINDOWS +#if defined(WINDOWS) WakeConditionVariable(&PRIVATE->nativeHandle); +#elif defined(FREERTOS) + xEventGroupSetBits(PRIVATE->nativeHandle, 1); #else pthread_cond_signal(&PRIVATE->nativeHandle); #endif @@ -138,8 +168,10 @@ void PIConditionVariable::notifyOne() { void PIConditionVariable::notifyAll() { -#ifdef WINDOWS +#if defined(WINDOWS) WakeAllConditionVariable(&PRIVATE->nativeHandle); +#elif defined(FREERTOS) + xEventGroupSetBits(PRIVATE->nativeHandle, 1); #else pthread_cond_broadcast(&PRIVATE->nativeHandle); #endif diff --git a/libs/main/thread/pimutex.cpp b/libs/main/thread/pimutex.cpp index 80ea11fd..db42b86f 100644 --- a/libs/main/thread/pimutex.cpp +++ b/libs/main/thread/pimutex.cpp @@ -36,8 +36,10 @@ #include "pimutex.h" #include "piincludes_p.h" -#ifdef WINDOWS +#if defined(WINDOWS) # include +#elif defined(FREERTOS) +# include #else # include #endif @@ -45,8 +47,10 @@ PRIVATE_DEFINITION_START(PIMutex) -#ifdef WINDOWS +#if defined(WINDOWS) CRITICAL_SECTION +#elif defined(FREERTOS) + SemaphoreHandle_t #else pthread_mutex_t #endif @@ -65,8 +69,10 @@ PIMutex::~PIMutex() { void PIMutex::lock() { -#ifdef WINDOWS +#if defined(WINDOWS) EnterCriticalSection(&(PRIVATE->mutex)); +#elif defined(FREERTOS) + xSemaphoreTake(PRIVATE->mutex, portMAX_DELAY); #else pthread_mutex_lock(&(PRIVATE->mutex)); #endif @@ -74,8 +80,10 @@ void PIMutex::lock() { void PIMutex::unlock() { -#ifdef WINDOWS +#if defined(WINDOWS) LeaveCriticalSection(&(PRIVATE->mutex)); +#elif defined(FREERTOS) + xSemaphoreGive(PRIVATE->mutex); #else pthread_mutex_unlock(&(PRIVATE->mutex)); #endif @@ -84,8 +92,10 @@ void PIMutex::unlock() { bool PIMutex::tryLock() { bool ret = -#ifdef WINDOWS +#if defined(WINDOWS) (TryEnterCriticalSection(&(PRIVATE->mutex)) != 0); +#elif defined(FREERTOS) + xSemaphoreTake(PRIVATE->mutex, 0); #else (pthread_mutex_trylock(&(PRIVATE->mutex)) == 0); #endif @@ -94,13 +104,19 @@ bool PIMutex::tryLock() { void * PIMutex::handle() { +#ifdef FREERTOS + return PRIVATE->mutex; +#else return (void*)&(PRIVATE->mutex); +#endif } void PIMutex::init() { -#ifdef WINDOWS +#if defined(WINDOWS) InitializeCriticalSection(&(PRIVATE->mutex)); +#elif defined(FREERTOS) + PRIVATE->mutex = xSemaphoreCreateMutex(); #else pthread_mutexattr_t attr; memset(&attr, 0, sizeof(attr)); @@ -114,8 +130,10 @@ void PIMutex::init() { void PIMutex::destroy() { -#ifdef WINDOWS +#if defined(WINDOWS) DeleteCriticalSection(&(PRIVATE->mutex)); +#elif defined(FREERTOS) + vSemaphoreDelete(PRIVATE->mutex); #else pthread_mutex_destroy(&(PRIVATE->mutex)); #endif diff --git a/libs/main/thread/pimutex.h b/libs/main/thread/pimutex.h index dab51359..847d5eb6 100644 --- a/libs/main/thread/pimutex.h +++ b/libs/main/thread/pimutex.h @@ -24,7 +24,6 @@ #define PIMUTEX_H #include "piinit.h" -#include class PIP_EXPORT PIMutex diff --git a/libs/main/thread/pithread.cpp b/libs/main/thread/pithread.cpp index 863d6a63..e1eb1f4d 100644 --- a/libs/main/thread/pithread.cpp +++ b/libs/main/thread/pithread.cpp @@ -19,27 +19,40 @@ #include "piincludes_p.h" #include "pithread.h" -#include "pisystemtests.h" #include "piintrospection_threads.h" +#ifndef MICRO_PIP +# include "pisystemtests.h" +#endif #include -#ifdef WINDOWS +#if defined(WINDOWS) # define __THREAD_FUNC_RET__ uint __stdcall +#elif defined(FREERTOS) +# define __THREAD_FUNC_RET__ void #else # define __THREAD_FUNC_RET__ void* #endif +#ifndef FREERTOS +# define __THREAD_FUNC_END__ 0 +#else +# define __THREAD_FUNC_END__ +#endif #if defined(LINUX) # include # define gettid() syscall(SYS_gettid) #endif -#if defined(MAC_OS) || defined(BLACKBERRY) || defined(FREERTOS) +#if defined(MAC_OS) || defined(BLACKBERRY) # include #endif -__THREAD_FUNC_RET__ thread_function(void * t) {((PIThread*)t)->__thread_func__(); return 0;} -__THREAD_FUNC_RET__ thread_function_once(void * t) {((PIThread*)t)->__thread_func_once__(); return 0;} - -#define REGISTER_THREAD(t) __PIThreadCollection::instance()->registerThread(t) -#define UNREGISTER_THREAD(t) __PIThreadCollection::instance()->unregisterThread(t) +__THREAD_FUNC_RET__ thread_function(void * t) {((PIThread*)t)->__thread_func__(); return __THREAD_FUNC_END__;} +__THREAD_FUNC_RET__ thread_function_once(void * t) {((PIThread*)t)->__thread_func_once__(); return __THREAD_FUNC_END__;} +#ifndef MICRO_PIP +# define REGISTER_THREAD(t) __PIThreadCollection::instance()->registerThread(t) +# define UNREGISTER_THREAD(t) __PIThreadCollection::instance()->unregisterThread(t) +#else +# define REGISTER_THREAD(t) +# define UNREGISTER_THREAD(t) +#endif /*! \class PIThread * @brief Thread class @@ -90,6 +103,7 @@ end(); * */ +#ifndef MICRO_PIP __PIThreadCollection *__PIThreadCollection::instance() { return __PIThreadCollection_Initializer__::__instance__; @@ -158,15 +172,17 @@ __PIThreadCollection_Initializer__::~__PIThreadCollection_Initializer__() { } } - +#endif // MICRO_PIP PRIVATE_DEFINITION_START(PIThread) -#ifndef WINDOWS +#if defined(WINDOWS) + void * thread; +#elif defined(FREERTOS) + TaskHandle_t thread; +#else pthread_t thread; sched_param sparam; -#else - void * thread; #endif PRIVATE_DEFINITION_END(PIThread) @@ -267,22 +283,22 @@ void PIThread::terminate() { terminating = running_ = false; tid_ = -1; //PICout(PICoutManipulators::DefaultControls) << "terminate" << PRIVATE->thread; -#ifndef WINDOWS -# ifdef ANDROID +# ifndef WINDOWS +# ifdef ANDROID pthread_kill(PRIVATE->thread, SIGTERM); -# else +# else //pthread_kill(PRIVATE->thread, SIGKILL); //void * ret(0); pthread_cancel(PRIVATE->thread); //pthread_join(PRIVATE->thread, &ret); -# endif -#else +# endif +# else TerminateThread(PRIVATE->thread, 0); CloseHandle(PRIVATE->thread); -#endif +# endif PRIVATE->thread = 0; end(); -#endif +#endif //FREERTOS PIINTROSPECTION_THREAD_STOP(this); //PICout(PICoutManipulators::DefaultControls) << "thread" << this << "terminate ok" << running_; } @@ -290,27 +306,31 @@ void PIThread::terminate() { int PIThread::priority2System(PIThread::Priority p) { switch (p) { -# ifdef QNX +#if defined(QNX) case piLowerst: return 8; case piLow: return 9; case piNormal: return 10; case piHigh: return 11; case piHighest: return 12; -# else -# ifdef WINDOWS +#elif defined(WINDOWS) case piLowerst: return -2; case piLow: return -1; case piNormal: return 0; case piHigh: return 1; case piHighest: return 2; -# else +#elif defined(FREERTOS) + case piLowerst: return 2; + case piLow: return 3; + case piNormal: return 4; + case piHigh: return 5; + case piHighest: return 6; +#else case piLowerst: return 2; case piLow: return 1; case piNormal: return 0; case piHigh: return -1; case piHighest: return -2; -# endif -# endif +#endif default: return 0; } return 0; @@ -320,11 +340,11 @@ int PIThread::priority2System(PIThread::Priority p) { bool PIThread::_startThread(void * func) { terminating = false; running_ = true; -#ifndef WINDOWS +#if !defined(WINDOWS) && !defined(FREERTOS) pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - int ret = pthread_create(&PRIVATE->thread, &attr, (void*(*)(void*))func, this); + int ret = pthread_create(&PRIVATE->thread, &attr, (__THREAD_FUNC_RET__(*)(void*))func, this); //PICout(PICoutManipulators::DefaultControls) << "pthread_create" << PRIVATE->thread; pthread_attr_destroy(&attr); if (ret == 0) { @@ -332,22 +352,32 @@ bool PIThread::_startThread(void * func) { pthread_setname_np(((PIString&)name().elided(15, 0.4f).resize(15, PIChar('\0'))).dataAscii()); pthread_threadid_np(PRIVATE->thread, (__uint64_t*)&tid_); # else -# ifdef FREERTOS - tid_ = PRIVATE->thread; -# else pthread_setname_np(PRIVATE->thread, ((PIString&)name().elided(15, 0.4f).resize(15, PIChar('\0'))).dataAscii()); -# endif # endif -#else +#endif +#ifdef WINDOWS if (PRIVATE->thread) CloseHandle(PRIVATE->thread); # ifdef CC_GCC - PRIVATE->thread = (void *)_beginthreadex(0, 0, (unsigned(__stdcall*)(void*))func, this, 0, 0); + PRIVATE->thread = (void *)_beginthreadex(0, 0, (__THREAD_FUNC_RET__(*)(void*))func, this, 0, 0); # else PRIVATE->thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)func, this, 0, 0); # endif if (PRIVATE->thread != 0) { #endif +#ifdef FREERTOS + if (xTaskCreate( + (__THREAD_FUNC_RET__(*)(void*))func, + ((PIString&)name().elided(15, 0.4f).resize(15, PIChar('\0'))).dataAscii(), // A name just for humans + 128, // This stack size can be checked & adjusted by reading the Stack Highwater + this, + priority_, + &PRIVATE->thread + ) == pdPASS) { + tid_ = (llong)PRIVATE->thread; +#endif +#ifndef FREERTOS setPriority(priority_); +#endif return true; } else { running_ = false; @@ -360,10 +390,12 @@ bool PIThread::_startThread(void * func) { void PIThread::setPriority(PIThread::Priority prior) { -#ifndef FREERTOS // FreeRTOS can't change priority runtime priority_ = prior; -# ifndef WINDOWS if (!running_ || (PRIVATE->thread == 0)) return; +#ifdef FREERTOS + vTaskPrioritySet(PRIVATE->thread, priority2System(priority_)); +#else +# ifndef WINDOWS //PICout(PICoutManipulators::DefaultControls) << "setPriority" << PRIVATE->thread; policy_ = 0; memset(&(PRIVATE->sparam), 0, sizeof(PRIVATE->sparam)); @@ -503,18 +535,18 @@ void PIThread::_endThread() { //PICout(PICoutManipulators::DefaultControls) << "pthread_exit" << (__privateinitializer__.p)->thread; UNREGISTER_THREAD(this); PIINTROSPECTION_THREAD_STOP(this); -#ifndef WINDOWS - pthread_detach(PRIVATE->thread); - PRIVATE->thread = 0; -#endif -#ifndef WINDOWS - pthread_exit(0); -#else +#if defined(WINDOWS) # ifdef CC_GCC _endthreadex(0); # else ExitThread(0); # endif +#elif defined(FREERTOS) + PRIVATE->thread = 0; +#else + pthread_detach(PRIVATE->thread); + PRIVATE->thread = 0; + pthread_exit(0); #endif } @@ -558,8 +590,10 @@ void PIThread::runOnce(PIObject * object, const char * handler, const PIString & delete t; return; } +#ifndef MICRO_PIP __PIThreadCollection::instance()->startedAuto(t); CONNECTU(t, stopped, __PIThreadCollection::instance(), stoppedAuto); +#endif t->startOnce(); } @@ -568,8 +602,10 @@ void PIThread::runOnce(std::function func, const PIString & name) { PIThread * t = new PIThread(); t->setName(name); t->setSlot(func); +#ifndef MICRO_PIP __PIThreadCollection::instance()->startedAuto(t); CONNECTU(t, stopped, __PIThreadCollection::instance(), stoppedAuto); +#endif t->startOnce(); } diff --git a/libs/main/thread/pithread.h b/libs/main/thread/pithread.h index db6053cd..6d676f68 100644 --- a/libs/main/thread/pithread.h +++ b/libs/main/thread/pithread.h @@ -30,6 +30,8 @@ #include "piobject.h" class PIThread; + +#ifndef MICRO_PIP class PIIntrospectionThreads; class PIP_EXPORT __PIThreadCollection: public PIObject { @@ -58,14 +60,16 @@ public: }; static __PIThreadCollection_Initializer__ __PIThreadCollection_initializer__; - +#endif // MICRO_PIP typedef std::function ThreadFunc; class PIP_EXPORT PIThread: public PIObject { PIOBJECT_SUBCLASS(PIThread, PIObject) +#ifndef MICRO_PIP friend class PIIntrospectionThreads; +#endif public: NO_COPY_CLASS(PIThread)