qpcpp/include/qk.hpp

230 lines
8.2 KiB
C++
Raw Normal View History

2015-05-14 16:05:04 -04:00
/// @file
/// @brief QK/C++ platform-independent public interface.
/// @ingroup qk
/// @cond
2014-04-13 21:35:34 -04:00
///***************************************************************************
2020-03-17 21:33:58 -04:00
/// Last updated for version 6.8.0
/// Last updated on 2020-01-13
2014-04-13 21:35:34 -04:00
///
2019-10-27 12:26:31 -04:00
/// Q u a n t u m L e a P s
/// ------------------------
/// Modern Embedded Software
2014-04-13 21:35:34 -04:00
///
2020-03-17 21:33:58 -04:00
/// Copyright (C) 2005-2020 Quantum Leaps. All rights reserved.
2014-04-13 21:35:34 -04:00
///
/// This program is open source software: you can redistribute it and/or
/// modify it under the terms of the GNU General Public License as published
/// by the Free Software Foundation, either version 3 of the License, or
/// (at your option) any later version.
2012-08-14 18:00:48 -04:00
///
2014-04-13 21:35:34 -04:00
/// Alternatively, this program may be distributed and modified under the
/// terms of Quantum Leaps commercial licenses, which expressly supersede
/// the GNU General Public License and are specifically designed for
/// licensees interested in retaining the proprietary status of their code.
///
/// This program is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/// GNU General Public License for more details.
///
/// You should have received a copy of the GNU General Public License
2019-10-27 12:26:31 -04:00
/// along with this program. If not, see <www.gnu.org/licenses>.
2014-04-13 21:35:34 -04:00
///
/// Contact information:
2019-12-31 15:56:23 -05:00
/// <www.state-machine.com/licensing>
2019-10-27 12:26:31 -04:00
/// <info@state-machine.com>
2014-04-13 21:35:34 -04:00
///***************************************************************************
2015-05-14 16:05:04 -04:00
/// @endcond
2014-04-13 21:35:34 -04:00
2019-10-27 12:26:31 -04:00
#ifndef QK_HPP
#define QK_HPP
2012-08-14 18:00:48 -04:00
2019-10-27 12:26:31 -04:00
#include "qequeue.hpp" // QK kernel uses the native QF event queue
#include "qmpool.hpp" // QK kernel uses the native QF memory pool
#include "qpset.hpp" // QK kernel uses the native QF priority set
2012-08-14 18:00:48 -04:00
2013-10-10 20:01:51 -04:00
//****************************************************************************
2018-02-18 12:08:21 -05:00
// QF configuration for QK -- data members of the QActive class...
2012-08-14 18:00:48 -04:00
2018-02-18 12:08:21 -05:00
//! Kernel-dependent type of the event queue used for QK threads
//
2016-09-01 11:58:57 -04:00
/// @description
2018-02-18 12:08:21 -05:00
/// QK uses the native QF event queue QEQueue.
#define QF_EQUEUE_TYPE QEQueue
//! Kernel-dependent type of the thread attribute
//
/// @description
/// QK uses this member to store the private Thread-Local Storage pointer.
///
#define QF_THREAD_TYPE void*
2015-12-31 14:56:37 -05:00
2016-09-01 11:58:57 -04:00
//****************************************************************************
2018-02-18 12:08:21 -05:00
namespace QP {
class QActive; // forward declaration
} // namespace QP
2016-09-01 11:58:57 -04:00
//! attributes of the QK kernel (in C for easy access in assembly)
extern "C" {
struct QK_Attr {
2020-03-17 21:33:58 -04:00
std::uint8_t volatile actPrio; //!< prio of the active AO
std::uint8_t volatile nextPrio; //!< prio of the next AO to execute
std::uint8_t volatile lockPrio; //!< lock prio (0 == no-lock)
std::uint8_t volatile lockHolder; //!< prio of the lock holder
std::uint8_t volatile intNest; //!< ISR nesting level
QP::QPSet readySet; //!< QK ready-set of AOs and "naked" threads
2016-09-01 11:58:57 -04:00
};
//! global attributes of the QK kernel
extern QK_Attr QK_attr_;
2016-09-29 19:54:50 -04:00
//! QK scheduler finds the highest-priority thread ready to run
2020-03-17 21:33:58 -04:00
std::uint_fast8_t QK_sched_(void) noexcept;
2016-09-01 11:58:57 -04:00
2016-09-29 19:54:50 -04:00
//! QK activator activates the next active object. The activated AO preempts
// the currently executing AOs.
2020-03-17 21:33:58 -04:00
void QK_activate_(void) noexcept;
2016-09-01 11:58:57 -04:00
2018-02-18 12:08:21 -05:00
#ifdef QK_ON_CONTEXT_SW
//! QK context switch callback (customized in BSPs for QK)
///
/// @description
/// This callback function provides a mechanism to perform additional
/// custom operations when QK switches context from one thread to
/// another.
///
/// @param[in] prev pointer to the previous thread (active object)
/// (prev==0 means that @p prev was the QK idle loop)
/// @param[in] next pointer to the next thread (active object)
/// (next==0) means that @p next is the QK idle loop)
/// @attention
/// QK_onContextSw() is invoked with interrupts **disabled** and must also
/// return with interrupts **disabled**.
///
/// @note
/// This callback is enabled by defining the macro #QK_ON_CONTEXT_SW.
///
/// @include qk_oncontextsw.cpp
///
void QK_onContextSw(QP::QActive *prev, QP::QActive *next);
#endif // QK_ON_CONTEXT_SW
2016-09-01 11:58:57 -04:00
} // extern "C"
2015-12-31 14:56:37 -05:00
2012-08-14 18:00:48 -04:00
2013-10-10 20:01:51 -04:00
//****************************************************************************
namespace QP {
2012-08-14 18:00:48 -04:00
2017-08-21 18:21:15 -04:00
//! The scheduler lock status
2020-03-17 21:33:58 -04:00
using QSchedStatus = std::uint_fast16_t;
2017-08-21 18:21:15 -04:00
2013-10-10 20:01:51 -04:00
//****************************************************************************
2014-04-13 21:35:34 -04:00
//! QK services.
2015-05-14 16:05:04 -04:00
/// @description
2012-08-14 18:00:48 -04:00
/// This class groups together QK services. It has only static members and
/// should not be instantiated.
///
2017-08-21 18:21:15 -04:00
/// @note
/// The QK scheduler, QK priority, QK ready set, etc. belong conceptually
/// to the QK class (as static class members). However, to avoid potential
/// C++ name-mangling problems in assembly language, these elements are
/// defined outside of the QK class and use the extern "C" linkage.
2012-08-14 18:00:48 -04:00
class QK {
public:
2017-08-21 18:21:15 -04:00
// QK scheduler locking...
//! QK selective scheduler lock
2020-03-17 21:33:58 -04:00
static QSchedStatus schedLock(std::uint_fast8_t const ceiling) noexcept;
2012-08-14 18:00:48 -04:00
2017-08-21 18:21:15 -04:00
//! QK selective scheduler unlock
2020-03-17 21:33:58 -04:00
static void schedUnlock(QSchedStatus const stat) noexcept;
2012-08-14 18:00:48 -04:00
2014-04-13 21:35:34 -04:00
//! QK idle callback (customized in BSPs for QK)
2015-05-14 16:05:04 -04:00
/// @description
2014-04-13 21:35:34 -04:00
/// QP::QK::onIdle() is called continously by the QK idle loop. This
/// callback gives the application an opportunity to enter a power-saving
/// CPU mode, or perform some other idle processing.
2012-08-14 18:00:48 -04:00
///
2018-02-18 12:08:21 -05:00
/// @note
/// QP::QK::onIdle() is invoked with interrupts enabled and must
2014-04-13 21:35:34 -04:00
/// also return with interrupts enabled.
2012-08-14 18:00:48 -04:00
///
2015-05-14 16:05:04 -04:00
/// @sa QP::QF::onIdle()
2012-08-14 18:00:48 -04:00
static void onIdle(void);
2017-08-21 18:21:15 -04:00
//! get the current QK version number string of the form X.Y.Z
2020-03-17 21:33:58 -04:00
static char_t const *getVersion(void) noexcept {
2017-08-21 18:21:15 -04:00
return versionStr;
}
2012-08-14 18:00:48 -04:00
};
2014-04-13 21:35:34 -04:00
} // namespace QP
2012-08-14 18:00:48 -04:00
2013-10-10 20:01:51 -04:00
//****************************************************************************
// interface used only inside QF, but not in applications
2014-04-13 21:35:34 -04:00
#ifdef QP_IMPL
2016-10-08 12:46:03 -04:00
2015-05-14 16:05:04 -04:00
#ifndef QK_ISR_CONTEXT_
//! Internal port-specific macro that reports the execution context
// (ISR vs. thread).
/// @returns true if the code executes in the ISR context and false
/// otherwise
2020-03-17 21:33:58 -04:00
#define QK_ISR_CONTEXT_() (QK_attr_.intNest != 0U)
2015-05-14 16:05:04 -04:00
#endif // QK_ISR_CONTEXT_
2016-09-29 19:54:50 -04:00
// QK-specific scheduler locking
//! Internal macro to represent the scheduler lock status
2016-04-01 13:55:34 -04:00
// that needs to be preserved to allow nesting of locks.
2016-09-29 19:54:50 -04:00
//
2017-08-21 18:21:15 -04:00
#define QF_SCHED_STAT_ QSchedStatus lockStat_;
2016-04-01 13:55:34 -04:00
2016-09-29 19:54:50 -04:00
//! Internal macro for selective scheduler locking.
2020-03-17 21:33:58 -04:00
#define QF_SCHED_LOCK_(prio_) do { \
if (QK_ISR_CONTEXT_()) { \
lockStat_ = 0xFFU; \
} else { \
2017-08-21 18:21:15 -04:00
lockStat_ = QK::schedLock((prio_)); \
2020-03-17 21:33:58 -04:00
} \
2016-04-01 13:55:34 -04:00
} while (false)
2016-09-29 19:54:50 -04:00
//! Internal macro for selective scheduler unlocking.
2020-03-17 21:33:58 -04:00
#define QF_SCHED_UNLOCK_() do { \
if (lockStat_ != 0xFFU) { \
2017-08-21 18:21:15 -04:00
QK::schedUnlock(lockStat_); \
2020-03-17 21:33:58 -04:00
} \
2016-09-29 19:54:50 -04:00
} while (false)
2016-04-01 13:55:34 -04:00
2016-10-08 12:46:03 -04:00
// QK-specific native event queue operations...
2013-10-10 20:01:51 -04:00
#define QACTIVE_EQUEUE_WAIT_(me_) \
2020-03-17 21:33:58 -04:00
Q_ASSERT_ID(110, (me_)->m_eQueue.m_frontEvt != nullptr)
#define QACTIVE_EQUEUE_SIGNAL_(me_) do { \
QK_attr_.readySet.insert( \
static_cast<std::uint_fast8_t>((me_)->m_prio)); \
if (!QK_ISR_CONTEXT_()) { \
if (QK_sched_() != 0U) { \
QK_activate_(); \
} \
} \
2013-10-10 20:01:51 -04:00
} while (false)
2016-10-08 12:46:03 -04:00
// QK-specific native QF event pool operations...
2013-10-10 20:01:51 -04:00
#define QF_EPOOL_TYPE_ QMPool
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \
2013-12-30 17:41:15 -05:00
(p_).init((poolSto_), (poolSize_), (evtSize_))
2020-03-17 21:33:58 -04:00
#define QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize())
2013-10-10 20:01:51 -04:00
#define QF_EPOOL_GET_(p_, e_, m_) \
((e_) = static_cast<QEvt *>((p_).get((m_))))
2013-12-30 17:41:15 -05:00
#define QF_EPOOL_PUT_(p_, e_) ((p_).put(e_))
2013-10-10 20:01:51 -04:00
2015-05-14 16:05:04 -04:00
#endif // QP_IMPL
2013-10-10 20:01:51 -04:00
2019-10-27 12:26:31 -04:00
#endif // QK_HPP
2018-03-19 14:51:26 -04:00