From 6913f8c69fe20c887f7a3b0679a6a63b4bec20c6 Mon Sep 17 00:00:00 2001 From: camilo Date: Thu, 2 Oct 2025 22:03:40 -0500 Subject: [PATCH 1/5] Added bool operator to some core objects. Fix task entries tracking at removal. Increase rev to 1.7.6 --- library.json | 2 +- library.properties | 2 +- src/CMakeLists.txt | 2 +- src/QuarkTS.h | 10 +++++----- src/include/bytebuffer.hpp | 16 +++++++++++++++- src/include/cli.hpp | 29 +++++++++++++++++++++++++++-- src/include/coroutine.hpp | 7 +++++++ src/include/fsm.hpp | 20 ++++++++++++++++---- src/include/input.hpp | 8 +++----- src/include/kernel.hpp | 9 ++++++++- src/include/list.hpp | 9 ++++++++- src/include/logger.hpp | 2 +- src/include/memory.hpp | 14 ++++++++++++++ src/include/prioqueue.hpp | 2 +- src/include/queue.hpp | 11 ++++++++--- src/include/response.hpp | 12 +++++++++--- src/include/task.hpp | 11 ++++++++--- src/include/timer.hpp | 8 ++++++++ src/include/types.hpp | 10 ++++++++++ src/kernel.cpp | 2 ++ 20 files changed, 153 insertions(+), 33 deletions(-) diff --git a/library.json b/library.json index 44bb3bbd..17e6bacb 100644 --- a/library.json +++ b/library.json @@ -16,7 +16,7 @@ "maintainer": true } ], - "version": "1.7.5", + "version": "1.7.6", "license": "MIT", "frameworks": "arduino", "platforms": "*" diff --git a/library.properties b/library.properties index f7e63914..06e09768 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=QuarkTS -version=1.7.5 +version=1.7.6 license=MIT author=J. Camilo Gomez C. maintainer=J. Camilo Gomez C. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ac716fd1..6df74fd3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required( VERSION 3.2 ) project( quarkts-cpp - VERSION 1.7.5 + VERSION 1.7.6 DESCRIPTION "An open-source OS for small embedded applications" LANGUAGES CXX ) diff --git a/src/QuarkTS.h b/src/QuarkTS.h index 77840f39..08e44cba 100644 --- a/src/QuarkTS.h +++ b/src/QuarkTS.h @@ -1,7 +1,7 @@ /*! * @file QuarkTS.h * @author J. Camilo Gomez C. - * @version 1.7.5 + * @version 1.7.6 * @note This file is part of the QuarkTS++ distribution. * @brief Global inclusion header **/ @@ -41,8 +41,8 @@ This file is part of the QuarkTS++ OS distribution. #ifndef QOS_CPP_H #define QOS_CPP_H -#define QUARKTS_CPP_VERSION "1.7.5" -#define QUARKTS_CPP_VERNUM ( 175u ) +#define QUARKTS_CPP_VERSION "1.7.6" +#define QUARKTS_CPP_VERNUM ( 176u ) #define QUARKTS_CPP_CAPTION "QuarkTS++ OS " QUARKTS_CPP_VERSION #include "config/config.h" @@ -66,7 +66,7 @@ This file is part of the QuarkTS++ OS distribution. namespace qOS { namespace build { - constexpr const uint32_t number = 4144; + constexpr const uint32_t number = 4149; constexpr const char* date = __DATE__; constexpr const char* time = __TIME__; constexpr const char* std = "c++11"; @@ -76,7 +76,7 @@ namespace qOS { constexpr const uint8_t number = QUARKTS_CPP_VERNUM; constexpr const uint8_t mayor = 1U; constexpr const uint8_t minor = 7U; - constexpr const uint8_t rev = 5U; + constexpr const uint8_t rev = 6U; } namespace product { constexpr const char* author = "J. Camilo Gomez C."; diff --git a/src/include/bytebuffer.hpp b/src/include/bytebuffer.hpp index 8f281155..605d178e 100644 --- a/src/include/bytebuffer.hpp +++ b/src/include/bytebuffer.hpp @@ -14,7 +14,7 @@ namespace qOS { /** * @brief A Byte-sized buffer object */ - class byteBuffer { + class byteBuffer : private nonCopyable { private: volatile byte_t *buffer{ nullptr }; volatile index_t tail{ 0U }; @@ -96,6 +96,20 @@ namespace qOS { * @return Number of elements in the byte-sized Buffer. */ size_t count( void ) const noexcept; + /** + * @brief Check if the byteBuffer instance has been initialized. + * @return @c true if instance has been initialized + */ + bool isInitialized( void ) const { + return ( nullptr != buffer ); + } + /** + * @brief Check if the byteBuffer instance has been initialized. + * @return @c true if instance has been initialized + */ + explicit operator bool() const noexcept { + return isInitialized(); + } }; /** @}*/ diff --git a/src/include/cli.hpp b/src/include/cli.hpp index 3e7f95ce..257ad295 100644 --- a/src/include/cli.hpp +++ b/src/include/cli.hpp @@ -299,7 +299,7 @@ namespace qOS { /** * @brief An AT-Command object */ - class command : protected node { + class command : protected node, private nonCopyable { private: commandCallback_t cmdCallback{ nullptr }; options_t cmdOpt{ 0U }; @@ -313,10 +313,21 @@ namespace qOS { /*! @cond */ virtual ~command() {} /*! @endcond */ + /** + * @brief Retrieve the command user-defined parameter. + * @return @c A generic pointer to the user-defined parameter + */ inline void* getParam( void ) noexcept { return param; } + /** + * @brief Check if the byteBuffer instance has been initialized. + * @return @c true if instance has been initialized + */ + explicit operator bool() const noexcept { + return ( nullptr != Text ) && ( nullptr != cmdCallback ); + } friend class qOS::commandLineInterface; }; /** @}*/ @@ -330,7 +341,7 @@ namespace qOS { * The instance should be initialized using the commandLineInterface::setup() * method. */ - class commandLineInterface : protected cli::input { + class commandLineInterface : protected cli::input, private nonCopyable { private: list subscribed; cli::commandHandler handler; @@ -462,6 +473,20 @@ namespace qOS { { handler.Data = pData; } + /** + * @brief Check if the CLI instance has been initialized. + * @return @c true if instance has been initialized + */ + bool isInitialized( void ) const { + return ( nullptr != cli::input::storage ); + } + /** + * @brief Check if the CLI instance has been initialized. + * @return @c true if instance has been initialized + */ + explicit operator bool() const noexcept { + return isInitialized(); + } friend class cli::commandHandler; friend class core; }; diff --git a/src/include/coroutine.hpp b/src/include/coroutine.hpp index 72bb861e..4e56d77c 100644 --- a/src/include/coroutine.hpp +++ b/src/include/coroutine.hpp @@ -77,6 +77,13 @@ namespace qOS { * @brief Try to execute co::setPosition() statement externally. */ void try_set( co::state p ) noexcept; + /** + * @brief Check if the Co-Routine handle is valid. + * @return @c true if handle is valid + */ + explicit operator bool() const noexcept { + return ( nullptr != ctx ); + } friend class co::coContext; }; diff --git a/src/include/fsm.hpp b/src/include/fsm.hpp index 317d8d52..3ef87d8d 100644 --- a/src/include/fsm.hpp +++ b/src/include/fsm.hpp @@ -355,7 +355,7 @@ namespace qOS { #endif /*! @cond */ - class stateHandler { + class stateHandler : private nonCopyable { protected: state *StartState{ nullptr }; state *NextState{ nullptr }; @@ -364,10 +364,8 @@ namespace qOS { historyMode TransitionHistory{ historyMode::NO_HISTORY }; status Status{ SUCCESS }; signalID Signal{ signalID::SIGNAL_NONE }; - stateHandler( stateHandler const& ) = delete; /* not copyable*/ - void operator=( stateHandler const& ) = delete; /* not assignable*/ - public: stateHandler() = default; + public: virtual ~stateHandler() {} void *SignalData{ nullptr }; /**< The data with which the signal is associated*/ void *Data{ nullptr }; /**< The user storage pointer. If the FSM its running as a task, this will point to the event_t structure*/ @@ -1032,6 +1030,20 @@ namespace qOS { * @c false. */ bool run( sm::signal_t sig ) noexcept; + /** + * @brief Check if the state machine instance has been initialized. + * @return @c true if instance has been initialized + */ + bool isInitialized( void ) const { + return ( nullptr != top.initState ); + } + /** + * @brief Check if the state machine instance has been initialized. + * @return @c true if instance has been initialized + */ + explicit operator bool() const noexcept { + return isInitialized(); + } friend class core; }; /** @}*/ diff --git a/src/include/input.hpp b/src/include/input.hpp index 926ce5a7..0fb60652 100644 --- a/src/include/input.hpp +++ b/src/include/input.hpp @@ -257,7 +257,7 @@ namespace qOS { * @param[in] inputChannel The specified channel(pin) number to read. * @param[in] invert To invert/negate the raw-reading. */ - digitalChannel( const uint8_t inputChannel, bool invert = false ) : channel( inputChannel ), negate( invert) {} + explicit digitalChannel( const uint8_t inputChannel, bool invert = false ) : channel( inputChannel ), negate( invert) {} /** * @brief Get the channel type. * @return The channel type. @@ -453,7 +453,7 @@ namespace qOS { /** * @brief The digital input-channel watcher class. */ - class watcher : protected node { + class watcher : protected node, private nonCopyable { private: eventCallback_t exception{ nullptr }; list digitalChannels; @@ -462,8 +462,6 @@ namespace qOS { qOS::duration_t debounceTime{ 100_ms }; digitalReaderFcn_t digitalReader{ nullptr }; analogReaderFcn_t analogReader{ nullptr }; - watcher( watcher const& ) = delete; - void operator=( watcher const& ) = delete; public: /*! @cond */ virtual ~watcher() {} @@ -473,7 +471,7 @@ namespace qOS { * @param[in] timeDebounce The specified time to bypass the * bounce of the digital input channels */ - watcher( const qOS::duration_t dt = 100_ms ) : debounceTime( dt ) {} + explicit watcher( const qOS::duration_t dt = 100_ms ) : debounceTime( dt ) {} /** * @brief Constructor for the input-watcher instance * @param[in] rDigital A pointer to a function that reads the specific diff --git a/src/include/kernel.hpp b/src/include/kernel.hpp index 5ff0e0d3..4a99de76 100644 --- a/src/include/kernel.hpp +++ b/src/include/kernel.hpp @@ -80,7 +80,7 @@ namespace qOS { * @brief The class to interface the OS * @note Use the predefined os instance */ - class core final : protected taskEvent { + class core final : protected taskEvent, private nonCopyable { private: task idle; taskFcn_t releaseSchedCallback{ nullptr }; @@ -452,6 +452,13 @@ namespace qOS { * @return Returns @c true if success, otherwise returns @c false. */ bool remove( input::watcher &w ) noexcept; + /** + * @brief Check if the OS instance has been initialized. + * @return @c true if OS instance has been initialized + */ + explicit operator bool() const noexcept { + return ( 0U == idle.entry ); + } }; /** @brief The predefined instance of the OS kernel interface */ extern core& os; // skipcq: CXX-W2011, CXX-W2009 diff --git a/src/include/list.hpp b/src/include/list.hpp index 5e62d605..cbb8c717 100644 --- a/src/include/list.hpp +++ b/src/include/list.hpp @@ -72,7 +72,7 @@ namespace qOS { * @brief Get a pointer to the list in which this node is contained. * @return A pointer to the list container. */ - inline list* getContainer( void ) noexcept + inline list* getContainer( void ) const noexcept { return container; } @@ -249,6 +249,13 @@ namespace qOS { * @return An iterator to the @a offset of the sequence container. */ listIterator from( void *offset ) noexcept; + /** + * @brief Check if the list has items (is non-empty). + * @return @c true if instance has items + */ + explicit operator bool() const noexcept { + return ( nullptr != head ); + } friend class listIterator; }; diff --git a/src/include/logger.hpp b/src/include/logger.hpp index e313859c..733a7b64 100644 --- a/src/include/logger.hpp +++ b/src/include/logger.hpp @@ -304,7 +304,7 @@ namespace qOS { extern const char * const wht; /*! @cond */ - class _logger final { + class _logger final : private nonCopyable { private: _logger() = default; _logger( _logger &other ) = delete; diff --git a/src/include/memory.hpp b/src/include/memory.hpp index 01b9dbf4..ceb1384d 100644 --- a/src/include/memory.hpp +++ b/src/include/memory.hpp @@ -107,6 +107,20 @@ namespace qOS { * @return The size of the unallocated heap. */ size_t getFreeSize( void ) const noexcept; + /** + * @brief Check if the memory pool instance has been initialized. + * @return @c true if instance has been initialized + */ + bool isInitialized( void ) const { + return ( nullptr != poolMemory ) && ( poolMemSize > 0U ); + } + /** + * @brief Check if the memory pool instance has been initialized. + * @return @c true if instance has been initialized + */ + explicit operator bool() const noexcept { + return isInitialized(); + } }; /** @}*/ diff --git a/src/include/prioqueue.hpp b/src/include/prioqueue.hpp index c99cbb2e..81f26fd4 100644 --- a/src/include/prioqueue.hpp +++ b/src/include/prioqueue.hpp @@ -15,7 +15,7 @@ namespace qOS { }; } - class prioQueue { + class prioQueue : private nonCopyable { private: volatile base_t index{ -1 }; void *data{ nullptr }; diff --git a/src/include/queue.hpp b/src/include/queue.hpp index ccedc619..65441426 100644 --- a/src/include/queue.hpp +++ b/src/include/queue.hpp @@ -41,7 +41,7 @@ namespace qOS { * writer and could be statically allocated at compile time or in run-time * using the memory management extension. */ - class queue { + class queue : private nonCopyable { private: uint8_t *head{ nullptr }; uint8_t *tail{ nullptr }; @@ -53,8 +53,6 @@ namespace qOS { void moveReader( void ) noexcept; void copyDataFromQueue( void * const dst ) noexcept; void copyDataToQueue( const void *itemToQueue, const queueSendMode xPosition ) noexcept; - queue( queue const& ) = delete; - void operator=( queue const& ) = delete; public: queue() = default; /*! @cond */ @@ -148,6 +146,13 @@ namespace qOS { */ bool isInitialized( void ) const noexcept; /** + * @brief Check if the queue is already initialized by using queue::setup() + * @return @c true if the queue is initialized, @c false if not. + */ + explicit operator bool() const noexcept { + return isInitialized(); + } + /** * @brief Get the size(in bytes) used for every item in the queue. * @return The item-size in bytes. */ diff --git a/src/include/response.hpp b/src/include/response.hpp index c61a79ca..ba5ce997 100644 --- a/src/include/response.hpp +++ b/src/include/response.hpp @@ -24,7 +24,7 @@ namespace qOS { /** * @brief A Response Handler object. */ - class response { + class response : private nonCopyable { private: char *pattern2Match{ nullptr }; timer timeout; @@ -32,8 +32,6 @@ namespace qOS { size_t patternLength{ 0U }; volatile size_t matchedCount{ 0U }; volatile bool responseReceived{ false }; - response( response const& ) = delete; - void operator=( response const& ) = delete; public: response() = default; /*! @cond */ @@ -75,6 +73,14 @@ namespace qOS { * @return @c true if the response object is initialized, @c false if not. */ bool isInitialized( void ) const noexcept; + /** + * @brief Check if the response object is already initialized by + * using response::setup() + * @return @c true if the response object is initialized, @c false if not. + */ + explicit operator bool() const noexcept { + return isInitialized(); + } }; /** @}*/ diff --git a/src/include/task.hpp b/src/include/task.hpp index bb973b3c..07f023dc 100644 --- a/src/include/task.hpp +++ b/src/include/task.hpp @@ -345,7 +345,7 @@ namespace qOS { * execution-state for that task, preventing the activation of other tasks. * @note Do not access any member of this structure directly. */ - class task : protected node { + class task : protected node, private nonCopyable { friend class core; private: void *taskData{ nullptr }; @@ -377,8 +377,6 @@ namespace qOS { static const uint32_t BIT_REMOVE_REQUEST; static const uint32_t EVENT_FLAGS_MASK; static const uint32_t QUEUE_FLAGS_MASK; - task( task const& ) = delete; - void operator=( task const& ) = delete; protected: virtual void activities( event_t e ); public: @@ -586,6 +584,13 @@ namespace qOS { * @return A @c void pointer to the attached object. */ queue* getQueue( void ) noexcept; + /** + * @brief Check if the task has been added to the OS scheduler. + * @return @c true if task is already added to the scheduler + */ + explicit operator bool() const noexcept { + return ( SIZE_MAX != entry ) && ( nullptr == getContainer() ); + } /** @brief A constant to indicate that the task will run every time * its timeout has expired. */ diff --git a/src/include/timer.hpp b/src/include/timer.hpp index ee55d31a..e4d0e97e 100644 --- a/src/include/timer.hpp +++ b/src/include/timer.hpp @@ -150,6 +150,14 @@ namespace qOS { * @param[in] en @c true for reload of @c false to disarm. */ void operator()( const bool en ); + /** + * @brief Non-Blocking timer check + * @return Returns @c true when timer expires, otherwise, returns @c false. + * @note A disarmed timer also returns @c false. + */ + explicit operator bool() const noexcept { + return expired(); + } /** @brief Constant that defines the status of an armed timer*/ static const bool ARMED; /** @brief Constant that defines the status of a disarmed timer*/ diff --git a/src/include/types.hpp b/src/include/types.hpp index 82a9f92e..c47f9e37 100644 --- a/src/include/types.hpp +++ b/src/include/types.hpp @@ -122,6 +122,16 @@ namespace qOS { #else using string = std::string; #endif + + class nonCopyable { + protected: + nonCopyable() {} + ~nonCopyable() {} + private: + nonCopyable( const nonCopyable & ); + nonCopyable& operator=( const nonCopyable & ); + }; + /*! @endcond */ /** diff --git a/src/kernel.cpp b/src/kernel.cpp index a3ea9def..af5156e2 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -253,6 +253,8 @@ bool core::checkIfReady( void ) noexcept critical::exit(); #endif xTask->setFlags( task::BIT_REMOVE_REQUEST, false ); + --core::taskEntries; + xTask->entry = SIZE_MAX; } else { list * const xList = ( trigger::None != xTask->Trigger ) ? &coreLists[ xTask->priority ] : &suspendedList; From 41ea814316902c75aa617d22bc7b093c0336a7e8 Mon Sep 17 00:00:00 2001 From: camilo Date: Fri, 10 Oct 2025 07:38:43 -0500 Subject: [PATCH 2/5] bump to 1.7.7 --- library.json | 2 +- library.properties | 2 +- src/CMakeLists.txt | 2 +- src/QuarkTS.h | 10 +++--- src/include/cli.hpp | 2 +- src/include/clock.hpp | 2 +- src/include/input.hpp | 8 ++--- src/include/kernel.hpp | 41 +++++++++++----------- src/include/list.hpp | 2 +- src/include/timer.hpp | 20 +++++++++-- src/input.cpp | 2 +- src/kernel.cpp | 77 ++++++++++++++++++++++++++---------------- src/timer.cpp | 18 ++++++++-- 13 files changed, 120 insertions(+), 68 deletions(-) diff --git a/library.json b/library.json index 17e6bacb..e42b7497 100644 --- a/library.json +++ b/library.json @@ -16,7 +16,7 @@ "maintainer": true } ], - "version": "1.7.6", + "version": "1.7.7", "license": "MIT", "frameworks": "arduino", "platforms": "*" diff --git a/library.properties b/library.properties index 06e09768..41dd5e0a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=QuarkTS -version=1.7.6 +version=1.7.7 license=MIT author=J. Camilo Gomez C. maintainer=J. Camilo Gomez C. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6df74fd3..d6ebd689 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required( VERSION 3.2 ) project( quarkts-cpp - VERSION 1.7.6 + VERSION 1.7.7 DESCRIPTION "An open-source OS for small embedded applications" LANGUAGES CXX ) diff --git a/src/QuarkTS.h b/src/QuarkTS.h index 08e44cba..7f8e261d 100644 --- a/src/QuarkTS.h +++ b/src/QuarkTS.h @@ -1,7 +1,7 @@ /*! * @file QuarkTS.h * @author J. Camilo Gomez C. - * @version 1.7.6 + * @version 1.7.7 * @note This file is part of the QuarkTS++ distribution. * @brief Global inclusion header **/ @@ -41,8 +41,8 @@ This file is part of the QuarkTS++ OS distribution. #ifndef QOS_CPP_H #define QOS_CPP_H -#define QUARKTS_CPP_VERSION "1.7.6" -#define QUARKTS_CPP_VERNUM ( 176u ) +#define QUARKTS_CPP_VERSION "1.7.7" +#define QUARKTS_CPP_VERNUM ( 177u ) #define QUARKTS_CPP_CAPTION "QuarkTS++ OS " QUARKTS_CPP_VERSION #include "config/config.h" @@ -66,7 +66,7 @@ This file is part of the QuarkTS++ OS distribution. namespace qOS { namespace build { - constexpr const uint32_t number = 4149; + constexpr const uint32_t number = 4181; constexpr const char* date = __DATE__; constexpr const char* time = __TIME__; constexpr const char* std = "c++11"; @@ -76,7 +76,7 @@ namespace qOS { constexpr const uint8_t number = QUARKTS_CPP_VERNUM; constexpr const uint8_t mayor = 1U; constexpr const uint8_t minor = 7U; - constexpr const uint8_t rev = 6U; + constexpr const uint8_t rev = 7U; } namespace product { constexpr const char* author = "J. Camilo Gomez C."; diff --git a/src/include/cli.hpp b/src/include/cli.hpp index 257ad295..c4546149 100644 --- a/src/include/cli.hpp +++ b/src/include/cli.hpp @@ -74,7 +74,7 @@ namespace qOS { volatile bool ready{ false }; void flush( void ); void operator=( input const& ) = delete; - input() {} + input() noexcept {} }; /*! @endcond */ diff --git a/src/include/clock.hpp b/src/include/clock.hpp index ec26c831..a4af7742 100644 --- a/src/include/clock.hpp +++ b/src/include/clock.hpp @@ -81,7 +81,7 @@ namespace qOS { /*! @cond */ static volatile qOS::clock_t sysTick_Epochs; // skipcq: CXX-W2009 static qOS::clock_t internalTick( void ) noexcept; - clock(); + clock() = default; /*! @endcond */ public: clock( clock &other ) = delete; diff --git a/src/include/input.hpp b/src/include/input.hpp index 0fb60652..05be189d 100644 --- a/src/include/input.hpp +++ b/src/include/input.hpp @@ -117,7 +117,7 @@ namespace qOS { public: /*! @cond */ virtual ~channel() {} - channel( uint8_t channelNumber ) : number( channelNumber ) {} + channel( uint8_t channelNumber ) noexcept : number( channelNumber ) {} /*! @endcond */ /** @@ -257,7 +257,7 @@ namespace qOS { * @param[in] inputChannel The specified channel(pin) number to read. * @param[in] invert To invert/negate the raw-reading. */ - explicit digitalChannel( const uint8_t inputChannel, bool invert = false ) : channel( inputChannel ), negate( invert) {} + explicit digitalChannel( const uint8_t inputChannel, bool invert = false ) noexcept : channel( inputChannel ), negate( invert) {} /** * @brief Get the channel type. * @return The channel type. @@ -373,7 +373,7 @@ namespace qOS { * @param[in] upperThreshold The upper threshold value. * @param[in] h Hysteresis for the in-band transition. */ - analogChannel( const uint8_t inputChannel, const analogValue_t lowerThreshold, const analogValue_t upperThreshold, const analogValue_t h = 20 ) + analogChannel( const uint8_t inputChannel, const analogValue_t lowerThreshold, const analogValue_t upperThreshold, const analogValue_t h = 20 ) noexcept : channel( inputChannel ), high( upperThreshold ), low( lowerThreshold ), @@ -453,7 +453,7 @@ namespace qOS { /** * @brief The digital input-channel watcher class. */ - class watcher : protected node, private nonCopyable { + class watcher : private nonCopyable { private: eventCallback_t exception{ nullptr }; list digitalChannels; diff --git a/src/include/kernel.hpp b/src/include/kernel.hpp index 4a99de76..9d9d6f3c 100644 --- a/src/include/kernel.hpp +++ b/src/include/kernel.hpp @@ -93,7 +93,8 @@ namespace qOS { list coreLists[ Q_PRIORITY_LEVELS + 2 ]; // skipcq: CXX-W2066 list& waitingList; // skipcq: CXX-W2012, CXX-W2010 list& suspendedList; // skipcq: CXX-W2012, CXX-W2010 - list inputWatchers; + //list inputWatchers; + void(*cpuIdle)(void){ nullptr }; static const priority_t MAX_PRIORITY_VALUE; static const uint32_t BIT_INIT; static const uint32_t BIT_FCALL_IDLE; @@ -104,8 +105,7 @@ namespace qOS { void dispatchTaskFillEventInfo( task *Task ) noexcept; void dispatch( list * const xList ) noexcept; void dispatchIdle( void ) noexcept; - void handleInputWatchers( void ) noexcept; - core() : waitingList( coreLists[ Q_PRIORITY_LEVELS ] ), suspendedList( coreLists[ Q_PRIORITY_LEVELS + 1 ] ) {} + core() noexcept : waitingList( coreLists[ Q_PRIORITY_LEVELS ] ), suspendedList( coreLists[ Q_PRIORITY_LEVELS + 1 ] ) {} core( core &other ) = delete; void operator=( const core & ) = delete; public: @@ -131,6 +131,8 @@ namespace qOS { * @param[in] callbackIdle Callback function to the Idle Task. To * disable the Idle-Task activities, ignore this parameter of pass * @c nullptr as argument. + * @param[in] coreIdleFcn The function that sets the CPU into + * low-power or idle state * @return @c true on success. Otherwise return @c false. * * Example : When tick is already provided @@ -165,7 +167,7 @@ namespace qOS { * } * @endcode */ - bool init( const getTickFcn_t tFcn = nullptr, taskFcn_t callbackIdle = nullptr ) noexcept; + bool init( const getTickFcn_t tFcn = nullptr, taskFcn_t callbackIdle = nullptr, void(*coreIdleFcn)(void) = nullptr ) noexcept; /** * @brief Add a task to the scheduling scheme. The task is scheduled to run * every @a t time units, @a n times and executing @a callback method on @@ -262,6 +264,15 @@ namespace qOS { bool add( task &Task, commandLineInterface &cli, const priority_t p, void *arg = nullptr ) noexcept; /** @}*/ #endif + + /** + * @brief Add an input-watcher so that its function is executed by + * the kernel + * @note The input-watcher is considered as an always-active task + * @param[in] w The input watcher. + * @return Returns @c true if success, otherwise returns @c false. + */ + bool add( task &Task, input::watcher &w, const priority_t p = HIGHEST_PRIORITY, const taskState s = taskState::ENABLED_STATE, void *arg = nullptr ) noexcept; /** * @brief Set/Change the callback for the Idle-task * @param[in] callback A pointer to a void callback method with a qOS::event_t @@ -277,6 +288,13 @@ namespace qOS { */ bool setNameIdleTask( const char *tName ) noexcept; /** + * @brief Set the function that puts the CPU into a low-power or + * idle state until an interrupt occurs. + * @param[in] pFcn The function to put the CPU into low-power or idle-state + * @return @c true on success. Otherwise return @c false. + */ + bool setCoreIdleFcn( void(*pFcn)(void) ) noexcept; + /** * @brief Disables the kernel scheduling. The main thread will continue * after the core::run() call. */ @@ -438,21 +456,6 @@ namespace qOS { */ globalState getGlobalState( task &Task ) const noexcept; /** - * @brief Add an input-watcher so that its function is executed by - * the kernel - * @note The input-watcher is considered as an always-active task - * @param[in] w The input watcher. - * @return Returns @c true if success, otherwise returns @c false. - */ - bool add( input::watcher &w ) noexcept; - /** - * @brief Remove an input-watcher so that the kernel stops executing - * its function - * @param[in] w The input-watcher. - * @return Returns @c true if success, otherwise returns @c false. - */ - bool remove( input::watcher &w ) noexcept; - /** * @brief Check if the OS instance has been initialized. * @return @c true if OS instance has been initialized */ diff --git a/src/include/list.hpp b/src/include/list.hpp index cbb8c717..5f1d6bfb 100644 --- a/src/include/list.hpp +++ b/src/include/list.hpp @@ -76,7 +76,7 @@ namespace qOS { { return container; } - node() : next(nullptr), prev(nullptr), container(nullptr) {} + node() noexcept : next(nullptr), prev(nullptr), container(nullptr) {} /*! @cond */ virtual ~node() {} /*! @endcond */ diff --git a/src/include/timer.hpp b/src/include/timer.hpp index e4d0e97e..7095ee50 100644 --- a/src/include/timer.hpp +++ b/src/include/timer.hpp @@ -28,7 +28,7 @@ namespace qOS { qOS::clock_t tStart{ 0U }; qOS::clock_t tv{ 0U }; public: - timer(); + timer() noexcept; /*! @cond */ virtual ~timer() {} /*! @endcond */ @@ -85,7 +85,23 @@ namespace qOS { * @return Returns @c true on success, otherwise, returns @c false. * @note A disarmed timer also returns @c false. */ - bool freeRun( const qOS::duration_t tTime ) noexcept; + bool reloadIfExpired( const qOS::duration_t tTime ) noexcept; + /** + * @brief Non-Blocking timer check with automatic arming. + * + * Behavior: + * If disarmed, it gets armed immediately with the previous + * specified time. + * + * If armed, the API only checks for expiration. When the time + * expires, the timer gets armed immediately using the previously + * assigned time. + * @note After the timer expiration, this method re-arms the timer + * @note The OS must be running before using a timer. + * @return Returns @c true on success, otherwise, returns @c false. + * @note A disarmed timer also returns @c false. + */ + bool reloadIfExpired( void ) noexcept; /** * @brief Retrieve the remaining time in epochs * @return The remaining time specified in epochs. diff --git a/src/input.cpp b/src/input.cpp index 7b19a5e4..fcc7ada6 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -262,7 +262,7 @@ void input::analogChannel::steadyInBandState( input::analogChannel& c ) /*============================================================================*/ bool input::watcher::watch( void ) noexcept { - const bool act = waitDebounce.freeRun( debounceTime ); + const bool act = waitDebounce.reloadIfExpired( debounceTime ); if ( ( digitalChannels.length() > 0U ) && act ) { for ( auto i = digitalChannels.begin(); i.untilEnd() ; i++ ) { input::channel& c = *i.get(); diff --git a/src/kernel.cpp b/src/kernel.cpp index af5156e2..a3c5f5af 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -21,12 +21,14 @@ const priority_t core::MEDIUM_PRIORITY = static_cast( Q_PRIORITY_LEV const priority_t core::HIGHEST_PRIORITY = static_cast( Q_PRIORITY_LEVELS ) - 1U; const notifier_t MAX_NOTIFICATION_VALUE = UINT32_MAX - 1UL; -#if ( Q_CLI == 1 ) +#if ( Q_FSM == 1 ) static void fsmTaskCallback( event_t e ); +#endif +#if ( Q_CLI == 1 ) static void cliTaskCallback( event_t e ); static void cliNotifyFcn( commandLineInterface *cli ); #endif - +static void inputWatcherTaskCallback( event_t e ); /*============================================================================*/ core& core::getInstance( void ) noexcept { @@ -35,13 +37,14 @@ core& core::getInstance( void ) noexcept } /*============================================================================*/ /*cstat -MISRAC++2008-7-1-2*/ -bool core::init( const getTickFcn_t tFcn, taskFcn_t callbackIdle ) noexcept +bool core::init( const getTickFcn_t tFcn, taskFcn_t callbackIdle, void(*coreIdleFcn)(void) ) noexcept { (void)clock::setTickProvider( tFcn ); (void)setNameIdleTask( "idle" ); (void)idle.setPriority( core::LOWEST_PRIORITY ); (void)idle.setState( taskState::DISABLED_STATE ); (void)idle.setCallback( callbackIdle ); + (void)setCoreIdleFcn( coreIdleFcn ); idle.entry = 0U; return true; } @@ -122,6 +125,26 @@ bool core::add( task &Task, commandLineInterface &cli, const priority_t p, void } #endif /*Q_CLI*/ /*============================================================================*/ +static void inputWatcherTaskCallback( event_t e ) +{ + /*cstat -CERT-EXP36-C_b*/ + input::watcher * const w = static_cast( e.thisTask().getBindedObject() ); + /*cstat +CERT-EXP36-C_b*/ + (void)w->watch(); +} +/*============================================================================*/ +bool core::add( task &Task, input::watcher &w, const priority_t p, const taskState s, void *arg ) noexcept +{ + bool retValue = core::add( Task, inputWatcherTaskCallback, p, 10_ms, task::PERIODIC, s, arg ); + + if ( retValue ) { + Task.aObj = &w; + retValue = true; + } + + return retValue; +} +/*============================================================================*/ /*cstat -MISRAC++2008-7-1-2*/ bool core::setIdleTask( taskFcn_t callback ) noexcept { @@ -143,6 +166,18 @@ bool core::setNameIdleTask( const char *tName ) noexcept return retValue; } /*============================================================================*/ +bool core::setCoreIdleFcn( void(*pFcn)(void) ) noexcept +{ + bool retValue = false; + + if ( pFcn != cpuIdle ) { + cpuIdle = pFcn; + retValue = true; + } + + return retValue; +} +/*============================================================================*/ bool core::schedulerRelease( void ) noexcept { bits::multipleSet( flag, BIT_RELEASE_SCHED ); @@ -373,7 +408,9 @@ bool core::run( void ) noexcept /*cstat +MISRAC++2008-0-1-6*/ do { - if ( checkIfReady() ) { + const bool anyActiveTask = checkIfReady(); + + if ( anyActiveTask) { priority_t xPriorityListIndex = MAX_PRIORITY_VALUE; do { @@ -383,14 +420,6 @@ bool core::run( void ) noexcept } } while( 0U != xPriorityListIndex-- ); } - else { - if ( nullptr != idle.callback ) { - dispatchIdle(); - } - } - if ( inputWatchers.length() > 0U ) { - handleInputWatchers(); - } if ( suspendedList.length() > 0U ) { (void)waitingList.move( suspendedList, listPosition::AT_BACK ); #if ( Q_PRESERVE_TASK_ENTRY_ORDER == 1 ) @@ -398,6 +427,13 @@ bool core::run( void ) noexcept (void)waitingList.sort( taskEntryOrderPreserver ); #endif } + + if ( !anyActiveTask ) { + dispatchIdle(); + if ( nullptr != cpuIdle ) { + cpuIdle(); + } + } } #if ( Q_ALLOW_SCHEDULER_RELEASE == 1 ) while ( !bits::multipleGet( flag, BIT_RELEASE_SCHED ) ); @@ -601,20 +637,3 @@ globalState core::getGlobalState( task &Task ) const noexcept return retValue; } /*============================================================================*/ -bool core::add( input::watcher &w ) noexcept -{ - return inputWatchers.insert( &w ); -} -/*============================================================================*/ -bool core::remove( input::watcher &w ) noexcept -{ - return inputWatchers.remove( &w ); -} -/*============================================================================*/ -void core::handleInputWatchers( void ) noexcept -{ - for ( auto i = inputWatchers.begin(); i.untilEnd() ; i++ ) { - input::watcher * const w = i.get(); - (void)w->watch(); - } -} \ No newline at end of file diff --git a/src/timer.cpp b/src/timer.cpp index ca64fc6b..8ef731cb 100644 --- a/src/timer.cpp +++ b/src/timer.cpp @@ -8,7 +8,7 @@ const qOS::clock_t timer::DISARM_VALUE = 0UL ; const qOS::clock_t timer::REMAINING_IN_DISARMED_STATE = 0xFFFFFFFFUL; /*============================================================================*/ -timer::timer() +timer::timer() noexcept { disarm(); } @@ -61,7 +61,7 @@ void timer::disarm( void ) noexcept tStart = timer::DISARM_VALUE; } /*============================================================================*/ -bool timer::freeRun( const qOS::duration_t tTime ) noexcept +bool timer::reloadIfExpired( const qOS::duration_t tTime ) noexcept { bool retValue = false; @@ -78,6 +78,20 @@ bool timer::freeRun( const qOS::duration_t tTime ) noexcept return retValue; } /*============================================================================*/ +bool timer::reloadIfExpired( void ) noexcept +{ + bool retValue = false; + + if ( timer::ARMED == status() ) { + if ( expired() ) { + reload(); + retValue = true; + } + } + + return retValue; +} +/*============================================================================*/ bool timer::operator()( const qOS::duration_t tTime ) { return set( tTime ); From 466c84be4bbbc168e8270a18c763c8e5a1180a60 Mon Sep 17 00:00:00 2001 From: camilo Date: Sat, 25 Oct 2025 19:43:46 -0500 Subject: [PATCH 3/5] bump to 1.7.8 --- check/sa_check.ewd | 14 +- check/sa_check.ewp | 68 ++++-- check/sa_check.ewt | 54 +++-- check/settings/sa_check.Debug.cspy.bat | 4 +- check/settings/sa_check.Debug.cspy.ps1 | 4 +- check/simple_dry_test.cpp | 55 ++--- .../LED_Blink_Flat_State_Machine.ino | 8 +- examples/Simple_Example/Simple_Example.ino | 14 +- library.json | 2 +- library.properties | 2 +- src/CMakeLists.txt | 2 +- src/QuarkTS.h | 10 +- src/critical.cpp | 56 +++-- src/include/critical.hpp | 60 ++++- src/include/list.hpp | 2 + src/include/logger.hpp | 79 +++++-- src/kernel.cpp | 8 +- src/logger.cpp | 206 ++++++++++++++---- src/prioqueue.cpp | 52 ++--- src/queue.cpp | 79 ++++--- 20 files changed, 516 insertions(+), 263 deletions(-) diff --git a/check/sa_check.ewd b/check/sa_check.ewd index b717b728..7fa1f613 100644 --- a/check/sa_check.ewd +++ b/check/sa_check.ewd @@ -88,7 +88,7 @@