Initial commit
This commit is contained in:
10
src/xf/config/xf-config.h
Normal file
10
src/xf/config/xf-config.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef XF_CONFIG_DEFAULT_H
|
||||
#define XF_CONFIG_DEFAULT_H
|
||||
|
||||
#warning "You should provide your own 'xf-config.h' file in your project!"
|
||||
|
||||
// If you need some inspiration on what to provide in the 'xf-config.h' file
|
||||
// please have a look onto the 'xf-config.h' files provided in the
|
||||
// XF test-bench tests.
|
||||
|
||||
#endif // XF_CONFIG_DEFAULT_H
|
104
src/xf/core/behavior.cpp
Normal file
104
src/xf/core/behavior.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
#include <cassert>
|
||||
#include "xf/xf.h"
|
||||
#include "xf/interface/resourcefactory.h"
|
||||
#include "xf/interface/dispatcher.h"
|
||||
#include "xf/timeout.h"
|
||||
#include "xf/initialevent.h"
|
||||
#include "xf/behavior.h"
|
||||
|
||||
using interface::XFResourceFactory;
|
||||
|
||||
XFBehavior::XFBehavior(bool ownDispatcher /* = false */) :
|
||||
pDispatcher_(nullptr),
|
||||
hasOwnDispatcher_(ownDispatcher),
|
||||
deleteOnTerminate_(false),
|
||||
pCurrentEvent_(nullptr)
|
||||
{
|
||||
if (ownDispatcher)
|
||||
{
|
||||
pDispatcher_ = XFResourceFactory::getInstance()->createDispatcher();
|
||||
}
|
||||
else
|
||||
{
|
||||
pDispatcher_ = XFResourceFactory::getInstance()->getDefaultDispatcher();
|
||||
}
|
||||
|
||||
// Force hasOwnDispatcher attribute to false in case actual
|
||||
// dispatcher is the default dispatcher. This may happen
|
||||
// if in an IDF an other dispatcher is requested, but
|
||||
// only the default dispatcher is present.
|
||||
if (pDispatcher_ == XFResourceFactory::getInstance()->getDefaultDispatcher())
|
||||
{
|
||||
hasOwnDispatcher_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
XFBehavior::~XFBehavior()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void XFBehavior::startBehavior()
|
||||
{
|
||||
// Send initial event to state machine
|
||||
GEN(XFInitialEvent());
|
||||
|
||||
// Start dispatcher if behavior has its own dispatcher
|
||||
if (hasOwnDispatcher())
|
||||
{
|
||||
getDispatcher()->start();
|
||||
}
|
||||
}
|
||||
|
||||
void XFBehavior::pushEvent(XFEvent * pEvent, bool fromISR)
|
||||
{
|
||||
// Set owner
|
||||
pEvent->setBehavior(this);
|
||||
// Push to dispatchers event queue
|
||||
getDispatcher()->pushEvent(pEvent, fromISR);
|
||||
}
|
||||
|
||||
bool XFBehavior::deleteOnTerminate() const
|
||||
{
|
||||
return deleteOnTerminate_;
|
||||
}
|
||||
|
||||
void XFBehavior::setDeleteOnTerminate(bool deleteBehaviour)
|
||||
{
|
||||
deleteOnTerminate_ = deleteBehaviour;
|
||||
}
|
||||
|
||||
XFBehavior::TerminateBehavior XFBehavior::process(const XFEvent * pEvent)
|
||||
{
|
||||
XFEventStatus eventStatus;
|
||||
|
||||
setCurrentEvent(pEvent);
|
||||
|
||||
eventStatus = processEvent();
|
||||
|
||||
setCurrentEvent(nullptr);
|
||||
|
||||
return (eventStatus == XFEventStatus::Terminate);
|
||||
}
|
||||
|
||||
interface::XFDispatcher * XFBehavior::getDispatcher()
|
||||
{
|
||||
return pDispatcher_;
|
||||
}
|
||||
|
||||
void XFBehavior::setCurrentEvent(const XFEvent * pEvent)
|
||||
{
|
||||
pCurrentEvent_ = pEvent;
|
||||
}
|
||||
|
||||
const XFEvent * XFBehavior::getCurrentEvent() const
|
||||
{
|
||||
return pCurrentEvent_;
|
||||
}
|
||||
|
||||
const XFTimeout * XFBehavior::getCurrentTimeout()
|
||||
{
|
||||
assert(getCurrentEvent()->getEventType() == XFEvent::Timeout);
|
||||
|
||||
return static_cast<const XFTimeout *>(getCurrentEvent());
|
||||
}
|
8
src/xf/core/customevent.cpp
Normal file
8
src/xf/core/customevent.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "xf/customevent.h"
|
||||
|
||||
XFCustomEvent::XFCustomEvent(int id, interface::XFReactive * pBehavior)
|
||||
: XFEvent(XFEvent::Event, id, pBehavior),
|
||||
bDeleteAfterConsume_(true)
|
||||
{
|
||||
|
||||
}
|
11
src/xf/core/initialevent.cpp
Normal file
11
src/xf/core/initialevent.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "xf/initialevent.h"
|
||||
|
||||
XFInitialEvent::XFInitialEvent()
|
||||
: XFEvent(XFEvent::Initial, 0, nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool XFInitialEvent::deleteAfterConsume() const
|
||||
{
|
||||
return true;
|
||||
}
|
11
src/xf/core/nulltransition.cpp
Normal file
11
src/xf/core/nulltransition.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "xf/nulltransition.h"
|
||||
|
||||
XFNullTransition::XFNullTransition(interface::XFReactive * pBehavior)
|
||||
: XFEvent(XFEvent::NullTransition, 0, pBehavior)
|
||||
{
|
||||
}
|
||||
|
||||
bool XFNullTransition::deleteAfterConsume() const
|
||||
{
|
||||
return true;
|
||||
}
|
19
src/xf/core/timeout.cpp
Normal file
19
src/xf/core/timeout.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include "xf/timeout.h"
|
||||
|
||||
XFTimeout::XFTimeout(int id, int interval, interface::XFReactive * pBehavior)
|
||||
: XFEvent(XFEvent::Timeout, id, pBehavior),
|
||||
interval_(interval),
|
||||
relTicks_(interval)
|
||||
{
|
||||
}
|
||||
|
||||
bool XFTimeout::operator ==(const XFTimeout & timeout) const
|
||||
{
|
||||
// Check behavior and timeout id attributes, if there are equal
|
||||
return (pBehavior_ == timeout.pBehavior_ && getId() == timeout.getId()) ? true : false;
|
||||
}
|
||||
|
||||
bool XFTimeout::deleteAfterConsume() const
|
||||
{
|
||||
return true;
|
||||
}
|
2515
src/xf/doxygen/Doxyfile
Normal file
2515
src/xf/doxygen/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
1556
src/xf/doxygen/xf.tag
Normal file
1556
src/xf/doxygen/xf.tag
Normal file
File diff suppressed because it is too large
Load Diff
101
src/xf/include/xf/behavior.h
Normal file
101
src/xf/include/xf/behavior.h
Normal file
@ -0,0 +1,101 @@
|
||||
#ifndef XF_BEHAVIOR_H
|
||||
#define XF_BEHAVIOR_H
|
||||
|
||||
#include "xf/interface/reactive.h"
|
||||
#include "xf/interface/dispatcher.h"
|
||||
#include "xf/eventstatus.h"
|
||||
#include "xf/initialevent.h"
|
||||
#include "xf/nulltransition.h"
|
||||
#include "xf/timeout.h"
|
||||
|
||||
class XFTimeout;
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Base class for state machines, activities, process and data flows.
|
||||
*
|
||||
* Reactive class implementing a behavior. This class can be used to
|
||||
* implement a state machine behavior or an activity behavior.
|
||||
*
|
||||
* Override the processEvent() operation in the inherited class to implement
|
||||
* your state machine behavior. The processEvent() method gets automatically
|
||||
* called every time an event or timeout arrives. The event (or timeout) can
|
||||
* be accessed via the getCurrentEvent() method.
|
||||
*/
|
||||
class XFBehavior : public interface::XFReactive
|
||||
{
|
||||
public:
|
||||
#define GEN(event) pushEvent(new event)
|
||||
|
||||
/**
|
||||
* @brief Default constructor for the behavior.
|
||||
*
|
||||
* Per default the XFBehavior chooses the 'default dispatcher' for event processing. In
|
||||
* case the ownDispatcher parameter is set to true, the XFBehavior creates internally
|
||||
* a separate dispatcher.
|
||||
*
|
||||
* @param ownDispatcher Set to true to get dedicated dispatcher for this behavior.
|
||||
*/
|
||||
explicit XFBehavior(bool ownDispatcher = false);
|
||||
~XFBehavior() override;
|
||||
|
||||
void startBehavior() override; ///< Starts the behavior, resp. the state machine.
|
||||
|
||||
void pushEvent(XFEvent * pEvent, bool fromISR=false) override;
|
||||
|
||||
bool deleteOnTerminate() const override;
|
||||
void setDeleteOnTerminate(bool deleteBehaviour) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Executes the current event in its implemented behavior.
|
||||
* This method needs to be overridden to implement the
|
||||
* behavior (i.e. state machine) needed.
|
||||
*/
|
||||
virtual XFEventStatus processEvent() = 0;
|
||||
|
||||
const XFEvent * getCurrentEvent() const; ///< Returns the current event to be processed in processEvent().
|
||||
interface::XFDispatcher * getDispatcher(); ///< Returns reference to #_pDispatcher.
|
||||
inline bool hasOwnDispatcher() const { return hasOwnDispatcher_; } ///< True if behavior has its own dispatcher.
|
||||
|
||||
|
||||
/** \brief Returns a reference to the actually processed timeout.
|
||||
*
|
||||
* Will work only if the current event is of type IXFEvent::Timeout.
|
||||
*/
|
||||
const XFTimeout * getCurrentTimeout();
|
||||
|
||||
inline void scheduleTimeout(int timeoutId, int interval) { getDispatcher()->scheduleTimeout(timeoutId, interval, this); } ///< @brief Schedules a timeout for this state machine.
|
||||
inline void unscheduleTimeout(int timeoutId) { getDispatcher()->unscheduleTimeout(timeoutId, this); } ///< @brief Unschedules a timeout for this state machine.
|
||||
|
||||
private:
|
||||
void setCurrentEvent(const XFEvent * pEvent); ///< Sets the current event to be processed in processEvent().
|
||||
|
||||
/**
|
||||
* \brief Processes the given event.
|
||||
*
|
||||
* The dispatcher calls this method every time a new event
|
||||
* or timeout arrives. The process method stores the actual
|
||||
* event using the #_pCurrentEvent and then calls
|
||||
* processEvent().
|
||||
*
|
||||
* In case you intend to call process() inside your state machine you
|
||||
* are doing something wrong! Call GEN() or pushEvent() instead!
|
||||
*
|
||||
* \param pEvent The event to process.
|
||||
*/
|
||||
TerminateBehavior process(const XFEvent * pEvent) override;
|
||||
|
||||
|
||||
protected:
|
||||
interface::XFDispatcher * pDispatcher_; ///< Reference to dispatcher processing this behavior.
|
||||
bool hasOwnDispatcher_; ///< True if behavior has its own dispatcher, False if the default dispatcher is used.
|
||||
bool deleteOnTerminate_; ///< Indicates if the behavior can be deleted after reception of a 'terminate event'.
|
||||
const XFEvent * pCurrentEvent_; ///< Reference to actually processed event.
|
||||
};
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // XF_BEHAVIOR_H
|
51
src/xf/include/xf/customevent.h
Normal file
51
src/xf/include/xf/customevent.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef XF_CUSTOMEVENT_H
|
||||
#define XF_CUSTOMEVENT_H
|
||||
|
||||
#include "xf/xf.h"
|
||||
#include "xf/event.h"
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Base class for project related events.
|
||||
*
|
||||
* It is possible to create custom events by deriving new classes/events from
|
||||
* this class.
|
||||
* All custom events have `#Event` as event type. In the state machine the event
|
||||
* can be uniquely identified with `getEventType() == Event` and the event id
|
||||
* `getId()` given to the object at construction time.
|
||||
*
|
||||
* It is up to the devoper to handle the different event ids.
|
||||
*/
|
||||
class XFCustomEvent : public XFEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor for the class
|
||||
*
|
||||
* @param id Event identifier to identify the custom event (in the context of the behavior).
|
||||
* @param pBehavior The behavior for which the event was constructed (will consume the event).
|
||||
**/
|
||||
XFCustomEvent(int id, interface::XFReactive * pBehavior = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Tells the XF if the event should be deleted after processing.
|
||||
* @return True if the event should be deleted.
|
||||
*/
|
||||
bool deleteAfterConsume() const override { return bDeleteAfterConsume_; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Setter for #_bDeleteAfterConsume attribute.
|
||||
* @param bDeleteAfterConsume Parameter to be assigned. Default: true.
|
||||
*/
|
||||
void setDeleteAfterConsume(bool bDeleteAfterConsume = true) { bDeleteAfterConsume_ = bDeleteAfterConsume; }
|
||||
|
||||
protected:
|
||||
bool bDeleteAfterConsume_; ///< True if the XF should delete event after consumption/dispatching.
|
||||
};
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // XF_CUSTOMEVENT_H
|
74
src/xf/include/xf/event.h
Normal file
74
src/xf/include/xf/event.h
Normal file
@ -0,0 +1,74 @@
|
||||
#ifndef XF_EVENT_H
|
||||
#define XF_EVENT_H
|
||||
|
||||
namespace interface {
|
||||
class XFReactive;
|
||||
}
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Base class for all types of events and timeouts.
|
||||
*
|
||||
* Requirements:
|
||||
* - Needs to hold a property which allows to distinguish between different
|
||||
* types of events (#_eventType).
|
||||
* - Use an enumeration to define the type for the event type property (#XFEventType).
|
||||
* - The event type property needs to be set at initialization time and cannot be
|
||||
* changed afterwards.
|
||||
*/
|
||||
class XFEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Defines the types of events
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
Unknown = 0, ///< Unknown state (not initialized).
|
||||
Initial = 1, ///< Initial pseudostate.
|
||||
NullTransition = 2, ///< Event generated by the state machine to define a null transition.
|
||||
Event = 3, ///< Custom event.
|
||||
Timeout = 4, ///< Defines a timeout event.
|
||||
Terminate = -1 ///< Defines a terminate state. Will end the state machine.
|
||||
} XFEventType;
|
||||
|
||||
public :
|
||||
/**
|
||||
* Default class constructor
|
||||
*/
|
||||
XFEvent(XFEventType eventType, int id, interface::XFReactive * pBehavior) : eventType_(eventType), id_(id), pBehavior_(pBehavior) {}
|
||||
virtual ~XFEvent() {} ///< Class destructor
|
||||
|
||||
/** \brief Returns the type of the event.
|
||||
*
|
||||
* Can be used to distinguish between an event or a timeout.
|
||||
*/
|
||||
inline XFEventType getEventType() const { return eventType_; }
|
||||
|
||||
/** \brief Returns pointer to behavioral class.
|
||||
*
|
||||
* Returns a pointer to the behavioral class processing the event (see #_pBehavior).
|
||||
*/
|
||||
inline interface::XFReactive * getBehavior() const { return pBehavior_; }
|
||||
|
||||
/** \brief Sets pointer to behavioral class (see #_pBehavior).
|
||||
* Sets the behavior in which the event should be executed.
|
||||
*/
|
||||
inline void setBehavior(interface::XFReactive * pBehavior) { pBehavior_ = pBehavior; }
|
||||
|
||||
inline int getId() const { return id_; } ///< Returns #_id identifying the event in the behaviors context.
|
||||
|
||||
virtual bool deleteAfterConsume() const { return false; } ///< Tells the dispatcher if the event must be deleted or not.
|
||||
|
||||
protected:
|
||||
const XFEventType eventType_; ///< Holds the type of the event.
|
||||
int id_; ///< Event id
|
||||
|
||||
interface::XFReactive * pBehavior_; ///< Pointer to behavioral class processing the event.
|
||||
};
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // XF_EVENT_H
|
75
src/xf/include/xf/eventstatus.h
Normal file
75
src/xf/include/xf/eventstatus.h
Normal file
@ -0,0 +1,75 @@
|
||||
#ifndef XF_EVENTSTATUS_H
|
||||
#define XF_EVENTSTATUS_H
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Event status returned after event processing.
|
||||
*
|
||||
* The XFEventStatus is used after consumption of an event. It gives an
|
||||
* information on how the event was consument and how the framework should
|
||||
* react.
|
||||
*/
|
||||
class XFEventStatus
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Status values about the event processed.
|
||||
*
|
||||
* \see XFBehavior::process
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
Unknown = 0,
|
||||
Consumed = 0x0001, ///< Event consumed
|
||||
NotConsumed = 0x0002, ///< Event not consumed
|
||||
RegionFinished = 0x0004, ///< Composite state machine finished
|
||||
Terminate = 0x0008 ///< Terminate state machine
|
||||
} eEventStatus;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param eventStatus Initial value of the event status.
|
||||
*/
|
||||
XFEventStatus(eEventStatus eventStatus = Unknown) : status_(eventStatus) {}
|
||||
|
||||
/**
|
||||
* Checks if both variables contain the same event status.
|
||||
*/
|
||||
bool operator == (const XFEventStatus::eEventStatus & eventStatus) const
|
||||
{
|
||||
return (this->status_ == eventStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief OR assignment.
|
||||
*
|
||||
* OR's the right event status with the left event status.
|
||||
*/
|
||||
void operator |= (const XFEventStatus & eventStatus)
|
||||
{
|
||||
unsigned int s1 = status_, s2 = eventStatus.status_;
|
||||
s1 |= s2;
|
||||
status_ = (eEventStatus)s1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the given event status (r-value) is present in the actual (l-value).
|
||||
*/
|
||||
bool is(const eEventStatus eventStatus) const
|
||||
{
|
||||
unsigned int mask = (unsigned int)eventStatus;
|
||||
return ((((unsigned int)status_) & mask) == mask);
|
||||
}
|
||||
|
||||
public:
|
||||
eEventStatus status_; ///< Attribute containing the status of the event.
|
||||
};
|
||||
|
||||
typedef XFEventStatus::eEventStatus eEventStatus;
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // XF_EVENTSTATUS_H
|
25
src/xf/include/xf/initialevent.h
Normal file
25
src/xf/include/xf/initialevent.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef INITIALEVENT_H
|
||||
#define INITIALEVENT_H
|
||||
|
||||
#include "xf/event.h"
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initial event to start a behavior.
|
||||
*
|
||||
* Represents for example the first transition executed
|
||||
* in a state machine.
|
||||
*/
|
||||
class XFInitialEvent : public XFEvent
|
||||
{
|
||||
public:
|
||||
XFInitialEvent();
|
||||
|
||||
bool deleteAfterConsume() const override;
|
||||
};
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // INITIALEVENT_H
|
98
src/xf/include/xf/interface/dispatcher.h
Normal file
98
src/xf/include/xf/interface/dispatcher.h
Normal file
@ -0,0 +1,98 @@
|
||||
#ifndef XF_INTERFACE_DISPATCHER_H
|
||||
#define XF_INTERFACE_DISPATCHER_H
|
||||
|
||||
#include "xf/event.h"
|
||||
|
||||
class XF;
|
||||
|
||||
namespace interface {
|
||||
|
||||
class XFReactive;
|
||||
class XFThread;
|
||||
|
||||
/**
|
||||
* @brief Interface for the XF dispatcher providing the event processing loop.
|
||||
*
|
||||
* Depending on the implementation the dispatcher is executed by
|
||||
* an internal thread. It is up to the port implementation how
|
||||
* the class behaves.
|
||||
*
|
||||
* The dispatcher should at least provide a queue to hold events
|
||||
* and an algorithm (typically in execute()) that dispatches the queued
|
||||
* events to the associated behavior (eq. state machine, activity).
|
||||
*
|
||||
* There may exist multiple dispatchers. Each behavior needs to be
|
||||
* bound to a dispatcher. One dispatcher may serve different behaviors.
|
||||
*
|
||||
* In an IDF the attribute _pThread is usually null.
|
||||
*/
|
||||
class XFDispatcher
|
||||
{
|
||||
friend class ::XF;
|
||||
|
||||
public:
|
||||
virtual ~XFDispatcher() = default;
|
||||
|
||||
virtual bool isActive() const = 0; ///< True if dispatcher has its own thread.
|
||||
|
||||
virtual void start() = 0; ///< Starts the thread.
|
||||
virtual void stop() = 0; ///< Stops the thread.
|
||||
virtual void pushEvent(XFEvent * pEvent, bool fromISR=false) = 0; ///< Adds event to the events queue.
|
||||
/**
|
||||
* @brief Adds a new timeout to be handled.
|
||||
*
|
||||
* The Thread will forward the timeout information to the timeout
|
||||
* manager which is responsible to handle all timeouts.
|
||||
*/
|
||||
virtual void scheduleTimeout(int timeoutId, int interval, interface::XFReactive * pReactive) = 0;
|
||||
|
||||
/**
|
||||
* @brief Removes all timeouts corresponding the given parameters.
|
||||
*/
|
||||
virtual void unscheduleTimeout(int timeoutId, interface::XFReactive * pReactive) = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Constructor is protected because only method createInstance()
|
||||
* should be called to create Dispatcher instances
|
||||
*/
|
||||
XFDispatcher() = default;
|
||||
|
||||
/**
|
||||
* @brief Returns pointer to thread executing the behavior.
|
||||
*
|
||||
* Within an IDF no threads are present and this method returns
|
||||
* always null.
|
||||
*/
|
||||
virtual interface::XFThread * getThread() const { return nullptr; }
|
||||
|
||||
/**
|
||||
* @brief Main loop of the dispatcher. Implements event loop processing.
|
||||
*/
|
||||
virtual int execute(const void * param = nullptr) = 0;
|
||||
|
||||
/**
|
||||
* @brief Executes once the dispatcher.
|
||||
*
|
||||
* Usually, this method must not be called explicitly. The
|
||||
* standard way to call the dispatcher is to call execute().
|
||||
*
|
||||
* This method can be called by the Thread (or main function) if it
|
||||
* must perform concurrent (non-XF related) tasks in addition.
|
||||
*
|
||||
* When using this method start() must not be called.
|
||||
*/
|
||||
virtual int executeOnce() = 0;
|
||||
|
||||
/**
|
||||
* @brief Dispatches the event to the corresponding behavioral part.
|
||||
*
|
||||
* For example the state machine which should process the event.
|
||||
*
|
||||
* \param pEvent The event to dispatch
|
||||
*/
|
||||
virtual void dispatchEvent(const XFEvent * pEvent) const = 0;
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // XF_INTERFACE_DISPATCHER_H
|
27
src/xf/include/xf/interface/eventqueue.h
Normal file
27
src/xf/include/xf/interface/eventqueue.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef XF_INTERFACE_EVENT_QUEUE_H
|
||||
#define XF_INTERFACE_EVENT_QUEUE_H
|
||||
|
||||
class XFEvent;
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Interface to be implemented by the event queue
|
||||
*/
|
||||
class XFEventQueue
|
||||
{
|
||||
public:
|
||||
virtual ~XFEventQueue() = default;
|
||||
|
||||
virtual bool empty() const = 0; ///< Returns true if no event is in the queue.
|
||||
virtual bool push(const XFEvent * pEvent, bool fromISR = false) = 0; ///< Pushes the given event onto the queue.
|
||||
virtual const XFEvent * front() = 0; ///< Returns pointer to next event to pop.
|
||||
virtual void pop() = 0; ///< Pops the next event from the queue.
|
||||
virtual bool pend() = 0; ///< Wait for the next event to arrive. Returns true if an event is in the queue.
|
||||
|
||||
public:
|
||||
XFEventQueue() = default;
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // XF_INTERFACE_EVENT_QUEUE_H
|
56
src/xf/include/xf/interface/mutex.h
Normal file
56
src/xf/include/xf/interface/mutex.h
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef XF_INTERFACE_MUTEX_H
|
||||
#define XF_INTERFACE_MUTEX_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Mutex interface needed by the XF to access a mutex.
|
||||
*
|
||||
* This interface only needs to be implemented for an XF port using
|
||||
* an underlying OS. An IDF based XF does not need to provide a
|
||||
* mutex.
|
||||
*
|
||||
* A non-recursive mutex needs to be implemented.
|
||||
*/
|
||||
class XFMutex
|
||||
{
|
||||
public:
|
||||
virtual ~XFMutex() = default;
|
||||
|
||||
virtual void lock() = 0; ///< Blocks until the mutex becomes available.
|
||||
virtual void unlock() = 0; ///< Releases the mutex so it can be taken by other threads.
|
||||
|
||||
/**
|
||||
* @brief Tries to get the mutex.
|
||||
*
|
||||
* If timeout is 0 method will leave immediately and then the return parameter indicates it the
|
||||
* mutex could be taken or not. Giving a negative value will block the thread until the mutex
|
||||
* becomes available.
|
||||
*/
|
||||
virtual bool tryLock(int32_t timeout = 0) = 0;
|
||||
|
||||
/**
|
||||
* @brief Creates and returns a new mutex instance.
|
||||
* @return Pointer to the created mutex object.
|
||||
*
|
||||
* The implementation of this method needs to be provided by
|
||||
* every XF port realizing a Mutex with this XFMutex interface.
|
||||
* Best way is to implement this method in the mutex.cpp
|
||||
* (or mutex-default.cpp) file of the XF port.
|
||||
*
|
||||
* Attention:
|
||||
* Do not forget to create an object of the class realizing
|
||||
* the interface and then return this object.
|
||||
*
|
||||
* You cannot instanciate an object of an abstract class!
|
||||
*/
|
||||
static XFMutex * create();
|
||||
|
||||
protected:
|
||||
XFMutex() = default;
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // XF_INTERFACE_MUTEX_H
|
53
src/xf/include/xf/interface/reactive.h
Normal file
53
src/xf/include/xf/interface/reactive.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef XF_INTERFACE_REACTIVE_H
|
||||
#define XF_INTERFACE_REACTIVE_H
|
||||
|
||||
#include <string>
|
||||
#include "xf/event.h"
|
||||
#include "xf/eventstatus.h"
|
||||
|
||||
class XFDispatcherDefault;
|
||||
class XFDispatcherActiveDefault;
|
||||
class XFDispatcherPort;
|
||||
class XFDispatcherActivePort;
|
||||
class XFDispatcher;
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Interface to receive and process events.
|
||||
*
|
||||
* Interface that needs to be implemented by every class having a
|
||||
* behavior. Interface methods are needed by the other parts of the XF.
|
||||
*
|
||||
* This interface is used by the dispatcher to process events.
|
||||
*/
|
||||
class XFReactive
|
||||
{
|
||||
// Only XFDispatchers should get access to the 'process' method
|
||||
friend class ::XFDispatcherDefault;
|
||||
friend class ::XFDispatcherActiveDefault;
|
||||
friend class ::XFDispatcherPort;
|
||||
friend class ::XFDispatcherActivePort;
|
||||
friend class ::XFDispatcher;
|
||||
|
||||
public:
|
||||
using TerminateBehavior = bool;
|
||||
|
||||
public:
|
||||
virtual ~XFReactive() = default;
|
||||
|
||||
virtual void startBehavior() = 0; ///< Starts the behavior.
|
||||
virtual void pushEvent(XFEvent * pEvent, bool fromISR = false) = 0; ///< Injects an event into the class.
|
||||
|
||||
virtual bool deleteOnTerminate() const = 0; ///< Tells XF to delete behavior when receiving terminate event.
|
||||
virtual void setDeleteOnTerminate(bool deleteBehaviour) = 0; ///< Sets/Clears the 'delete on terminate' property.
|
||||
|
||||
protected:
|
||||
virtual TerminateBehavior process(const XFEvent * pEvent) = 0; ///< Called by the dispatcher to process an event.
|
||||
|
||||
protected:
|
||||
XFReactive() = default;
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // XF_INTERFACE_REACTIVE_H
|
76
src/xf/include/xf/interface/resourcefactory.h
Normal file
76
src/xf/include/xf/interface/resourcefactory.h
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef XF_INTERFACE_RESOURCE_FACTORY_H
|
||||
#define XF_INTERFACE_RESOURCE_FACTORY_H
|
||||
|
||||
#include "xf/interface/dispatcher.h"
|
||||
#include "xf/interface/thread.h"
|
||||
#include "xf/interface/mutex.h"
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Responsible to create and return XF resources.
|
||||
*
|
||||
* The XF resource factory provides instances of following classes
|
||||
* - Dispatcher
|
||||
* - Thread
|
||||
* - Mutex
|
||||
*
|
||||
* The XFResourceFactory::getInstance() method needs to be implemented
|
||||
* in the class realizing this interface.
|
||||
*
|
||||
*/
|
||||
class XFResourceFactory
|
||||
{
|
||||
public:
|
||||
static XFResourceFactory * getInstance(); ///< Returns a pointer to the unique instance of the XF resource factory.
|
||||
|
||||
/**
|
||||
* @brief Returns the default dispatcher.
|
||||
*
|
||||
* In case a bahavior does not have a specific dispatcher the
|
||||
* default dispatcher ist used.
|
||||
*
|
||||
* @return A pointer to the default dispatcher.
|
||||
*/
|
||||
virtual interface::XFDispatcher * getDefaultDispatcher() = 0;
|
||||
|
||||
/**
|
||||
* @brief Creates a new dispatcher.
|
||||
*
|
||||
* Per default this method returns a new active dispatcher. In
|
||||
* case there is no OS present (IDF) the default dispatcher may
|
||||
* be returned.
|
||||
*
|
||||
* @return The new dispatcher
|
||||
*/
|
||||
virtual interface::XFDispatcher * createDispatcher() = 0;
|
||||
|
||||
/**
|
||||
* @brief Creates a new Thread.
|
||||
* @param pProvider The instance providing the entry method.
|
||||
* @param entryMethod The method to by called by the new thread.
|
||||
* @param threadName The name of the thread.
|
||||
* @param stackSize The stack size of the thread.
|
||||
* @return Pointer to new thread
|
||||
*
|
||||
* The method may return null in case there is no OS present.
|
||||
*/
|
||||
virtual interface::XFThread * createThread(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize = 0) = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns a new mutex.
|
||||
* @return Pointer to new mutex.
|
||||
*/
|
||||
virtual interface::XFMutex * createMutex() = 0;
|
||||
|
||||
virtual ~XFResourceFactory() = default;
|
||||
|
||||
protected:
|
||||
XFResourceFactory() = default;
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // XF_INTERFACE_RESOURCE_FACTORY_H
|
60
src/xf/include/xf/interface/thread.h
Normal file
60
src/xf/include/xf/interface/thread.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef XF_INTERFACE_THREAD_H
|
||||
#define XF_INTERFACE_THREAD_H
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
XF_THREAD_PRIO_UNKNOWN = 0,
|
||||
XF_THREAD_PRIO_LOW = 5,
|
||||
XF_THREAD_PRIO_NORMAL = 10,
|
||||
XF_THREAD_PRIO_HIGH = 15,
|
||||
XF_THREAD_PRIO_MAX = 20
|
||||
} XFThreadPriority;
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Interface to be implemented by the class providing the thread entry method.
|
||||
*/
|
||||
class XFThreadEntryPointProvider
|
||||
{
|
||||
public:
|
||||
virtual ~XFThreadEntryPointProvider() = default;
|
||||
protected:
|
||||
XFThreadEntryPointProvider() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface for a Thread.
|
||||
*
|
||||
* Thread interface representing the instance executing the behavior. In an OS less XF
|
||||
* (hence an IDF), usually this class is not needed. In an XF interfacing an OS,
|
||||
* multiple instances can be made, each interfacing the real OS thread.
|
||||
*
|
||||
* Thread instances can be created using the ResourceFactory instance.
|
||||
*
|
||||
* The XF assumes that the Thread is in suspend state after creation. Automatically
|
||||
* starting the thread after creation may lead to unwanted behavior!
|
||||
*/
|
||||
class XFThread
|
||||
{
|
||||
public:
|
||||
virtual ~XFThread() = default;
|
||||
|
||||
typedef void (XFThreadEntryPointProvider::*EntryMethodBody)(const void *); ///< Prototype of method to be executed by the thread.
|
||||
|
||||
virtual void start() = 0; ///< Starts the thread.
|
||||
virtual void stop() = 0; ///< Requests the thread to stop execution.
|
||||
|
||||
virtual void setPriority(XFThreadPriority priority) = 0; ///< Set the thread priority.
|
||||
virtual XFThreadPriority getPriority() const = 0; ///< Returns the thread priority.
|
||||
|
||||
virtual void delay(uint32_t milliseconds) = 0; ///< Causes the thread to sleep (for the given milliseconds).
|
||||
|
||||
protected:
|
||||
XFThread() = default;
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // XF_INTERFACE_THREAD_H
|
89
src/xf/include/xf/interface/timeoutmanager.h
Normal file
89
src/xf/include/xf/interface/timeoutmanager.h
Normal file
@ -0,0 +1,89 @@
|
||||
#ifndef XF_INTERFACE_TIMEOUTMANAGER_H
|
||||
#define XF_INTERFACE_TIMEOUTMANAGER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace interface {
|
||||
class XFReactive;
|
||||
}
|
||||
class XFTimeout;
|
||||
|
||||
namespace interface {
|
||||
|
||||
/**
|
||||
* @brief Interface for TimerManager classes (and some few 'tick' stuff already provided).
|
||||
*
|
||||
* The TimeoutManager is responsible to handle timeouts used
|
||||
* in state machines. It decrements them accordingly and inject
|
||||
* them back to the state machine when timeouted.
|
||||
*
|
||||
* <b>Requirements:</b>
|
||||
* - Implements the Singleton pattern
|
||||
* - Handle timeouts (hold, decrement, re-inject)
|
||||
*/
|
||||
class XFTimeoutManager
|
||||
{
|
||||
public:
|
||||
virtual ~XFTimeoutManager() = default;
|
||||
|
||||
static XFTimeoutManager * getInstance(); ///< Returns a pointer to the single instance of TimeoutManager.
|
||||
|
||||
/**
|
||||
* Sets the time interval in milliseconds in which the timeout manager
|
||||
* should handle the timeouts.
|
||||
*/
|
||||
virtual void initialize(int32_t tickInterval)
|
||||
{
|
||||
tickInterval_ = tickInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns tick interval in milliseconds.
|
||||
*/
|
||||
virtual int32_t getTickInterval() const
|
||||
{
|
||||
return tickInterval_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the timeout manager.
|
||||
*/
|
||||
virtual void start() = 0;
|
||||
|
||||
/**
|
||||
* Adds a timeout to the timeout manager.
|
||||
*
|
||||
* \param timeoutId The timeout id known by the reactive parameter. Is needed by the reactive part to uniquely identify the timeout.
|
||||
* \param interval The time in milliseconds to wait until the timeout expires.
|
||||
* \param pReactive The reactive instance where to inject the timeout when it timeouts.
|
||||
*/
|
||||
virtual void scheduleTimeout(int32_t timeoutId, int32_t interval, interface::XFReactive * pReactive) = 0;
|
||||
|
||||
/**
|
||||
* Removes all timeouts corresponding the given parameters.
|
||||
*/
|
||||
virtual void unscheduleTimeout(int32_t timeoutId, interface::XFReactive * pReactive) = 0;
|
||||
|
||||
/** \brief Called periodically with a delay defined by TimeoutManager::_tickInterval.
|
||||
*
|
||||
* On each call to this method, TimeoutManager::_tickInterval will be removed from the
|
||||
* timeouts.
|
||||
* When a timeout expires it is pushed back to the dispatcher. To which
|
||||
* dispatcher it must be given is known by the reactive instance to which the timeout
|
||||
* belongs.
|
||||
*/
|
||||
virtual void tick() = 0;
|
||||
|
||||
protected:
|
||||
XFTimeoutManager() :
|
||||
tickInterval_(0)
|
||||
{}
|
||||
|
||||
virtual void addTimeout(XFTimeout * pNewTimeout) = 0; ///< Adds the timeout to the list of timeouts.
|
||||
|
||||
protected:
|
||||
int32_t tickInterval_; ///< Interval in milliseconds the TimeoutManager is decrementing the timeouts.
|
||||
};
|
||||
|
||||
} // namespace interface
|
||||
#endif // XF_INTERFACE_TIMEOUTMANAGER_H
|
33
src/xf/include/xf/nulltransition.h
Normal file
33
src/xf/include/xf/nulltransition.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef XF_NULLTRANSITION_H
|
||||
#define XF_NULLTRANSITION_H
|
||||
|
||||
#include "xf.h"
|
||||
#include "xf/event.h"
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief State machine transition without trigger.
|
||||
*
|
||||
* Represents a transition in a state machine having no trigger.
|
||||
*
|
||||
* In case one wants to directly transition from one state to
|
||||
* an other (without a trigger) a null transition must be pushed.
|
||||
*/
|
||||
class XFNullTransition : public XFEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param pBehavior Behavior in which the null transition will be executed.
|
||||
*/
|
||||
XFNullTransition(interface::XFReactive * pBehavior = nullptr);
|
||||
|
||||
bool deleteAfterConsume() const override;
|
||||
};
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // XF_NULLTRANSITION_H
|
59
src/xf/include/xf/timeout.h
Normal file
59
src/xf/include/xf/timeout.h
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef XF_TIMEOUT_H
|
||||
#define XF_TIMEOUT_H
|
||||
|
||||
#include "xf/event.h"
|
||||
|
||||
namespace interface {
|
||||
class XFTimeoutManager;
|
||||
}
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Used by the TimeoutManager to create and handle a timeout.
|
||||
*
|
||||
* Timeouts are created automatically by the TimeoutManager when
|
||||
* scheduling a timeout. After expiration they are queued to the event queue
|
||||
* and afterwards dispatched to the corresonding behavior.
|
||||
*
|
||||
* A timeout can be identified by checking against #Timeout using
|
||||
* the `getEventType()` method.
|
||||
*
|
||||
* XFTimeout is inheriting from XFEvent, so every timeout is
|
||||
* also an event.
|
||||
*/
|
||||
class XFTimeout : public XFEvent
|
||||
{
|
||||
friend class interface::XFTimeoutManager;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor of the class.
|
||||
* \param id The id given by the behavioral class to uniquely identifying the timeout
|
||||
* \param interval The interval in milliseconds the timeout expires
|
||||
* \param pBehavior Pointer to behavioral class to which the timeout belongs
|
||||
*/
|
||||
XFTimeout(int id, int interval, interface::XFReactive * pBehavior);
|
||||
|
||||
/**
|
||||
* Operator checks if #_pBehavior and #_id are equal and returns
|
||||
* true if so. All other attributes get no attention.
|
||||
*/
|
||||
bool operator ==(const XFTimeout & timeout) const;
|
||||
|
||||
bool deleteAfterConsume() const override; ///< Tells the dispatcher if the event must be deleted or not.
|
||||
|
||||
inline void setRelTicks(int relTicks) { relTicks_ = relTicks; } ///< Sets remaining ticks.
|
||||
inline int getRelTicks() const { return relTicks_; } ///< Returns remaining ticks.
|
||||
inline void substractFromRelTicks(int ticksToSubstract) { relTicks_ -= ticksToSubstract; } ///< Substracts `ticksToSubstract` from remaining ticks.
|
||||
inline void addToRelTicks(int ticksToAdd) { relTicks_ += ticksToAdd; } ///< Adds `ticksToAdd` to remaining ticks.
|
||||
|
||||
protected:
|
||||
int interval_; ///< Timeout interval
|
||||
int relTicks_; ///< Used by the TimeoutManager to calculate remaining time. Can get negative!
|
||||
};
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // XF_TIMEOUT_H
|
6
src/xf/include/xf/xf-core.dox
Normal file
6
src/xf/include/xf/xf-core.dox
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
/** @defgroup xf_core XF Core Classes
|
||||
*
|
||||
* XF core classes.
|
||||
*
|
||||
*/
|
171
src/xf/include/xf/xf.h
Normal file
171
src/xf/include/xf/xf.h
Normal file
@ -0,0 +1,171 @@
|
||||
#ifndef XF_XF_H
|
||||
#define XF_XF_H
|
||||
|
||||
#include "config/xf-config.h"
|
||||
|
||||
//
|
||||
// What is seen only by the C++ compiler
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "xf/interface/dispatcher.h"
|
||||
|
||||
/** \mainpage PTR Execution Framework Documentation
|
||||
*
|
||||
* \section sec_xf_intro Introduction
|
||||
*
|
||||
* This library implements an e<b>X</b>ecution <b>F</b>ramework (XF) to drive finite
|
||||
* state machines. Using this framework, it is possible to drive multiple state machines
|
||||
* in a concurrent manner (pseudo-parallel) without having an operating system.
|
||||
*
|
||||
* The XF defines an interface which gives the ability to reimplement parts of the XF to
|
||||
* make changes to an other target/platform. It is also possible to let the XF run with an RTOS.
|
||||
* This gives the possibility to run state machines in a OS like concurrent manner with
|
||||
* threads provided by the underlying RTOS.
|
||||
*
|
||||
* \section sec_xf_comp XF Component Diagram
|
||||
* The XF is split into two parts. One part is the XF core containing classes which
|
||||
* never change across platforms. The other part is the XF port containing classes
|
||||
* adjusted for a specific platform:
|
||||
*
|
||||
* \image html comp-xf.png "Component Class Diagram"
|
||||
*
|
||||
* The XF core together with a port forms a complete XF which can be integrated into
|
||||
* a software project.
|
||||
*
|
||||
* \section sec_xf_cmd XF Class Diagram
|
||||
*
|
||||
* Following class diagram shows the basic relations between the most important classes
|
||||
* in the PTR XF. It shall give you a basic understanding about the relations between
|
||||
* these classes:
|
||||
*
|
||||
* \image html cmd-xf.png "XF Class Diagram"
|
||||
*
|
||||
* \section sec_xf_start Starting Point
|
||||
*
|
||||
* A good point to jump into the definitions of the classes is the `#XF` class. Other classes
|
||||
* of interest are `interface::XFTimeoutManager`, `interface::XFDispatcher` and `interface::XFReactive`.
|
||||
*
|
||||
* \section sec_xf_external_links Links to related Documentation
|
||||
* \if DOC_WITH_TESTBENCH
|
||||
* - <a href="../../../../../test-bench/doxygen/output/html/index.html">Test Bench Documentation</a>
|
||||
* \endif
|
||||
* - <a href="../../../../../src/mdw/trace/doxygen/output/html/index.html">Trace Documentation</a>
|
||||
*
|
||||
* \if DOC_WITH_RELEASE_HISTORY
|
||||
* \section sec_xf_releases XF Releases
|
||||
* \subsection xf_v_4_0_1 XF Version: 4.0.1 (2021-08)
|
||||
* - crc: Added parameter 'fromISR' for push() methods
|
||||
* - sth: Added XF_isRunning() function to port-functions.h
|
||||
* \subsection xf_v_4_0_0 XF Version: 4.0.0 (2021-05)
|
||||
* - crc: Migration from IDE-STM / CubeMX to CubeIDE
|
||||
* - crc: Changed CMSIS port from `CMSIS_RTOS_V1` to `CMSIS_RTOS_V2`
|
||||
* \subsection xf_v_3_3_2 XF Version: 3.3.2 (2020-09)
|
||||
* - sth: Added 'override' keywords to derived methods
|
||||
* - sth: Removed attribute '_mainDispatcher' from XFResourceFactoryDefault
|
||||
* \subsection xf_v_3_3_1 XF Version: 3.3.1 (2020-04)
|
||||
* - sth: Added XF::isRunning() method
|
||||
* \subsection xf_v_3_3_0 XF Version: 3.3.0 (2020-02)
|
||||
* - sth: Introduced per platform default port implementations (port/default-qt, port/default-idf, etc.)
|
||||
* - sth: Moved mutex and thread classes into the platform default port folders
|
||||
* - sth: Added 'interface::XFReactive::deleteOnTerminate()' method
|
||||
* \subsection xf_v_3_2_1 XF Version: 3.2.1 (2019-04)
|
||||
* - sth: Made several bugfixes.
|
||||
* \subsection xf_v_3_2 XF Version: 3.2 (2018-09)
|
||||
* - sth: Updated XF interfaces.
|
||||
* - sth: Added IDF_STM32CUBE, STM32CUBE_CMSIS_FREERTOS and ACTIVE_QT ports.
|
||||
* - sth: Removed old ports IDF_STM32F4 and CMSIS_RTOS_FREERTOS.
|
||||
* \subsection xf_v_3_1 XF Version: 3.1 (2017-11)
|
||||
* - sth: Fixed bug in removeTimeouts() method of XFTimeoutManager. Thanks to Gregory Dumoulin.
|
||||
* \subsection xf_v_3_0 XF Version: 3.0 (2017-10)
|
||||
* - sth: The new XF is providing interfaces to support other OS's.
|
||||
* - sth: Changed XF interfaces. Porting older applications to new XF need some adjustments.
|
||||
* - sth: Added 'port' folder to allow extensions to other platforms.
|
||||
* - sth: Added IDF_STM32F4, CMSIS_RTOS_FREERTOS and IDF_QT ports.
|
||||
* \subsection xf_v_2_1 XF Version: 2.1 (2015-03-02)
|
||||
* - sth: XFTimoutManager now returns timeouts with same value correctly.
|
||||
* \subsection xf_v_2_0 XF Version: 2.0 (2014-04-28)
|
||||
* - sth: Changed way how XFTimeoutManager handles timeouts which timeout at the same time.
|
||||
* Now new timeouts get behind the timeouts with the same (timeout) time.
|
||||
* \subsection xf_v_1_0 XF Version: 1.0 (2014-04-24)
|
||||
* - sth: Renamed class XFEvent to XFCustomEvent
|
||||
* - sth: Renamed IXFEvent to XFEvent (because it was never a real interface)
|
||||
* \subsection xf_v_0_5 XF Version: 0.5 (2013-12-09)
|
||||
* - sth: Now properly stopping and terminating MainThreadExec instance
|
||||
* - sth: Added new literal to XFEventStatus to handle composite states
|
||||
* \subsection xf_v_0_4 XF Version: 0.4 (2013-12-05)
|
||||
* - sth: Added scheduleTimeout and unscheduleTimeout to XFBehavior class (helper operations)
|
||||
* \subsection xf_v_0_3 XF Version: 0.3 (2013-09-19)
|
||||
* - sth: Added handling for static events (IXFEvent::deleteAfterConsume())
|
||||
* \subsection xf_v_0_2 XF Version: 0.2 (2011-08-14)
|
||||
* - sth: Fixed bug in XFTimeoutManager::addTimeout method
|
||||
* \subsection xf_v_0_1 XF Version: 0.1 (2010-11-26)
|
||||
* - sth: First release
|
||||
* \endif
|
||||
*/
|
||||
|
||||
/** @ingroup xf_core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Static class grouping the basic methods for the XF together.
|
||||
*/
|
||||
class XF
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes the e<b>X</b>ecution <b>F</b>ramework (XF). Call
|
||||
* this method prior to initialize the other objects of the system.
|
||||
*
|
||||
* @param timeInterval The interval in milliseconds with which the TimeoutManager should run.
|
||||
* @param argc Optional parameter to pass application argument number to XF.
|
||||
* @param argv Optional parameter to pass application arguments to XF.
|
||||
*/
|
||||
static void initialize(int timeInterval = 10, int argc = 0, char * argv[] = nullptr);
|
||||
|
||||
/**
|
||||
* Starts execution of the framework. This
|
||||
* results in processing the events in main loop.
|
||||
*
|
||||
* This method is blocking.
|
||||
*/
|
||||
static int exec();
|
||||
|
||||
/**
|
||||
* Executes once the dispatcher. To be called regularly in a while loop.
|
||||
*
|
||||
* This method is non-blocking.
|
||||
*/
|
||||
static int execOnce();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Returns true in case the XF is initialized and running.
|
||||
*/
|
||||
static bool isRunning();
|
||||
|
||||
protected:
|
||||
static bool isInitialized_; ///< Changes from false to true after calling method initialize(int). Used to handle multiple calls to init(int).
|
||||
static bool isRunning_; ///< Tells if the XF is initialized and running.
|
||||
};
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
//
|
||||
// What is seen by the C and C++ compiler
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
void XF_initialize(int timeInterval); ///< Initializes XF within C code
|
||||
void XF_exec(); ///< Calls XF execution in C code (blocking call)
|
||||
void XF_execOnce(); ///< Calls XF execution in C code (non-blocking call)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
/** @} */ // end of xf_core group
|
||||
#endif // XF_XF_H
|
62
src/xf/port/README.md
Normal file
62
src/xf/port/README.md
Normal file
@ -0,0 +1,62 @@
|
||||
# XF Ports
|
||||
|
||||
## Introduction
|
||||
An XF (execution framework) consist of a view classes which some need to be adjusted
|
||||
when used on another platform.
|
||||
|
||||
Following you will find a list of classes which may be adjusted/reimplemented when
|
||||
changing to another platform/environment:
|
||||
- `XF`
|
||||
- `ResourceFactory`
|
||||
- `TimeoutManager`
|
||||
- `Dispatcher`
|
||||
- `EventQueue`
|
||||
- `Thread`
|
||||
- `Mutex`
|
||||
|
||||
These classes are also named `port classes` because they can be ported to another
|
||||
platform. All port classes can be found in the _port_ folder whereas every port is
|
||||
located in a separate folder.
|
||||
|
||||
Every port may pick some default implementation classes from the _default_ folders
|
||||
also located in the _port_ folder.
|
||||
|
||||
In case you are going to implement an OS-less XF (hence an IDF) usually, you do not
|
||||
need to implement the classes `Thread` and `Mutex`.
|
||||
|
||||
## Default Port Classes
|
||||
There are already some default port class implementations present. You can find
|
||||
them in the `default` folder and may suit your needs for a first version
|
||||
of your XF. These default port classes are platform independent and can be
|
||||
used by any port implementation.
|
||||
|
||||
## Default Platform Classes
|
||||
Some classes depent on external resources like for example an OS. These
|
||||
classes are located in the _default-<platform>_ specific folders. Currently,
|
||||
the following default platfroms are available:
|
||||
|
||||
| Platform | Folder | Description |
|
||||
|--|--|--|
|
||||
| CMSIS-OS | [default-cmsis-os](./default-cmsis-os) | CMSIS-OS abstraction layer |
|
||||
| IDF | [default-idf](./default-idf) | Interrupt driven framework |
|
||||
| QT | [default-qt](./default-qt) | Qt library |
|
||||
|
||||
## Port Folder Structure
|
||||
In case you want to add support for another platform to the XF, you need to add a
|
||||
subfolder to the _port_ folder and put the port class files in there. Best is to
|
||||
take an already present port which is most similar to what you need, rename it and
|
||||
start adaption of these files.
|
||||
|
||||
You may also mix-up you port with classes from the _default_, _default-<platform>_
|
||||
folder and your custom folder (or even reference classes from other ports).
|
||||
|
||||
## Available Ports
|
||||
|
||||
Here is a list of currently available ports:
|
||||
|
||||
| Port Name | OS | Platform | Folder Name | Description |
|
||||
|--|--|--|--|--|
|
||||
| PORT_IDF_QT | Qt (IDF) | Qt library based implementation | idf-qt | XF support for OS X, Linux and Windows |
|
||||
| PORT_IDF_STM32CUBE | Bare-Metal (IDF) | STM32CubeMX based port | idf-stm32cube | XF for ARM Cortex based microcontrollers from STMicroelectronics |
|
||||
| PORT_STM32CUBE_CMSIS_FREERTOS | CMSIS OS (FreeRTOS) | Any platform supporting CMSIS OS | stm32cube-cmsis-freertos | FreeRTOS based port |
|
||||
| PORT_ACTIVE_QT | Qt multi-thread | Qt library based implementation | active-qt | XF support for OS X, Linux and Windows (multi-thread) |
|
38
src/xf/port/active-qt/README.md
Normal file
38
src/xf/port/active-qt/README.md
Normal file
@ -0,0 +1,38 @@
|
||||
# XF Port - Active Qt
|
||||
|
||||
This port folder contains specific classes for the _Active Qt_
|
||||
XF port.
|
||||
|
||||
# Classes used by the _Active Qt_ Port
|
||||
|
||||
| Class name | File location | Define to set |
|
||||
|--|--|--|
|
||||
| XFTimeoutManagerDefault | xf/port/default/timeoutmanager-default.cpp | USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION |
|
||||
| XFDispatcherActiveDefault | xf/port/default/dispatcher-active.cpp | USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION |
|
||||
| XF | xf/port/idf-qt/xf.cpp | USE_XF_PORT_IDF_QT_XF_IMPLEMENTATION |
|
||||
| XFMutexPort | xf/port/default-qt/mutex-default.cpp | USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION |
|
||||
| XFThreadPort | xf/port/default-qt/thread-default.cpp | USE_XF_THREAD_DEFAULT_QT_IMPLEMENTATION |
|
||||
| XFEventQueuePort | xf/port/idf-qt/eventqueue.cpp | USE_XF_PORT_IDF_QT_EVENT_QUEUE_IMPLEMENTATION |
|
||||
| Port Functions | xf/port/idf-qt/port-functions.cpp | USE_XF_PORT_IDF_QT_PORT_FUNCTIONS_IMPLEMENTATION |
|
||||
| XFResourceFactoryPort | xf/port/active-qt/resourcefactory.cpp | USE_XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_IMPLEMENTATION |
|
||||
|
||||
# Example _config/xf-config.h_ File
|
||||
```c++
|
||||
// Take all the port classes from the IDF_QT port expect...
|
||||
#define USE_XF_PORT_IDF_QT_XF_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_IDF_QT_EVENT_QUEUE_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_IDF_QT_PORT_FUNCTIONS_IMPLEMENTATION 1
|
||||
|
||||
// ... the resource factory. Must provide active dispatchers!
|
||||
#define USE_XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_IMPLEMENTATION 1
|
||||
|
||||
// ... mutexes and threads from the 'default-qt' port package
|
||||
#define USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_THREAD_DEFAULT_QT_IMPLEMENTATION 1
|
||||
|
||||
// ... and the remaining classes from the default port package.
|
||||
#define USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION 1
|
||||
|
||||
#include "idf-qt/eventqueue.h"
|
||||
```
|
BIN
src/xf/port/active-qt/README.pdf
Normal file
BIN
src/xf/port/active-qt/README.pdf
Normal file
Binary file not shown.
51
src/xf/port/active-qt/resourcefactory.cpp
Normal file
51
src/xf/port/active-qt/resourcefactory.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_IMPLEMENTATION != 0)
|
||||
|
||||
#include <QtGlobal>
|
||||
#include "xf/interface/mutex.h"
|
||||
#include "thread-default.h"
|
||||
#include "default/dispatcher-active.h"
|
||||
#include "resourcefactory.h"
|
||||
|
||||
using interface::XFMutex;
|
||||
|
||||
//static
|
||||
interface::XFResourceFactory * interface::XFResourceFactory::getInstance()
|
||||
{
|
||||
return XFResourceFactoryPort::getInstance();
|
||||
}
|
||||
|
||||
// static
|
||||
interface::XFResourceFactory * XFResourceFactoryPort::getInstance()
|
||||
{
|
||||
static XFResourceFactoryPort theResourceFactory;
|
||||
return &theResourceFactory;
|
||||
}
|
||||
|
||||
interface::XFDispatcher * XFResourceFactoryPort::getDefaultDispatcher()
|
||||
{
|
||||
static XFDispatcherActiveDefault mainDispatcher;
|
||||
return &mainDispatcher;
|
||||
}
|
||||
|
||||
interface::XFDispatcher * XFResourceFactoryPort::createDispatcher()
|
||||
{
|
||||
// Create the new active dispatcher
|
||||
return new XFDispatcherActiveDefault;
|
||||
}
|
||||
|
||||
interface::XFThread * XFResourceFactoryPort::createThread(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize /* = 0 */)
|
||||
{
|
||||
return new XFThreadDefault(pProvider, entryMethod, threadName, stackSize);
|
||||
}
|
||||
|
||||
interface::XFMutex * XFResourceFactoryPort::createMutex()
|
||||
{
|
||||
return XFMutex::create();
|
||||
}
|
||||
|
||||
#endif // USE_XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_IMPLEMENTATION
|
31
src/xf/port/active-qt/resourcefactory.h
Normal file
31
src/xf/port/active-qt/resourcefactory.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_H
|
||||
#define XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_H
|
||||
|
||||
#include "config/xf-config.h"
|
||||
|
||||
#if (USE_XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_IMPLEMENTATION != 0)
|
||||
|
||||
#include "xf/interface/resourcefactory.h"
|
||||
#include "xf/interface/dispatcher.h"
|
||||
|
||||
class XFResourceFactoryPort : public interface::XFResourceFactory
|
||||
{
|
||||
public:
|
||||
~XFResourceFactoryPort() override {}
|
||||
|
||||
static interface::XFResourceFactory * getInstance();
|
||||
|
||||
interface::XFDispatcher * getDefaultDispatcher() override;
|
||||
interface::XFDispatcher * createDispatcher() override;
|
||||
interface::XFThread * createThread(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize = 0) override;
|
||||
interface::XFMutex * createMutex() override;
|
||||
|
||||
protected:
|
||||
XFResourceFactoryPort() {}
|
||||
};
|
||||
|
||||
#endif // USE_XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_IMPLEMENTATION
|
||||
#endif // XF_PORT_ACTIVE_QT_RESOURCE_FACTORY_H
|
8
src/xf/port/active-qt/xf-port-active.pri
Normal file
8
src/xf/port/active-qt/xf-port-active.pri
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
INCLUDEPATH += $$PWD/..
|
||||
|
||||
SOURCES += \
|
||||
"$$PWD/resourcefactory.cpp"
|
||||
|
||||
HEADERS += \
|
||||
"$$PWD/resourcefactory.h"
|
24
src/xf/port/active-qt/xf-port-default.pri
Normal file
24
src/xf/port/active-qt/xf-port-default.pri
Normal file
@ -0,0 +1,24 @@
|
||||
#
|
||||
# This PRI file takes only the classes needed from the
|
||||
# 'default' port.
|
||||
#
|
||||
|
||||
INCLUDEPATH += $$PWD/..
|
||||
|
||||
# Path to default implementation of the XF port
|
||||
DEFAULT_IMPL_PATH = $$PWD/../default
|
||||
|
||||
DEFAULT_IMPL_SOURCES += \
|
||||
"$${DEFAULT_IMPL_PATH}/xf-default.cpp" \
|
||||
"$${DEFAULT_IMPL_PATH}/timeoutmanager-default.cpp" \
|
||||
"$${DEFAULT_IMPL_PATH}/dispatcher-active.cpp"
|
||||
|
||||
DEFAULT_IMPL_HEADERS += \
|
||||
"$${DEFAULT_IMPL_PATH}/timeoutmanager-default.h" \
|
||||
"$${DEFAULT_IMPL_PATH}/dispatcher-active.h"
|
||||
|
||||
SOURCES += \
|
||||
$${DEFAULT_IMPL_SOURCES}$$
|
||||
|
||||
HEADERS += \
|
||||
$${DEFAULT_IMPL_HEADERS}$$
|
39
src/xf/port/default-cmsis-os/README.md
Normal file
39
src/xf/port/default-cmsis-os/README.md
Normal file
@ -0,0 +1,39 @@
|
||||
# CMSIS-OS Platform Default Port
|
||||
|
||||
This folder provides a default implementation for CMSIS-OS platform
|
||||
related XF classes. You can use these classes to construct a CMSIS-OS
|
||||
based XF.
|
||||
|
||||
If these classes do not suit your needs, they can be reimplemented for
|
||||
your platform. Create an additional folder in the 'port' folder and
|
||||
implement there the classes you need for your platform.
|
||||
|
||||
# Available Default CMSIS-OS Port Classes
|
||||
|
||||
| Class name | File location | Define to set |
|
||||
| -------------- | ------------------------------------- | --------------------------------------- |
|
||||
| XFMutexDefault | xf/port/default-cmsis-os/mutex-default.cpp | USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION |
|
||||
| XFThreadDefault | xf/port/default-cmsis-os/thread-default.cpp | USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION |
|
||||
|
||||
If you need more information about the classes mentioned above, please
|
||||
have a look into their header files and the doxygen comments in code.
|
||||
|
||||
# Example _config/xf-config.h_ File
|
||||
|
||||
Following you will find an example giving you a basic idea which define
|
||||
to set in the application specific _config/xf-config.h_ file.
|
||||
|
||||
The _Stm32Cube CMSIS FreeRTOS_ port uses these classes:
|
||||
|
||||
```c++
|
||||
// Defines to set to use the Stm32Cube CMSIS FreeRTOS port
|
||||
#define USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION 1
|
||||
#define USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_RESOURCE_FACTORY_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_TIMEOUTMANAGER_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_EVENT_QUEUE_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_THREAD_IMPLEMENTATION 1
|
||||
|
||||
#include "stm32cube-cmsis-freertos/eventqueue.h"
|
||||
```
|
BIN
src/xf/port/default-cmsis-os/README.pdf
Normal file
BIN
src/xf/port/default-cmsis-os/README.pdf
Normal file
Binary file not shown.
51
src/xf/port/default-cmsis-os/mutex-default.cpp
Normal file
51
src/xf/port/default-cmsis-os/mutex-default.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION != 0)
|
||||
|
||||
#include "mutex-default.h"
|
||||
|
||||
/**
|
||||
* @brief Implementation of interface::XFMutex::create method.
|
||||
*/
|
||||
interface::XFMutex * interface::XFMutex::create()
|
||||
{
|
||||
return new XFMutexDefault;
|
||||
}
|
||||
|
||||
XFMutexDefault::XFMutexDefault() :
|
||||
_mutexId(0)
|
||||
{
|
||||
memset(&_mutexDefinition,0,sizeof(_mutexDefinition));
|
||||
_mutexId = osMutexNew(&_mutexDefinition);
|
||||
assert(_mutexId);
|
||||
}
|
||||
|
||||
XFMutexDefault::~XFMutexDefault()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void XFMutexDefault::lock()
|
||||
{
|
||||
assert(_mutexId);
|
||||
osStatus status = osMutexWait(_mutexId, osWaitForever);
|
||||
assert(status == osOK);
|
||||
}
|
||||
|
||||
|
||||
void XFMutexDefault::unlock()
|
||||
{
|
||||
osStatus status = osMutexRelease(_mutexId);
|
||||
assert(status == osOK);
|
||||
}
|
||||
|
||||
|
||||
bool XFMutexDefault::tryLock(int32_t timeout /* = 0 */)
|
||||
{
|
||||
osStatus status = osMutexWait(_mutexId, timeout);
|
||||
return (status == osOK) ? true : false;
|
||||
}
|
||||
|
||||
#endif // USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION
|
38
src/xf/port/default-cmsis-os/mutex-default.h
Normal file
38
src/xf/port/default-cmsis-os/mutex-default.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef XF_MUTEX_DEFAULT_CMSIS_OS_H
|
||||
#define XF_MUTEX_DEFAULT_CMSIS_OS_H
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION != 0)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cmsis_os.h>
|
||||
#include "xf/interface/mutex.h"
|
||||
|
||||
/** @ingroup port_default_cmsis_os
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Default CMSIS-OS imlementation XFMutex interface.
|
||||
*
|
||||
*/
|
||||
class XFMutexDefault : public interface::XFMutex
|
||||
{
|
||||
public:
|
||||
XFMutexDefault();
|
||||
virtual ~XFMutexDefault();
|
||||
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
|
||||
virtual bool tryLock(int32_t timeout = 0);
|
||||
|
||||
protected:
|
||||
osMutexDef_t _mutexDefinition;
|
||||
osMutexId _mutexId;
|
||||
};
|
||||
|
||||
/** @} */ // end of port_default_cmsis_os group
|
||||
#endif // USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION
|
||||
#endif // XF_MUTEX_DEFAULT_CMSIS_OS_H
|
6
src/xf/port/default-cmsis-os/port-default-cmsis-os.dox
Normal file
6
src/xf/port/default-cmsis-os/port-default-cmsis-os.dox
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
/** @defgroup port_default_cmsis_os CMSIS-OS Platform Default Port Classes
|
||||
*
|
||||
* CMSIS-OS platform default port classes.
|
||||
*
|
||||
*/
|
134
src/xf/port/default-cmsis-os/thread-default.cpp
Normal file
134
src/xf/port/default-cmsis-os/thread-default.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION != 0)
|
||||
|
||||
#include <cassert>
|
||||
#include <string.h>
|
||||
#include "thread-default.h"
|
||||
|
||||
#if !defined(XFTHREAD_DEFAULT_STACK_SIZE)
|
||||
# define XFTHREAD_DEFAULT_STACK_SIZE 512
|
||||
#endif
|
||||
|
||||
//extern "C" const int uxTopUsedPriority;
|
||||
//const int __attribute__((used)) uxTopUsedPriority = configMAX_PRIORITIES - 1;
|
||||
|
||||
/**
|
||||
* Always keep threads after creation in suspended state.
|
||||
* Threads must be explicitly started with start()!
|
||||
*/
|
||||
|
||||
|
||||
/// Attributes structure for thread.
|
||||
/*
|
||||
typedef struct {
|
||||
const char *name; ///< name of the thread
|
||||
uint32_t attr_bits; ///< attribute bits
|
||||
void *cb_mem; ///< memory for control block
|
||||
uint32_t cb_size; ///< size of provided memory for control block
|
||||
void *stack_mem; ///< memory for stack
|
||||
uint32_t stack_size; ///< size of stack
|
||||
osPriority_t priority; ///< initial thread priority (default: osPriorityNormal)
|
||||
TZ_ModuleId_t tz_module; ///< TrustZone module identifier
|
||||
uint32_t reserved; ///< reserved (must be 0)
|
||||
} osThreadAttr_t;*/
|
||||
|
||||
XFThreadDefault::XFThreadDefault(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize /* = 0 */)
|
||||
{
|
||||
uint32_t threadStackSize = stackSize;
|
||||
|
||||
_pEntryMethodProvider = pProvider;
|
||||
_entryMethod = entryMethod;
|
||||
|
||||
strcpy(_threadName, threadName);
|
||||
|
||||
if (threadStackSize == 0)
|
||||
{
|
||||
threadStackSize = XFTHREAD_DEFAULT_STACK_SIZE;
|
||||
}
|
||||
|
||||
::memset(&_threadAttr, 0, sizeof(_threadAttr));
|
||||
|
||||
_threadAttr.name = _threadName;
|
||||
_threadAttr.priority = osPriorityNormal;
|
||||
_threadAttr.stack_size = threadStackSize;
|
||||
|
||||
_threadFunc = &threadEntryPoint;
|
||||
|
||||
_threadId = osThreadNew(_threadFunc, this, &_threadAttr);
|
||||
assert(_threadId); // Check if thread creation was successful
|
||||
|
||||
// Always keep threads after creation in suspended state.
|
||||
// Must be explicitly started with start();
|
||||
osThreadSuspend(_threadId);
|
||||
}
|
||||
|
||||
//static
|
||||
void XFThreadDefault::threadEntryPoint(void * param)
|
||||
{
|
||||
XFThreadDefault * pThis = (XFThreadDefault *)param;
|
||||
|
||||
(pThis->_pEntryMethodProvider->*pThis->_entryMethod)(param);
|
||||
}
|
||||
|
||||
void XFThreadDefault::start()
|
||||
{
|
||||
assert(_threadId != 0); // Check if thread was created
|
||||
osThreadResume(_threadId);
|
||||
}
|
||||
|
||||
void XFThreadDefault::stop()
|
||||
{
|
||||
osThreadTerminate(_threadId);
|
||||
}
|
||||
|
||||
void XFThreadDefault::setPriority(XFThreadPriority priority)
|
||||
{
|
||||
osPriority prio = osPriorityNormal;
|
||||
switch (priority)
|
||||
{
|
||||
case XF_THREAD_PRIO_LOW:
|
||||
prio = osPriorityLow;
|
||||
break;
|
||||
case XF_THREAD_PRIO_HIGH:
|
||||
prio = osPriorityHigh;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
osThreadSetPriority(_threadId, prio);
|
||||
}
|
||||
|
||||
XFThreadPriority XFThreadDefault::getPriority() const
|
||||
{
|
||||
const osPriority prio = osThreadGetPriority(_threadId);
|
||||
XFThreadPriority priority = XF_THREAD_PRIO_UNKNOWN;
|
||||
|
||||
switch (prio)
|
||||
{
|
||||
case osPriorityLow:
|
||||
priority = XF_THREAD_PRIO_LOW;
|
||||
break;
|
||||
case osPriorityNormal:
|
||||
priority = XF_THREAD_PRIO_NORMAL;
|
||||
break;
|
||||
case osPriorityHigh:
|
||||
priority = XF_THREAD_PRIO_HIGH;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
void XFThreadDefault::delay(uint32_t milliseconds)
|
||||
{
|
||||
osDelay(milliseconds);
|
||||
}
|
||||
|
||||
#endif // USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION
|
45
src/xf/port/default-cmsis-os/thread-default.h
Normal file
45
src/xf/port/default-cmsis-os/thread-default.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef XF_THREAD_DEFAULT_CMSIS_OS_H
|
||||
#define XF_THREAD_DEFAULT_CMSIS_OS_H
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION != 0)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cmsis_os.h>
|
||||
#include "xf/interface/thread.h"
|
||||
|
||||
class XFThreadDefault : public interface::XFThread
|
||||
{
|
||||
friend class XFResourceFactoryPort;
|
||||
|
||||
public:
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
|
||||
virtual void setPriority(XFThreadPriority priority);
|
||||
virtual XFThreadPriority getPriority() const;
|
||||
|
||||
virtual void delay(uint32_t milliseconds);
|
||||
|
||||
protected:
|
||||
XFThreadDefault(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize = 0);
|
||||
|
||||
static void threadEntryPoint(void * param);
|
||||
|
||||
protected:
|
||||
interface::XFThreadEntryPointProvider * _pEntryMethodProvider;
|
||||
interface::XFThread::EntryMethodBody _entryMethod;
|
||||
|
||||
osThreadAttr_t _threadAttr;
|
||||
osThreadFunc_t _threadFunc;
|
||||
char _threadName[32];
|
||||
|
||||
osThreadId _threadId;
|
||||
};
|
||||
|
||||
#endif // USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION
|
||||
#endif // XF_THREAD_DEFAULT_CMSIS_OS_H
|
42
src/xf/port/default-idf/README.md
Normal file
42
src/xf/port/default-idf/README.md
Normal file
@ -0,0 +1,42 @@
|
||||
# IDF (Interrupt Driven Framework) Platform Default Port
|
||||
|
||||
This folder provides a default implementation for IDF related XF classes.
|
||||
You can use these classes to construct an IDF based XF.
|
||||
|
||||
If these classes do not suit your needs, they can be reimplemented for
|
||||
your platform. Create an additional folder in the 'port' folder and
|
||||
implement there the classes you need for your platform.
|
||||
|
||||
# Available Default IDF Port Classes
|
||||
|
||||
| Class name | File location | Define to set |
|
||||
| -------------- | ------------------------------------- | --------------------------------------- |
|
||||
| XFEventQueueDefault | xf/port/default-idf/eventqueue-default.cpp | USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION |
|
||||
| XFMutexDefault | xf/port/default-idf/mutex-default.cpp | USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION |
|
||||
|
||||
If you need more information about the classes mentioned above, please
|
||||
have a look into their header files and the doxygen comments in code.
|
||||
|
||||
# Example _config/xf-config.h_ File
|
||||
|
||||
Following you will find an example giving you a basic idea which define
|
||||
to set in the application specific _config/xf-config.h_ file.
|
||||
|
||||
The _IDF Stm32Cube_ port uses quite all default implementations:
|
||||
|
||||
```c++
|
||||
// Defines to set to use the IDF Stm32Cube port
|
||||
#define USE_XF_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_DISPATCHER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_RESOURCE_FACTORY_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION 1
|
||||
#define USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION 1
|
||||
|
||||
#define USE_XF_PORT_IDF_STM32CUBE_PORT_FUNCTIONS_IMPLEMENTATION 1
|
||||
|
||||
#include "default-idf/eventqueue-default.h"
|
||||
#ifdef __cplusplus
|
||||
using XFEventQueue = XFEventQueueDefault;
|
||||
#endif // __cplusplus
|
||||
```
|
BIN
src/xf/port/default-idf/README.pdf
Normal file
BIN
src/xf/port/default-idf/README.pdf
Normal file
Binary file not shown.
61
src/xf/port/default-idf/eventqueue-default.cpp
Normal file
61
src/xf/port/default-idf/eventqueue-default.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION != 0)
|
||||
|
||||
#include <cassert>
|
||||
#include "eventqueue-default.h"
|
||||
|
||||
XFEventQueueDefault::XFEventQueueDefault()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
XFEventQueueDefault::~XFEventQueueDefault()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool XFEventQueueDefault::empty() const
|
||||
{
|
||||
return _queue.empty();
|
||||
}
|
||||
|
||||
bool XFEventQueueDefault::push(const XFEvent * pEvent, bool fromISR)
|
||||
{
|
||||
_mutex.lock();
|
||||
{
|
||||
_queue.push(pEvent);
|
||||
}
|
||||
_mutex.unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const XFEvent * XFEventQueueDefault::front()
|
||||
{
|
||||
const XFEvent * event;
|
||||
_mutex.lock();
|
||||
{
|
||||
event = _queue.front();
|
||||
}
|
||||
_mutex.unlock();
|
||||
return event;
|
||||
}
|
||||
|
||||
void XFEventQueueDefault::pop()
|
||||
{
|
||||
_mutex.lock();
|
||||
{
|
||||
_queue.pop();
|
||||
}
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
bool XFEventQueueDefault::pend()
|
||||
{
|
||||
// Method cannot be used in an IDF! Waiting within
|
||||
// this method would block the whole XF
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION
|
51
src/xf/port/default-idf/eventqueue-default.h
Normal file
51
src/xf/port/default-idf/eventqueue-default.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef XF_EVENT_QUEUE_DEFAULT_H
|
||||
#define XF_EVENT_QUEUE_DEFAULT_H
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "config/xf-config.h"
|
||||
|
||||
#if (USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION != 0)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <queue>
|
||||
#include "xf/interface/eventqueue.h"
|
||||
#include "default-idf/mutex-default.h"
|
||||
|
||||
/** @ingroup port_default
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Default implementation of the event queue using a `std::queue` as container.
|
||||
*
|
||||
* This class does not provide a blocking pend() method. This means that this class
|
||||
* can be used in an IDF, but is not the right choice for a RTOS based XF.
|
||||
*/
|
||||
class XFEventQueueDefault : public interface::XFEventQueue
|
||||
{
|
||||
using Mutex = XFMutexDefault;
|
||||
public:
|
||||
XFEventQueueDefault();
|
||||
virtual ~XFEventQueueDefault();
|
||||
|
||||
// XFEventQueue interface implementation
|
||||
public:
|
||||
virtual bool empty() const; ///< Returns true if no event is in the queue.
|
||||
virtual bool push(const XFEvent * pEvent,
|
||||
bool fromISR = false); ///< Pushes the given event onto the queue.
|
||||
virtual const XFEvent * front(); ///< Returns pointer to next event to pop.
|
||||
virtual void pop(); ///< Pops the next event from the queue.
|
||||
///< Wait for the next event to arrive. Returns true if an event is in the queue.
|
||||
virtual bool pend();
|
||||
|
||||
protected:
|
||||
typedef std::queue<const XFEvent *> EventQueue; ///< Type of the event queue.
|
||||
|
||||
Mutex _mutex; ///< Mutex protecting access to _queue.
|
||||
EventQueue _queue; ///< Internal queue holding the events.
|
||||
};
|
||||
|
||||
/** @} */ // end of port_default group
|
||||
#endif // USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION
|
||||
#endif // __cplusplus
|
||||
#endif // XF_EVENT_QUEUE_DEFAULT_H
|
40
src/xf/port/default-idf/mutex-default.cpp
Normal file
40
src/xf/port/default-idf/mutex-default.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION != 0)
|
||||
|
||||
#include "critical/critical.h" // Provided by the platform used
|
||||
#include "mutex-default.h"
|
||||
|
||||
/**
|
||||
* @brief Implementation of interface::XFMutex::create method.
|
||||
*/
|
||||
interface::XFMutex * interface::XFMutex::create()
|
||||
{
|
||||
return new XFMutexDefault;
|
||||
}
|
||||
|
||||
XFMutexDefault::XFMutexDefault()
|
||||
{
|
||||
}
|
||||
|
||||
XFMutexDefault::~XFMutexDefault()
|
||||
{
|
||||
}
|
||||
|
||||
void XFMutexDefault::lock()
|
||||
{
|
||||
critical_enter();
|
||||
}
|
||||
|
||||
|
||||
void XFMutexDefault::unlock()
|
||||
{
|
||||
critical_exit();
|
||||
}
|
||||
|
||||
bool XFMutexDefault::tryLock(int32_t timeout /* = 0 */)
|
||||
{
|
||||
return true; // Always allow
|
||||
}
|
||||
|
||||
#endif // USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION
|
37
src/xf/port/default-idf/mutex-default.h
Normal file
37
src/xf/port/default-idf/mutex-default.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef XF_MUTEX_DEFAULT_IDF_H
|
||||
#define XF_MUTEX_DEFAULT_IDF_H
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION != 0)
|
||||
|
||||
#include <stdint.h>
|
||||
#include "xf/interface/mutex.h"
|
||||
|
||||
/** @ingroup port_default_idf
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Default IDF imlementation XFMutex interface.
|
||||
*
|
||||
* This class uses `enterCritical()` and `exitCritical()`
|
||||
* functions which must be provided by the platform.
|
||||
* Therefore, this mutex implementation can be used
|
||||
* in Embedded Systems without OS.
|
||||
*/
|
||||
class XFMutexDefault : public interface::XFMutex
|
||||
{
|
||||
public:
|
||||
XFMutexDefault();
|
||||
virtual ~XFMutexDefault();
|
||||
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
|
||||
virtual bool tryLock(int32_t timeout = 0);
|
||||
};
|
||||
|
||||
/** @} */ // end of port_default_idf group
|
||||
#endif // USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION
|
||||
#endif // XF_MUTEX_DEFAULT_IDF_H
|
6
src/xf/port/default-idf/port-default-idf.dox
Normal file
6
src/xf/port/default-idf/port-default-idf.dox
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
/** @defgroup port_default_idf IDF Platform Default Port Classes
|
||||
*
|
||||
* IDF platform default port classes.
|
||||
*
|
||||
*/
|
46
src/xf/port/default-qt/README.md
Normal file
46
src/xf/port/default-qt/README.md
Normal file
@ -0,0 +1,46 @@
|
||||
# Qt Platform Default Port
|
||||
|
||||
This folder provides a default implementation for Qt platform
|
||||
related XF classes. You can use these classes to construct a Qt
|
||||
based XF.
|
||||
|
||||
If these classes do not suit your needs, they can be reimplemented for
|
||||
your platform. Create an additional folder in the 'port' folder and
|
||||
implement there the classes you need for your platform.
|
||||
|
||||
# Available Default Qt Port Classes
|
||||
|
||||
| Class name | File location | Define to set |
|
||||
| -- | -- | -- |
|
||||
| XFEventQueueDefault | xf/port/default-qt/eventqueue-default.cpp | USE_XF_EVENT_QUEUE_DEFAULT_QT_IMPLEMENTATION |
|
||||
| XFMutexDefault | xf/port/default-qt/mutex-default.cpp | USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION |
|
||||
| XFThreadDefault | xf/port/default-qt/thread-default.cpp | USE_XF_THREAD_DEFAULT_QT_IMPLEMENTATION |
|
||||
|
||||
If you need more information about the classes mentioned above, please
|
||||
have a look into their header files and the doxygen comments in code.
|
||||
|
||||
# Example _config/xf-config.h_ File
|
||||
|
||||
Following you will find an example giving you a basic idea which define
|
||||
to set in the application specific _config/xf-config.h_ file.
|
||||
|
||||
The _IDF Qt_ port uses these classes:
|
||||
|
||||
```c++
|
||||
// Defines to set to use the IDF Qt port
|
||||
#define USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_EVENT_QUEUE_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_THREAD_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_CLASS_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_FUNCTIONS_DEFAULT_QT_IMPLEMENTATION 1
|
||||
|
||||
#define USE_XF_PORT_IDF_QT_RESOURCE_FACTORY_IMPLEMENTATION 1
|
||||
|
||||
#include "default-qt/eventqueue-default.h"
|
||||
#ifdef __cplusplus
|
||||
// Force to take the XFEventQueueDefault implementation for the event queue
|
||||
using XFEventQueue = XFEventQueueDefault;
|
||||
#endif // __cplusplus
|
||||
```
|
BIN
src/xf/port/default-qt/README.pdf
Normal file
BIN
src/xf/port/default-qt/README.pdf
Normal file
Binary file not shown.
55
src/xf/port/default-qt/eventqueue-default.cpp
Normal file
55
src/xf/port/default-qt/eventqueue-default.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_EVENT_QUEUE_DEFAULT_QT_IMPLEMENTATION != 0)
|
||||
|
||||
#include <cassert>
|
||||
#include <QtGlobal>
|
||||
#include <QMutexLocker>
|
||||
#include "eventqueue-default.h"
|
||||
|
||||
XFEventQueueDefault::XFEventQueueDefault() :
|
||||
mutex_(QMutex::NonRecursive)
|
||||
{
|
||||
}
|
||||
|
||||
XFEventQueueDefault::~XFEventQueueDefault()
|
||||
{
|
||||
newEvents_.wakeAll();
|
||||
}
|
||||
|
||||
bool XFEventQueueDefault::empty() const
|
||||
{
|
||||
return queue_.isEmpty();
|
||||
}
|
||||
|
||||
bool XFEventQueueDefault::push(const XFEvent * pEvent)
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
queue_.enqueue(pEvent);
|
||||
// Tell waiting thread(s) there is again an event present
|
||||
newEvents_.wakeAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
const XFEvent * XFEventQueueDefault::front()
|
||||
{
|
||||
return queue_.front();
|
||||
}
|
||||
|
||||
void XFEventQueueDefault::pop()
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
queue_.dequeue();
|
||||
}
|
||||
|
||||
bool XFEventQueueDefault::pend()
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
// Wait for new events. Mutex needs to be in lock-state
|
||||
// prior to call wait()!
|
||||
newEvents_.wait(&mutex_);
|
||||
|
||||
return !queue_.isEmpty();
|
||||
}
|
||||
|
||||
#endif // USE_XF_EVENT_QUEUE_DEFAULT_QT_IMPLEMENTATION
|
45
src/xf/port/default-qt/eventqueue-default.h
Normal file
45
src/xf/port/default-qt/eventqueue-default.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef XF_EVENT_QUEUE_DEFAULT_QT_H
|
||||
#define XF_EVENT_QUEUE_DEFAULT_QT_H
|
||||
|
||||
#include "config/xf-config.h"
|
||||
|
||||
#if (USE_XF_EVENT_QUEUE_DEFAULT_QT_IMPLEMENTATION != 0)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
#include <QQueue>
|
||||
#include "xf/interface/eventqueue.h"
|
||||
|
||||
/** @ingroup port_default_qt
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Default Qt implementation for the XFEventQueue interface.
|
||||
*/
|
||||
class XFEventQueueDefault : public interface::XFEventQueue
|
||||
{
|
||||
public:
|
||||
XFEventQueueDefault();
|
||||
~XFEventQueueDefault() override;
|
||||
|
||||
// XFEventQueue interface implementation
|
||||
public:
|
||||
bool empty() const override; ///< Returns true if no event is in the queue.
|
||||
bool push(const XFEvent * pEvent, bool fromISR = false) override; ///< Pushes the given event onto the queue. Returns false if the event could not be pushed.
|
||||
const XFEvent * front() override; ///< Returns pointer to next event to pop.
|
||||
void pop() override; ///< Pops the next event from the queue.
|
||||
bool pend() override; ///< Wait for the next event to arrive. Returns true if an event is in the queue.
|
||||
|
||||
protected:
|
||||
typedef QQueue<const XFEvent *> EventQueue; ///< Type of the event queue.
|
||||
|
||||
QMutex mutex_; ///< Mutex protecting access to _queue.
|
||||
QWaitCondition newEvents_; ///< Wait condition to let thread wait until a new event arrives.
|
||||
EventQueue queue_; ///< Internal queue holding the events.
|
||||
};
|
||||
|
||||
/** @} */ // end of port_default_qt group
|
||||
#endif // USE_XF_EVENT_QUEUE_DEFAULT_QT_IMPLEMENTATION
|
||||
#endif // XF_EVENT_QUEUE_DEFAULT_QT_H
|
31
src/xf/port/default-qt/mutex-default.cpp
Normal file
31
src/xf/port/default-qt/mutex-default.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include <cassert>
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION != 0)
|
||||
|
||||
#include "mutex-default.h"
|
||||
|
||||
/**
|
||||
* @brief Implementation of interface::XFMutex::create method.
|
||||
*/
|
||||
interface::XFMutex * interface::XFMutex::create()
|
||||
{
|
||||
return new XFMutexDefault;
|
||||
}
|
||||
|
||||
void XFMutexDefault::lock()
|
||||
{
|
||||
mutex_.lock();
|
||||
}
|
||||
|
||||
void XFMutexDefault::unlock()
|
||||
{
|
||||
mutex_.unlock();
|
||||
}
|
||||
|
||||
bool XFMutexDefault::tryLock(int32_t timeout /* = 0 */)
|
||||
{
|
||||
return mutex_.tryLock(timeout);
|
||||
}
|
||||
|
||||
#endif // USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION
|
39
src/xf/port/default-qt/mutex-default.h
Normal file
39
src/xf/port/default-qt/mutex-default.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef XF_MUTEX_DEFAULT_QT_H
|
||||
#define XF_MUTEX_DEFAULT_QT_H
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION != 0)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <QMutex>
|
||||
#include "xf/interface/mutex.h"
|
||||
|
||||
/** @ingroup port_default_qt
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Default Qt implementation for the XFMutex interface.
|
||||
*/
|
||||
class XFMutexDefault : public interface::XFMutex
|
||||
{
|
||||
friend class XFResourceFactoryPort;
|
||||
friend class interface::XFMutex;
|
||||
public:
|
||||
|
||||
void lock() override;
|
||||
void unlock() override;
|
||||
|
||||
bool tryLock(int32_t timeout = 0) override;
|
||||
|
||||
protected:
|
||||
XFMutexDefault() = default; ///< Do not allow to directly create an object of this class. Call XFMutex::create() instead.
|
||||
|
||||
protected:
|
||||
QMutex mutex_; ///< The real mutex.
|
||||
};
|
||||
|
||||
/** @} */ // end of port_default_qt group
|
||||
#endif // USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION
|
||||
#endif // XF_MUTEX_DEFAULT_QT_H
|
6
src/xf/port/default-qt/port-default-qt.dox
Normal file
6
src/xf/port/default-qt/port-default-qt.dox
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
/** @defgroup port_default_qt Qt Platform Default Port Classes
|
||||
*
|
||||
* Qt platform default port classes.
|
||||
*
|
||||
*/
|
41
src/xf/port/default-qt/port-functions.cpp
Normal file
41
src/xf/port/default-qt/port-functions.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include <config/xf-config.h>
|
||||
#include "xf/interface/timeoutmanager.h"
|
||||
|
||||
#if (USE_XF_PORT_FUNCTIONS_DEFAULT_QT_IMPLEMENTATION != 0)
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimerEvent>
|
||||
#include "port-functions.h"
|
||||
|
||||
static class TimeoutManagerTimer : public QObject
|
||||
{
|
||||
public:
|
||||
TimeoutManagerTimer()
|
||||
: _timerId(0)
|
||||
{
|
||||
}
|
||||
|
||||
void start(int32_t tickInterval)
|
||||
{
|
||||
Q_ASSERT(_timerId == 0); // Method should be called only once!
|
||||
_timerId = startTimer(tickInterval, Qt::PreciseTimer);
|
||||
}
|
||||
|
||||
void timerEvent(QTimerEvent * event) override
|
||||
{
|
||||
if (event->timerId() == _timerId)
|
||||
{
|
||||
interface::XFTimeoutManager::getInstance()->tick();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int32_t _timerId;
|
||||
} timeoutManagerTimer;
|
||||
|
||||
void XF_startTimeoutManagerTimer(uint32_t tickInterval)
|
||||
{
|
||||
timeoutManagerTimer.start(int32_t(tickInterval));
|
||||
}
|
||||
|
||||
#endif // USE_XF_PORT_FUNCTIONS_DEFAULT_QT_IMPLEMENTATION
|
101
src/xf/port/default-qt/thread-default.cpp
Normal file
101
src/xf/port/default-qt/thread-default.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_THREAD_DEFAULT_QT_IMPLEMENTATION != 0)
|
||||
|
||||
#include <cassert>
|
||||
#include <string.h>
|
||||
#include "thread-default.h"
|
||||
|
||||
#if !defined(XFTHREAD_DEFAULT_STACK_SIZE)
|
||||
#define XFTHREAD_DEFAULT_STACK_SIZE 256
|
||||
#endif
|
||||
|
||||
XFThreadDefault::XFThreadDefault(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize /* = 0 */)
|
||||
{
|
||||
uint32_t threadStackSize = stackSize;
|
||||
|
||||
pEntryMethodProvider_ = pProvider;
|
||||
entryMethod_ = entryMethod;
|
||||
|
||||
const QString name(threadName);
|
||||
if (!name.isEmpty())
|
||||
{
|
||||
setObjectName(name);
|
||||
}
|
||||
|
||||
if (threadStackSize == 0)
|
||||
{
|
||||
threadStackSize = XFTHREAD_DEFAULT_STACK_SIZE;
|
||||
}
|
||||
|
||||
setStackSize(threadStackSize);
|
||||
}
|
||||
|
||||
void XFThreadDefault::run()
|
||||
{
|
||||
// Call the entry point method with received provider
|
||||
(this->pEntryMethodProvider_->*this->entryMethod_)(this);
|
||||
}
|
||||
|
||||
void XFThreadDefault::start()
|
||||
{
|
||||
QThread::start();
|
||||
}
|
||||
|
||||
void XFThreadDefault::stop()
|
||||
{
|
||||
QThread::terminate();
|
||||
QThread::wait(); // Wait on thread to terminate
|
||||
}
|
||||
|
||||
|
||||
void XFThreadDefault::setPriority(XFThreadPriority priority)
|
||||
{
|
||||
auto prio = QThread::NormalPriority;
|
||||
switch (priority)
|
||||
{
|
||||
case XF_THREAD_PRIO_LOW:
|
||||
prio = QThread::LowPriority;
|
||||
break;
|
||||
case XF_THREAD_PRIO_HIGH:
|
||||
prio = QThread::HighPriority;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QThread::setPriority(prio);
|
||||
}
|
||||
|
||||
XFThreadPriority XFThreadDefault::getPriority() const
|
||||
{
|
||||
const auto prio = QThread::priority();
|
||||
XFThreadPriority priority = XF_THREAD_PRIO_UNKNOWN;
|
||||
|
||||
switch (prio)
|
||||
{
|
||||
case QThread::LowPriority:
|
||||
priority = XF_THREAD_PRIO_LOW;
|
||||
break;
|
||||
case QThread::NormalPriority:
|
||||
priority = XF_THREAD_PRIO_NORMAL;
|
||||
break;
|
||||
case QThread::HighPriority:
|
||||
priority = XF_THREAD_PRIO_HIGH;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
void XFThreadDefault::delay(uint32_t milliseconds)
|
||||
{
|
||||
QThread::msleep(milliseconds);
|
||||
}
|
||||
|
||||
#endif // USE_XF_THREAD_DEFAULT_QT_IMPLEMENTATION
|
61
src/xf/port/default-qt/thread-default.h
Normal file
61
src/xf/port/default-qt/thread-default.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef XF_THREAD_DEFAULT_QT_H
|
||||
#define XF_THREAD_DEFAULT_QT_H
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_THREAD_DEFAULT_QT_IMPLEMENTATION != 0)
|
||||
|
||||
#include <QThread>
|
||||
#include <stdint.h>
|
||||
#include "xf/interface/thread.h"
|
||||
|
||||
/** @ingroup port_default_qt
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Default thread implementation for the IDF Qt port
|
||||
*/
|
||||
class XFThreadDefault : public QThread,
|
||||
public interface::XFThread
|
||||
{
|
||||
friend class XFResourceFactoryPort;
|
||||
|
||||
// interface::Thread interface implementation
|
||||
public:
|
||||
void start() override;
|
||||
void stop() override;
|
||||
|
||||
void setPriority(XFThreadPriority priority) override;
|
||||
XFThreadPriority getPriority() const override;
|
||||
|
||||
void delay(uint32_t milliseconds) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Protected XFThreadDefault constructor
|
||||
* @param pProvider Instance providing the method to be executed by the thread.
|
||||
* @param entryMethod Method to be executed by the Thread (usually containing a infinite loop).
|
||||
* @param threadName Name of the thread.
|
||||
* @param stackSize Stack size of the thread.
|
||||
*
|
||||
* Constructor is protected because only the XFResourceFactory interface
|
||||
* based class (XFResourceFactoryPort) is allowed to created threads.
|
||||
*/
|
||||
XFThreadDefault(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize = 0);
|
||||
|
||||
// QThread interface implementation
|
||||
protected:
|
||||
void run() override; ///< Override of the QThread run method.
|
||||
|
||||
protected:
|
||||
interface::XFThreadEntryPointProvider * pEntryMethodProvider_; ///< Pointer to object providing the entry method.
|
||||
interface::XFThread::EntryMethodBody entryMethod_; ///< Entry method to be called/executed by the thread.
|
||||
};
|
||||
|
||||
/** @} */ // end of port_default_qt group
|
||||
#endif // USE_XF_THREAD_DEFAULT_QT_IMPLEMENTATION
|
||||
#endif // XF_THREAD_DEFAULT_QT_H
|
20
src/xf/port/default-qt/xf-port-default-qt.pri
Normal file
20
src/xf/port/default-qt/xf-port-default-qt.pri
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
INCLUDEPATH += $$PWD/..
|
||||
|
||||
# Path to default qt platform implementation of the XF port
|
||||
DEFAULT_QT_PATH = $$PWD/../default-qt
|
||||
|
||||
INCLUDEPATH += \
|
||||
"$${DEFAULT_QT_PATH}"
|
||||
|
||||
HEADERS += \
|
||||
"$${DEFAULT_QT_PATH}/mutex-default.h" \
|
||||
"$${DEFAULT_QT_PATH}/thread-default.h" \
|
||||
"$${DEFAULT_QT_PATH}/eventqueue-default.h"
|
||||
|
||||
SOURCES += \
|
||||
"$${DEFAULT_QT_PATH}/mutex-default.cpp" \
|
||||
"$${DEFAULT_QT_PATH}/thread-default.cpp" \
|
||||
"$${DEFAULT_QT_PATH}/eventqueue-default.cpp" \
|
||||
"$${DEFAULT_QT_PATH}/port-functions.cpp" \
|
||||
"$${DEFAULT_QT_PATH}/xf.cpp"
|
70
src/xf/port/default-qt/xf.cpp
Normal file
70
src/xf/port/default-qt/xf.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_CLASS_DEFAULT_QT_IMPLEMENTATION != 0)
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include "xf/interface/timeoutmanager.h"
|
||||
#include "xf/interface/resourcefactory.h"
|
||||
#include "xf/interface/dispatcher.h"
|
||||
#include "xf/xf.h"
|
||||
|
||||
using interface::XFResourceFactory;
|
||||
|
||||
/**
|
||||
* In the Qt port we are going to use a QCoreApplication instance
|
||||
* which gets executed by the XF::exec() method.
|
||||
*
|
||||
* The default dispatcher is active in this port implementation.
|
||||
* This means, the default dispatcher has its own thread.
|
||||
*
|
||||
* The XF::execOnce() method is not applicable for this port.
|
||||
*/
|
||||
|
||||
bool XF::isInitialized_ = false;
|
||||
bool XF::isRunning_ = false;
|
||||
|
||||
static QCoreApplication & getApplication(int argc = 0, char * argv[] = nullptr)
|
||||
{
|
||||
static QCoreApplication app(argc, argv);
|
||||
return app;
|
||||
}
|
||||
|
||||
void XF::initialize(int timeInterval /* = 10 */, int argc /* = 0 */, char * argv[] /* = nullptr */)
|
||||
{
|
||||
if (!isInitialized_)
|
||||
{
|
||||
// Call getApplication() to create QT application instance
|
||||
::getApplication(argc, argv);
|
||||
|
||||
// Create and initialize TimeoutManager
|
||||
interface::XFTimeoutManager::getInstance()->initialize(timeInterval);
|
||||
// Start it
|
||||
interface::XFTimeoutManager::getInstance()->start();
|
||||
|
||||
isInitialized_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
int XF::exec()
|
||||
{
|
||||
// Start default dispatcher
|
||||
XFResourceFactory::getInstance()->getDefaultDispatcher()->start();
|
||||
|
||||
isRunning_ = true;
|
||||
|
||||
// Start Qt event loop
|
||||
return ::getApplication().exec();
|
||||
}
|
||||
|
||||
int XF::execOnce()
|
||||
{
|
||||
Q_ASSERT(false); // Not applicable for this port
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool XF::isRunning()
|
||||
{
|
||||
return isRunning_;
|
||||
}
|
||||
|
||||
#endif // USE_XF_CLASS_DEFAULT_QT_IMPLEMENTATION
|
72
src/xf/port/default/README.md
Normal file
72
src/xf/port/default/README.md
Normal file
@ -0,0 +1,72 @@
|
||||
# XF Default Port
|
||||
|
||||
This folder provides default implementations for some platform
|
||||
indipendent XF classes.
|
||||
You can use these classes to construct the XF needed.
|
||||
|
||||
If these classes do not suit your needs, they can be reimplemented for
|
||||
your platform. Create an additional folder in the 'port' folder and
|
||||
implement there the classes you need for your platform.
|
||||
|
||||
# Available Default Port Classes
|
||||
|
||||
| Class name | File location | Define to set |
|
||||
|--|--|--|
|
||||
| XF | xf/port/default/xf-default.cpp | USE_XF_DEFAULT_IMPLEMENTATION |
|
||||
| XFResourceFactoryDefault | xf/port/default/resourcefactory-default.cpp | USE_XF_RESOURCE_FACTORY_DEFAULT_IMPLEMENTATION |
|
||||
| XFTimeoutManagerDefault | xf/port/default/timeoutmanager-default.cpp | USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION |
|
||||
| XFDispatcherDefault | xf/port/default/dispatcher-default.cpp | USE_XF_DISPATCHER_DEFAULT_IMPLEMENTATION |
|
||||
| XFDispatcherActiveDefault | xf/port/default/dispatcher-active.cpp | USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION |
|
||||
|
||||
If you need more information about the classes mentioned above, please
|
||||
have a look into their header files and the doxygen comments in code.
|
||||
|
||||
# Platform Dependend Default Port Classes
|
||||
In the following folders you can pick some platform dependend
|
||||
port classes:
|
||||
|
||||
| Platform | Folder |
|
||||
|--|--|
|
||||
| CMSIS-OS | [default-cmsis-os](../default-cmsis-os) |
|
||||
| IDF | [default-idf](../default-idf) |
|
||||
| QT | [default-qt](../default-qt) |
|
||||
|
||||
# Example _config/xf-config.h_ File
|
||||
Following you will find some examples giving you a basic idea which define
|
||||
to set in the application specific _config/xf-config.h_ file.
|
||||
|
||||
The _IDF Stm32Cube_ port uses quite all default implementations:
|
||||
|
||||
```c++
|
||||
// Defines to set to use the IDF Stm32Cube port
|
||||
#define USE_XF_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_DISPATCHER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_RESOURCE_FACTORY_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION 1
|
||||
#define USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_IDF_STM32CUBE_PORT_FUNCTIONS_IMPLEMENTATION 1
|
||||
|
||||
#include "default-idf/eventqueue-default.h"
|
||||
#ifdef __cplusplus
|
||||
using XFEventQueue = XFEventQueueDefault;
|
||||
#endif // __cplusplus
|
||||
```
|
||||
|
||||
If you want to build an XF on Windows, macOS or Linux use the _IDF Qt_ port.
|
||||
Following defines need to be set in the application specific
|
||||
_config/xf-config.h_ file:
|
||||
```c++
|
||||
// Defines to set to use the IDF Qt port
|
||||
#define USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_THREAD_DEFAULT_QT_IMPLEMENTATION 1
|
||||
|
||||
#define USE_XF_PORT_IDF_QT_XF_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_IDF_QT_RESOURCE_FACTORY_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_IDF_QT_EVENT_QUEUE_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_IDF_QT_PORT_FUNCTIONS_IMPLEMENTATION 1
|
||||
|
||||
#include "idf-qt/eventqueue.h"
|
||||
```
|
BIN
src/xf/port/default/README.pdf
Normal file
BIN
src/xf/port/default/README.pdf
Normal file
Binary file not shown.
139
src/xf/port/default/dispatcher-active.cpp
Normal file
139
src/xf/port/default/dispatcher-active.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION != 0)
|
||||
|
||||
#include <cassert>
|
||||
#if defined(XF_TRACE_EVENT_PUSH_POP) && (XF_TRACE_EVENT_PUSH_POP != 0)
|
||||
#include "trace/trace.h"
|
||||
#endif // XF_TRACE_EVENT_PUSH_POP
|
||||
#include "xf/eventstatus.h"
|
||||
#include "xf/interface/timeoutmanager.h"
|
||||
#include "xf/interface/reactive.h"
|
||||
#include "xf/interface/thread.h"
|
||||
#include "xf/interface/resourcefactory.h"
|
||||
#include "dispatcher-active.h"
|
||||
|
||||
using interface::XFTimeoutManager;
|
||||
using interface::XFResourceFactory;
|
||||
using interface::XFReactive;
|
||||
|
||||
XFDispatcherActiveDefault::XFDispatcherActiveDefault() :
|
||||
isExecuting_(false),
|
||||
pThread_(nullptr)
|
||||
{
|
||||
// Create Thread
|
||||
pThread_ = XFResourceFactory::getInstance()->createThread(this,
|
||||
interface::XFThread::EntryMethodBody(&XFDispatcherActiveDefault::execute),
|
||||
"dispatcherThread");
|
||||
assert(pThread_);
|
||||
}
|
||||
|
||||
XFDispatcherActiveDefault::~XFDispatcherActiveDefault()
|
||||
{
|
||||
isExecuting_ = false;
|
||||
pThread_->stop();
|
||||
|
||||
if (pThread_)
|
||||
{
|
||||
delete pThread_;
|
||||
}
|
||||
}
|
||||
|
||||
void XFDispatcherActiveDefault::start()
|
||||
{
|
||||
assert(pThread_);
|
||||
isExecuting_ = true;
|
||||
pThread_->start();
|
||||
}
|
||||
|
||||
void XFDispatcherActiveDefault::stop()
|
||||
{
|
||||
isExecuting_ = false;
|
||||
pThread_->stop();
|
||||
}
|
||||
|
||||
void XFDispatcherActiveDefault::pushEvent(XFEvent * pEvent, bool fromISR)
|
||||
{
|
||||
#if defined(XF_TRACE_EVENT_PUSH_POP) && (XF_TRACE_EVENT_PUSH_POP != 0)
|
||||
Trace::out("Push event: 0x%x", pEvent);
|
||||
#endif // XF_TRACE_EVENT_PUSH_POP
|
||||
events_.push(pEvent, fromISR);
|
||||
}
|
||||
|
||||
void XFDispatcherActiveDefault::scheduleTimeout(int timeoutId, int interval, interface::XFReactive * pReactive)
|
||||
{
|
||||
// Forward timeout to the timeout manager
|
||||
XFTimeoutManager::getInstance()->scheduleTimeout(timeoutId, interval, pReactive);
|
||||
}
|
||||
|
||||
void XFDispatcherActiveDefault::unscheduleTimeout(int timeoutId, interface::XFReactive * pReactive)
|
||||
{
|
||||
// Forward timeout to the timeout manager
|
||||
XFTimeoutManager::getInstance()->unscheduleTimeout(timeoutId, pReactive);
|
||||
}
|
||||
|
||||
int XFDispatcherActiveDefault::execute(const void * param /* = nullptr */)
|
||||
{
|
||||
(void)param;
|
||||
|
||||
while(isExecuting_)
|
||||
{
|
||||
while (events_.empty() && isExecuting_)
|
||||
{
|
||||
events_.pend(); // Wait until something to do
|
||||
}
|
||||
|
||||
executeOnce();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XFDispatcherActiveDefault::executeOnce()
|
||||
{
|
||||
if (!events_.empty())
|
||||
{
|
||||
const XFEvent * pEvent;
|
||||
|
||||
// Deque next event from queue
|
||||
pEvent = events_.front(); events_.pop();
|
||||
#if defined(XF_TRACE_EVENT_PUSH_POP) && (XF_TRACE_EVENT_PUSH_POP != 0)
|
||||
Trace::out("Pop event: 0x%x", pEvent);
|
||||
#endif // XF_TRACE_EVENT_PUSH_POP
|
||||
|
||||
if (pEvent)
|
||||
{
|
||||
// Forward the event to the behavioral class
|
||||
dispatchEvent(pEvent);
|
||||
|
||||
if (pEvent->getEventType() == XFEvent::Terminate)
|
||||
{
|
||||
// Exit the event loop
|
||||
isExecuting_ = false;
|
||||
}
|
||||
|
||||
if (pEvent->deleteAfterConsume())
|
||||
{
|
||||
// Remove the consumed event
|
||||
delete pEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isExecuting_;
|
||||
}
|
||||
|
||||
void XFDispatcherActiveDefault::dispatchEvent(const XFEvent * pEvent) const
|
||||
{
|
||||
XFReactive::TerminateBehavior terminateBehavior;
|
||||
|
||||
terminateBehavior = pEvent->getBehavior()->process(pEvent);
|
||||
|
||||
// Check if behavior should be deleted
|
||||
if (terminateBehavior and pEvent->getBehavior()->deleteOnTerminate())
|
||||
{
|
||||
delete pEvent->getBehavior();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION
|
57
src/xf/port/default/dispatcher-active.h
Normal file
57
src/xf/port/default/dispatcher-active.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef XF_DISPATCHER_ACTIVE_H
|
||||
#define XF_DISPATCHER_ACTIVE_H
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION != 0)
|
||||
|
||||
#include "xf/interface/dispatcher.h"
|
||||
#include "xf/interface/thread.h"
|
||||
#include "xf/interface/mutex.h"
|
||||
|
||||
/*
|
||||
* Please specify/include the XFEventQueuePort class in the xf-config file!
|
||||
*/
|
||||
|
||||
/** @ingroup port_default
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief A dispatcher implementation which may be executed using an internal thread.
|
||||
*
|
||||
* The active dispatcher internally requests a Thread from the XFResourceFactory and
|
||||
* starts it with the start() method. The thread itself is responsible to execute the
|
||||
* protected method execute().
|
||||
*/
|
||||
class XFDispatcherActiveDefault : public interface::XFThreadEntryPointProvider,
|
||||
public interface::XFDispatcher
|
||||
{
|
||||
public:
|
||||
XFDispatcherActiveDefault();
|
||||
~XFDispatcherActiveDefault() override;
|
||||
|
||||
bool isActive() const override { return (pThread_ != nullptr) ? true : false; }
|
||||
|
||||
void start() override;
|
||||
void stop() override;
|
||||
void pushEvent(XFEvent * pEvent, bool fromISR=false) override;
|
||||
|
||||
void scheduleTimeout(int timeoutId, int interval, interface::XFReactive * pReactive) override;
|
||||
void unscheduleTimeout(int timeoutId, interface::XFReactive * pReactive) override;
|
||||
|
||||
int executeOnce() override;
|
||||
|
||||
protected:
|
||||
int execute(const void * param = nullptr) override;
|
||||
void dispatchEvent(const XFEvent * pEvent) const override;
|
||||
|
||||
protected:
|
||||
bool isExecuting_; ///< True as long as the thread is executing the main loop.
|
||||
interface::XFThread * pThread_; ///< Pointer to Thread executing the dispatcher.
|
||||
XFEventQueue events_; ///< Thread-safe queue holding events waiting to get dispatched.
|
||||
};
|
||||
|
||||
/** @} */ // end of port_default group
|
||||
#endif // USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION
|
||||
#endif // XF_DISPATCHER_ACTIVE_H
|
136
src/xf/port/default/dispatcher-default.cpp
Normal file
136
src/xf/port/default/dispatcher-default.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
#include <cassert>
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_DISPATCHER_DEFAULT_IMPLEMENTATION != 0)
|
||||
#if (XF_TRACE_EVENT_PUSH_POP != 0)
|
||||
#include "trace/trace.h"
|
||||
#endif // XF_TRACE_EVENT_PUSH_POP
|
||||
#include "xf/eventstatus.h"
|
||||
#include "xf/interface/timeoutmanager.h"
|
||||
#include "xf/interface/reactive.h"
|
||||
#include "xf/interface/resourcefactory.h"
|
||||
#include "dispatcher-default.h"
|
||||
|
||||
using interface::XFTimeoutManager;
|
||||
using interface::XFResourceFactory;
|
||||
using interface::XFReactive;
|
||||
using interface::XFMutex;
|
||||
|
||||
XFDispatcherDefault::XFDispatcherDefault() :
|
||||
_bExecuting(false),
|
||||
_pMutex(nullptr)
|
||||
{
|
||||
_pMutex = XFMutex::create();
|
||||
assert(_pMutex);
|
||||
}
|
||||
|
||||
XFDispatcherDefault::~XFDispatcherDefault()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void XFDispatcherDefault::start()
|
||||
{
|
||||
assert(_pMutex);
|
||||
_bExecuting = true;
|
||||
}
|
||||
|
||||
void XFDispatcherDefault::stop()
|
||||
{
|
||||
_bExecuting = false;
|
||||
}
|
||||
|
||||
void XFDispatcherDefault::pushEvent(XFEvent * pEvent, bool fromISR)
|
||||
{
|
||||
(void)fromISR;
|
||||
_pMutex->lock();
|
||||
{
|
||||
#ifdef XF_TRACE_EVENT_PUSH_POP
|
||||
Trace::out("Push event: 0x%x", pEvent);
|
||||
#endif // XF_TRACE_EVENT_PUSH_POP
|
||||
_events.push(pEvent);
|
||||
}
|
||||
_pMutex->unlock();
|
||||
}
|
||||
|
||||
void XFDispatcherDefault::scheduleTimeout(int timeoutId, int interval, interface::XFReactive * pReactive)
|
||||
{
|
||||
// Forward timeout to the timeout manager
|
||||
XFTimeoutManager::getInstance()->scheduleTimeout(timeoutId, interval, pReactive);
|
||||
}
|
||||
|
||||
void XFDispatcherDefault::unscheduleTimeout(int timeoutId, interface::XFReactive * pReactive)
|
||||
{
|
||||
// Forward timeout to the timeout manager
|
||||
XFTimeoutManager::getInstance()->unscheduleTimeout(timeoutId, pReactive);
|
||||
}
|
||||
|
||||
int XFDispatcherDefault::execute(const void * param /* = nullptr */)
|
||||
{
|
||||
(void)param; // Parameter not used at the method
|
||||
|
||||
while(_bExecuting)
|
||||
{
|
||||
while (_events.empty() && _bExecuting)
|
||||
{
|
||||
continue; // Wait until something to do
|
||||
}
|
||||
|
||||
executeOnce(); // Dispatch next event
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XFDispatcherDefault::executeOnce()
|
||||
{
|
||||
if (!_events.empty() and _bExecuting)
|
||||
{
|
||||
const XFEvent * pEvent;
|
||||
|
||||
_pMutex->lock();
|
||||
{
|
||||
// Deque next event from queue
|
||||
pEvent = _events.front(); _events.pop();
|
||||
#ifdef XF_TRACE_EVENT_PUSH_POP
|
||||
Trace::out("Pop event: 0x%x", pEvent);
|
||||
#endif // XF_TRACE_EVENT_PUSH_POP
|
||||
}
|
||||
_pMutex->unlock();
|
||||
|
||||
if (pEvent)
|
||||
{
|
||||
// Forward the event to the behavioral class
|
||||
dispatchEvent(pEvent);
|
||||
|
||||
if (pEvent->getEventType() == XFEvent::Terminate)
|
||||
{
|
||||
// Exit the event loop
|
||||
_bExecuting = false;
|
||||
}
|
||||
|
||||
if (pEvent->deleteAfterConsume())
|
||||
{
|
||||
// Remove the consumed event
|
||||
delete pEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _bExecuting;
|
||||
}
|
||||
|
||||
void XFDispatcherDefault::dispatchEvent(const XFEvent * pEvent) const
|
||||
{
|
||||
XFReactive::TerminateBehavior terminateBehavior;
|
||||
|
||||
terminateBehavior = pEvent->getBehavior()->process(pEvent);
|
||||
|
||||
// Check if behavior should be deleted
|
||||
if (terminateBehavior and pEvent->getBehavior()->deleteOnTerminate())
|
||||
{
|
||||
delete pEvent->getBehavior();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_XF_DISPATCHER_DEFAULT_IMPLEMENTATION
|
61
src/xf/port/default/dispatcher-default.h
Normal file
61
src/xf/port/default/dispatcher-default.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef XF_DISPATCHER_DEFAULT_H
|
||||
#define XF_DISPATCHER_DEFAULT_H
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_DISPATCHER_DEFAULT_IMPLEMENTATION != 0)
|
||||
|
||||
#include "xf/interface/dispatcher.h"
|
||||
#include "xf/interface/mutex.h"
|
||||
|
||||
/*
|
||||
* Please include the XFEventQueueDefault class in the xf-config file!
|
||||
* Example: #include "default/eventqueue-default.h"
|
||||
* and
|
||||
* define the XFEventQueueDefault class as the class representing the
|
||||
* XFEventQueue used by the dispatcher.
|
||||
* Example: using XFEventQueue = XFEventQueueDefault;
|
||||
*
|
||||
* In case you want to provide you own event queue, you must implement
|
||||
* your own XFEventQueue class and include the header file in the xf-config file.
|
||||
*/
|
||||
|
||||
/** @ingroup port_default
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief A dispatcher implementation which can be used without an OS.
|
||||
*
|
||||
* The dispatcher can be used when an IDF on a bare-metal embedded system is needed.
|
||||
*/
|
||||
class XFDispatcherDefault : public interface::XFDispatcher
|
||||
{
|
||||
public:
|
||||
XFDispatcherDefault();
|
||||
virtual ~XFDispatcherDefault();
|
||||
|
||||
virtual bool isActive() const { return false; } ///< Default dispatcher does not have a composite thread.
|
||||
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual void pushEvent(XFEvent * pEvent, bool fromISR=false);
|
||||
|
||||
virtual void scheduleTimeout(int timeoutId, int interval, interface::XFReactive * pReactive);
|
||||
virtual void unscheduleTimeout(int timeoutId, interface::XFReactive * pReactive);
|
||||
|
||||
virtual int executeOnce();
|
||||
virtual int execute(const void * param = nullptr);
|
||||
|
||||
protected:
|
||||
virtual void dispatchEvent(const XFEvent * pEvent) const;
|
||||
|
||||
protected:
|
||||
bool _bExecuting; ///< True as long as the thread is executing the main loop.
|
||||
XFEventQueue _events; ///< Queue holding events waiting to get dispatched.
|
||||
interface::XFMutex * _pMutex; ///< Mutex to protect event queue.
|
||||
};
|
||||
|
||||
/** @} */ // end of port_default group
|
||||
#endif // USE_XF_DISPATCHER_DEFAULT_IMPLEMENTATION
|
||||
#endif // XF_DISPATCHER_DEFAULT_H
|
6
src/xf/port/default/port-default.dox
Normal file
6
src/xf/port/default/port-default.dox
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
/** @defgroup port_default XF Default Port Classes
|
||||
*
|
||||
* XF default port classes.
|
||||
*
|
||||
*/
|
51
src/xf/port/default/resourcefactory-default.cpp
Normal file
51
src/xf/port/default/resourcefactory-default.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_RESOURCE_FACTORY_DEFAULT_IMPLEMENTATION != 0)
|
||||
|
||||
#include "resourcefactory-default.h"
|
||||
#include "mutex-default.h"
|
||||
|
||||
//static
|
||||
interface::XFResourceFactory * interface::XFResourceFactory::getInstance()
|
||||
{
|
||||
return XFResourceFactoryDefault::getInstance();
|
||||
}
|
||||
|
||||
//static
|
||||
interface::XFResourceFactory * XFResourceFactoryDefault::getInstance()
|
||||
{
|
||||
static XFResourceFactoryDefault theResourceFactory;
|
||||
|
||||
return &theResourceFactory;
|
||||
}
|
||||
|
||||
interface::XFDispatcher * XFResourceFactoryDefault::getDefaultDispatcher()
|
||||
{
|
||||
static XFDispatcherDefault mainDispatcher;
|
||||
|
||||
return &mainDispatcher;
|
||||
}
|
||||
|
||||
interface::XFDispatcher * XFResourceFactoryDefault::createDispatcher()
|
||||
{
|
||||
// Default implementation cannot create new dispatcher. Return the default dispatcher
|
||||
return getDefaultDispatcher();
|
||||
}
|
||||
|
||||
interface::XFThread * XFResourceFactoryDefault::createThread(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize /* = 0 */)
|
||||
{
|
||||
// Default implementation cannot create threads (no underlying OS present)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
interface::XFMutex * XFResourceFactoryDefault::createMutex()
|
||||
{
|
||||
static XFMutexDefault mutex;
|
||||
|
||||
return &mutex;
|
||||
}
|
||||
|
||||
#endif // USE_XF_RESOURCE_FACTORY_DEFAULT_IMPLEMENTATION
|
39
src/xf/port/default/resourcefactory-default.h
Normal file
39
src/xf/port/default/resourcefactory-default.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef XF_RESOURCE_FACTORY_DEFAULT_H
|
||||
#define XF_RESOURCE_FACTORY_DEFAULT_H
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_RESOURCE_FACTORY_DEFAULT_IMPLEMENTATION != 0)
|
||||
|
||||
#include "xf/interface/resourcefactory.h"
|
||||
#include "dispatcher-default.h"
|
||||
|
||||
/** @ingroup port_default
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Default implementation of the XF resource factory.
|
||||
*/
|
||||
class XFResourceFactoryDefault : public interface::XFResourceFactory
|
||||
{
|
||||
public:
|
||||
virtual ~XFResourceFactoryDefault() = default;
|
||||
|
||||
static interface::XFResourceFactory * getInstance(); ///< Returns a pointer to the unique instance of the XF resource factory.
|
||||
|
||||
virtual interface::XFDispatcher * getDefaultDispatcher(); ///< Returns the default dispatcher.
|
||||
virtual interface::XFDispatcher * createDispatcher(); ///< Creates and returns a new dispatcher.
|
||||
virtual interface::XFThread * createThread(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize = 0); ///< Creates and returns a new thread.
|
||||
virtual interface::XFMutex * createMutex(); ///< Creates and returns a new mutex.
|
||||
|
||||
protected:
|
||||
XFResourceFactoryDefault() = default;
|
||||
};
|
||||
|
||||
/** @} */ // end of port_default group
|
||||
#endif // USE_XF_RESOURCE_FACTORY_DEFAULT_IMPLEMENTATION
|
||||
#endif // XF_RESOURCE_FACTORY_DEFAULT_H
|
226
src/xf/port/default/timeoutmanager-default.cpp
Normal file
226
src/xf/port/default/timeoutmanager-default.cpp
Normal file
@ -0,0 +1,226 @@
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION != 0)
|
||||
|
||||
#include <cassert>
|
||||
#include "xf/interface/reactive.h"
|
||||
#include "xf/interface/mutex.h"
|
||||
#include "port-functions.h"
|
||||
#include "timeoutmanager-default.h"
|
||||
|
||||
using interface::XFMutex;
|
||||
|
||||
interface::XFTimeoutManager * interface::XFTimeoutManager::getInstance()
|
||||
{
|
||||
return XFTimeoutManagerDefault::getInstance();
|
||||
}
|
||||
|
||||
interface::XFTimeoutManager * XFTimeoutManagerDefault::getInstance()
|
||||
{
|
||||
static XFTimeoutManagerDefault timeoutManager;
|
||||
return &timeoutManager;
|
||||
}
|
||||
|
||||
XFTimeoutManagerDefault::XFTimeoutManagerDefault() :
|
||||
pMutex_(nullptr)
|
||||
{
|
||||
pMutex_ = XFMutex::create();
|
||||
assert(pMutex_);
|
||||
}
|
||||
|
||||
XFTimeoutManagerDefault::~XFTimeoutManagerDefault()
|
||||
{
|
||||
}
|
||||
|
||||
void XFTimeoutManagerDefault::start()
|
||||
{
|
||||
// Check tickInterval. Set default value if not set
|
||||
if (tickInterval_ == 0)
|
||||
{
|
||||
tickInterval_ = 10;
|
||||
}
|
||||
|
||||
XF_startTimeoutManagerTimer(uint32_t(tickInterval_));
|
||||
}
|
||||
|
||||
void XFTimeoutManagerDefault::scheduleTimeout(int32_t timeoutId, int32_t interval, interface::XFReactive * pReactive)
|
||||
{
|
||||
XFTimeout * pTimeout = new XFTimeout(timeoutId, interval, pReactive);
|
||||
|
||||
if (pTimeout)
|
||||
{
|
||||
addTimeout(pTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
void XFTimeoutManagerDefault::unscheduleTimeout(int32_t timeoutId, interface::XFReactive * pReactive)
|
||||
{
|
||||
const XFTimeout timeout(timeoutId, 0, pReactive);
|
||||
XFTimeout * pTimeout;
|
||||
|
||||
pMutex_->lock();
|
||||
{
|
||||
for (TimeoutList::iterator i = timeouts_.begin();
|
||||
i != timeouts_.end(); /*Do not increment here!*/)
|
||||
{
|
||||
pTimeout = *i;
|
||||
|
||||
// Check if behavior and timeout id are equal
|
||||
if (*pTimeout == timeout)
|
||||
{
|
||||
TimeoutList::iterator next = i;
|
||||
|
||||
// Check if remaining ticks can be given further
|
||||
if (++next != timeouts_.end())
|
||||
{
|
||||
// Add (remaining) ticks to next timeout in list
|
||||
(*next)->addToRelTicks(pTimeout->getRelTicks());
|
||||
}
|
||||
|
||||
i = timeouts_.erase(i);
|
||||
// Iterator now points to the next element
|
||||
|
||||
delete pTimeout;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
pMutex_->unlock();
|
||||
}
|
||||
|
||||
void XFTimeoutManagerDefault::tick()
|
||||
{
|
||||
assert(tickInterval_); // Did you call start()?!
|
||||
int32_t intervalToSubtract = tickInterval_;
|
||||
|
||||
while (!timeouts_.empty())
|
||||
{
|
||||
pMutex_->lock();
|
||||
{
|
||||
XFTimeout * pFirstTimeout = timeouts_.front();
|
||||
|
||||
// Subtract time elapsed
|
||||
pFirstTimeout->substractFromRelTicks(intervalToSubtract);
|
||||
|
||||
// From now on set it to zero.
|
||||
intervalToSubtract = 0;
|
||||
|
||||
// Check timeout timed out
|
||||
if (pFirstTimeout->getRelTicks() <= 0)
|
||||
{
|
||||
// Check remaining ticks can be given further
|
||||
if (timeouts_.size() > 1)
|
||||
{
|
||||
TimeoutList::iterator i = timeouts_.begin();
|
||||
|
||||
// Add ticks overrun to next timeout
|
||||
i++;
|
||||
(*i)->substractFromRelTicks(abs(pFirstTimeout->getRelTicks()));
|
||||
}
|
||||
|
||||
// Inject the timeout back to the behavioral class
|
||||
returnTimeout(pFirstTimeout);
|
||||
|
||||
// Remove timeout
|
||||
timeouts_.pop_front();
|
||||
|
||||
// Check if timeouts with same timeout value are present
|
||||
for (TimeoutList::iterator it = timeouts_.begin(); it != timeouts_.end(); /*Do not increment here!*/)
|
||||
{
|
||||
if ((*it)->getRelTicks() == 0)
|
||||
{
|
||||
returnTimeout(*it); // Return them true
|
||||
it = timeouts_.erase(it); // Remove timeout and adjust iterator to next element
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pMutex_->unlock();
|
||||
// Done. Exit while loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
pMutex_->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void XFTimeoutManagerDefault::addTimeout(XFTimeout * pNewTimeout)
|
||||
{
|
||||
if (!timeouts_.empty())
|
||||
{
|
||||
pMutex_->lock();
|
||||
{
|
||||
// Insert timeout before timeout(s) triggering later
|
||||
TimeoutList::iterator i = timeouts_.begin();
|
||||
|
||||
unsigned int index = 0;
|
||||
|
||||
// Find the right place to insert new timeout
|
||||
while (i != timeouts_.end() &&
|
||||
(*i)->getRelTicks() < pNewTimeout->getRelTicks())
|
||||
{ // -> by: test4, test5
|
||||
pNewTimeout->substractFromRelTicks((*i)->getRelTicks());
|
||||
i++; index++;
|
||||
}
|
||||
|
||||
if (i != timeouts_.end())
|
||||
{
|
||||
if ((*i)->getRelTicks() != pNewTimeout->getRelTicks())
|
||||
{ // -> by: test1, test4, test5
|
||||
// Timeout are going to timeout at different times
|
||||
|
||||
// Insert new timeout before
|
||||
timeouts_.insert(i, pNewTimeout);
|
||||
|
||||
// Remove time from following timeout
|
||||
(*i)->substractFromRelTicks(pNewTimeout->getRelTicks());
|
||||
|
||||
}
|
||||
else
|
||||
{ // -> by: test1, test5
|
||||
const int32_t relTicks = (*i)->getRelTicks();
|
||||
// Timeouts timeout at the same time. Put
|
||||
// the new one behind the actual.
|
||||
i++;
|
||||
|
||||
// Check if even more timeouts with the same timeout
|
||||
while(i != timeouts_.end() && (*i)->getRelTicks() == 0)
|
||||
{ // -> by: test5
|
||||
i++;
|
||||
}
|
||||
|
||||
// Insert new timeout behind actual
|
||||
timeouts_.insert(i, pNewTimeout);
|
||||
// Remove time from actual timeout
|
||||
pNewTimeout->substractFromRelTicks(relTicks);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // -> by: test4, test5
|
||||
// Add timeout at the end of the list
|
||||
timeouts_.insert(timeouts_.end(), pNewTimeout);
|
||||
}
|
||||
}
|
||||
pMutex_->unlock();
|
||||
}
|
||||
else
|
||||
{ // -> by: test1, test2, test3, test4, test5
|
||||
timeouts_.push_front(pNewTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
void XFTimeoutManagerDefault::returnTimeout(XFTimeout * pTimeout)
|
||||
{
|
||||
pTimeout->getBehavior()->pushEvent(pTimeout);
|
||||
}
|
||||
|
||||
#endif // USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION
|
53
src/xf/port/default/timeoutmanager-default.h
Normal file
53
src/xf/port/default/timeoutmanager-default.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef XF_TIMEOUTMANAGER_DEFAULT_H
|
||||
#define XF_TIMEOUTMANAGER_DEFAULT_H
|
||||
|
||||
#include <list>
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION != 0)
|
||||
|
||||
#include "xf/interface/timeoutmanager.h"
|
||||
#include "xf/timeout.h"
|
||||
#include "xf/interface/mutex.h"
|
||||
|
||||
/** @ingroup port_default
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Default implementation of the XF TimeoutManager
|
||||
*/
|
||||
class XFTimeoutManagerDefault : public interface::XFTimeoutManager
|
||||
{
|
||||
friend interface::XFTimeoutManager * interface::XFTimeoutManager::getInstance();
|
||||
public:
|
||||
~XFTimeoutManagerDefault() override;
|
||||
|
||||
static interface::XFTimeoutManager * getInstance(); ///< Returns a pointer to the single instance of the class.
|
||||
|
||||
void start() override; ///< See interface::XFTimeoutManager
|
||||
void scheduleTimeout(int32_t timeoutId, int32_t interval, interface::XFReactive * pReactive) override; ///< See interface::XFTimeoutManager
|
||||
void unscheduleTimeout(int32_t timeoutId, interface::XFReactive * pReactive) override; ///< See interface::XFTimeoutManager
|
||||
void tick() override; ///< See interface::XFTimeoutManager
|
||||
|
||||
protected:
|
||||
XFTimeoutManagerDefault();
|
||||
void addTimeout(XFTimeout * pNewTimeout) override; ///< Adds the timeout to #_timeouts.
|
||||
|
||||
/**
|
||||
* Returns the timeout back to the queue of the thread executing
|
||||
* the behavioral instance.
|
||||
*/
|
||||
void returnTimeout(XFTimeout * pTimeout); ///< Returns timeout back to behavioral class.
|
||||
|
||||
protected:
|
||||
typedef std::list<XFTimeout *> TimeoutList; ///< Type used for the _timeouts property.
|
||||
|
||||
TimeoutList timeouts_; ///< Container holding timeouts to manage.
|
||||
|
||||
interface::XFMutex * pMutex_; ///< Mutex to protect access to TimeoutList.
|
||||
};
|
||||
|
||||
/** @} */ // end of port_default group
|
||||
#endif // USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION
|
||||
#endif // XF_TIMEOUTMANAGER_DEFAULT_H
|
91
src/xf/port/default/xf-default.cpp
Normal file
91
src/xf/port/default/xf-default.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include <cassert>
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_DEFAULT_IMPLEMENTATION != 0)
|
||||
|
||||
#include "xf/interface/timeoutmanager.h"
|
||||
#include "xf/interface/resourcefactory.h"
|
||||
#include "xf/interface/dispatcher.h"
|
||||
#include "xf/xf.h"
|
||||
|
||||
using interface::XFResourceFactory;
|
||||
using interface::XFTimeoutManager;
|
||||
|
||||
bool XF::isInitialized_ = false;
|
||||
bool XF::isRunning_ = false;
|
||||
|
||||
void XF_initialize(int timeInterval)
|
||||
{
|
||||
XF::initialize(timeInterval);
|
||||
}
|
||||
|
||||
void XF_exec()
|
||||
{
|
||||
XF::exec();
|
||||
}
|
||||
|
||||
void XF_execOnce()
|
||||
{
|
||||
XF::execOnce();
|
||||
}
|
||||
|
||||
void XF::initialize(int timeInterval /* = 10 */, int argc /* = 0 */, char * argv[] /* = nullptr */)
|
||||
{
|
||||
if (!isInitialized_)
|
||||
{
|
||||
// Create and initialize TimeoutManager
|
||||
XFTimeoutManager::getInstance()->initialize(timeInterval);
|
||||
|
||||
isInitialized_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
int XF::exec()
|
||||
{
|
||||
// Start timeout manager
|
||||
XFTimeoutManager::getInstance()->start();
|
||||
|
||||
// Start default dispatcher
|
||||
XFResourceFactory::getInstance()->getDefaultDispatcher()->start();
|
||||
|
||||
isRunning_ = true; // From here the XF is running
|
||||
|
||||
// In case default dispatcher does not have a thread executing it,
|
||||
// call it with this thread
|
||||
if (!XFResourceFactory::getInstance()->getDefaultDispatcher()->isActive())
|
||||
{
|
||||
XFResourceFactory::getInstance()->getDefaultDispatcher()->execute();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XF::execOnce()
|
||||
{
|
||||
static bool usingExecOnce = false;
|
||||
|
||||
if (!usingExecOnce)
|
||||
{
|
||||
usingExecOnce = true;
|
||||
|
||||
// Start timeout manager
|
||||
XFTimeoutManager::getInstance()->start();
|
||||
|
||||
// It makes no sense to call execOnce() with
|
||||
// an active default dispatcher!
|
||||
assert(!XFResourceFactory::getInstance()->getDefaultDispatcher()->isActive());
|
||||
// Default dispatcher needs to be started explicitly
|
||||
XFResourceFactory::getInstance()->getDefaultDispatcher()->start();
|
||||
|
||||
isRunning_ = true; // From here the XF is running
|
||||
}
|
||||
|
||||
// Execute once the default dispatcher
|
||||
return XFResourceFactory::getInstance()->getDefaultDispatcher()->executeOnce();
|
||||
}
|
||||
|
||||
bool XF::isRunning()
|
||||
{
|
||||
return isRunning_;
|
||||
}
|
||||
|
||||
#endif // USE_XF_DEFAULT_IMPLEMENTATION
|
38
src/xf/port/idf-qt/README.md
Normal file
38
src/xf/port/idf-qt/README.md
Normal file
@ -0,0 +1,38 @@
|
||||
# XF Port - IDF Qt
|
||||
|
||||
This port folder contains specific classes for the _IDF Qt_
|
||||
XF port.
|
||||
|
||||
# Classes used by the _IDF Qt_ Port
|
||||
|
||||
| Class name | File location | Define to set |
|
||||
|--|--|--|
|
||||
| XFTimeoutManagerDefault | xf/port/default/timeoutmanager-default.cpp | USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION |
|
||||
| XFDispatcherActiveDefault | xf/port/default/dispatcher-active.cpp | USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION |
|
||||
| XFMutexDefault | xf/port/default-qt/mutex-default.cpp | USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION |
|
||||
| XFThreadDefault | xf/port/default-qt/thread-default.cpp | USE_XF_THREAD_DEFAULT_QT_IMPLEMENTATION |
|
||||
| XF | xf/port/default-qt/xf.cpp | USE_XF_CLASS_DEFAULT_QT_IMPLEMENTATION |
|
||||
| XFEventQueuePort | xf/port/default-qt/eventqueue.cpp | USE_XF_EVENT_QUEUE_DEFAULT_QT_IMPLEMENTATION |
|
||||
| Port Functions | xf/port/default-qt/port-functions.cpp | USE_XF_PORT_FUNCTIONS_DEFAULT_QT_IMPLEMENTATION |
|
||||
| XFResourceFactoryPort | xf/port/idf-qt/resourcefactory.cpp | USE_XF_PORT_IDF_QT_RESOURCE_FACTORY_IMPLEMENTATION |
|
||||
|
||||
# Example _config/xf-config.h_ File
|
||||
|
||||
```c++
|
||||
// Defines to set to use the IDF Qt port
|
||||
#define USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_EVENT_QUEUE_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_MUTEX_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_THREAD_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_CLASS_DEFAULT_QT_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_FUNCTIONS_DEFAULT_QT_IMPLEMENTATION 1
|
||||
|
||||
#define USE_XF_PORT_IDF_QT_RESOURCE_FACTORY_IMPLEMENTATION 1
|
||||
|
||||
#include "default-qt/eventqueue-default.h"
|
||||
#ifdef __cplusplus
|
||||
// Force to take the XFEventQueueDefault implementation for the event queue
|
||||
using XFEventQueue = XFEventQueueDefault;
|
||||
#endif // __cplusplus
|
||||
```
|
BIN
src/xf/port/idf-qt/README.pdf
Normal file
BIN
src/xf/port/idf-qt/README.pdf
Normal file
Binary file not shown.
6
src/xf/port/idf-qt/port-idf-qt.dox
Normal file
6
src/xf/port/idf-qt/port-idf-qt.dox
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
/** @defgroup port_idf_qt IDF Qt Port Classes
|
||||
*
|
||||
* XF port classes for the `IDF Qt` port.
|
||||
*
|
||||
*/
|
59
src/xf/port/idf-qt/resourcefactory.cpp
Normal file
59
src/xf/port/idf-qt/resourcefactory.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_PORT_IDF_QT_RESOURCE_FACTORY_IMPLEMENTATION != 0)
|
||||
|
||||
#include <QtGlobal>
|
||||
#include "thread-default.h"
|
||||
#include "default/dispatcher-active.h"
|
||||
#include "xf/interface/mutex.h"
|
||||
#include "resourcefactory.h"
|
||||
|
||||
using interface::XFMutex;
|
||||
|
||||
//static
|
||||
interface::XFResourceFactory * interface::XFResourceFactory::getInstance()
|
||||
{
|
||||
return XFResourceFactoryPort::getInstance();
|
||||
}
|
||||
|
||||
// static
|
||||
interface::XFResourceFactory * XFResourceFactoryPort::getInstance()
|
||||
{
|
||||
static XFResourceFactoryPort theResourceFactory;
|
||||
return &theResourceFactory;
|
||||
}
|
||||
|
||||
interface::XFDispatcher * XFResourceFactoryPort::getDefaultDispatcher()
|
||||
{
|
||||
static XFDispatcherActiveDefault mainDispatcher;
|
||||
return &mainDispatcher;
|
||||
}
|
||||
|
||||
interface::XFDispatcher * XFResourceFactoryPort::createDispatcher()
|
||||
{
|
||||
// With an IDF implementation only one dispatcher is allowed. This
|
||||
// prohibits to create new dispatchers. Return the default dispatcher.
|
||||
return getDefaultDispatcher();
|
||||
}
|
||||
|
||||
interface::XFThread * XFResourceFactoryPort::createThread(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize /* = 0 */)
|
||||
{
|
||||
// With an IDF implementation normaly only one thread is created and it handles
|
||||
// all the XF related stuff. With the Qt based IDF, there is a dedicated thread needed
|
||||
// which executes the XF. The primary thread (executing the main function) is
|
||||
// needed to execute the QApplication instance (for timers, signals and slots).
|
||||
//
|
||||
// The method createThread() is only called once at XF initialization to provide
|
||||
// the thread executing the XF.
|
||||
return new XFThreadDefault(pProvider, entryMethod, threadName, stackSize);
|
||||
}
|
||||
|
||||
interface::XFMutex * XFResourceFactoryPort::createMutex()
|
||||
{
|
||||
return XFMutex::create();
|
||||
}
|
||||
|
||||
#endif // USE_XF_PORT_IDF_QT_RESOURCE_FACTORY_IMPLEMENTATION
|
39
src/xf/port/idf-qt/resourcefactory.h
Normal file
39
src/xf/port/idf-qt/resourcefactory.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef XF_PORT_IDF_QT_RESOURCE_FACTORY_H
|
||||
#define XF_PORT_IDF_QT_RESOURCE_FACTORY_H
|
||||
|
||||
#include "config/xf-config.h"
|
||||
|
||||
#if (USE_XF_PORT_IDF_QT_RESOURCE_FACTORY_IMPLEMENTATION != 0)
|
||||
|
||||
/** @ingroup port_idf_qt
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "xf/interface/resourcefactory.h"
|
||||
#include "xf/interface/dispatcher.h"
|
||||
|
||||
/**
|
||||
* @brief XFResourceFactoryPort implementation for the IDF Qt port.
|
||||
*/
|
||||
class XFResourceFactoryPort : public interface::XFResourceFactory
|
||||
{
|
||||
public:
|
||||
~XFResourceFactoryPort() override {}
|
||||
|
||||
static interface::XFResourceFactory * getInstance(); ///< Returns a pointer to the unique instance of the XF resource factory.
|
||||
|
||||
interface::XFDispatcher * getDefaultDispatcher() override; ///< Returns the default dispatcher.
|
||||
interface::XFDispatcher * createDispatcher() override; ///< Creates and returns a new dispatcher.
|
||||
interface::XFThread * createThread(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize = 0) override; ///< Creates and returns a new thread.
|
||||
interface::XFMutex * createMutex() override; ///< Creates and returns a new mutex.
|
||||
|
||||
protected:
|
||||
XFResourceFactoryPort() {}
|
||||
};
|
||||
|
||||
/** @} */ // end of port_idf_qt group
|
||||
#endif // USE_XF_PORT_IDF_QT_RESOURCE_FACTORY_IMPLEMENTATION
|
||||
#endif // XF_PORT_IDF_QT_RESOURCE_FACTORY_H
|
24
src/xf/port/idf-qt/xf-port-default.pri
Normal file
24
src/xf/port/idf-qt/xf-port-default.pri
Normal file
@ -0,0 +1,24 @@
|
||||
#
|
||||
# This PRI file takes only the classes needed from the
|
||||
# 'default' port.
|
||||
#
|
||||
|
||||
INCLUDEPATH += $$PWD/..
|
||||
|
||||
# Path to default implementation of the XF port
|
||||
DEFAULT_IMPL_PATH = $$PWD/../default
|
||||
|
||||
DEFAULT_IMPL_SOURCES += \
|
||||
"$${DEFAULT_IMPL_PATH}/timeoutmanager-default.cpp" \
|
||||
"$${DEFAULT_IMPL_PATH}/dispatcher-active.cpp"
|
||||
|
||||
DEFAULT_IMPL_HEADERS += \
|
||||
"$${DEFAULT_IMPL_PATH}/timeoutmanager-default.h" \
|
||||
"$${DEFAULT_IMPL_PATH}/dispatcher-active.h"
|
||||
|
||||
SOURCES += \
|
||||
$${DEFAULT_IMPL_SOURCES}$$
|
||||
|
||||
HEADERS += \
|
||||
$${DEFAULT_IMPL_HEADERS}$$ \
|
||||
"$$PWD/../port-functions.h"
|
8
src/xf/port/idf-qt/xf-port-idf.pri
Normal file
8
src/xf/port/idf-qt/xf-port-idf.pri
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
INCLUDEPATH += $$PWD/..
|
||||
|
||||
SOURCES += \
|
||||
"$$PWD/resourcefactory.cpp"
|
||||
|
||||
HEADERS += \
|
||||
"$$PWD/resourcefactory.h"
|
32
src/xf/port/idf-stm32cube/README.md
Normal file
32
src/xf/port/idf-stm32cube/README.md
Normal file
@ -0,0 +1,32 @@
|
||||
# XF Port - IDF Stm32Cube
|
||||
|
||||
This port folder contains specific classes for the _IDF Stm32Cube_
|
||||
XF port.
|
||||
|
||||
# Classes used by the _IDF Stm32Cube_ Port
|
||||
|
||||
| Class name | File location | Define to set |
|
||||
|--|--|--|
|
||||
| XF | xf/port/default/xf-default.cpp | USE_XF_DEFAULT_IMPLEMENTATION |
|
||||
| XFDispatcherDefault | xf/port/default/dispatcher-default.cpp | USE_XF_DISPATCHER_DEFAULT_IMPLEMENTATION |
|
||||
| XFTimeoutManagerDefault | xf/port/default/timeoutmanager-default.cpp | USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION |
|
||||
| XFResourceFactoryDefault | xf/port/default/resourcefactory-default.cpp | USE_XF_RESOURCE_FACTORY_DEFAULT_IMPLEMENTATION |
|
||||
| XFMutexDefault | xf/port/default-idf/mutex-default.cpp | USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION |
|
||||
| XFEventQueueDefault | xf/port/default-idf/eventqueue-default.cpp | USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION |
|
||||
| Port Functions | xf/port/idf-stm32cube/port-functions.cpp | USE_XF_PORT_IDF_STM32CUBE_PORT_FUNCTIONS_IMPLEMENTATION |
|
||||
|
||||
# Example _config/xf-config.h_ File
|
||||
```c++
|
||||
#define USE_XF_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_DISPATCHER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_RESOURCE_FACTORY_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_MUTEX_DEFAULT_IDF_IMPLEMENTATION 1
|
||||
#define USE_XF_EVENT_QUEUE_DEFAULT_IDF_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_IDF_STM32CUBE_PORT_FUNCTIONS_IMPLEMENTATION 1
|
||||
|
||||
#include "default-idf/eventqueue-default.h"
|
||||
#ifdef __cplusplus
|
||||
using XFEventQueue = XFEventQueueDefault;
|
||||
#endif // __cplusplus
|
||||
```
|
BIN
src/xf/port/idf-stm32cube/README.pdf
Normal file
BIN
src/xf/port/idf-stm32cube/README.pdf
Normal file
Binary file not shown.
63
src/xf/port/idf-stm32cube/port-functions.cpp
Normal file
63
src/xf/port/idf-stm32cube/port-functions.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_PORT_IDF_STM32CUBE_PORT_FUNCTIONS_IMPLEMENTATION != 0)
|
||||
|
||||
#include <cassert>
|
||||
#include "mcu/mcu.h"
|
||||
#include "critical/critical.h"
|
||||
#include "xf/xf.h"
|
||||
#include "xf/interface/timeoutmanager.h"
|
||||
#include "xf/port/port-functions.h"
|
||||
|
||||
using interface::XFTimeoutManager;
|
||||
|
||||
/**
|
||||
* For this port the following port functions need to be implemented:
|
||||
* - XF_startTimeoutManagerTimer()
|
||||
* - XF_tick()
|
||||
* - XF_tickIntervalInMilliseconds()
|
||||
|
||||
* In the XF_startTimeoutManagerTimer() function no code needs to
|
||||
* be implemented because the SysTick peripheral is already initialized
|
||||
* be the STM32CubeMX HAL.
|
||||
* This means that changes in 'tickInterval' needs to be handled elsewhere
|
||||
* using the XF_tickIntervalInMilliseconds() function.
|
||||
*/
|
||||
|
||||
void XF_startTimeoutManagerTimer(uint32_t tickInterval)
|
||||
{
|
||||
(void)tickInterval;
|
||||
|
||||
// SysTick gets already started by the STM32CubeMX HAL.
|
||||
// So nothing to do here.
|
||||
}
|
||||
|
||||
/**
|
||||
* SysTick_Handler() function is already implemented in the STM32CubeMX generated
|
||||
* code (see Src/stm32fxxx_it.c file). Therefore, we must provide here a function
|
||||
* which can be explicitly called in SysTick_Handler() to tick the XF.
|
||||
*/
|
||||
void XF_tick()
|
||||
{
|
||||
critical_setInIsr(true); // Tell critical section we are in an ISR
|
||||
if (XF::isRunning()) // Call tick only if XF is running
|
||||
{
|
||||
XFTimeoutManager::getInstance()->tick(); // Call framework hook tick function
|
||||
}
|
||||
critical_setInIsr(false); // Tell critical section we are leaving the ISR
|
||||
}
|
||||
|
||||
/**
|
||||
* C function wrapping getTickInterval() method of XFTimeoutManager.
|
||||
*/
|
||||
int32_t XF_tickIntervalInMilliseconds()
|
||||
{
|
||||
return XFTimeoutManager::getInstance()->getTickInterval();
|
||||
}
|
||||
|
||||
bool XF_isRunning()
|
||||
{
|
||||
return XF::isRunning();
|
||||
}
|
||||
|
||||
#endif // USE_XF_PORT_IDF_STM32CUBE_PORT_FUNCTIONS_IMPLEMENTATION
|
7
src/xf/port/idf-stm32cube/port-idf-stm32cube.dox
Normal file
7
src/xf/port/idf-stm32cube/port-idf-stm32cube.dox
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
/** @defgroup port_idf_stm32cube IDF STM32Cube Port Classes
|
||||
*
|
||||
* XF port classes for the `IDF STM32Cube` port.
|
||||
*
|
||||
* For the `IDF STM32Cube` port only default port classes are used.
|
||||
*/
|
44
src/xf/port/port-functions.h
Normal file
44
src/xf/port/port-functions.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef XF_PORT_FUNCTIONS_H
|
||||
#define XF_PORT_FUNCTIONS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* Following functions need to have "C" signature as they can be
|
||||
* called in C (and C++).
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief C function allowing to start the timer needed by the TimeoutManager instance.
|
||||
*/
|
||||
void XF_startTimeoutManagerTimer(uint32_t tickInterval);
|
||||
|
||||
/**
|
||||
* @brief Must be called regularly in a timer ISR or software timer callback.
|
||||
*
|
||||
* The XF_tick() function must be called with the same interval given to the
|
||||
* TimeoutManager (tickInterval).
|
||||
*/
|
||||
void XF_tick();
|
||||
|
||||
/**
|
||||
* C function returning the tick interval in milliseconds with which the XF_tick()
|
||||
* function should be called. This is the parameter given to the XF::init() method
|
||||
* and may be different for each project.
|
||||
*/
|
||||
int32_t XF_tickIntervalInMilliseconds();
|
||||
|
||||
/**
|
||||
* C function wrapping to XF::isRunning() method.
|
||||
*/
|
||||
bool XF_isRunning();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // XF_PORT_FUNCTIONS_H
|
27
src/xf/port/stm32cube-cmsis-freertos/README.md
Normal file
27
src/xf/port/stm32cube-cmsis-freertos/README.md
Normal file
@ -0,0 +1,27 @@
|
||||
# XF Port - Stm32Cube CMSIS FreeRTOS
|
||||
|
||||
This port folder contains specific classes for the _Stm32Cube CMSIS FreeRTOS_
|
||||
XF port.
|
||||
|
||||
# Classes used by the _Stm32Cube CMSIS FreeRTOS_ Port
|
||||
|
||||
| Class name | File location | Define to set |
|
||||
|--|--|--|
|
||||
| XFDispatcherActiveDefault | xf/port/default/dispatcher-active.cpp | USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION |
|
||||
| XFMutexDefault | xf/port/default-cmsis-os/mutex-default.cpp | USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION |
|
||||
| XFThreadDefault | xf/port/default-cmsis-os/thread-default.cpp | USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION |
|
||||
| XFResourceFactoryPort | xf/port/stm32cube-cmsis-freertos/resourcefactory.cpp | USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_RESOURCE_FACTORY_IMPLEMENTATION |
|
||||
| XFTimeoutManagerPort | xf/port/stm32cube-cmsis-freertos/timeoutmanager.cpp | USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_TIMEOUTMANAGER_IMPLEMENTATION |
|
||||
| XFEventQueuePort | xf/port/stm32cube-cmsis-freertos/eventqueue.cpp | USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_EVENT_QUEUE_IMPLEMENTATION |
|
||||
|
||||
# Example _config/xf-config.h_ File
|
||||
```c++
|
||||
#define USE_XF_DISPATCHER_ACTIVE_DEFAULT_IMPLEMENTATION 1
|
||||
#define USE_XF_MUTEX_DEFAULT_CMSIS_OS_IMPLEMENTATION 1
|
||||
#define USE_XF_THREAD_DEFAULT_CMSIS_OS_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_RESOURCE_FACTORY_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_TIMEOUTMANAGER_IMPLEMENTATION 1
|
||||
#define USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_EVENT_QUEUE_IMPLEMENTATION 1
|
||||
|
||||
#include "stm32cube-cmsis-freertos/eventqueue.h"
|
||||
```
|
BIN
src/xf/port/stm32cube-cmsis-freertos/README.pdf
Normal file
BIN
src/xf/port/stm32cube-cmsis-freertos/README.pdf
Normal file
Binary file not shown.
71
src/xf/port/stm32cube-cmsis-freertos/eventqueue.cpp
Normal file
71
src/xf/port/stm32cube-cmsis-freertos/eventqueue.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_EVENT_QUEUE_IMPLEMENTATION != 0)
|
||||
|
||||
#include <cassert>
|
||||
#include <croutine.h>
|
||||
#include "queue.h"
|
||||
#include "eventqueue.h"
|
||||
|
||||
XFEventQueuePort::XFEventQueuePort(const uint32_t queueSize /* = 8 */)
|
||||
{
|
||||
popedEvent = nullptr;
|
||||
|
||||
_queueId = osMessageQueueNew(queueSize, sizeof(XFEvent *), nullptr);
|
||||
assert(_queueId);
|
||||
}
|
||||
|
||||
XFEventQueuePort::~XFEventQueuePort()
|
||||
{
|
||||
osMessageQueueDelete(_queueId);
|
||||
}
|
||||
|
||||
bool XFEventQueuePort::empty() const
|
||||
{
|
||||
return (osMessageQueueGetCount(_queueId) == 0);
|
||||
}
|
||||
|
||||
bool XFEventQueuePort::push(const XFEvent * pEvent, bool fromISR)
|
||||
{
|
||||
if(fromISR){
|
||||
BaseType_t pxHigherPriorityTaskWoken = false;
|
||||
BaseType_t status = xQueueSendFromISR((QueueHandle_t)_queueId, &pEvent, &pxHigherPriorityTaskWoken);
|
||||
return (status == pdPASS);
|
||||
}
|
||||
else{
|
||||
const osStatus status = osMessageQueuePut(_queueId, &pEvent, 0, 100);
|
||||
return (status == osOK);
|
||||
}
|
||||
}
|
||||
|
||||
XFEvent * XFEventQueuePort::front()
|
||||
{
|
||||
assert(!empty());
|
||||
|
||||
if(popedEvent==nullptr)
|
||||
{
|
||||
osStatus_t status = osMessageQueueGet(_queueId, &popedEvent, nullptr, 100);
|
||||
assert(status == osStatus_t::osOK);
|
||||
}
|
||||
return popedEvent;
|
||||
}
|
||||
|
||||
void XFEventQueuePort::pop()
|
||||
{
|
||||
if(popedEvent != nullptr)
|
||||
{
|
||||
popedEvent = nullptr;
|
||||
}
|
||||
else{
|
||||
XFEvent * pEvent;
|
||||
osMessageQueueGet(_queueId, &pEvent, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool XFEventQueuePort::pend()
|
||||
{
|
||||
XFEvent * dummy;
|
||||
return xQueuePeek(reinterpret_cast<QueueHandle_t>(_queueId), &dummy, 0xFFFFFFFFL);
|
||||
}
|
||||
|
||||
#endif // USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_EVENT_QUEUE_IMPLEMENTATION
|
35
src/xf/port/stm32cube-cmsis-freertos/eventqueue.h
Normal file
35
src/xf/port/stm32cube-cmsis-freertos/eventqueue.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef XF_PORT_STM32CUBE_CMSIS_FREERTOS_EVENT_QUEUE_H
|
||||
#define XF_PORT_STM32CUBE_CMSIS_FREERTOS_EVENT_QUEUE_H
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_EVENT_QUEUE_IMPLEMENTATION != 0)
|
||||
|
||||
#include "xf/interface/eventqueue.h"
|
||||
#include "cmsis_os.h"
|
||||
|
||||
class XFEventQueuePort : public interface::XFEventQueue
|
||||
{
|
||||
public:
|
||||
XFEventQueuePort(const uint32_t queueSize = 8);
|
||||
virtual ~XFEventQueuePort();
|
||||
|
||||
// XFEventQueue interface implementation
|
||||
public:
|
||||
virtual bool empty() const;
|
||||
virtual bool push(const XFEvent * pEvent, bool fromISR = false);
|
||||
virtual XFEvent * front();
|
||||
virtual void pop();
|
||||
|
||||
virtual bool pend();
|
||||
|
||||
protected:
|
||||
XFEvent * popedEvent; ///< Contain the last event after a front()
|
||||
|
||||
osMessageQId _queueId; ///< Unique identifier of the queue.
|
||||
};
|
||||
|
||||
#endif // USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_EVENT_QUEUE_IMPLEMENTATION
|
||||
#endif // __cplusplus
|
||||
#endif // XF_PORT_STM32CUBE_CMSIS_FREERTOS_EVENT_QUEUE_H
|
43
src/xf/port/stm32cube-cmsis-freertos/resourcefactory.cpp
Normal file
43
src/xf/port/stm32cube-cmsis-freertos/resourcefactory.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_RESOURCE_FACTORY_IMPLEMENTATION != 0)
|
||||
|
||||
#include "thread-default.h"
|
||||
#include "xf/interface/mutex.h"
|
||||
#include "default/dispatcher-active.h"
|
||||
#include "resourcefactory.h"
|
||||
|
||||
using interface::XFMutex;
|
||||
|
||||
//static
|
||||
interface::XFResourceFactory * interface::XFResourceFactory::getInstance()
|
||||
{
|
||||
static XFResourceFactoryPort theResourceFactory;
|
||||
return &theResourceFactory;
|
||||
}
|
||||
|
||||
interface::XFDispatcher * XFResourceFactoryPort::getDefaultDispatcher()
|
||||
{
|
||||
static XFDispatcherActiveDefault mainDispatcher;
|
||||
return &mainDispatcher;
|
||||
}
|
||||
|
||||
interface::XFDispatcher * XFResourceFactoryPort::createDispatcher()
|
||||
{
|
||||
return new XFDispatcherActiveDefault;
|
||||
}
|
||||
|
||||
interface::XFThread * XFResourceFactoryPort::createThread(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize /* = 0 */)
|
||||
{
|
||||
return new XFThreadDefault(pProvider, entryMethod, threadName, stackSize);
|
||||
}
|
||||
|
||||
interface::XFMutex * XFResourceFactoryPort::createMutex()
|
||||
{
|
||||
return XFMutex::create();
|
||||
}
|
||||
|
||||
#endif // USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_RESOURCE_FACTORY_IMPLEMENTATION
|
28
src/xf/port/stm32cube-cmsis-freertos/resourcefactory.h
Normal file
28
src/xf/port/stm32cube-cmsis-freertos/resourcefactory.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef XF_PORT_STM32CUBE_CMSIS_FREERTOS_RESOURCE_FACTORY_H
|
||||
#define XF_PORT_STM32CUBE_CMSIS_FREERTOS_RESOURCE_FACTORY_H
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_RESOURCE_FACTORY_IMPLEMENTATION != 0)
|
||||
|
||||
#include <stdint.h>
|
||||
#include "xf/interface/resourcefactory.h"
|
||||
#include "xf/interface/dispatcher.h"
|
||||
|
||||
class XFResourceFactoryPort : public interface::XFResourceFactory
|
||||
{
|
||||
public:
|
||||
XFResourceFactoryPort() {}
|
||||
virtual interface::XFDispatcher * getDefaultDispatcher();
|
||||
virtual interface::XFDispatcher * createDispatcher();
|
||||
virtual interface::XFThread * createThread(interface::XFThreadEntryPointProvider * pProvider,
|
||||
interface::XFThread::EntryMethodBody entryMethod,
|
||||
const char * threadName,
|
||||
const uint32_t stackSize = 0);
|
||||
virtual interface::XFMutex * createMutex();
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif // USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_RESOURCE_FACTORY_IMPLEMENTATION
|
||||
#endif // XF_PORT_STM32CUBE_CMSIS_FREERTOS_RESOURCE_FACTORY_H
|
244
src/xf/port/stm32cube-cmsis-freertos/timeoutmanager.cpp
Normal file
244
src/xf/port/stm32cube-cmsis-freertos/timeoutmanager.cpp
Normal file
@ -0,0 +1,244 @@
|
||||
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_TIMEOUTMANAGER_IMPLEMENTATION != 0)
|
||||
|
||||
#include <cassert>
|
||||
#include "xf/interface/reactive.h"
|
||||
#include "timeoutmanager.h"
|
||||
|
||||
interface::XFTimeoutManager * interface::XFTimeoutManager::getInstance()
|
||||
{
|
||||
return XFTimeoutManagerPort::getInstance();
|
||||
}
|
||||
|
||||
interface::XFTimeoutManager * XFTimeoutManagerPort::getInstance()
|
||||
{
|
||||
static XFTimeoutManagerPort timeoutManager;
|
||||
return &timeoutManager;
|
||||
}
|
||||
|
||||
XFTimeoutManagerPort::XFTimeoutManagerPort() :
|
||||
_osTimerId(0)
|
||||
{
|
||||
_osTimerFunc = &XFTimeoutManagerPort::timerCallback;
|
||||
_osTimerAttr.name="TimeoutManager";
|
||||
_osTimerAttr.attr_bits=0;
|
||||
_osTimerAttr.cb_mem=0;
|
||||
_osTimerAttr.cb_size=0;
|
||||
|
||||
_osTimerId = osTimerNew(_osTimerFunc, osTimerPeriodic, this, &_osTimerAttr);
|
||||
assert(_osTimerId); // You may need to enable timers in the FreeRTOS section of the STM32CubeMX project (USE_TIMERS = Enabled)
|
||||
}
|
||||
|
||||
XFTimeoutManagerPort::~XFTimeoutManagerPort()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets called every #_tickInterval interval.
|
||||
*/
|
||||
//static
|
||||
void XFTimeoutManagerPort::timerCallback(void * argument)
|
||||
{
|
||||
XFTimeoutManagerPort * const pThis = reinterpret_cast<XFTimeoutManagerPort * const>(argument);
|
||||
|
||||
pThis->tick(); // Call method handling timeouts
|
||||
}
|
||||
|
||||
void XFTimeoutManagerPort::start()
|
||||
{
|
||||
// Check tickInterval. Set default value if not set
|
||||
if (tickInterval_ == 0)
|
||||
{
|
||||
tickInterval_ = 10;
|
||||
}
|
||||
|
||||
assert(_osTimerId); // Check existence of timer
|
||||
osTimerStart(_osTimerId, tickInterval_); // Start OS timer
|
||||
}
|
||||
|
||||
void XFTimeoutManagerPort::scheduleTimeout(int32_t timeoutId, int32_t interval, interface::XFReactive * pReactive)
|
||||
{
|
||||
XFTimeout * pTimeout = new XFTimeout(timeoutId, interval, pReactive);
|
||||
|
||||
if (pTimeout)
|
||||
{
|
||||
addTimeout(pTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
void XFTimeoutManagerPort::unscheduleTimeout(int32_t timeoutId, interface::XFReactive * pReactive)
|
||||
{
|
||||
removeTimeouts(timeoutId, pReactive);
|
||||
}
|
||||
|
||||
void XFTimeoutManagerPort::tick()
|
||||
{
|
||||
int32_t intervalToSubtract = tickInterval_;
|
||||
|
||||
while (!_timeouts.empty())
|
||||
{
|
||||
_mutex.lock();
|
||||
{
|
||||
XFTimeout * pFirstTimeout = _timeouts.front();
|
||||
|
||||
// Subtract time elapsed
|
||||
pFirstTimeout->substractFromRelTicks(intervalToSubtract);
|
||||
|
||||
// From now on set it to zero.
|
||||
intervalToSubtract = 0;
|
||||
|
||||
// Check timeout timed out
|
||||
if (pFirstTimeout->getRelTicks() <= 0)
|
||||
{
|
||||
// Check remaining ticks can be given further
|
||||
if (_timeouts.size() > 1)
|
||||
{
|
||||
TimeoutList::iterator i = _timeouts.begin();
|
||||
|
||||
// Add ticks overrun to next timeout
|
||||
i++;
|
||||
(*i)->substractFromRelTicks(abs(pFirstTimeout->getRelTicks()));
|
||||
}
|
||||
|
||||
// Inject the timeout back to the behavioral class
|
||||
returnTimeout(pFirstTimeout);
|
||||
|
||||
// Remove timeout
|
||||
_timeouts.pop_front();
|
||||
|
||||
// Check if timeouts with same timeout value are present
|
||||
for (TimeoutList::iterator it = _timeouts.begin(); it != _timeouts.end(); /*Do not increment here!*/)
|
||||
{
|
||||
if ((*it)->getRelTicks() == 0)
|
||||
{
|
||||
returnTimeout(*it); // Return them true
|
||||
it = _timeouts.erase(it); // Remove timeout and adjust iterator to next element
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_mutex.unlock();
|
||||
// Done. Exit while loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void XFTimeoutManagerPort::addTimeout(XFTimeout * pNewTimeout)
|
||||
{
|
||||
_mutex.lock();
|
||||
{
|
||||
if (!_timeouts.empty())
|
||||
{
|
||||
// Insert timeout before timeout(s) triggering later
|
||||
TimeoutList::iterator i = _timeouts.begin();
|
||||
|
||||
unsigned int index = 0;
|
||||
|
||||
// Find the right place to insert new timeout
|
||||
while (i != _timeouts.end() &&
|
||||
(*i)->getRelTicks() < pNewTimeout->getRelTicks())
|
||||
{ // -> by: test4, test5
|
||||
pNewTimeout->substractFromRelTicks((*i)->getRelTicks());
|
||||
i++; index++;
|
||||
}
|
||||
|
||||
if (i != _timeouts.end())
|
||||
{
|
||||
if ((*i)->getRelTicks() != pNewTimeout->getRelTicks())
|
||||
{ // -> by: test1, test4, test5
|
||||
// Timeout are going to timeout at different times
|
||||
|
||||
// Insert new timeout before
|
||||
_timeouts.insert(i, pNewTimeout);
|
||||
|
||||
// Remove time from following timeout
|
||||
(*i)->substractFromRelTicks(pNewTimeout->getRelTicks());
|
||||
|
||||
}
|
||||
else
|
||||
{ // -> by: test1, test5
|
||||
const int32_t relTicks = (*i)->getRelTicks();
|
||||
// Timeouts timeout at the same time. Put
|
||||
// the new one behind the actual.
|
||||
i++;
|
||||
|
||||
// Check if even more timeouts with the same timeout
|
||||
while(i != _timeouts.end() && (*i)->getRelTicks() == 0)
|
||||
{ // -> by: test5
|
||||
i++;
|
||||
}
|
||||
|
||||
// Insert new timeout behind actual
|
||||
_timeouts.insert(i, pNewTimeout);
|
||||
// Remove time from actual timeout
|
||||
pNewTimeout->substractFromRelTicks(relTicks);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // -> by: test4, test5
|
||||
// Add timeout at the end of the list
|
||||
_timeouts.insert(_timeouts.end(), pNewTimeout);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // -> by: test1, test2, test3, test4, test5
|
||||
_timeouts.push_front(pNewTimeout);
|
||||
}
|
||||
}
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
void XFTimeoutManagerPort::removeTimeouts(int32_t timeoutId, interface::XFReactive * pReactive)
|
||||
{
|
||||
const XFTimeout timeout(timeoutId, 0, pReactive);
|
||||
XFTimeout * pTimeout;
|
||||
|
||||
_mutex.lock();
|
||||
{
|
||||
for (TimeoutList::iterator i = _timeouts.begin();
|
||||
i != _timeouts.end(); /*Do not increment here!*/)
|
||||
{
|
||||
pTimeout = *i;
|
||||
|
||||
// Check if behavior and timeout id are equal
|
||||
if (*pTimeout == timeout)
|
||||
{
|
||||
TimeoutList::iterator next = i;
|
||||
|
||||
// Check if remaining ticks can be given further
|
||||
if (++next != _timeouts.end())
|
||||
{
|
||||
// Add (remaining) ticks to next timeout in list
|
||||
(*next)->addToRelTicks(pTimeout->getRelTicks());
|
||||
}
|
||||
|
||||
i = _timeouts.erase(i);
|
||||
// Iterator now points to the next element
|
||||
|
||||
delete pTimeout;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
void XFTimeoutManagerPort::returnTimeout(XFTimeout * pTimeout)
|
||||
{
|
||||
pTimeout->getBehavior()->pushEvent(pTimeout);
|
||||
}
|
||||
|
||||
#endif // USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_TIMEOUTMANAGER_IMPLEMENTATION
|
60
src/xf/port/stm32cube-cmsis-freertos/timeoutmanager.h
Normal file
60
src/xf/port/stm32cube-cmsis-freertos/timeoutmanager.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef XF_PORT_STM32CUBE_CMSIS_FREERTOS_TIMEOUTMANAGER_H
|
||||
#define XF_PORT_STM32CUBE_CMSIS_FREERTOS_TIMEOUTMANAGER_H
|
||||
|
||||
#include <list>
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_TIMEOUTMANAGER_IMPLEMENTATION != 0)
|
||||
|
||||
#include <cmsis_os.h>
|
||||
#include "xf/interface/timeoutmanager.h"
|
||||
#include "xf/timeout.h"
|
||||
#include "mutex-default.h"
|
||||
|
||||
/**
|
||||
* Default implementation of the XF TimeoutManager
|
||||
*/
|
||||
class XFTimeoutManagerPort : public interface::XFTimeoutManager
|
||||
{
|
||||
friend interface::XFTimeoutManager * interface::XFTimeoutManager::getInstance();
|
||||
public:
|
||||
virtual ~XFTimeoutManagerPort();
|
||||
|
||||
static interface::XFTimeoutManager * getInstance();
|
||||
|
||||
virtual void start();
|
||||
virtual void scheduleTimeout(int32_t timeoutId, int32_t interval, interface::XFReactive * pReactive);
|
||||
virtual void unscheduleTimeout(int32_t timeoutId, interface::XFReactive * pReactive);
|
||||
virtual void tick();
|
||||
|
||||
protected:
|
||||
XFTimeoutManagerPort();
|
||||
virtual void addTimeout(XFTimeout * pNewTimeout); ///< Adds the timeout to #_timeouts.
|
||||
|
||||
/**
|
||||
* Removes all timeouts corresponding the given parameters.
|
||||
*/
|
||||
virtual void removeTimeouts(int32_t timeoutId, interface::XFReactive * pReactive);
|
||||
|
||||
/**
|
||||
* Returns the timeout back to the queue of the thread executing
|
||||
* the behavioral instance.
|
||||
*/
|
||||
void returnTimeout(XFTimeout * pTimeout); ///< Returns timeout back to behavioral class.
|
||||
|
||||
static void timerCallback(void * argument); ///< Callback "function" needed by OS timer.
|
||||
|
||||
protected:
|
||||
typedef std::list<XFTimeout *> TimeoutList; ///< Type used for the _timeouts property.
|
||||
|
||||
TimeoutList _timeouts; ///< Container holding timeouts to manage.
|
||||
|
||||
osTimerAttr_t _osTimerAttr; ///< Timer definition
|
||||
osTimerFunc_t _osTimerFunc; ///< Variable containing the callback to tick()
|
||||
osTimerId _osTimerId; ///< OS timer used to handle timeouts.
|
||||
|
||||
XFMutexDefault _mutex; ///< Mutex to protect the timeout list.
|
||||
};
|
||||
|
||||
#endif // USE_XF_PORT_STM32CUBE_CMSIS_FREERTOS_TIMEOUTMANAGER_IMPLEMENTATION
|
||||
#endif // XF_PORT_STM32CUBE_CMSIS_FREERTOS_TIMEOUTMANAGER_H
|
72
src/xf/port/stm32cube-cmsis-freertos/xf.cpp
Normal file
72
src/xf/port/stm32cube-cmsis-freertos/xf.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
#include <config/xf-config.h>
|
||||
|
||||
#if (PORT_STM32CUBE_CMSIS_FREERTOS != 0)
|
||||
|
||||
#include <cassert>
|
||||
#include <cmsis_os.h>
|
||||
|
||||
#include "xf/interface/timeoutmanager.h"
|
||||
#include "xf/interface/resourcefactory.h"
|
||||
#include "xf/interface/dispatcher.h"
|
||||
#include "xf/xf.h"
|
||||
|
||||
using interface::XFTimeoutManager;
|
||||
using interface::XFResourceFactory;
|
||||
|
||||
bool XF::isInitialized_ = false;
|
||||
|
||||
void XF_initialize(int timeInterval)
|
||||
{
|
||||
XF::initialize(timeInterval);
|
||||
}
|
||||
|
||||
void XF_exec()
|
||||
{
|
||||
XF::exec();
|
||||
}
|
||||
|
||||
void XF_execOnce()
|
||||
{
|
||||
XF::execOnce();
|
||||
}
|
||||
|
||||
void XF::initialize(int timeInterval /* = 10 */, int argc /* = 0 */, char * argv[] /* = nullptr */)
|
||||
{
|
||||
if (!isInitialized_)
|
||||
{
|
||||
//osKernelInitialize();
|
||||
|
||||
// Create and initialize TimeoutManager
|
||||
XFTimeoutManager::getInstance()->initialize(timeInterval);
|
||||
|
||||
isInitialized_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
int XF::exec()
|
||||
{
|
||||
// Start timeout manager
|
||||
XFTimeoutManager::getInstance()->start();
|
||||
|
||||
// Start default dispatcher
|
||||
XFResourceFactory::getInstance()->getDefaultDispatcher()->start();
|
||||
|
||||
// Start RTOS if it is not already running.
|
||||
// With STM32CubeMX, FreeRTOS and uGFX
|
||||
// OS may already run at this stage!
|
||||
|
||||
if (osKernelGetState()!=osKernelRunning)
|
||||
{
|
||||
osKernelStart();
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XF::execOnce()
|
||||
{
|
||||
assert(false); // Should not be called within the FreeRTOS based port! Call XF_exec() instead!
|
||||
}
|
||||
|
||||
#endif // PORT_STM32CUBE_CMSIS_FREERTOS
|
Reference in New Issue
Block a user