diff --git a/doxygen/Doxyfile b/doxygen/Doxyfile
index ee1f8d8e..1f124ebe 100644
--- a/doxygen/Doxyfile
+++ b/doxygen/Doxyfile
@@ -5,7 +5,7 @@
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = QP/C++
-PROJECT_NUMBER = 7.1.1
+PROJECT_NUMBER = 7.1.2
PROJECT_BRIEF = "Real-Time Embedded Framework"
PROJECT_LOGO = ../../ql-doxygen/images/logo_ql.png
OUTPUT_DIRECTORY =
diff --git a/doxygen/gs.dox b/doxygen/gs.dox
index 486b9a5c..49ab1e80 100644
--- a/doxygen/gs.dox
+++ b/doxygen/gs.dox
@@ -144,7 +144,7 @@ The DPP example is provided for most supported boards as well as in the command-
The Dining Philosophers Problem (DPP) example is described in the @webref{doc/AN_DPP.pdf, Application Note: Dining Philosophers Problem (DPP) Example}.
-[![Application Note: Dining Philosophers Problem (DPP) Example](AN_DPP.jpg)](https://www.state-machine.com/doc/AN_Fly-n-Shoot.pdf)
+[![Application Note: Dining Philosophers Problem (DPP) Example](AN_DPP.jpg)](https://www.state-machine.com/doc/AN_DPP.pdf)
@note
diff --git a/doxygen/history.dox b/doxygen/history.dox
index 6da2ce2b..e8f01110 100644
--- a/doxygen/history.dox
+++ b/doxygen/history.dox
@@ -1,33 +1,23 @@
/** @page history Revision History
-@section qpcpp_7_1_1 Version 7.1.1, 2022-09-30
-This release improves @ref srs_qs "software tracing" of the scheduler activity in the preemptive @ref srs_qk "QK" and @ref srs_qxk "QXK" kernels.
-
-@note
-The QP framework "knows" the type of preemption (synchronous/asynchronous) and this information is now provided in the software trace to the user.
-
+@section qpcpp_7_1_2 Version 7.1.2, 2022-10-07
+This release improves preemption-threshold scheduling (PTS) in @ref srs_qk "QK" kernel, especially the generation of the software tracing information about the scheduler activity. Also, PTS has been removed from the @ref srs_qxk "QXK" kernel because of the inherent complexity of that kernel.
Additionally, the default for #QF_TIMEEVT_CTR_SIZE has been increased from 2 to 4 bytes. This increases the default dynamic range for QTimeEvt counters to 32-bits.
__Source__
-- Added new pre-defined QS trace records:
- + QP::QS_SCHED_PREEMPT - for reporting *asynchronous* preemption
- + QP::QS_SCHED_RESTORE - for reporting restoring the context
- after an *asynchronous* preemption
-- Added parameter `asynch` to QK_activate_(). This parameter is used to indicate the type of preemption and is set to 1 for asynchronous preemption and 0 for synchronous. This parameter is used in the #Q_SPY configuration only.
-- changed all calls to QK_activate_() to add the `asynch` parameter, whereas all cases of synchronous preemption call QK_activate_(0U), while cases for asynchronous preemption call QK_activate_(1U);
-- Added parameter `asynch` to QXK_activate_(). This parameter indicates the asynchronous preemption. This parameter is used in the #Q_SPY configuration only.
-- Added parameter `asynch` to QXK_sched_(). This parameter is used to indicate the type of preemption and is set to 1 for asynchronous preemption and 0 for synchronous. This parameter is used in the #Q_SPY configuration only.
-- changed all calls to QXK_sched_() and QXK_activate_() to add the `asynch` parameter, whereas all cases of synchronous preemption call QXK_sched_(0U)/XK_activate_(0U), while cases for asynchronous preemption call QXK_sched_(1U)/XK_activate_(1U);
+- Modified QK_sched_() and QK_activate_()
+- Modified QXK_sched_() and QXK_activate_()
+- Added QXK_contextSw() to handle context switching (generation of software tracing information and invoking of the QXK_onContextSw() callback, if configured
- increased default for #QF_TIMEEVT_CTR_SIZE 4
- changed inclusion guards in the QP/C++ header files (e.g. `QF_HPP` -> `QP_INC_QF_HPP_`) for compliance with the updated Quantum Leaps coding standard and to make the names more unique.
__Ports__
-- All QK ports have been updated to set the `asynch` parameter for calling QK_activate_()
-- All QXK ports have been updated to set the `asynch` parameter for calling QXK_sched_()/XK_activate_()
+- Modified QXK ports (assembly) to call QXK_contextSw()
+- Added port to RISC-V with the cooperative @ref srs_qvk "QV" kernel
__Testing__
-- Added new directory `qpcpp/test/` for **system**-level testing QP/C++ itself.
+- Added new directory `qpcpp/test/` for **system**-level testing of QP/C itself.
- Added new tests for QK: `qpcpp/test/qk`
- Added new tests for QXK: `qpcpp/test/qutest/qxk`
@@ -35,7 +25,7 @@ __Testing__
The `qpcpp/test/` directory is planned to contain a growing number of system-level tests, which are based on QUTest, but *without* the QP-stub. The tests take advantage of the new QUTest configuration, where the QP-stub is NOT included (because the actual QP framework is linked). This configuration is activated by defining macro `Q_UTEST=0`.
@attention
-Many tests provided in the `qpcpp/test/` directory run only on embedded targets and cannot run on the host machine.
+Most tests provided in the `qpcpp/test/` directory run only on embedded targets and cannot run on the host machine.
@section qpcpp_7_1_0 Version 7.1.0, 2022-08-30
diff --git a/doxygen/metrics.dox b/doxygen/metrics.dox
index fc62d98f..208b6bfe 100644
--- a/doxygen/metrics.dox
+++ b/doxygen/metrics.dox
@@ -66,8 +66,8 @@
14 3 70 1 14 QP::QS::rxPut@805-818@..\include\qs.hpp
9 1 49 5 9 QP::QActiveDummy::start@1517-1525@..\include\qs.hpp
3 1 18 0 3 QP::QSpyId::getPrio@134-136@..\include\qs_dummy.hpp
- 3 1 11 0 3 QP::QXThread::getTimeEvt@210-212@..\include\qxk.hpp
- 9 1 49 5 9 QP::QXThread::start@312-320@..\include\qxk.hpp
+ 3 1 11 0 3 QP::QXThread::getTimeEvt@208-210@..\include\qxk.hpp
+ 9 1 49 5 9 QP::QXThread::start@310-318@..\include\qxk.hpp
2 1 15 2 3 QP::QEvt@101-103@..\src\qf\qep_hsm.cpp
4 1 27 1 4 QP::QHsm::QHsm@130-133@..\src\qf\qep_hsm.cpp
50 7 303 2 71 QP::QHsm::init@136-206@..\src\qf\qep_hsm.cpp
@@ -200,7 +200,7 @@ NLOC Avg.NLOC AvgCCN Avg.token function_cnt file
25 0.0 0.0 0.0 0 ..\include\qs_pkg.hpp
9 0.0 0.0 0.0 0 ..\include\quit.hpp
8 0.0 0.0 0.0 0 ..\include\qv.hpp
- 122 6.0 1.0 30.0 2 ..\include\qxk.hpp
+ 120 6.0 1.0 30.0 2 ..\include\qxk.hpp
323 37.5 5.9 199.0 8 ..\src\qf\qep_hsm.cpp
307 41.4 7.1 228.1 7 ..\src\qf\qep_msm.cpp
2 0.0 0.0 0.0 0 ..\src\qf\qf_act.cpp
@@ -231,6 +231,6 @@ NLOC Avg.NLOC AvgCCN Avg.token function_cnt file
==========================================================================================
Total nloc Avg.NLOC AvgCCN Avg.token Fun Cnt Warning cnt Fun Rt nloc Rt
------------------------------------------------------------------------------------------
- 4523 18.2 3.2 108.0 176 3 0.02 0.09
+ 4521 18.2 3.2 108.0 176 3 0.02 0.09
@endcode
*/
diff --git a/doxygen/snippets/qf_main.cpp b/doxygen/snippets/qf_main.cpp
index 7b254105..2b3dfd86 100644
--- a/doxygen/snippets/qf_main.cpp
+++ b/doxygen/snippets/qf_main.cpp
@@ -1,6 +1,6 @@
-#include "qpc.h"
-#include "dpp.h"
-#include "bsp.h"
+#include "qpcpp.hpp"
+#include "dpp.hpp"
+#include "bsp.hpp"
namespace DPP {
@@ -12,14 +12,13 @@ int_t main(void) {
// object dictionaries...
QS_OBJ_DICTIONARY(AO_Table);
- QS_OBJ_DICTIONARY(AO_Philo[0]);
- QS_OBJ_DICTIONARY(AO_Philo[1]);
- QS_OBJ_DICTIONARY(AO_Philo[2]);
- QS_OBJ_DICTIONARY(AO_Philo[3]);
- QS_OBJ_DICTIONARY(AO_Philo[4]);
+ for (std::uint8_t n = 0U; n < N_PHILO; ++n) {
+ QS_OBJ_ARR_DICTIONARY(AO_Philo[n], n);
+ }
+ // initialize publish-subscribe...
static QP::QSubscrList subscrSto[MAX_PUB_SIG];
- QP::QActive::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe
+ QP::QActive::psInit(subscrSto, Q_DIM(subscrSto));
// initialize event pools...
static QF_MPOOL_EL(TableEvt) smlPoolSto[2*N_PHILO];
@@ -29,15 +28,21 @@ int_t main(void) {
// start the active objects...
static QP::QEvt const *philoQueueSto[N_PHILO][N_PHILO];
for (std::uint8_t n = 0U; n < N_PHILO; ++n) {
- AO_Philo[n]->start(n + 1U,
- philoQueueSto[n], Q_DIM(philoQueueSto[n]),
- nullptr, 0U);
+ AO_Philo[n]->start(
+ Q_PRIO(n + 1U, N_PHILO), // QF-priority/preemption-threshold
+ philoQueueSto[n], // event queue storage
+ Q_DIM(philoQueueSto[n]), // event queue length [events]
+ nullptr, // stack storage (not used)
+ 0U); // stack size [bytes] (not used)
}
static QP::QEvt const *tableQueueSto[N_PHILO];
- AO_Table->start(N_PHILO + 1U,
- tableQueueSto, Q_DIM(tableQueueSto),
- nullptr, 0U);
+ AO_Table->start(
+ N_PHILO + 1U,
+ tableQueueSto,
+ Q_DIM(tableQueueSto),
+ nullptr,
+ 0U);
return QP::QF::run(); // run the QF application
}
diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qk/main.cpp b/examples/arm-cm/dpp_efm32-slstk3401a/qk/main.cpp
index 847ce07d..d49507cc 100644
--- a/examples/arm-cm/dpp_efm32-slstk3401a/qk/main.cpp
+++ b/examples/arm-cm/dpp_efm32-slstk3401a/qk/main.cpp
@@ -1,11 +1,11 @@
//============================================================================
// DPP example
-// Last updated for version 7.1.1
-// Last updated on 2022-09-23
+// Last updated for version 7.1.2
+// Last updated on 2022-10-05
//
-// Q u a n t u m L e a P s
-// ---------------------------
-// innovating embedded systems
+// Q u a n t u m L e a P s
+// ------------------------
+// Modern Embedded Software
//
// Copyright (C) Quantum Leaps, LLC. All rights reserved.
//
@@ -65,11 +65,11 @@ int main() {
}
// example of prioritizing the Ticker0 active object
- DPP::the_Ticker0->start(Q_PRIO(N_PHILO + 1U, 2U), // priority
+ DPP::the_Ticker0->start(N_PHILO + 1U, // priority
0, 0, 0, 0);
DPP::AO_Table->start(
- (N_PHILO + 2U, // QF-prio/preempt-thre.
+ N_PHILO + 2U, // QF-prio/preempt-thre.
tableQueueSto, // event queue storage
Q_DIM(tableQueueSto), // queue length [events]
nullptr, 0U); // no stack storage
diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/armclang/dpp-qxk.uvoptx b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/armclang/dpp-qxk.uvoptx
index 19d27a72..b9783b64 100644
--- a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/armclang/dpp-qxk.uvoptx
+++ b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/armclang/dpp-qxk.uvoptx
@@ -152,9 +152,9 @@
0
0
- 355
+ 362
1
- 2142
+ 2144
0
0
0
@@ -163,39 +163,23 @@
1
..\bsp.cpp
- \\dpp_qxk\../bsp.cpp\355
+ \\dpp_qxk\../bsp.cpp\362
1
0
- 292
+ 355
1
- 7064
+ 0
0
0
0
0
0
- 1
- ..\..\..\..\..\src\qf\qf_time.cpp
+ 0
+ ..\bsp.cpp
- \\dpp_qxk\../../../../../src/qf/qf_time.cpp\292
-
-
- 2
- 0
- 112
- 1
- 6920
- 0
- 0
- 0
- 0
- 0
- 1
- ..\..\..\..\..\src\qf\qf_time.cpp
-
- \\dpp_qxk\../../../../../src/qf/qf_time.cpp\112
+
@@ -753,7 +737,7 @@
QP
- 0
+ 1
0
0
0
diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/main.cpp b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/main.cpp
index 0900f0d0..6a466168 100644
--- a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/main.cpp
+++ b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/main.cpp
@@ -1,7 +1,7 @@
//============================================================================
// DPP example for QXK
-// Last updated for version 7.1.1
-// Last updated on 2022-09-23
+// Last updated for version 7.1.2
+// Last updated on 2022-10-05
//
// Q u a n t u m L e a P s
// ---------------------------
@@ -78,7 +78,7 @@ int main() {
// start the Philo active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start(
- Q_PRIO(n + 3U, N_PHILO + 2U), // QF-prio/preempt-thre.
+ n + 3U, // QF-prio/preempt-thre.
philoQueueSto[n], // event queue storage
Q_DIM(philoQueueSto[n]), // queue length [events]
nullptr, 0U); // no stack storage
diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/qk/main.cpp b/examples/arm-cm/dpp_ek-tm4c123gxl/qk/main.cpp
index 9d41617a..dbb72858 100644
--- a/examples/arm-cm/dpp_ek-tm4c123gxl/qk/main.cpp
+++ b/examples/arm-cm/dpp_ek-tm4c123gxl/qk/main.cpp
@@ -1,11 +1,11 @@
//============================================================================
// DPP example
-// Last updated for version 6.3.3
-// Last updated on 2018-06-23
+// Last updated for version 7.1.2
+// Last updated on 2022-10-05
//
-// Q u a n t u m L e a P s
-// ---------------------------
-// innovating embedded systems
+// Q u a n t u m L e a P s
+// ------------------------
+// Modern Embedded Software
//
// Copyright (C) Quantum Leaps, LLC. All rights reserved.
//
@@ -57,17 +57,18 @@ int main() {
// start the active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) {
- DPP::AO_Philo[n]->start((uint_fast8_t)(n + 1U), // priority
- philoQueueSto[n], Q_DIM(philoQueueSto[n]),
- nullptr, 0U);
+ DPP::AO_Philo[n]->start(
+ Q_PRIO(n + 1U, N_PHILO), // QF-prio/preempt-thre.
+ philoQueueSto[n], Q_DIM(philoQueueSto[n]),
+ nullptr, 0U);
}
// example of prioritizing the Ticker0 active object
- DPP::the_Ticker0->start((uint_fast8_t)(N_PHILO + 1U), // priority
+ DPP::the_Ticker0->start(N_PHILO + 1U, // priority
0, 0,
0, 0);
- DPP::AO_Table->start((uint_fast8_t)(N_PHILO + 2U), // priority
+ DPP::AO_Table->start(N_PHILO + 2U, // priority
tableQueueSto, Q_DIM(tableQueueSto),
nullptr, 0U);
diff --git a/examples/arm-cm/dpp_nucleo-h743zi/qk/main.cpp b/examples/arm-cm/dpp_nucleo-h743zi/qk/main.cpp
index 7e551378..5c6c2d99 100644
--- a/examples/arm-cm/dpp_nucleo-h743zi/qk/main.cpp
+++ b/examples/arm-cm/dpp_nucleo-h743zi/qk/main.cpp
@@ -1,13 +1,13 @@
//============================================================================
// DPP example
-// Last updated for: @qpcpp_7_0_0
-// Last updated on 2022-02-28
+// Last updated for version 7.1.2
+// Last updated on 2022-10-05
//
-// Q u a n t u m L e a P s
-// ---------------------------
-// innovating embedded systems
+// Q u a n t u m L e a P s
+// ------------------------
+// Modern Embedded Software
//
-// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
+// Copyright (C) Quantum Leaps, LLC. All rights reserved.
//
// 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
@@ -25,7 +25,7 @@
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
+// along with this program. If not, see .
//
// Contact information:
//
@@ -54,12 +54,15 @@ int main() {
// start the active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) {
- DPP::AO_Philo[n]->start((uint_fast8_t)(n + 1U), // priority
- philoQueueSto[n], Q_DIM(philoQueueSto[n]),
- nullptr, 0U);
+ DPP::AO_Philo[n]->start(
+ Q_PRIO(n + 1U, N_PHILO), // QF-prio/preempt-thre.
+ philoQueueSto[n], // event queue storage
+ Q_DIM(philoQueueSto[n]), // queue length [events]
+ nullptr, 0U); // no stack storage
}
- DPP::AO_Table->start((uint_fast8_t)(N_PHILO + 1U), // priority
+ DPP::AO_Table->start(
+ N_PHILO + 1U, // priority
tableQueueSto, Q_DIM(tableQueueSto),
nullptr, 0U);
diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qk/main.cpp b/examples/arm-cm/dpp_nucleo-l053r8/qk/main.cpp
index ecebcdb3..6091f666 100644
--- a/examples/arm-cm/dpp_nucleo-l053r8/qk/main.cpp
+++ b/examples/arm-cm/dpp_nucleo-l053r8/qk/main.cpp
@@ -1,11 +1,11 @@
//============================================================================
// DPP example
-// Last updated for version 6.3.3
-// Last updated on 2018-06-23
+// Last updated for version 7.1.2
+// Last updated on 2022-10-05
//
-// Q u a n t u m L e a P s
-// ---------------------------
-// innovating embedded systems
+// Q u a n t u m L e a P s
+// ------------------------
+// Modern Embedded Software
//
// Copyright (C) Quantum Leaps, LLC. All rights reserved.
//
@@ -55,14 +55,20 @@ int main() {
// start the active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) {
- DPP::AO_Philo[n]->start((uint8_t)(n + 1U),
- philoQueueSto[n], Q_DIM(philoQueueSto[n]),
- nullptr, 0U);
+ DPP::AO_Philo[n]->start(
+ Q_PRIO(n + 1U, N_PHILO), // QF-prio/preempt-thre.
+ philoQueueSto[n], // event queue storage
+ Q_DIM(philoQueueSto[n]), // queue length [events]
+ nullptr, 0U); // no stack storage
}
+
// leave the priority level (N_PHILO + 1) free for the mutex in BSP
- DPP::AO_Table->start((uint8_t)(N_PHILO + 2U),
- tableQueueSto, Q_DIM(tableQueueSto),
- nullptr, 0U);
+
+ DPP::AO_Table->start(
+ N_PHILO + 2U, // QF-prio/preempt-thre.
+ tableQueueSto, // event queue storage
+ Q_DIM(tableQueueSto), // queue length [events]
+ nullptr, 0U); // no stack storage
return QP::QF::run(); // run the QF application
}
diff --git a/examples/arm-cm/dpp_nucleo-l152re/qk/main.cpp b/examples/arm-cm/dpp_nucleo-l152re/qk/main.cpp
index f19ec8ae..53f76dd0 100644
--- a/examples/arm-cm/dpp_nucleo-l152re/qk/main.cpp
+++ b/examples/arm-cm/dpp_nucleo-l152re/qk/main.cpp
@@ -1,13 +1,13 @@
//============================================================================
// DPP example
-// Last updated for version 6.3.3
-// Last updated on 2018-06-23
+// Last updated for version 7.1.2
+// Last updated on 2022-10-05
//
-// Q u a n t u m L e a P s
-// ---------------------------
-// innovating embedded systems
+// Q u a n t u m L e a P s
+// ------------------------
+// Modern Embedded Software
//
-// Copyright (C) Quantum Leaps, www.state-machine.com.
+// Copyright (C) Quantum Leaps, LLC. All rights reserved.
//
// 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
@@ -56,13 +56,17 @@ int main() {
// start the active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) {
- DPP::AO_Philo[n]->start((uint8_t)(n + 1U),
- philoQueueSto[n], Q_DIM(philoQueueSto[n]),
- nullptr, 0U);
+ DPP::AO_Philo[n]->start(
+ Q_PRIO(n + 1U, N_PHILO), // QF-prio/preempt-thre.
+ philoQueueSto[n], // event queue storage
+ Q_DIM(philoQueueSto[n]), // queue length [events]
+ nullptr, 0U); // no stack storage
}
- DPP::AO_Table->start((uint8_t)(N_PHILO + 1U),
- tableQueueSto, Q_DIM(tableQueueSto),
- nullptr, 0U);
+ DPP::AO_Table->start(
+ N_PHILO + 1U, // QF-prio/preempt-thre.
+ tableQueueSto, // event queue storage
+ Q_DIM(tableQueueSto), // queue length [events]
+ nullptr, 0U); // no stack storage
return QP::QF::run(); // run the QF application
}
diff --git a/examples/arm-cm/dpp_nucleo-l552ze/qk/main.cpp b/examples/arm-cm/dpp_nucleo-l552ze/qk/main.cpp
index 7e551378..bac89e38 100644
--- a/examples/arm-cm/dpp_nucleo-l552ze/qk/main.cpp
+++ b/examples/arm-cm/dpp_nucleo-l552ze/qk/main.cpp
@@ -1,13 +1,13 @@
//============================================================================
// DPP example
-// Last updated for: @qpcpp_7_0_0
-// Last updated on 2022-02-28
+// Last updated for version 7.1.2
+// Last updated on 2022-10-05
//
-// Q u a n t u m L e a P s
-// ---------------------------
-// innovating embedded systems
+// Q u a n t u m L e a P s
+// ------------------------
+// Modern Embedded Software
//
-// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
+// Copyright (C) Quantum Leaps, LLC. All rights reserved.
//
// 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
@@ -25,7 +25,7 @@
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
+// along with this program. If not, see .
//
// Contact information:
//
@@ -54,14 +54,18 @@ int main() {
// start the active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) {
- DPP::AO_Philo[n]->start((uint_fast8_t)(n + 1U), // priority
- philoQueueSto[n], Q_DIM(philoQueueSto[n]),
- nullptr, 0U);
+ DPP::AO_Philo[n]->start(
+ Q_PRIO(n + 1U, N_PHILO), // QF-prio/preempt-thre.
+ philoQueueSto[n], // event queue storage
+ Q_DIM(philoQueueSto[n]), // queue length [events]
+ nullptr, 0U); // no stack storage
}
- DPP::AO_Table->start((uint_fast8_t)(N_PHILO + 1U), // priority
- tableQueueSto, Q_DIM(tableQueueSto),
- nullptr, 0U);
+ DPP::AO_Table->start(
+ N_PHILO + 1U, // QF-prio/preempt-thre.
+ tableQueueSto, // event queue storage
+ Q_DIM(tableQueueSto), // queue length [events]
+ nullptr, 0U); // no stack storage
return QP::QF::run(); // run the QF application
}
diff --git a/examples/arm-cm/dpp_stm32f4-discovery/qk/main.cpp b/examples/arm-cm/dpp_stm32f4-discovery/qk/main.cpp
index 6040d007..327b7342 100644
--- a/examples/arm-cm/dpp_stm32f4-discovery/qk/main.cpp
+++ b/examples/arm-cm/dpp_stm32f4-discovery/qk/main.cpp
@@ -1,11 +1,11 @@
//============================================================================
// DPP example
-// Last updated for version 6.0.4
-// Last updated on 2018-01-07
+// Last updated for version 7.1.2
+// Last updated on 2022-10-05
//
-// Q u a n t u m L e a P s
-// ---------------------------
-// innovating embedded systems
+// Q u a n t u m L e a P s
+// ------------------------
+// Modern Embedded Software
//
// Copyright (C) Quantum Leaps, LLC. All rights reserved.
//
@@ -64,19 +64,24 @@ int main() {
// start the active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) {
- DPP::AO_Philo[n]->start((uint_fast8_t)(n + 1U), // priority
- philoQueueSto[n], Q_DIM(philoQueueSto[n]),
- nullptr, 0U);
+ DPP::AO_Philo[n]->start(
+ Q_PRIO(n + 1U, N_PHILO), // QF-prio/preempt-thre.
+ philoQueueSto[n], // event queue storage
+ Q_DIM(philoQueueSto[n]), // queue length [events]
+ nullptr, 0U); // no stack storage
}
// example of prioritizing the Ticker0 active object
- DPP::the_Ticker0->start((uint_fast8_t)(N_PHILO + 1U), // priority
+ DPP::the_Ticker0->start(
+ N_PHILO + 1U, // priority
(QP::QEvt const **)0, 0U,
nullptr, 0U);
- DPP::AO_Table->start((uint_fast8_t)(N_PHILO + 2U), // priority
- tableQueueSto, Q_DIM(tableQueueSto),
- nullptr, 0U);
+ DPP::AO_Table->start(
+ N_PHILO + 2U, // QF-prio/preempt-thre.
+ tableQueueSto, // event queue storage
+ Q_DIM(tableQueueSto), // queue length [events]
+ nullptr, 0U); // no stack storage
return QP::QF::run(); // run the QF application
}
diff --git a/examples/arm-cr/dpp_launchxl2-tms57012/qk/main.cpp b/examples/arm-cr/dpp_launchxl2-tms57012/qk/main.cpp
index 8366e1f1..bcccf811 100644
--- a/examples/arm-cr/dpp_launchxl2-tms57012/qk/main.cpp
+++ b/examples/arm-cr/dpp_launchxl2-tms57012/qk/main.cpp
@@ -1,11 +1,11 @@
//============================================================================
// DPP example
-// Last updated for version 5.6.2
-// Last updated on 2016-03-31
+// Last updated for version 7.1.2
+// Last updated on 2022-10-05
//
-// Q u a n t u m L e a P s
-// ---------------------------
-// innovating embedded systems
+// Q u a n t u m L e a P s
+// ------------------------
+// Modern Embedded Software
//
// Copyright (C) Quantum Leaps, LLC. All rights reserved.
//
@@ -28,7 +28,7 @@
// along with this program. If not, see .
//
// Contact information:
-// https://state-machine.com
+//
//
//============================================================================
#include "qpcpp.hpp"
@@ -48,7 +48,8 @@ int main() {
DPP::BSP::init(); // initialize the BSP
- QP::QActive::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe
+ // init publish-subscribe
+ QP::QActive::psInit(subscrSto, Q_DIM(subscrSto));
// initialize event pools...
QP::QF::poolInit(smlPoolSto,
@@ -56,13 +57,17 @@ int main() {
// start the active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) {
- DPP::AO_Philo[n]->start((uint_fast8_t)(n + 1U),
- philoQueueSto[n], Q_DIM(philoQueueSto[n]),
- nullptr, 0U);
+ DPP::AO_Philo[n]->start(
+ Q_PRIO(n + 1U, N_PHILO), // QF-prio/preempt-thre.
+ philoQueueSto[n], // event queue storage
+ Q_DIM(philoQueueSto[n]), // queue length [events]
+ nullptr, 0U); // no stack storage
}
- DPP::AO_Table->start((uint_fast8_t)(N_PHILO + 1U),
- tableQueueSto, Q_DIM(tableQueueSto),
- nullptr, 0U);
+ DPP::AO_Table->start(
+ N_PHILO + 1U, // QF-prio/preempt-thre.
+ tableQueueSto, // event queue storage
+ Q_DIM(tableQueueSto), // queue length [events]
+ nullptr, 0U); // no stack storage
return QP::QF::run(); // run the QF application
}
diff --git a/include/qep.hpp b/include/qep.hpp
index 1c30b234..3a911b1a 100644
--- a/include/qep.hpp
+++ b/include/qep.hpp
@@ -52,7 +52,7 @@
// major version number, Y is a 1-digit minor version number, and Z is
// a 1-digit release number.
//
-#define QP_VERSION 710U
+#define QP_VERSION 712U
//! The current QP version as a zero terminated string literal.
//
@@ -61,10 +61,10 @@
// major version number, Y is a 1-digit minor version number, and Z is
// a 1-digit release number.
//
-#define QP_VERSION_STR "7.1.0"
+#define QP_VERSION_STR "7.1.2"
-//! Encrypted current QP release (7.1.0) and date (2022-08-30)
-#define QP_RELEASE 0x7C600159U
+//! Encrypted current QP release (7.1.2) and date (2022-10-07)
+#define QP_RELEASE 0x7C44FF47U
//============================================================================
// Global namespace...
diff --git a/include/qf.hpp b/include/qf.hpp
index d82a4eea..a863ac2e 100644
--- a/include/qf.hpp
+++ b/include/qf.hpp
@@ -201,7 +201,7 @@ using QTimeEvtCtr = std::uint32_t;
//! When QP runs on top of 3rd-party kernels/RTOSes or general-purpose
//! operating systems, sthe second priority can have different meaning,
//! depending on the specific RTOS/GPOS used.
-using QPrioSpec = std::uint_fast16_t;
+using QPrioSpec = std::uint16_t;
//${QF-types::QSchedStatus} ..................................................
//! The scheduler lock status used in some real-time kernels
diff --git a/include/qk.hpp b/include/qk.hpp
index 9e4ce6e0..fa326d10 100644
--- a/include/qk.hpp
+++ b/include/qk.hpp
@@ -150,8 +150,9 @@ extern QK_Attr QK_attr_;
//! that (1) has events to process and (2) has priority that is above the
//! current priority.
//!
-//! @returns the 1-based priority of the the active object, or zero if
-//! no eligible active object is ready to run.
+//! @returns
+//! The QF-priority of the next active object to activate, or zero
+//! if no activation of AO is needed.
//!
//! @attention
//! QK_sched_() must be always called with interrupts **disabled** and
@@ -162,17 +163,14 @@ std::uint_fast8_t QK_sched_() noexcept;
//! QK activator activates the next active object. The activated AO preempts
//! the currently executing AOs
//!
-//! @param[in] asynch flag conveying the type of activation:
-//! != 0 for asynchronous activation and
-//! == 0 for synchronous activation
//! @details
//! QK_activate_() activates ready-to run AOs that are above the initial
-//! active priority (QK_attr_.actPrio).
+//! preemption-threshold.
//!
//! @note
//! The activator might enable interrupts internally, but always returns with
//! interrupts **disabled**.
-void QK_activate_(std::uint_fast8_t const asynch) noexcept;
+void QK_activate_() noexcept;
//${QK-extern-C::QK_onContextSw} .............................................
#ifdef QK_ON_CONTEXT_SW
@@ -251,7 +249,7 @@ void QK_onContextSw(
static_cast((me_)->m_prio)); \
if (!QK_ISR_CONTEXT_()) { \
if (QK_sched_() != 0U) { \
- QK_activate_(0U); \
+ QK_activate_(); \
} \
} \
} while (false)
diff --git a/include/qs.hpp b/include/qs.hpp
index 2950c57c..44c35cef 100644
--- a/include/qs.hpp
+++ b/include/qs.hpp
@@ -205,7 +205,7 @@ enum QSpyPre : std::int8_t {
QS_SCHED_UNLOCK, //!< scheduler was unlocked
QS_SCHED_NEXT, //!< scheduler found next task to execute
QS_SCHED_IDLE, //!< scheduler became idle
- QS_SCHED_RESUME, //!< scheduler resumed previous task (not idle)
+ QS_SCHED_RESUME, //!< scheduler resumed a (blocked) task
// [55] Additional QEP records
QS_QEP_TRAN_HIST, //!< a tran to history was taken
diff --git a/include/qxk.hpp b/include/qxk.hpp
index 5f5c2e1d..8906d04a 100644
--- a/include/qxk.hpp
+++ b/include/qxk.hpp
@@ -145,10 +145,8 @@ void schedUnlock(QSchedStatus const stat) noexcept;
//${QXK::QXK-base::Timeouts} .................................................
//! timeout signals for extended threads
enum Timeouts : enum_t {
- DELAY_SIG = Q_USER_SIG,
- QUEUE_SIG,
- SEMA_SIG,
- MUTEX_SIG
+ DELAY_SIG = 1,
+ TIMEOUT_SIG
};
} // namespace QXK
@@ -600,15 +598,9 @@ public:
//! the priority and priority-threshold of the holding thread to the
//! priority specification in `prioSpec` (see QP::QPrioSpec).
//!
- //! @attention
- //! When the priority-ceiling protocol is used (`prioSpec != 0`), the
- //! QF-priority specified in `prioSpec` must be unused by any other thread
- //! or mutex. Also, the priority-threshold must be higher or equal to the
- //! threshold of any thread that uses this mutex (see QP::QPrioSpec).
- //!
//! @usage
//! @include qxk_mutex.cpp
- void init(QPrioSpec const prioSpec) noexcept override;
+ void init(QPrioSpec const prioSpec) noexcept;
//! try to lock the QXK priority-ceiling mutex QP::QXMutex
//!
@@ -684,8 +676,8 @@ extern "C" {
struct QXK_Attr {
QP::QActive * volatile curr; //!< currently executing thread
QP::QActive * volatile next; //!< next thread to execute
- std::uint8_t volatile actPrio; //!< prio of the active AO
- std::uint8_t volatile actThre; //!< active preemption-threshold
+ QP::QActive * volatile prev; //!< previous thread
+ std::uint8_t volatile actPrio; //!< QF-prio of the active AO
std::uint8_t volatile lockCeil; //!< lock preemption-ceiling (0==no-lock)
std::uint8_t volatile lockHolder; //!< prio of the lock holder
};
@@ -697,9 +689,6 @@ extern QXK_Attr QXK_attr_;
//${QXK-extern-C::QXK_sched_} ................................................
//! QXK scheduler finds the highest-priority thread ready to run
//!
-//! @param[in] asynch flag conveying the type of scheduling:
-//! != 0 for asynchronous scheduling and
-//! == 0 for synchronous scheduling
//! @details
//! The QXK scheduler finds the priority of the highest-priority thread
//! that is ready to run.
@@ -710,15 +699,12 @@ extern QXK_Attr QXK_attr_;
//! @attention
//! QXK_sched_() must be always called with interrupts **disabled** and
//! returns with interrupts **disabled**.
-std::uint_fast8_t QXK_sched_(std::uint_fast8_t const asynch) noexcept;
+std::uint_fast8_t QXK_sched_() noexcept;
//${QXK-extern-C::QXK_activate_} .............................................
//! QXK activator activates the next active object. The activated AO preempts
//! the currently executing AOs
//!
-//! @param[in] asynch flag conveying the type of activation:
-//! != 0 for asynchronous activation and
-//! == 0 for synchronous activation
//! @attention
//! QXK_activate_() must be always called with interrupts **disabled** and
//! returns with interrupts **disabled**.
@@ -726,10 +712,13 @@ std::uint_fast8_t QXK_sched_(std::uint_fast8_t const asynch) noexcept;
//! @note
//! The activate function might enable interrupts internally, but it always
//! returns with interrupts **disabled**.
-void QXK_activate_(std::uint_fast8_t const asynch) noexcept;
+void QXK_activate_() noexcept;
//${QXK-extern-C::QXK_current} ...............................................
-//! return the currently executing active-object/thread
+//! obtain the currently executing active-object/thread
+//!
+//! @returns
+//! pointer to the currently executing active-object/thread
QP::QActive * QXK_current() noexcept;
//${QXK-extern-C::QXK_stackInit_} ............................................
@@ -740,6 +729,22 @@ void QXK_stackInit_(
void * const stkSto,
std::uint_fast16_t const stkSize) noexcept;
+//${QXK-extern-C::QXK_contextSw} .............................................
+#if defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
+//! QXK context switch management
+//!
+//! @details
+//! This function performs software tracing (if #Q_SPY is defined)
+//! and calls QXK_onContextSw() (if #QXK_ON_CONTEXT_SW is defined)
+//!
+//! @param[in] next pointer to the next thread (NULL for basic-thread)
+//!
+//! @attention
+//! QXK_contextSw() is invoked with interrupts **disabled** and must also
+//! return with interrupts **disabled**.
+void QXK_contextSw(QP::QActive * const next);
+#endif // defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
+
//${QXK-extern-C::QXK_onContextSw} ...........................................
#ifdef QXK_ON_CONTEXT_SW
//! QXK context switch callback (customized in BSPs for QXK)
@@ -856,8 +861,8 @@ void QXK_threadExit_();
QF::readySet_.insert( \
static_cast((me_)->m_prio)); \
if (!QXK_ISR_CONTEXT_()) { \
- if (QXK_sched_(0U) != 0U) { \
- QXK_activate_(0U); \
+ if (QXK_sched_() != 0U) { \
+ QXK_activate_(); \
} \
} \
} while (false)
diff --git a/ports/arm-cm/qxk/armclang/qxk_port.cpp b/ports/arm-cm/qxk/armclang/qxk_port.cpp
index 4d225fe1..e387eb55 100644
--- a/ports/arm-cm/qxk/armclang/qxk_port.cpp
+++ b/ports/arm-cm/qxk/armclang/qxk_port.cpp
@@ -23,8 +23,8 @@
*
============================================================================*/
/*!
-* @date Last updated on: 2022-09-04
-* @version Last updated for: @ref qpcpp_7_1_1
+* @date Last updated on: 2022-10-04
+* @version Last updated for: @ref qpcpp_7_1_2
*
* @file
* @brief QXK/C++ port to ARM Cortex-M, ARM-CLANG toolset
@@ -165,21 +165,21 @@ void QXK_stackInit_(void *thr, QP::QXThreadHandler const handler,
/* NOTE: keep in synch with struct QXK_Attr in "qxk.hpp" !!! */
#define QXK_CURR 0
#define QXK_NEXT 4
-#define QXK_ACT_THRE 9
+#define QXK_ACT_PRIO 12
/* make sure that the offsets match the QXK declaration in "qxk.hpp" */
Q_ASSERT_STATIC(QXK_CURR == offsetof(QXK_Attr, curr));
Q_ASSERT_STATIC(QXK_NEXT == offsetof(QXK_Attr, next));
-Q_ASSERT_STATIC(QXK_ACT_THRE == offsetof(QXK_Attr, actThre));
+Q_ASSERT_STATIC(QXK_ACT_PRIO == offsetof(QXK_Attr, actPrio));
+
/* offsets within struct QActive; NOTE: keep in synch with "qf.hpp" !!! */
#define QACTIVE_OSOBJ 28
#define QACTIVE_PRIO 36
-#define QACTIVE_PTHRE 37
/* make sure that the offsets match the QXK declaration in "qf.hpp" */
Q_ASSERT_STATIC(QACTIVE_OSOBJ == offsetof(QP::QActive, m_osObject));
-Q_ASSERT_STATIC(QACTIVE_PTHRE == offsetof(QP::QActive, m_pthre));
+Q_ASSERT_STATIC(QACTIVE_PRIO == offsetof(QP::QActive, m_prio));
/* helper macros to "stringify" values */
#define VAL(x) #x
@@ -273,11 +273,6 @@ __asm volatile (
" ADD r0,sp,#(5*4) \n" /* r0 := 5 registers below the top of stack */
" STM r0!,{r1-r3} \n" /* save xpsr,pc,lr */
-#ifdef Q_SPY
- " MOVS r0,#1 \n" /* set the parameter 'asynch` */
- " STR r0,[sp] \n" /* for call QK_activate_(asynch == 1) */
-#endif /* Q_SPY */
-
" MOVS r0,#6 \n"
" MVNS r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */
#if (__ARM_ARCH != 6) /* ARMv7-M or higher */
@@ -328,9 +323,9 @@ __asm volatile (
* r12 -> QXK_attr_.next / basic-thread
*/
"PendSV_restore_ao: \n"
- " MOVS r0,#0 \n"
- " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := 0 */
- /* don't clear QXK_attr_.next, as it might be needed for AO activation */
+ /* don NOT clear QXK_attr_.curr or QXK_attr_.next,
+ * as they might be needed for AO activation
+ */
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
" MOV r0,sp \n" /* r0 := top of stack */
@@ -361,26 +356,25 @@ __asm volatile (
#endif /* ARMv7-M or higher */
" MOV r0,r12 \n" /* r0 := QXK_attr_.next */
- " MOVS r2,#" STRINGIFY(QACTIVE_PTHRE) "\n" /* r2 := offset of .pthre */
- " LDRB r0,[r0,r2] \n" /* r0 := QXK_attr_.next->pthre */
- " LDRB r2,[r3,#" STRINGIFY(QXK_ACT_THRE) "]\n" /* r2 := QXK_attr_.actThre */
+ " MOVS r2,#" STRINGIFY(QACTIVE_PRIO) "\n" /* r2 := offset of .prio */
+ " LDRB r0,[r0,r2] \n" /* r0 := QXK_attr_.next->prio */
+ " LDRB r2,[r3,#" STRINGIFY(QXK_ACT_PRIO) "]\n" /* r2 := QXK_attr_.actPrio */
" CMP r2,r0 \n"
- " BCC PendSV_activate \n" /* if (next->pthre > actThre) activate the next AO */
+ " BCC PendSV_activate \n" /* if (next->prio > actPrio) activate the next AO */
/* otherwise no activation needed... */
" MOVS r0,#0 \n"
- " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* QXK_attr_.next := 0 (clear the next) */
- " MOV r12,r0 \n" /* also clear r12==QXK_attr_.next */
+ " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := 0 */
+ " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* QXK_attr_.next := 0 */
-#ifdef QXK_ON_CONTEXT_SW
- " MOVS r0,r1 \n" /* r0 := QXK_attr_.curr / basic */
- " MOV r1,r12 \n" /* r1 := QXK_attr_.next / basic */
- " LDR r2,=QXK_onContextSw \n"
- " PUSH {r1,lr} \n" /* save the aligner + exception lr */
- " BLX r2 \n" /* call QXK_onContextSw() */
- " POP {r1,r2} \n" /* restore the aligner + lr into r2 */
- " MOV lr,r2 \n" /* restore the exception lr */
-#endif /* QXK_ON_CONTEXT_SW */
+#if defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
+ " MOVS r0,#0 \n" /* r0 := 0 (next is basic) */
+ " PUSH {r3,lr} \n" /* save QXK_attr_ + exception lr */
+ " LDR r3,=QXK_contextSw \n"
+ " BLX r3 \n" /* call QXK_contextSw() */
+ " POP {r0,r1} \n" /* restore the aligner + lr into r1 */
+ " MOV lr,r1 \n" /* restore the exception lr */
+#endif /* defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW) */
/* re-enable interrupts and return from PendSV */
"PendSV_return: \n"
@@ -395,7 +389,7 @@ __asm volatile (
" BX lr \n" /* return to the preempted AO-thread */
/*-------------------------------------------------------------------------
- * Saving extended-thread before crossing to AO-thread
+ * Saving extended-thread
* expected register contents:
* r0 -> QXK_attr_.next / basic-thread
* r1 -> QXK_attr_.curr / basic-thread
@@ -437,7 +431,7 @@ __asm volatile (
/* otherwise continue to restoring next extended-thread... */
/*-------------------------------------------------------------------------
- * Restoring extended-thread after crossing from AO-thread
+ * Restoring extended-thread
* expected register contents:
* r0 -> QXK_attr_.next / basic-thread
* r1 -> QXK_attr_.curr / basic-thread
@@ -446,20 +440,19 @@ __asm volatile (
* r12 -> QXK_attr_.next / basic-thread
*/
"PendSV_restore_ex: \n"
-#ifdef QXK_ON_CONTEXT_SW
- " MOVS r0,r1 \n" /* r0 := QXK_attr_.curr / basic */
- " MOV r1,r12 \n" /* r1 := QXK_attr_.next / basic */
- " LDR r2,=QXK_onContextSw \n"
- " PUSH {r1,lr} \n" /* save the aligner + exception lr */
- " BLX r2 \n" /* call QXK_onContextSw() */
- " POP {r1,r2} \n" /* restore the aligner + lr into r2 */
- " MOV lr,r2 \n" /* restore the exception lr */
+#if defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
+ " MOV r0,r12 \n" /* r0 := next */
+ " PUSH {r3,lr} \n" /* save QXK_attr_ + exception lr */
+ " LDR r3,=QXK_contextSw \n"
+ " BLX r3 \n" /* call QXK_contextSw() */
+ " POP {r0,r1} \n" /* restore the aligner + lr into r1 */
+ " MOV lr,r1 \n" /* restore the exception lr */
+ " MOVS r3,r0 \n" /* restore the saved QXK_attr_ in r3 */
/* restore the AAPCS-clobbered registers after a functin call... */
- " LDR r3,=QXK_attr_ \n"
" LDR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* r0 := QXK_attr_.next */
" LDR r2,[r0,#" STRINGIFY(QACTIVE_OSOBJ) "]\n" /* r2 := QXK_attr_.curr->osObject */
-#endif /* QXK_ON_CONTEXT_SW */
+#endif /* defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW) */
" STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := r0 (QXK_attr_.next) */
" MOVS r0,#0 \n"
diff --git a/ports/arm-cm/qxk/armclang/qxk_port.hpp b/ports/arm-cm/qxk/armclang/qxk_port.hpp
index 9ae6ff12..c59385fc 100644
--- a/ports/arm-cm/qxk/armclang/qxk_port.hpp
+++ b/ports/arm-cm/qxk/armclang/qxk_port.hpp
@@ -21,8 +21,8 @@
//
//
//============================================================================
-//! @date Last updated on: 2022-09-04
-//! @version Last updated for: @ref qpcpp_7_1_1
+//! @date Last updated on: 2022-10-04
+//! @version Last updated for: @ref qpcpp_7_1_2
//!
//! @file
//! @brief QXK/C++ port to ARM Cortex-M, ARM-CLANG toolset
@@ -49,7 +49,7 @@ static inline uint32_t QXK_get_IPSR(void) {
#define QXK_ISR_EXIT() do { \
QF_INT_DISABLE(); \
- if (QXK_sched_(1U) != 0U) {\
+ if (QXK_sched_() != 0U) { \
QXK_CONTEXT_SWITCH_(); \
} \
QF_INT_ENABLE(); \
diff --git a/ports/arm-cm/qxk/gnu/qxk_port.cpp b/ports/arm-cm/qxk/gnu/qxk_port.cpp
index d1a3e09f..6d82ad14 100644
--- a/ports/arm-cm/qxk/gnu/qxk_port.cpp
+++ b/ports/arm-cm/qxk/gnu/qxk_port.cpp
@@ -23,8 +23,8 @@
*
============================================================================*/
/*!
-* @date Last updated on: 2022-09-20
-* @version Last updated for: @ref qpcpp_7_1_1
+* @date Last updated on: 2022-10-04
+* @version Last updated for: @ref qpcpp_7_1_2
*
* @file
* @brief QXK/C++ port to ARM Cortex-M, GNU-ARM toolset
@@ -165,21 +165,21 @@ void QXK_stackInit_(void *thr, QP::QXThreadHandler const handler,
/* NOTE: keep in synch with struct QXK_Attr in "qxk.hpp" !!! */
#define QXK_CURR 0
#define QXK_NEXT 4
-#define QXK_ACT_THRE 9
+#define QXK_ACT_PRIO 12
/* make sure that the offsets match the QXK declaration in "qxk.hpp" */
//Q_ASSERT_STATIC(QXK_CURR == offsetof(QXK_Attr, curr));
//Q_ASSERT_STATIC(QXK_NEXT == offsetof(QXK_Attr, next));
-//Q_ASSERT_STATIC(QXK_ACT_THRE == offsetof(QXK_Attr, actThre));
+//Q_ASSERT_STATIC(QXK_ACT_PRIO == offsetof(QXK_Attr, actPrio));
+
/* offsets within struct QActive; NOTE: keep in synch with "qf.hpp" !!! */
#define QACTIVE_OSOBJ 28
#define QACTIVE_PRIO 36
-#define QACTIVE_PTHRE 37
/* make sure that the offsets match the QXK declaration in "qf.hpp" */
//Q_ASSERT_STATIC(QACTIVE_OSOBJ == offsetof(QP::QActive, m_osObject));
-//Q_ASSERT_STATIC(QACTIVE_PTHRE == offsetof(QP::QActive, m_pthre));
+//Q_ASSERT_STATIC(QACTIVE_PRIO == offsetof(QP::QActive, m_prio));
/* helper macros to "stringify" values */
#define VAL(x) #x
@@ -278,11 +278,6 @@ __asm volatile (
" ADD r0,sp,#(5*4) \n" /* r0 := 5 registers below the top of stack */
" STM r0!,{r1-r3} \n" /* save xpsr,pc,lr */
-#ifdef Q_SPY
- " MOV r0,#1 \n" /* set the parameter 'asynch` */
- " STR r0,[sp] \n" /* for call QK_activate_(asynch == 1) */
-#endif /* Q_SPY */
-
" MOV r0,#6 \n"
" MVN r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */
#if (__ARM_ARCH != 6) /* ARMv7-M or higher */
@@ -333,9 +328,9 @@ __asm volatile (
* r12 -> QXK_attr_.next / basic-thread
*/
"PendSV_restore_ao: \n"
- " MOV r0,#0 \n"
- " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := 0 */
- /* don't clear QXK_attr_.next, as it might be needed for AO activation */
+ /* don NOT clear QXK_attr_.curr or QXK_attr_.next,
+ * as they might be needed for AO activation
+ */
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
" MOV r0,sp \n" /* r0 := top of stack */
@@ -366,26 +361,25 @@ __asm volatile (
#endif /* ARMv7-M or higher */
" MOV r0,r12 \n" /* r0 := QXK_attr_.next */
- " MOV r2,#" STRINGIFY(QACTIVE_PTHRE) "\n" /* r2 := offset of .pthre */
- " LDRB r0,[r0,r2] \n" /* r0 := QXK_attr_.next->pthre */
- " LDRB r2,[r3,#" STRINGIFY(QXK_ACT_THRE) "]\n" /* r2 := QXK_attr_.actThre */
+ " MOV r2,#" STRINGIFY(QACTIVE_PRIO) "\n" /* r2 := offset of .prio */
+ " LDRB r0,[r0,r2] \n" /* r0 := QXK_attr_.next->prio */
+ " LDRB r2,[r3,#" STRINGIFY(QXK_ACT_PRIO) "]\n" /* r2 := QXK_attr_.actPrio */
" CMP r2,r0 \n"
- " BCC PendSV_activate \n" /* if (next->pthre > actThre) activate the next AO */
+ " BCC PendSV_activate \n" /* if (next->prio > actPrio) activate the next AO */
/* otherwise no activation needed... */
" MOV r0,#0 \n"
- " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* QXK_attr_.next := 0 (clear the next) */
- " MOV r12,r0 \n" /* also clear r12==QXK_attr_.next */
+ " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := 0 */
+ " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* QXK_attr_.next := 0 */
-#ifdef QXK_ON_CONTEXT_SW
- " MOV r0,r1 \n" /* r0 := QXK_attr_.curr / basic */
- " MOV r1,r12 \n" /* r1 := QXK_attr_.next / basic */
- " LDR r2,=QXK_onContextSw \n"
- " PUSH {r1,lr} \n" /* save the aligner + exception lr */
- " BLX r2 \n" /* call QXK_onContextSw() */
- " POP {r1,r2} \n" /* restore the aligner + lr into r2 */
- " MOV lr,r2 \n" /* restore the exception lr */
-#endif /* QXK_ON_CONTEXT_SW */
+#if defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
+ " MOV r0,#0 \n" /* r0 := 0 (next is basic) */
+ " PUSH {r3,lr} \n" /* save QXK_attr_ + exception lr */
+ " LDR r3,=QXK_contextSw \n"
+ " BLX r3 \n" /* call QXK_contextSw() */
+ " POP {r0,r1} \n" /* restore the aligner + lr into r1 */
+ " MOV lr,r1 \n" /* restore the exception lr */
+#endif /* defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW) */
/* re-enable interrupts and return from PendSV */
"PendSV_return: \n"
@@ -400,7 +394,7 @@ __asm volatile (
" BX lr \n" /* return to the preempted AO-thread */
/*-------------------------------------------------------------------------
- * Saving extended-thread before crossing to AO-thread
+ * Saving extended-thread
* expected register contents:
* r0 -> QXK_attr_.next / basic-thread
* r1 -> QXK_attr_.curr / basic-thread
@@ -442,7 +436,7 @@ __asm volatile (
/* otherwise continue to restoring next extended-thread... */
/*-------------------------------------------------------------------------
- * Restoring extended-thread after crossing from AO-thread
+ * Restoring extended-thread
* expected register contents:
* r0 -> QXK_attr_.next / basic-thread
* r1 -> QXK_attr_.curr / basic-thread
@@ -451,20 +445,19 @@ __asm volatile (
* r12 -> QXK_attr_.next / basic-thread
*/
"PendSV_restore_ex: \n"
-#ifdef QXK_ON_CONTEXT_SW
- " MOV r0,r1 \n" /* r0 := QXK_attr_.curr / basic */
- " MOV r1,r12 \n" /* r1 := QXK_attr_.next / basic */
- " LDR r2,=QXK_onContextSw \n"
- " PUSH {r1,lr} \n" /* save the aligner + exception lr */
- " BLX r2 \n" /* call QXK_onContextSw() */
- " POP {r1,r2} \n" /* restore the aligner + lr into r2 */
- " MOV lr,r2 \n" /* restore the exception lr */
+#if defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
+ " MOV r0,r12 \n" /* r0 := next */
+ " PUSH {r3,lr} \n" /* save QXK_attr_ + exception lr */
+ " LDR r3,=QXK_contextSw \n"
+ " BLX r3 \n" /* call QXK_contextSw() */
+ " POP {r0,r1} \n" /* restore the aligner + lr into r1 */
+ " MOV lr,r1 \n" /* restore the exception lr */
+ " MOV r3,r0 \n" /* restore the saved QXK_attr_ in r3 */
/* restore the AAPCS-clobbered registers after a functin call... */
- " LDR r3,=QXK_attr_ \n"
" LDR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* r0 := QXK_attr_.next */
" LDR r2,[r0,#" STRINGIFY(QACTIVE_OSOBJ) "]\n" /* r2 := QXK_attr_.curr->osObject */
-#endif /* QXK_ON_CONTEXT_SW */
+#endif /* defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW) */
" STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := r0 (QXK_attr_.next) */
" MOV r0,#0 \n"
@@ -539,7 +532,7 @@ __asm volatile (
" ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */
#endif /*--------- VFP available */
-#ifndef QXK_USE_IRQ_NUM /*--------- IRQ NOT defined, used NMI by default */
+#ifndef QXK_USE_IRQ_NUM /*--------- IRQ NOT defined, use NMI by default */
" LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */
" MOV r1,#1 \n"
" LSL r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */
diff --git a/ports/arm-cm/qxk/gnu/qxk_port.hpp b/ports/arm-cm/qxk/gnu/qxk_port.hpp
index 74ddd034..2e236df1 100644
--- a/ports/arm-cm/qxk/gnu/qxk_port.hpp
+++ b/ports/arm-cm/qxk/gnu/qxk_port.hpp
@@ -21,8 +21,8 @@
//
//
//============================================================================
-//! @date Last updated on: 2022-09-04
-//! @version Last updated for: @ref qpcpp_7_1_1
+//! @date Last updated on: 2022-10-04
+//! @version Last updated for: @ref qpcpp_7_1_2
//!
//! @file
//! @brief QXK/C++ port to ARM Cortex-M, GNU-ARM toolset
@@ -49,7 +49,7 @@ static inline uint32_t QXK_get_IPSR(void) {
#define QXK_ISR_EXIT() do { \
QF_INT_DISABLE(); \
- if (QXK_sched_(1U) != 0U) {\
+ if (QXK_sched_() != 0U) { \
QXK_CONTEXT_SWITCH_(); \
} \
QF_INT_ENABLE(); \
diff --git a/ports/arm-cm/qxk/iar/qxk_port.cpp b/ports/arm-cm/qxk/iar/qxk_port.cpp
index e03b7f18..c24731a1 100644
--- a/ports/arm-cm/qxk/iar/qxk_port.cpp
+++ b/ports/arm-cm/qxk/iar/qxk_port.cpp
@@ -23,8 +23,8 @@
*
============================================================================*/
/*!
-* @date Last updated on: 2022-09-20
-* @version Last updated for: @ref qpcpp_7_1_1
+* @date Last updated on: 2022-10-04
+* @version Last updated for: @ref qpcpp_7_1_2
*
* @file
* @brief QXK/C++ port to ARM Cortex-M, IAR-ARM toolset
@@ -165,21 +165,21 @@ void QXK_stackInit_(void *thr, QP::QXThreadHandler const handler,
/* NOTE: keep in synch with struct QXK_Attr in "qxk.hpp" !!! */
#define QXK_CURR 0
#define QXK_NEXT 4
-#define QXK_ACT_THRE 9
+#define QXK_ACT_PRIO 12
/* make sure that the offsets match the QXK declaration in "qxk.hpp" */
Q_ASSERT_STATIC(QXK_CURR == offsetof(QXK_Attr, curr));
Q_ASSERT_STATIC(QXK_NEXT == offsetof(QXK_Attr, next));
-Q_ASSERT_STATIC(QXK_ACT_THRE == offsetof(QXK_Attr, actThre));
+Q_ASSERT_STATIC(QXK_ACT_PRIO == offsetof(QXK_Attr, actPrio));
+
/* offsets within struct QActive; NOTE: keep in synch with "qf.hpp" !!! */
#define QACTIVE_OSOBJ 28
#define QACTIVE_PRIO 36
-#define QACTIVE_PTHRE 37
/* make sure that the offsets match the QXK declaration in "qf.hpp" */
Q_ASSERT_STATIC(QACTIVE_OSOBJ == offsetof(QP::QActive, m_osObject));
-Q_ASSERT_STATIC(QACTIVE_PTHRE == offsetof(QP::QActive, m_pthre));
+Q_ASSERT_STATIC(QACTIVE_PRIO == offsetof(QP::QActive, m_prio));
/* helper macros to "stringify" values */
#define VAL(x) #x
@@ -273,11 +273,6 @@ __asm volatile (
" ADD r0,sp,#(5*4) \n" /* r0 := 5 registers below the top of stack */
" STM r0!,{r1-r3} \n" /* save xpsr,pc,lr */
-#ifdef Q_SPY
- " MOVS r0,#1 \n" /* set the parameter 'asynch` */
- " STR r0,[sp] \n" /* for call QK_activate_(asynch == 1) */
-#endif /* Q_SPY */
-
" MOVS r0,#6 \n"
" MVNS r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */
#if (__ARM_ARCH != 6) /* ARMv7-M or higher */
@@ -328,9 +323,9 @@ __asm volatile (
* r12 -> QXK_attr_.next / basic-thread
*/
"PendSV_restore_ao: \n"
- " MOVS r0,#0 \n"
- " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := 0 */
- /* don't clear QXK_attr_.next, as it might be needed for AO activation */
+ /* don NOT clear QXK_attr_.curr or QXK_attr_.next,
+ * as they might be needed for AO activation
+ */
#if (__ARM_ARCH == 6) /* if ARMv6-M... */
" MOV r0,sp \n" /* r0 := top of stack */
@@ -361,26 +356,25 @@ __asm volatile (
#endif /* ARMv7-M or higher */
" MOV r0,r12 \n" /* r0 := QXK_attr_.next */
- " MOVS r2,#" STRINGIFY(QACTIVE_PTHRE) "\n" /* r2 := offset of .pthre */
- " LDRB r0,[r0,r2] \n" /* r0 := QXK_attr_.next->pthre */
- " LDRB r2,[r3,#" STRINGIFY(QXK_ACT_THRE) "]\n" /* r2 := QXK_attr_.actThre */
+ " MOVS r2,#" STRINGIFY(QACTIVE_PRIO) "\n" /* r2 := offset of .prio */
+ " LDRB r0,[r0,r2] \n" /* r0 := QXK_attr_.next->prio */
+ " LDRB r2,[r3,#" STRINGIFY(QXK_ACT_PRIO) "]\n" /* r2 := QXK_attr_.actPrio */
" CMP r2,r0 \n"
- " BCC PendSV_activate \n" /* if (next->pthre > actThre) activate the next AO */
+ " BCC PendSV_activate \n" /* if (next->prio > actPrio) activate the next AO */
/* otherwise no activation needed... */
" MOVS r0,#0 \n"
- " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* QXK_attr_.next := 0 (clear the next) */
- " MOV r12,r0 \n" /* also clear r12==QXK_attr_.next */
+ " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := 0 */
+ " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* QXK_attr_.next := 0 */
-#ifdef QXK_ON_CONTEXT_SW
- " MOVS r0,r1 \n" /* r0 := QXK_attr_.curr / basic */
- " MOV r1,r12 \n" /* r1 := QXK_attr_.next / basic */
- " LDR r2,=QXK_onContextSw \n"
- " PUSH {r1,lr} \n" /* save the aligner + exception lr */
- " BLX r2 \n" /* call QXK_onContextSw() */
- " POP {r1,r2} \n" /* restore the aligner + lr into r2 */
- " MOV lr,r2 \n" /* restore the exception lr */
-#endif /* QXK_ON_CONTEXT_SW */
+#if defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
+ " MOVS r0,#0 \n" /* r0 := 0 (next is basic) */
+ " PUSH {r3,lr} \n" /* save QXK_attr_ + exception lr */
+ " LDR r3,=QXK_contextSw \n"
+ " BLX r3 \n" /* call QXK_contextSw() */
+ " POP {r0,r1} \n" /* restore the aligner + lr into r1 */
+ " MOV lr,r1 \n" /* restore the exception lr */
+#endif /* defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW) */
/* re-enable interrupts and return from PendSV */
"PendSV_return: \n"
@@ -395,7 +389,7 @@ __asm volatile (
" BX lr \n" /* return to the preempted AO-thread */
/*-------------------------------------------------------------------------
- * Saving extended-thread before crossing to AO-thread
+ * Saving extended-thread
* expected register contents:
* r0 -> QXK_attr_.next / basic-thread
* r1 -> QXK_attr_.curr / basic-thread
@@ -437,7 +431,7 @@ __asm volatile (
/* otherwise continue to restoring next extended-thread... */
/*-------------------------------------------------------------------------
- * Restoring extended-thread after crossing from AO-thread
+ * Restoring extended-thread
* expected register contents:
* r0 -> QXK_attr_.next / basic-thread
* r1 -> QXK_attr_.curr / basic-thread
@@ -446,20 +440,19 @@ __asm volatile (
* r12 -> QXK_attr_.next / basic-thread
*/
"PendSV_restore_ex: \n"
-#ifdef QXK_ON_CONTEXT_SW
- " MOVS r0,r1 \n" /* r0 := QXK_attr_.curr / basic */
- " MOV r1,r12 \n" /* r1 := QXK_attr_.next / basic */
- " LDR r2,=QXK_onContextSw \n"
- " PUSH {r1,lr} \n" /* save the aligner + exception lr */
- " BLX r2 \n" /* call QXK_onContextSw() */
- " POP {r1,r2} \n" /* restore the aligner + lr into r2 */
- " MOV lr,r2 \n" /* restore the exception lr */
+#if defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
+ " MOV r0,r12 \n" /* r0 := next */
+ " PUSH {r3,lr} \n" /* save QXK_attr_ + exception lr */
+ " LDR r3,=QXK_contextSw \n"
+ " BLX r3 \n" /* call QXK_contextSw() */
+ " POP {r0,r1} \n" /* restore the aligner + lr into r1 */
+ " MOV lr,r1 \n" /* restore the exception lr */
+ " MOVS r3,r0 \n" /* restore the saved QXK_attr_ in r3 */
/* restore the AAPCS-clobbered registers after a functin call... */
- " LDR r3,=QXK_attr_ \n"
" LDR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* r0 := QXK_attr_.next */
" LDR r2,[r0,#" STRINGIFY(QACTIVE_OSOBJ) "]\n" /* r2 := QXK_attr_.curr->osObject */
-#endif /* QXK_ON_CONTEXT_SW */
+#endif /* defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW) */
" STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := r0 (QXK_attr_.next) */
" MOVS r0,#0 \n"
diff --git a/ports/arm-cm/qxk/iar/qxk_port.hpp b/ports/arm-cm/qxk/iar/qxk_port.hpp
index 723ffc0f..833c538e 100644
--- a/ports/arm-cm/qxk/iar/qxk_port.hpp
+++ b/ports/arm-cm/qxk/iar/qxk_port.hpp
@@ -21,8 +21,8 @@
//
//
//============================================================================
-//! @date Last updated on: 2022-09-04
-//! @version Last updated for: @ref qpcpp_7_1_1
+//! @date Last updated on: 2022-10-04
+//! @version Last updated for: @ref qpcpp_7_1_2
//!
//! @file
//! @brief QXK/C++ port to ARM Cortex-M, QXK kernel, IAR-ARM toolset
@@ -42,7 +42,7 @@
#define QXK_ISR_EXIT() do { \
QF_INT_DISABLE(); \
- if (QXK_sched_(1U) != 0U) {\
+ if (QXK_sched_() != 0U) { \
QXK_CONTEXT_SWITCH_(); \
} \
QF_INT_ENABLE(); \
diff --git a/ports/arm-cr/qk/gnu/qk_port.hpp b/ports/arm-cr/qk/gnu/qk_port.hpp
index 2657f261..27d8eeda 100644
--- a/ports/arm-cr/qk/gnu/qk_port.hpp
+++ b/ports/arm-cr/qk/gnu/qk_port.hpp
@@ -22,8 +22,8 @@
//
//
//============================================================================
-//! @date Last updated on: 2022-09-04
-//! @version Last updated for: @ref qpcpp_7_1_1
+//! @date Last updated on: 2022-10-04
+//! @version Last updated for: @ref qpcpp_7_1_2
//!
//! @file
//! @brief QK/C++ port to ARM Cortex-R, preemptive QK kernel, GNU-ARM toolset
@@ -71,7 +71,7 @@
} --QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) { \
if (QK_sched_() != 0U) { \
- QK_activate_(1U); \
+ QK_activate_(); \
} \
} \
__asm volatile (" POP {R3, LR}\n" \
@@ -89,7 +89,7 @@
} --QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) { \
if (QK_sched_() != 0U) { \
- QK_activate_(1U); \
+ QK_activate_(); \
} \
} \
__asm volatile (" POP {R3, LR}\n" \
diff --git a/ports/arm-cr/qk/iar/qk_port.hpp b/ports/arm-cr/qk/iar/qk_port.hpp
index 28470f92..6769b78e 100644
--- a/ports/arm-cr/qk/iar/qk_port.hpp
+++ b/ports/arm-cr/qk/iar/qk_port.hpp
@@ -22,8 +22,8 @@
//
//
//============================================================================
-//! @date Last updated on: 2022-09-04
-//! @version Last updated for: @ref qpcpp_7_1_1
+//! @date Last updated on: 2022-10-04
+//! @version Last updated for: @ref qpcpp_7_1_2
//!
//! @file
//! @brief QK/C++ port to ARM Cortex-R, preemptive QK kernel, IAR-ARM toolset
@@ -67,7 +67,7 @@
} --QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) { \
if (QK_sched_() != 0U) { \
- QK_activate_(1U); \
+ QK_activate_(); \
} \
} \
__asm(" POP {R3, LR}\n" \
@@ -85,7 +85,7 @@
} --QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) { \
if (QK_sched_() != 0U) { \
- QK_activate_(1U); \
+ QK_activate_(); \
} \
} \
__asm(" POP {R3, LR}\n" \
diff --git a/ports/arm-cr/qk/ti/qk_port.hpp b/ports/arm-cr/qk/ti/qk_port.hpp
index f3aff513..639d724a 100644
--- a/ports/arm-cr/qk/ti/qk_port.hpp
+++ b/ports/arm-cr/qk/ti/qk_port.hpp
@@ -22,8 +22,8 @@
//
//
//============================================================================
-//! @date Last updated on: 2022-09-04
-//! @version Last updated for: @ref qpcpp_7_1_1
+//! @date Last updated on: 2022-10-04
+//! @version Last updated for: @ref qpcpp_7_1_2
//!
//! @file
//! @brief QK/C++ port to ARM Cortex-R, preemptive QK kernel, TI-ARM toolset
@@ -73,7 +73,7 @@
} --QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) { \
if (QK_sched_() != 0U) { \
- QK_activate_(1U); \
+ QK_activate_(); \
} \
} \
}
diff --git a/ports/lint-plus/qk/qk_port.hpp b/ports/lint-plus/qk/qk_port.hpp
index ac974419..42a0d2ad 100644
--- a/ports/lint-plus/qk/qk_port.hpp
+++ b/ports/lint-plus/qk/qk_port.hpp
@@ -22,8 +22,8 @@
//
//
//============================================================================
-//! @date Last updated on: 2022-09-04
-//! @version Last updated for: @ref qpcpp_7_1_1
+//! @date Last updated on: 2022-10-04
+//! @version Last updated for: @ref qpcpp_7_1_2
//!
//! @file
//! @brief QK/C++ port to Lint, Generic C++ compiler
@@ -60,7 +60,7 @@
--QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) {\
if (QK_sched_() != 0U) { \
- QK_activate_(1U); \
+ QK_activate_(); \
} \
} \
else { \
diff --git a/ports/lint-plus/qxk/qxk_port.hpp b/ports/lint-plus/qxk/qxk_port.hpp
index e0de1f9c..de3d515c 100644
--- a/ports/lint-plus/qxk/qxk_port.hpp
+++ b/ports/lint-plus/qxk/qxk_port.hpp
@@ -22,8 +22,8 @@
//
//
//============================================================================
-//! @date Last updated on: 2022-09-04
-//! @version Last updated for: @ref qpcpp_7_1_1
+//! @date Last updated on: 2022-10-04
+//! @version Last updated for: @ref qpcpp_7_1_2
//!
//! @file
//! @brief QXK/C++ port example, Generic C++ compiler
@@ -70,8 +70,8 @@
#define QXK_ISR_EXIT() do { \
--QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) { \
- if (QXK_sched_(1U) != 0U) {\
- QXK_activate_(1U); \
+ if (QXK_sched_() != 0U) { \
+ QXK_activate_(); \
} \
} \
else { \
diff --git a/ports/msp430/qk/qk_port.hpp b/ports/msp430/qk/qk_port.hpp
index 70e01c24..ed42c4f5 100644
--- a/ports/msp430/qk/qk_port.hpp
+++ b/ports/msp430/qk/qk_port.hpp
@@ -22,8 +22,8 @@
//
//
//============================================================================
-//! @date Last updated on: 2022-09-04
-//! @version Last updated for: @ref qpcpp_7_1_1
+//! @date Last updated on: 2022-10-04
+//! @version Last updated for: @ref qpcpp_7_1_2
//!
//! @file
//! @brief QK/C++ port to MSP430
@@ -38,7 +38,7 @@
--QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) {\
if (QK_sched_() != 0U) { \
- QK_activate_(1U); \
+ QK_activate_(); \
} \
} \
else { \
diff --git a/ports/pic32/qk/xc32/qk_port.cpp b/ports/pic32/qk/xc32/qk_port.cpp
index 1d9d44ec..70768e3f 100644
--- a/ports/pic32/qk/xc32/qk_port.cpp
+++ b/ports/pic32/qk/xc32/qk_port.cpp
@@ -22,8 +22,8 @@
//
//
//============================================================================
-//! @date Last updated on: 2022-09-04
-//! @version Last updated for: @ref qpcpp_7_1_1
+//! @date Last updated on: 2022-10-04
+//! @version Last updated for: @ref qpcpp_7_1_2
//!
//! @file
//! @brief QK/C++ port to PIC32, preemptive QK kernel, XC32 toolchain
@@ -49,7 +49,7 @@ void QK_isr_(void) { // see NOTE2
QF_INT_DISABLE();
_mtc0(_CP0_STATUS, _CP0_STATUS_SELECT, 0U); // drop IPL to 0
- (void)QK_activate_(1U); // asynchronously activate higher priority AO
+ (void)QK_activate_(); // asynchronously activate higher priority AO
_mtc0(_CP0_STATUS, _CP0_STATUS_SELECT, 1U << 10); //restore IPL to 1
QF_INT_ENABLE();
}
diff --git a/qpcpp.qm b/qpcpp.qm
index fc67e1c2..15182ba0 100644
--- a/qpcpp.qm
+++ b/qpcpp.qm
@@ -2323,7 +2323,7 @@ return r;
//! When QP runs on top of 3rd-party kernels/RTOSes or general-purpose
//! operating systems, sthe second priority can have different meaning,
//! depending on the specific RTOS/GPOS used.
- = std::uint_fast16_t;
+ = std::uint16_t;
@@ -3759,7 +3759,7 @@ QF_QMACTIVE_TO_QMSM_CAST_(this)->QMsm::init(qs_id);
m_interval(0U)
//! @pre The signal must be valid and the tick rate in range
-Q_REQUIRE_ID(300, (sgnl >= Q_USER_SIG)
+Q_REQUIRE_ID(300, (sgnl != 0)
&& (tickRate < QF_MAX_TICK_RATE));
#ifndef Q_EVT_CTOR
@@ -6560,7 +6560,7 @@ if (QS_GLB_CHECK_(rec_) && QS_LOC_CHECK_(qs_id_)) { \
QS_SCHED_UNLOCK, //!< scheduler was unlocked
QS_SCHED_NEXT, //!< scheduler found next task to execute
QS_SCHED_IDLE, //!< scheduler became idle
- QS_SCHED_RESUME, //!< scheduler resumed previous task (not idle)
+ QS_SCHED_RESUME, //!< scheduler resumed a (blocked) task
// [55] Additional QEP records
QS_QEP_TRAN_HIST, //!< a tran to history was taken
@@ -9637,8 +9637,8 @@ if (stat != 0xFFU) {
QS_BEGIN_NOCRIT_PRE_(QS_SCHED_UNLOCK, 0U)
QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(lockCeil, // current lock ceiling (old)
- prevCeil); // previous lock ceiling (new)
+ // current lock ceiling (old), previous lock ceiling (new)
+ QS_2U8_PRE_(lockCeil, prevCeil);
QS_END_NOCRIT_PRE_()
// restore the previous lock ceiling and lock holder
@@ -9647,7 +9647,7 @@ if (stat != 0xFFU) {
// find if any AOs should be run after unlocking the scheduler
if (QK_sched_() != 0U) { // synchronous preemption needed?
- QK_activate_(0U); // synchronously activate any unlocked AOs
+ QK_activate_(); // synchronously activate any unlocked AOs
}
QF_CRIT_X_();
@@ -9691,7 +9691,7 @@ QK_attr_.lockCeil = 0U; // scheduler unlocked
// any active objects need to be scheduled before starting event loop?
if (QK_sched_() != 0U) { // synchronous preemption needed?
- QK_activate_(0U); // synchronously activate AOs to process events
+ QK_activate_(); // synchronously activate AOs to process events
}
onStartup(); // application-specific startup callback
@@ -9752,7 +9752,7 @@ QS_FLUSH(); // flush the trace buffer to the host
QF_CRIT_STAT_
QF_CRIT_E_();
if (QK_sched_() != 0U) { // synchronous preemption needed?
- QK_activate_(0U); // synchronously activate AOs
+ QK_activate_(); // synchronously activate AOs
}
QF_CRIT_X_();
@@ -9785,26 +9785,33 @@ QF_CRIT_X_();
//! that (1) has events to process and (2) has priority that is above the
//! current priority.
//!
-//! @returns the 1-based priority of the the active object, or zero if
-//! no eligible active object is ready to run.
+//! @returns
+//! The QF-priority of the next active object to activate, or zero
+//! if no activation of AO is needed.
//!
//! @attention
//! QK_sched_() must be always called with interrupts **disabled** and
//! returns with interrupts **disabled**.
- // find the highest-prio AO with non-empty event queue
-std::uint_fast8_t p = QP::QF::readySet_.findMax();
+ std::uint_fast8_t p;
-// is the AO's priority below the active preemption-threshold?
-if (p <= QK_attr_.actThre) {
- p = 0U; // no preemption needed
-}
-// is the AO's priority below the lock preemption-ceiling?
-else if (p <= QK_attr_.lockCeil) {
- p = 0U; // no preemption needed
+if (QP::QF::readySet_.isEmpty()) {
+ p = 0U; // no activation needed
}
else {
- Q_ASSERT_ID(410, p <= QF_MAX_ACTIVE);
- QK_attr_.nextPrio = static_cast<std::uint8_t>(p); // next AO to run
+ // find the highest-prio AO with non-empty event queue
+ p = QP::QF::readySet_.findMax();
+
+ // is the AO's priority below the active preemption-threshold?
+ if (p <= QK_attr_.actThre) {
+ p = 0U; // no activation needed
+ }
+ // is the AO's priority below the lock preemption-ceiling?
+ else if (p <= QK_attr_.lockCeil) {
+ p = 0U; // no activation needed
+ }
+ else {
+ QK_attr_.nextPrio = static_cast<std::uint8_t>(p);
+ }
}
return p;
@@ -9814,21 +9821,14 @@ return p;
//! QK activator activates the next active object. The activated AO preempts
//! the currently executing AOs
//!
-//! @param[in] asynch flag conveying the type of activation:
-//! != 0 for asynchronous activation and
-//! == 0 for synchronous activation
//! @details
//! QK_activate_() activates ready-to run AOs that are above the initial
-//! active priority (QK_attr_.actPrio).
+//! preemption-threshold.
//!
//! @note
//! The activator might enable interrupts internally, but always returns with
//! interrupts **disabled**.
-
-
- Q_UNUSED_PAR(asynch); // unused when Q_SPY not defined
-
-std::uint8_t const prio_in = QK_attr_.actPrio; // saved initial priority
+ std::uint8_t const prio_in = QK_attr_.actPrio; // saved initial priority
std::uint_fast8_t p = QK_attr_.nextPrio; // next prio to run
QK_attr_.nextPrio = 0U; // clear for the next time
@@ -9849,25 +9849,14 @@ do {
QK_attr_.actPrio = static_cast<std::uint8_t>(p);
QK_attr_.actThre = QP::QActive::registry_[p]->m_pthre;
-#ifdef Q_SPY
- if ((asynch != 0U) && (pprev == prio_in)) {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_PREEMPT, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(p, // priority of the scheduled AO
- pprev); // previous priority
- QS_END_NOCRIT_PRE_()
- }
- else {
+#if (defined QK_ON_CONTEXT_SW) || (defined Q_SPY)
+ if (p != pprev) { // changing threads?
+
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a->m_prio)
QS_TIME_PRE_(); // timestamp
QS_2U8_PRE_(p, // priority of the scheduled AO
pprev); // previous priority
QS_END_NOCRIT_PRE_()
- }
-#endif // Q_SPY
-
-#if (defined QK_ON_CONTEXT_SW) || (defined Q_SPY)
- if (p != pprev) { // changing threads?
#ifdef QK_ON_CONTEXT_SW
// context-switch callback
@@ -9892,6 +9881,7 @@ do {
#if (QF_MAX_EPOOL > 0U)
QP::QF::gc(e);
#endif
+
// determine the next highest-priority AO ready to run...
QF_INT_DISABLE(); // unconditionally disable interrupts
@@ -9899,19 +9889,24 @@ do {
QP::QF::readySet_.remove(p);
}
- // find new highest-prio AO ready to run...
- p = QP::QF::readySet_.findMax();
-
- // is the new priority below the initial preemption-threshold?
- if (p <= QP::QActive::registry_[prio_in]->m_pthre) {
- p = 0U; // no preemption needed
- }
- // is the AO's priority below the lock preemption-ceiling?
- else if (p <= QK_attr_.lockCeil) {
- p = 0U; // no preemption needed
+ if (QP::QF::readySet_.isEmpty()) {
+ p = 0U; // no activation needed
}
else {
- Q_ASSERT_ID(510, p <= QF_MAX_ACTIVE);
+ // find new highest-prio AO ready to run...
+ p = QP::QF::readySet_.findMax();
+
+ // is the new priority below the initial preemption-threshold?
+ if (p <= QP::QActive::registry_[prio_in]->m_pthre) {
+ p = 0U; // no activation needed
+ }
+ // is the AO's priority below the lock preemption-ceiling?
+ else if (p <= QK_attr_.lockCeil) {
+ p = 0U; // no activation needed
+ }
+ else {
+ Q_ASSERT_ID(510, p <= QF_MAX_ACTIVE);
+ }
}
} while (p != 0U);
@@ -9923,22 +9918,11 @@ QK_attr_.actThre = QP::QActive::registry_[prio_in]->m_pthre;
if (prio_in != 0U) { // resuming an active object?
a = QP::QActive::registry_[prio_in]; // pointer to preempted AO
-#ifdef Q_SPY
- if (asynch != 0U) {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_RESTORE, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(prio_in, // priority of the resumed AO
- pprev); // previous priority
- QS_END_NOCRIT_PRE_()
- }
- else {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_RESUME, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(prio_in, // priority of the resumed AO
- pprev); // previous priority
- QS_END_NOCRIT_PRE_()
- }
-#endif // Q_SPY
+ QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a->m_prio)
+ QS_TIME_PRE_(); // timestamp
+ // priority of the resumed AO, previous priority
+ QS_2U8_PRE_(prio_in, pprev);
+ QS_END_NOCRIT_PRE_()
}
else { // resuming priority==0 --> idle
a = nullptr; // QK idle loop
@@ -10038,7 +10022,7 @@ QK_onContextSw(QP::QActive::registry_[pprev], a);
static_cast<std::uint_fast8_t>((me_)->m_prio)); \
if (!QK_ISR_CONTEXT_()) { \
if (QK_sched_() != 0U) { \
- QK_activate_(0U); \
+ QK_activate_(); \
} \
} \
} while (false)
@@ -10174,8 +10158,8 @@ if (stat != 0xFFU) {
QXK_attr_.lockHolder = static_cast<std::uint8_t>(stat & 0xFFU);
// find the highest-prio thread ready to run
- if (QXK_sched_(0U) != 0U) { // synchronous preemption needed?
- QXK_activate_(0U); // synchronously activate unlocked AOs
+ if (QXK_sched_() != 0U) { // synchronous preemption needed?
+ QXK_activate_(); // synchronously activate unlocked AOs
}
QF_CRIT_X_();
@@ -10185,10 +10169,8 @@ if (stat != 0xFFU) {
//! timeout signals for extended threads
: enum_t {
- DELAY_SIG = Q_USER_SIG,
- QUEUE_SIG,
- SEMA_SIG,
- MUTEX_SIG
+ DELAY_SIG = 1,
+ TIMEOUT_SIG
};
@@ -10386,10 +10368,10 @@ if (thr->m_eQueue.m_frontEvt == nullptr) {
// remember the blocking object (the thread's queue)
thr->m_temp.obj = QXK_PTR_CAST_(QMState*, &thr->m_eQueue);
- thr->teArm_(static_cast<enum_t>(QXK::QUEUE_SIG), nTicks);
+ thr->teArm_(static_cast<enum_t>(QXK::TIMEOUT_SIG), nTicks);
QF::readySet_.remove(
static_cast<std::uint_fast8_t>(thr->m_prio));
- static_cast<void>(QXK_sched_(0U)); // synchronous scheduling
+ static_cast<void>(QXK_sched_()); // synchronous scheduling
QF_CRIT_X_();
QF_CRIT_EXIT_NOP(); // BLOCK here
@@ -10527,10 +10509,13 @@ Q_ERROR_ID(120);
//! - NOT be called from an ISR;
//! - the stack storage must be provided;
//! - the thread must be instantiated (see #QXThread).
+//! - preemption-threshold is NOT provided (because QXK kernel
+//! does not support preemption-threshold scheduling)
Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_())
&& (stkSto != nullptr)
&& (stkSize != 0U)
- && (m_state.act == nullptr));
+ && (m_state.act == nullptr)
+ && ((prioSpec & 0xFF00U) == 0U));
// is storage for the queue buffer provided?
if (qSto != nullptr) {
@@ -10542,7 +10527,7 @@ if (qSto != nullptr) {
QXK_stackInit_(this, m_temp.thr, stkSto, stkSize);
m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU); // QF-prio.
-m_pthre = static_cast<std::uint8_t>(prioSpec >> 8U); // preemption-thre.
+m_pthre = 0U; // preemption-threshold NOT used
register_(); // make QF aware of this AO
// the new thread is not blocked on any object
@@ -10554,7 +10539,9 @@ QF_CRIT_E_();
QF::readySet_.insert(static_cast<std::uint_fast8_t>(m_prio));
// see if this thread needs to be scheduled in case QXK is running
-static_cast<void>(QXK_sched_(0U)); // synchronous scheduling
+if (QXK_attr_.lockCeil <= QF_MAX_ACTIVE) {
+ static_cast<void>(QXK_sched_()); // synchronous scheduling
+}
QF_CRIT_X_();
@@ -10691,7 +10678,7 @@ else if (m_eQueue.m_end != 0U) {
QF::readySet_.insert(
static_cast<std::uint_fast8_t>(m_prio));
if (!QXK_ISR_CONTEXT_()) {
- static_cast<void>(QXK_sched_(0U));
+ static_cast<void>(QXK_sched_());
}
}
}
@@ -10770,7 +10757,7 @@ Q_ERROR_ID(410);
//! @pre the thread holding the lock cannot block!
Q_REQUIRE_ID(600, (QXK_attr_.lockHolder != m_prio));
QF::readySet_.remove(static_cast<std::uint_fast8_t>(m_prio));
-static_cast<void>(QXK_sched_(0U)); // synchronous scheduling
+static_cast<void>(QXK_sched_()); // synchronous scheduling
@@ -10787,7 +10774,7 @@ static_cast<void>(QXK_sched_(0U)); // synchronous scheduling
if ((!QXK_ISR_CONTEXT_()) // not inside ISR?
&& (QActive::registry_[0] != nullptr)) // kernel started?
{
- static_cast<void>(QXK_sched_(0U)); // synchronous scheduling
+ static_cast<void>(QXK_sched_()); // synchronous scheduling
}
@@ -10992,7 +10979,7 @@ else {
// remember the blocking object (this semaphore)
curr->m_temp.obj = QXK_PTR_CAST_(QMState*, this);
- curr->teArm_(static_cast<enum_t>(QXK::SEMA_SIG), nTicks);
+ curr->teArm_(static_cast<enum_t>(QXK::TIMEOUT_SIG), nTicks);
QS_BEGIN_NOCRIT_PRE_(QS_SEM_BLOCK, curr->m_prio)
QS_TIME_PRE_(); // timestamp
@@ -11001,7 +10988,7 @@ else {
QS_END_NOCRIT_PRE_()
// schedule the next thread if multitasking started
- static_cast<void>(QXK_sched_(0U)); // synchronous scheduling
+ static_cast<void>(QXK_sched_()); // synchronous scheduling
QF_CRIT_X_();
QF_CRIT_EXIT_NOP(); // BLOCK here !!!
@@ -11157,7 +11144,7 @@ if (m_count < m_max_count) {
QS_END_NOCRIT_PRE_()
if (!QXK_ISR_CONTEXT_()) { // not inside ISR?
- static_cast<void>(QXK_sched_(0U)); // synchronous scheduling
+ static_cast<void>(QXK_sched_()); // synchronous scheduling
}
}
}
@@ -11218,7 +11205,7 @@ return signaled;
- noexcept override
+ noexcept
//! initialize the QXK priority-ceiling mutex QP::QXMutex
//!
//! @details
@@ -11242,18 +11229,15 @@ return signaled;
//! the priority and priority-threshold of the holding thread to the
//! priority specification in `prioSpec` (see QP::QPrioSpec).
//!
-//! @attention
-//! When the priority-ceiling protocol is used (`prioSpec != 0`), the
-//! QF-priority specified in `prioSpec` must be unused by any other thread
-//! or mutex. Also, the priority-threshold must be higher or equal to the
-//! threshold of any thread that uses this mutex (see QP::QPrioSpec).
-//!
//! @usage
//! @include qxk_mutex.cpp
- m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU);
-m_pthre = static_cast<std::uint8_t>(prioSpec >> 8U);
+ //! @pre preemption-threshold must not be used
+Q_REQUIRE_ID(100, (prioSpec & 0xFF00U) == 0U);
+
+m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU);
+m_pthre = 0U; // preemption-threshold not used
if (prioSpec != 0U) { // priority-ceiling protocol used?
register_(); // register this mutex as AO
@@ -11495,7 +11479,7 @@ else { // the mutex is already locked by a different thread
// set the blocking object (this mutex)
curr->m_temp.obj = QXK_PTR_CAST_(QMState*, this);
- curr->teArm_(static_cast<enum_t>(QXK::MUTEX_SIG), nTicks);
+ curr->teArm_(static_cast<enum_t>(QXK::TIMEOUT_SIG), nTicks);
QS_BEGIN_NOCRIT_PRE_(QS_MTX_BLOCK, curr->m_prio)
QS_TIME_PRE_(); // timestamp
@@ -11505,7 +11489,7 @@ else { // the mutex is already locked by a different thread
QS_END_NOCRIT_PRE_()
// schedule the next thread if multitasking started
- static_cast<void>(QXK_sched_(0U)); // synchronous scheduling
+ static_cast<void>(QXK_sched_()); // synchronous scheduling
QF_CRIT_X_();
QF_CRIT_EXIT_NOP(); // BLOCK here !!!
@@ -11663,8 +11647,8 @@ if (m_eQueue.m_nFree == 1U) {
}
// schedule the next thread if multitasking started
- if (QXK_sched_(0U) != 0U) { // synchronous preemption needed?
- QXK_activate_(0U); // synchronously activate basic threads
+ if (QXK_sched_() != 0U) { // synchronous preemption needed?
+ QXK_activate_(); // synchronously activate basic threads
}
}
else { // releasing one level of nested mutex lock
@@ -11699,11 +11683,11 @@ bzero(&QXK_attr_, sizeof(QXK_attr_));
QXK_attr_.lockCeil = (QF_MAX_ACTIVE + 1U); // scheduler locked
// QXK idle AO object (const in ROM)
-static QActive * const idle_obj[(sizeof(QActive)/sizeof(QActive*)) + 1U]
+static QActive * const idle_ao[(sizeof(QActive)/sizeof(QActive*)) + 1U]
= { nullptr };
// register the idle AO object (cast 'const' away)
QActive::registry_[0] = QF_CONST_CAST_(QActive*,
- QXK_PTR_CAST_(QActive const*, &idle_obj[0]));
+ QXK_PTR_CAST_(QActive const*, &idle_ao[0]));
#ifdef QXK_INIT
QXK_INIT(); // port-specific initialization of the QXK kernel
@@ -11724,9 +11708,10 @@ QXK_INIT(); // port-specific initialization of the QXK kernel
QXK_attr_.lockCeil = 0U; // unlock the scheduler
// any active objects need to be scheduled before starting event loop?
-if (QXK_sched_(0U) != 0U) { // synchronous preemption needed?
- QXK_activate_(0U); // synchronously activate AOs to process events
+if (QXK_sched_() != 0U) { // synchronous preemption needed?
+ QXK_activate_(); // synchronously activate AOs to process events
}
+
onStartup(); // application-specific startup callback
// produce the QS_QF_RUN trace record
@@ -11735,6 +11720,9 @@ QS_END_NOCRIT_PRE_()
QF_INT_ENABLE();
+QS_SIG_DICTIONARY(QP::QXK::DELAY_SIG, nullptr);
+QS_SIG_DICTIONARY(QP::QXK::TIMEOUT_SIG, nullptr);
+
// the QXK idle loop...
for (;;) {
QXK::onIdle(); // application-specific QXK idle callback
@@ -11770,15 +11758,18 @@ Q_UNUSED_PAR(stkSize); // not needed in QXK
//! @pre AO cannot be started:
//! - from an ISR;
//! - the stack storage must NOT be provided
+//! - preemption-threshold is NOT provided (because QXK kernel
+//! does not support preemption-threshold scheduling)
Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_())
- && (stkSto == nullptr));
+ && (stkSto == nullptr)
+ && ((prioSpec & 0xFF00U) == 0U));
m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU); // QF-prio.
-m_pthre = static_cast<std::uint8_t>(prioSpec >> 8U); // preemption-thre.
+m_pthre = 0U; // preemption-threshold NOT used
register_(); // make QF aware of this AO
-m_osObject = nullptr; // no private stack for AO
m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO
+m_osObject = nullptr; // no private stack for AO
this->init(par, m_prio); // take the top-most initial tran. (virtual)
QS_FLUSH(); // flush the trace buffer to the host
@@ -11786,8 +11777,10 @@ QS_FLUSH(); // flush the trace buffer to the host
// see if this AO needs to be scheduled in case QXK is running
QF_CRIT_STAT_
QF_CRIT_E_();
-if (QXK_sched_(0U) != 0U) { // synchronous preemption needed?
- QXK_activate_(0U); // synchronously activate basic threads
+if (QXK_attr_.lockCeil <= QF_MAX_ACTIVE) { // scheduler running?
+ if (QXK_sched_() != 0U) { // synchronous preemption needed?
+ QXK_activate_(); // synchronously activate basic threads
+ }
}
QF_CRIT_X_();
@@ -11806,8 +11799,8 @@ QF_CRIT_X_();
{
QP::QActive * volatile curr; //!< currently executing thread
QP::QActive * volatile next; //!< next thread to execute
- std::uint8_t volatile actPrio; //!< prio of the active AO
- std::uint8_t volatile actThre; //!< active preemption-threshold
+ QP::QActive * volatile prev; //!< previous thread
+ std::uint8_t volatile actPrio; //!< QF-prio of the active AO
std::uint8_t volatile lockCeil; //!< lock preemption-ceiling (0==no-lock)
std::uint8_t volatile lockHolder; //!< prio of the lock holder
};
@@ -11821,9 +11814,6 @@ QF_CRIT_X_();
noexcept
//! QXK scheduler finds the highest-priority thread ready to run
//!
-//! @param[in] asynch flag conveying the type of scheduling:
-//! != 0 for asynchronous scheduling and
-//! == 0 for synchronous scheduling
//! @details
//! The QXK scheduler finds the priority of the highest-priority thread
//! that is ready to run.
@@ -11834,103 +11824,56 @@ QF_CRIT_X_();
//! @attention
//! QXK_sched_() must be always called with interrupts **disabled** and
//! returns with interrupts **disabled**.
-
-
- Q_UNUSED_PAR(asynch); // unused when Q_SPY not defined
+ std::uint_fast8_t p;
-// find the highest-prio thread ready to run
-std::uint_fast8_t p = QP::QF::readySet_.findMax();
-
-if (p <= QXK_attr_.lockCeil) {
- // priority of the thread holding the lock
- p = static_cast<std::uint_fast8_t>(
- QP::QActive::registry_[QXK_attr_.lockHolder]->m_prio);
- if (p != 0U) {
- Q_ASSERT_ID(610, QP::QF::readySet_.hasElement(p));
+if (QP::QF::readySet_.isEmpty()) {
+ p = 0U; // no activation needed
+}
+else {
+ // find the highest-prio thread ready to run
+ p = QP::QF::readySet_.findMax();
+ if (p <= QXK_attr_.lockCeil) {
+ // priority of the thread holding the lock
+ p = static_cast<std::uint_fast8_t>(
+ QP::QActive::registry_[QXK_attr_.lockHolder]->m_prio);
+ if (p != 0U) {
+ Q_ASSERT_ID(610, QP::QF::readySet_.hasElement(p));
+ }
}
}
-
+QP::QActive const * const curr = QXK_attr_.curr;
QP::QActive * const next = QP::QActive::registry_[p];
// the thread found must be registered in QF
Q_ASSERT_ID(620, next != nullptr);
// is the current thread a basic-thread?
-if (QXK_attr_.curr == nullptr) {
+if (curr == nullptr) {
- // is next a basic-thread?
- if (next->m_osObject == nullptr) {
- // is the new priority above the actvie pre-thre?
- if (p > QXK_attr_.actThre) {
- QXK_attr_.next = next; // set the next AO to activate
- }
- else {
- QXK_attr_.next = nullptr;
+ // is the new priority above the active priority?
+ if (p > QXK_attr_.actPrio) {
+ QXK_attr_.next = next; // set the next AO to activate
+
+ if (next->m_osObject != nullptr) { // is next extended?
+ QXK_CONTEXT_SWITCH_();
p = 0U; // no activation needed
}
}
- else { // the next thread is extended
-
-#ifdef Q_SPY
- if (asynch != 0U) {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_PREEMPT, next->m_prio)
- QS_TIME_PRE_(); // timestamp
- // prio of the next AO & prio of the curr AO
- QS_2U8_PRE_(p, QXK_attr_.actPrio);
- QS_END_NOCRIT_PRE_() }
- else {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, next->m_prio)
- QS_TIME_PRE_(); // timestamp
- // prio of the next AO & prio of the curr AO
- QS_2U8_PRE_(p, QXK_attr_.actPrio);
- QS_END_NOCRIT_PRE_()
- }
-#endif // Q_SPY
-
- QXK_attr_.next = next;
+ else { // below the pre-thre
+ QXK_attr_.next = nullptr;
p = 0U; // no activation needed
- QXK_CONTEXT_SWITCH_();
}
}
else { // currently executing an extended-thread
-
- // is the next thread different from the current?
- if (next != QXK_attr_.curr) {
-
-#ifdef Q_SPY
- if (next->m_prio != 0U) {
- if (asynch != 0U) {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_PREEMPT, next->m_prio)
- QS_TIME_PRE_(); // timestamp
- // previous prio & current prio
- QS_2U8_PRE_(static_cast<std::uint8_t>(p),
- QXK_attr_.curr->m_prio);
- QS_END_NOCRIT_PRE_()
- }
- else {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, next->m_prio)
- QS_TIME_PRE_(); // timestamp
- // previous prio & current prio
- QS_2U8_PRE_(static_cast<std::uint8_t>(p),
- QXK_attr_.curr->m_prio);
- QS_END_NOCRIT_PRE_()
- }
- }
- else { // resuming the idle thread
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_IDLE, 0U)
- QS_TIME_PRE_(); // timestamp
- QS_U8_PRE_(QXK_attr_.curr->m_prio); // previous prio
- QS_END_NOCRIT_PRE_()
- }
-#endif
+ // is the current thread different from the next?
+ if (curr != next) {
QXK_attr_.next = next;
- p = 0U; // no activation needed
QXK_CONTEXT_SWITCH_();
}
else { // next is the same as current
QXK_attr_.next = nullptr; // no need to context-switch
- p = 0U; // no activation needed
}
+ p = 0U; // no activation needed
}
return p;
@@ -11940,9 +11883,6 @@ return p;
//! QXK activator activates the next active object. The activated AO preempts
//! the currently executing AOs
//!
-//! @param[in] asynch flag conveying the type of activation:
-//! != 0 for asynchronous activation and
-//! == 0 for synchronous activation
//! @attention
//! QXK_activate_() must be always called with interrupts **disabled** and
//! returns with interrupts **disabled**.
@@ -11950,63 +11890,26 @@ return p;
//! @note
//! The activate function might enable interrupts internally, but it always
//! returns with interrupts **disabled**.
-
-
- Q_UNUSED_PAR(asynch); // unused when Q_SPY not defined
-
-std::uint8_t const prio_in = QXK_attr_.actPrio;
-QP::QActive *a = QXK_attr_.next; // the next AO (basic-thread) to run
+ std::uint8_t const prio_in = QXK_attr_.actPrio;
+QP::QActive *next = QXK_attr_.next; // the next AO (basic-thread) to run
//! @pre QXK_attr_.next must be valid and the prio must be in range
-Q_REQUIRE_ID(700, (a != nullptr) && (prio_in <= QF_MAX_ACTIVE));
+Q_REQUIRE_ID(700, (next != nullptr) && (prio_in <= QF_MAX_ACTIVE));
// QXK Context switch callback defined or QS tracing enabled?
#if (defined QXK_ON_CONTEXT_SW) || (defined Q_SPY)
-std::uint_fast8_t pprev = prio_in;
+QXK_contextSw(next);
#endif // QXK_ON_CONTEXT_SW || Q_SPY
-// priority and preemption-threshold of the next AO
-std::uint_fast8_t p = static_cast<std::uint_fast8_t>(a->m_prio);
+QXK_attr_.next = nullptr; // clear the next AO
+QXK_attr_.curr = nullptr; // current is basic-thread
+
+// priority of the next thread
+std::uint_fast8_t p = static_cast<std::uint_fast8_t>(next->m_prio);
// loop until no more ready-to-run AOs of higher prio than the initial
do {
- a = QP::QActive::registry_[p]; // obtain the pointer to the AO
-
- QXK_attr_.actPrio = static_cast<std::uint8_t>(p); // new active prio
- QXK_attr_.actThre = QP::QActive::registry_[p]->m_pthre; // new pthre
- QXK_attr_.next = nullptr; // clear the next AO
-
-#ifdef Q_SPY
- if ((asynch != 0U) && (pprev == prio_in)) {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_PREEMPT, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(p, pprev); // next prio & prev prio
- QS_END_NOCRIT_PRE_()
- }
- else {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(p, pprev); // next prio & prev prio
- QS_END_NOCRIT_PRE_()
- }
-#endif // Q_SPY
-
-#if (defined QXK_ON_CONTEXT_SW) || (defined Q_SPY)
- if (p != pprev) { // changing threads?
-
-#ifdef QXK_ON_CONTEXT_SW
- Q_ASSERT_ID(710, pprev <= QF_MAX_ACTIVE);
-
- // context-switch callback
- QXK_onContextSw(((pprev!=0U)
- ? QP::QActive::registry_[pprev]
- : nullptr),
- a);
-#endif // QXK_ON_CONTEXT_SW
-
- pprev = p; // update previous priority
- }
-#endif // QXK_ON_CONTEXT_SW || Q_SPY
+ QXK_attr_.actPrio = static_cast<std::uint8_t>(p); // next active prio
QF_INT_ENABLE(); // unconditionally enable interrupts
@@ -12016,109 +11919,81 @@ do {
// 2. dispatch the event to the AO's state machine.
// 3. determine if event is garbage and collect it if so
//
- QP::QEvt const * const e = a->get_();
- a->dispatch(e, a->m_prio);
+ QP::QEvt const * const e = next->get_();
+ next->dispatch(e, next->m_prio);
#if (QF_MAX_EPOOL > 0U)
QP::QF::gc(e);
#endif
+
QF_INT_DISABLE(); // unconditionally disable interrupts
- if (a->m_eQueue.isEmpty()) { // empty queue?
+ if (next->m_eQueue.isEmpty()) { // empty queue?
QP::QF::readySet_.remove(p);
}
- // find new highest-prio AO ready to run...
- p = QP::QF::readySet_.findMax();
- a = QP::QActive::registry_[p];
-
- // the AO must be registered in QF
- Q_ASSERT_ID(720, a != nullptr);
-
- // is the new priority below the lock ceiling?
- if (p <= static_cast<std::uint_fast8_t>(QXK_attr_.lockCeil)) {
- p = static_cast<std::uint_fast8_t>(QXK_attr_.lockHolder);
- if (p != 0U) {
- Q_ASSERT_ID(710, QP::QF::readySet_.hasElement(p));
- }
+ if (QP::QF::readySet_.isEmpty()) {
+ QXK_attr_.next = nullptr;
+ next = QP::QActive::registry_[0];
+ p = 0U; // no activation needed
}
+ else {
+ // find new highest-prio AO ready to run...
+ p = QP::QF::readySet_.findMax();
+ next = QP::QActive::registry_[p];
- // is the next a basic thread?
- if (a->m_osObject == nullptr) {
- // is the new priority above the initial pre-thre?
- if (p > QP::QActive::registry_[prio_in]->m_pthre) {
- QXK_attr_.next = a;
+ // the AO must be registered in QF
+ Q_ASSERT_ID(710, next != nullptr);
+
+ // is the new priority below the lock ceiling?
+ if (p <= static_cast<std::uint_fast8_t>(QXK_attr_.lockCeil)) {
+ p = static_cast<std::uint_fast8_t>(QXK_attr_.lockHolder);
+ if (p != 0U) {
+ Q_ASSERT_ID(720, QP::QF::readySet_.hasElement(p));
+ }
}
- else {
- QXK_attr_.next = nullptr;
+
+ // is the next a basic thread?
+ if (next->m_osObject == nullptr) {
+ // is the next priority above the initial priority?
+ if (p > QP::QActive::registry_[prio_in]->m_prio) {
+#if (defined QXK_ON_CONTEXT_SW) || (defined Q_SPY)
+ if (p != QXK_attr_.actPrio) { // changing threads?
+ QXK_contextSw(next);
+ }
+#endif // QXK_ON_CONTEXT_SW || Q_SPY
+ QXK_attr_.next = next;
+ }
+ else {
+ QXK_attr_.next = nullptr;
+ p = 0U; // no activation needed
+ }
+ }
+ else { // next is the extended-thread
+ QXK_attr_.next = next;
+ QXK_CONTEXT_SWITCH_();
p = 0U; // no activation needed
}
}
- else { // next is the extended thread
+} while (p != 0U); // while activation needed
-#ifdef Q_SPY
- if (asynch != 0U) {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_PREEMPT, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(p, QXK_attr_.actPrio);
- QS_END_NOCRIT_PRE_()
- }
- else {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(p, QXK_attr_.actPrio);
- QS_END_NOCRIT_PRE_()
- }
-#endif // Q_SPY
-
- QXK_attr_.next = a;
- p = 0U; // no activation needed
- QXK_CONTEXT_SWITCH_();
- }
-} while (p != 0U); // while preemption needed
-
-// restore the active priority and preemption-threshold
+// restore the active priority
QXK_attr_.actPrio = prio_in;
-QXK_attr_.actThre = QP::QActive::registry_[prio_in]->m_pthre;
#if (defined QXK_ON_CONTEXT_SW) || (defined Q_SPY)
-if (prio_in != 0U) { // resuming an active object?
- a = QP::QActive::registry_[prio_in]; // pointer to the preempted AO
-
-#ifdef Q_SPY
- if (asynch != 0U) {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_RESTORE, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(prio_in, pprev); // resumed prio & previous prio
- QS_END_NOCRIT_PRE_()
- }
- else {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_RESUME, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(prio_in, pprev); // resumed prio & previous prio
- QS_END_NOCRIT_PRE_()
- }
-#endif // Q_SPY
+if (next->m_osObject == nullptr) {
+ QXK_contextSw((prio_in == 0U)
+ ? nullptr
+ : QP::QActive::registry_[prio_in]);
}
-else { // resuming priority==0 --> idle
- a = nullptr;
-
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_IDLE, 0U)
- QS_TIME_PRE_(); // timestamp
- QS_U8_PRE_(pprev); // previous prio
- QS_END_NOCRIT_PRE_()
-}
-
-#ifdef QXK_ON_CONTEXT_SW
-// context-switch callback
-QXK_onContextSw(QP::QActive::registry_[pprev], a);
-#endif // QXK_ON_CONTEXT_SW
-
#endif // QXK_ON_CONTEXT_SW || Q_SPY
noexcept
- //! return the currently executing active-object/thread
+ //! obtain the currently executing active-object/thread
+//!
+//! @returns
+//! pointer to the currently executing active-object/thread
//! @pre the QXK kernel must be running
Q_REQUIRE_ID(800, QXK_attr_.lockCeil <= QF_MAX_ACTIVE);
@@ -12149,6 +12024,51 @@ return curr;
+
+
+ //! QXK context switch management
+//!
+//! @details
+//! This function performs software tracing (if #Q_SPY is defined)
+//! and calls QXK_onContextSw() (if #QXK_ON_CONTEXT_SW is defined)
+//!
+//! @param[in] next pointer to the next thread (NULL for basic-thread)
+//!
+//! @attention
+//! QXK_contextSw() is invoked with interrupts **disabled** and must also
+//! return with interrupts **disabled**.
+
+
+ std::uint8_t const prev_prio = (QXK_attr_.prev != nullptr)
+ ? QXK_attr_.prev->m_prio
+ : 0U;
+std::uint8_t const next_prio = (next != nullptr)
+ ? next->m_prio
+ : QXK_attr_.actPrio;
+
+if (next_prio == 0U) { // going to idle?
+ QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_IDLE, 0U)
+ QS_TIME_PRE_(); // timestamp
+ QS_U8_PRE_(prev_prio);
+ QS_END_NOCRIT_PRE_()
+
+#ifdef QXK_ON_CONTEXT_SW
+ QXK_onContextSw(QXK_attr_.prev, nullptr);
+#endif // QXK_ON_CONTEXT_SW
+}
+else {
+ QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, next_prio)
+ QS_TIME_PRE_(); // timestamp
+ QS_2U8_PRE_(next_prio, prev_prio);
+ QS_END_NOCRIT_PRE_()
+
+#ifdef QXK_ON_CONTEXT_SW
+ QXK_onContextSw(QXK_attr_.prev, next);
+#endif // QXK_ON_CONTEXT_SW
+}
+
+QXK_attr_.prev = next; // update the previous thread
+
//! QXK context switch callback (customized in BSPs for QXK)
@@ -12206,7 +12126,7 @@ std::uint_fast8_t const p =
// remove this thread from the QF
QP::QActive::registry_[p] = nullptr;
QP::QF::readySet_.remove(p);
-static_cast<void>(QXK_sched_(0U)); // synchronous scheduling
+static_cast<void>(QXK_sched_()); // synchronous scheduling
QF_CRIT_X_();
@@ -12301,8 +12221,8 @@ QF_CRIT_X_();
QF::readySet_.insert( \
static_cast<std::uint_fast8_t>((me_)->m_prio)); \
if (!QXK_ISR_CONTEXT_()) { \
- if (QXK_sched_(0U) != 0U) { \
- QXK_activate_(0U); \
+ if (QXK_sched_() != 0U) { \
+ QXK_activate_(); \
} \
} \
} while (false)
@@ -12328,7 +12248,7 @@ QF_CRIT_X_();
// major version number, Y is a 1-digit minor version number, and Z is
// a 1-digit release number.
//
-#define QP_VERSION 710U
+#define QP_VERSION 712U
//! The current QP version as a zero terminated string literal.
//
@@ -12337,10 +12257,10 @@ QF_CRIT_X_();
// major version number, Y is a 1-digit minor version number, and Z is
// a 1-digit release number.
//
-#define QP_VERSION_STR "7.1.0"
+#define QP_VERSION_STR "7.1.2"
-//! Encrypted current QP release (7.1.0) and date (2022-08-30)
-#define QP_RELEASE 0x7C600159U
+//! Encrypted current QP release (7.1.2) and date (2022-10-07)
+#define QP_RELEASE 0x7C44FF47U
//============================================================================
// Global namespace...
diff --git a/src/qf/qf_time.cpp b/src/qf/qf_time.cpp
index 55e7a638..be14d823 100644
--- a/src/qf/qf_time.cpp
+++ b/src/qf/qf_time.cpp
@@ -85,7 +85,7 @@ QTimeEvt::QTimeEvt(
m_interval(0U)
{
//! @pre The signal must be valid and the tick rate in range
- Q_REQUIRE_ID(300, (sgnl >= Q_USER_SIG)
+ Q_REQUIRE_ID(300, (sgnl != 0)
&& (tickRate < QF_MAX_TICK_RATE));
#ifndef Q_EVT_CTOR
diff --git a/src/qk/qk.cpp b/src/qk/qk.cpp
index 5ca5600a..ca136bd9 100644
--- a/src/qk/qk.cpp
+++ b/src/qk/qk.cpp
@@ -123,8 +123,8 @@ void schedUnlock(QSchedStatus const stat) noexcept {
QS_BEGIN_NOCRIT_PRE_(QS_SCHED_UNLOCK, 0U)
QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(lockCeil, // current lock ceiling (old)
- prevCeil); // previous lock ceiling (new)
+ // current lock ceiling (old), previous lock ceiling (new)
+ QS_2U8_PRE_(lockCeil, prevCeil);
QS_END_NOCRIT_PRE_()
// restore the previous lock ceiling and lock holder
@@ -133,7 +133,7 @@ void schedUnlock(QSchedStatus const stat) noexcept {
// find if any AOs should be run after unlocking the scheduler
if (QK_sched_() != 0U) { // synchronous preemption needed?
- QK_activate_(0U); // synchronously activate any unlocked AOs
+ QK_activate_(); // synchronously activate any unlocked AOs
}
QF_CRIT_X_();
@@ -179,7 +179,7 @@ int_t run() {
// any active objects need to be scheduled before starting event loop?
if (QK_sched_() != 0U) { // synchronous preemption needed?
- QK_activate_(0U); // synchronously activate AOs to process events
+ QK_activate_(); // synchronously activate AOs to process events
}
onStartup(); // application-specific startup callback
@@ -238,7 +238,7 @@ void QActive::start(
QF_CRIT_STAT_
QF_CRIT_E_();
if (QK_sched_() != 0U) { // synchronous preemption needed?
- QK_activate_(0U); // synchronously activate AOs
+ QK_activate_(); // synchronously activate AOs
}
QF_CRIT_X_();
}
@@ -255,28 +255,32 @@ QK_Attr QK_attr_;
//${QK-extern-C::QK_sched_} ..................................................
std::uint_fast8_t QK_sched_() noexcept {
- // find the highest-prio AO with non-empty event queue
- std::uint_fast8_t p = QP::QF::readySet_.findMax();
+ std::uint_fast8_t p;
- // is the AO's priority below the active preemption-threshold?
- if (p <= QK_attr_.actThre) {
- p = 0U; // no preemption needed
- }
- // is the AO's priority below the lock preemption-ceiling?
- else if (p <= QK_attr_.lockCeil) {
- p = 0U; // no preemption needed
+ if (QP::QF::readySet_.isEmpty()) {
+ p = 0U; // no activation needed
}
else {
- Q_ASSERT_ID(410, p <= QF_MAX_ACTIVE);
- QK_attr_.nextPrio = static_cast(p); // next AO to run
+ // find the highest-prio AO with non-empty event queue
+ p = QP::QF::readySet_.findMax();
+
+ // is the AO's priority below the active preemption-threshold?
+ if (p <= QK_attr_.actThre) {
+ p = 0U; // no activation needed
+ }
+ // is the AO's priority below the lock preemption-ceiling?
+ else if (p <= QK_attr_.lockCeil) {
+ p = 0U; // no activation needed
+ }
+ else {
+ QK_attr_.nextPrio = static_cast(p);
+ }
}
return p;
}
//${QK-extern-C::QK_activate_} ...............................................
-void QK_activate_(std::uint_fast8_t const asynch) noexcept {
- Q_UNUSED_PAR(asynch); // unused when Q_SPY not defined
-
+void QK_activate_() noexcept {
std::uint8_t const prio_in = QK_attr_.actPrio; // saved initial priority
std::uint_fast8_t p = QK_attr_.nextPrio; // next prio to run
QK_attr_.nextPrio = 0U; // clear for the next time
@@ -298,25 +302,14 @@ void QK_activate_(std::uint_fast8_t const asynch) noexcept {
QK_attr_.actPrio = static_cast(p);
QK_attr_.actThre = QP::QActive::registry_[p]->m_pthre;
- #ifdef Q_SPY
- if ((asynch != 0U) && (pprev == prio_in)) {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_PREEMPT, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(p, // priority of the scheduled AO
- pprev); // previous priority
- QS_END_NOCRIT_PRE_()
- }
- else {
+ #if (defined QK_ON_CONTEXT_SW) || (defined Q_SPY)
+ if (p != pprev) { // changing threads?
+
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a->m_prio)
QS_TIME_PRE_(); // timestamp
QS_2U8_PRE_(p, // priority of the scheduled AO
pprev); // previous priority
QS_END_NOCRIT_PRE_()
- }
- #endif // Q_SPY
-
- #if (defined QK_ON_CONTEXT_SW) || (defined Q_SPY)
- if (p != pprev) { // changing threads?
#ifdef QK_ON_CONTEXT_SW
// context-switch callback
@@ -341,6 +334,7 @@ void QK_activate_(std::uint_fast8_t const asynch) noexcept {
#if (QF_MAX_EPOOL > 0U)
QP::QF::gc(e);
#endif
+
// determine the next highest-priority AO ready to run...
QF_INT_DISABLE(); // unconditionally disable interrupts
@@ -348,19 +342,24 @@ void QK_activate_(std::uint_fast8_t const asynch) noexcept {
QP::QF::readySet_.remove(p);
}
- // find new highest-prio AO ready to run...
- p = QP::QF::readySet_.findMax();
-
- // is the new priority below the initial preemption-threshold?
- if (p <= QP::QActive::registry_[prio_in]->m_pthre) {
- p = 0U; // no preemption needed
- }
- // is the AO's priority below the lock preemption-ceiling?
- else if (p <= QK_attr_.lockCeil) {
- p = 0U; // no preemption needed
+ if (QP::QF::readySet_.isEmpty()) {
+ p = 0U; // no activation needed
}
else {
- Q_ASSERT_ID(510, p <= QF_MAX_ACTIVE);
+ // find new highest-prio AO ready to run...
+ p = QP::QF::readySet_.findMax();
+
+ // is the new priority below the initial preemption-threshold?
+ if (p <= QP::QActive::registry_[prio_in]->m_pthre) {
+ p = 0U; // no activation needed
+ }
+ // is the AO's priority below the lock preemption-ceiling?
+ else if (p <= QK_attr_.lockCeil) {
+ p = 0U; // no activation needed
+ }
+ else {
+ Q_ASSERT_ID(510, p <= QF_MAX_ACTIVE);
+ }
}
} while (p != 0U);
@@ -372,22 +371,11 @@ void QK_activate_(std::uint_fast8_t const asynch) noexcept {
if (prio_in != 0U) { // resuming an active object?
a = QP::QActive::registry_[prio_in]; // pointer to preempted AO
- #ifdef Q_SPY
- if (asynch != 0U) {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_RESTORE, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(prio_in, // priority of the resumed AO
- pprev); // previous priority
- QS_END_NOCRIT_PRE_()
- }
- else {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_RESUME, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(prio_in, // priority of the resumed AO
- pprev); // previous priority
- QS_END_NOCRIT_PRE_()
- }
- #endif // Q_SPY
+ QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a->m_prio)
+ QS_TIME_PRE_(); // timestamp
+ // priority of the resumed AO, previous priority
+ QS_2U8_PRE_(prio_in, pprev);
+ QS_END_NOCRIT_PRE_()
}
else { // resuming priority==0 --> idle
a = nullptr; // QK idle loop
diff --git a/src/qxk/qxk.cpp b/src/qxk/qxk.cpp
index 1aa12947..210c2526 100644
--- a/src/qxk/qxk.cpp
+++ b/src/qxk/qxk.cpp
@@ -136,8 +136,8 @@ void schedUnlock(QSchedStatus const stat) noexcept {
QXK_attr_.lockHolder = static_cast(stat & 0xFFU);
// find the highest-prio thread ready to run
- if (QXK_sched_(0U) != 0U) { // synchronous preemption needed?
- QXK_activate_(0U); // synchronously activate unlocked AOs
+ if (QXK_sched_() != 0U) { // synchronous preemption needed?
+ QXK_activate_(); // synchronously activate unlocked AOs
}
QF_CRIT_X_();
@@ -166,11 +166,11 @@ void init() {
QXK_attr_.lockCeil = (QF_MAX_ACTIVE + 1U); // scheduler locked
// QXK idle AO object (const in ROM)
- static QActive * const idle_obj[(sizeof(QActive)/sizeof(QActive*)) + 1U]
+ static QActive * const idle_ao[(sizeof(QActive)/sizeof(QActive*)) + 1U]
= { nullptr };
// register the idle AO object (cast 'const' away)
QActive::registry_[0] = QF_CONST_CAST_(QActive*,
- QXK_PTR_CAST_(QActive const*, &idle_obj[0]));
+ QXK_PTR_CAST_(QActive const*, &idle_ao[0]));
#ifdef QXK_INIT
QXK_INIT(); // port-specific initialization of the QXK kernel
@@ -189,9 +189,10 @@ int_t run() {
QXK_attr_.lockCeil = 0U; // unlock the scheduler
// any active objects need to be scheduled before starting event loop?
- if (QXK_sched_(0U) != 0U) { // synchronous preemption needed?
- QXK_activate_(0U); // synchronously activate AOs to process events
+ if (QXK_sched_() != 0U) { // synchronous preemption needed?
+ QXK_activate_(); // synchronously activate AOs to process events
}
+
onStartup(); // application-specific startup callback
// produce the QS_QF_RUN trace record
@@ -200,6 +201,9 @@ int_t run() {
QF_INT_ENABLE();
+ QS_SIG_DICTIONARY(QP::QXK::DELAY_SIG, nullptr);
+ QS_SIG_DICTIONARY(QP::QXK::TIMEOUT_SIG, nullptr);
+
// the QXK idle loop...
for (;;) {
QXK::onIdle(); // application-specific QXK idle callback
@@ -233,15 +237,18 @@ void QActive::start(
//! @pre AO cannot be started:
//! - from an ISR;
//! - the stack storage must NOT be provided
+ //! - preemption-threshold is NOT provided (because QXK kernel
+ //! does not support preemption-threshold scheduling)
Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_())
- && (stkSto == nullptr));
+ && (stkSto == nullptr)
+ && ((prioSpec & 0xFF00U) == 0U));
m_prio = static_cast(prioSpec & 0xFFU); // QF-prio.
- m_pthre = static_cast(prioSpec >> 8U); // preemption-thre.
+ m_pthre = 0U; // preemption-threshold NOT used
register_(); // make QF aware of this AO
- m_osObject = nullptr; // no private stack for AO
m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO
+ m_osObject = nullptr; // no private stack for AO
this->init(par, m_prio); // take the top-most initial tran. (virtual)
QS_FLUSH(); // flush the trace buffer to the host
@@ -249,8 +256,10 @@ void QActive::start(
// see if this AO needs to be scheduled in case QXK is running
QF_CRIT_STAT_
QF_CRIT_E_();
- if (QXK_sched_(0U) != 0U) { // synchronous preemption needed?
- QXK_activate_(0U); // synchronously activate basic threads
+ if (QXK_attr_.lockCeil <= QF_MAX_ACTIVE) { // scheduler running?
+ if (QXK_sched_() != 0U) { // synchronous preemption needed?
+ QXK_activate_(); // synchronously activate basic threads
+ }
}
QF_CRIT_X_();
}
@@ -266,163 +275,83 @@ extern "C" {
QXK_Attr QXK_attr_;
//${QXK-extern-C::QXK_sched_} ................................................
-std::uint_fast8_t QXK_sched_(std::uint_fast8_t const asynch) noexcept {
- Q_UNUSED_PAR(asynch); // unused when Q_SPY not defined
+std::uint_fast8_t QXK_sched_() noexcept {
+ std::uint_fast8_t p;
- // find the highest-prio thread ready to run
- std::uint_fast8_t p = QP::QF::readySet_.findMax();
-
- if (p <= QXK_attr_.lockCeil) {
- // priority of the thread holding the lock
- p = static_cast(
- QP::QActive::registry_[QXK_attr_.lockHolder]->m_prio);
- if (p != 0U) {
- Q_ASSERT_ID(610, QP::QF::readySet_.hasElement(p));
+ if (QP::QF::readySet_.isEmpty()) {
+ p = 0U; // no activation needed
+ }
+ else {
+ // find the highest-prio thread ready to run
+ p = QP::QF::readySet_.findMax();
+ if (p <= QXK_attr_.lockCeil) {
+ // priority of the thread holding the lock
+ p = static_cast(
+ QP::QActive::registry_[QXK_attr_.lockHolder]->m_prio);
+ if (p != 0U) {
+ Q_ASSERT_ID(610, QP::QF::readySet_.hasElement(p));
+ }
}
}
-
+ QP::QActive const * const curr = QXK_attr_.curr;
QP::QActive * const next = QP::QActive::registry_[p];
// the thread found must be registered in QF
Q_ASSERT_ID(620, next != nullptr);
// is the current thread a basic-thread?
- if (QXK_attr_.curr == nullptr) {
+ if (curr == nullptr) {
- // is next a basic-thread?
- if (next->m_osObject == nullptr) {
- // is the new priority above the actvie pre-thre?
- if (p > QXK_attr_.actThre) {
- QXK_attr_.next = next; // set the next AO to activate
- }
- else {
- QXK_attr_.next = nullptr;
+ // is the new priority above the active priority?
+ if (p > QXK_attr_.actPrio) {
+ QXK_attr_.next = next; // set the next AO to activate
+
+ if (next->m_osObject != nullptr) { // is next extended?
+ QXK_CONTEXT_SWITCH_();
p = 0U; // no activation needed
}
}
- else { // the next thread is extended
-
- #ifdef Q_SPY
- if (asynch != 0U) {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_PREEMPT, next->m_prio)
- QS_TIME_PRE_(); // timestamp
- // prio of the next AO & prio of the curr AO
- QS_2U8_PRE_(p, QXK_attr_.actPrio);
- QS_END_NOCRIT_PRE_() }
- else {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, next->m_prio)
- QS_TIME_PRE_(); // timestamp
- // prio of the next AO & prio of the curr AO
- QS_2U8_PRE_(p, QXK_attr_.actPrio);
- QS_END_NOCRIT_PRE_()
- }
- #endif // Q_SPY
-
- QXK_attr_.next = next;
+ else { // below the pre-thre
+ QXK_attr_.next = nullptr;
p = 0U; // no activation needed
- QXK_CONTEXT_SWITCH_();
}
}
else { // currently executing an extended-thread
-
- // is the next thread different from the current?
- if (next != QXK_attr_.curr) {
-
- #ifdef Q_SPY
- if (next->m_prio != 0U) {
- if (asynch != 0U) {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_PREEMPT, next->m_prio)
- QS_TIME_PRE_(); // timestamp
- // previous prio & current prio
- QS_2U8_PRE_(static_cast(p),
- QXK_attr_.curr->m_prio);
- QS_END_NOCRIT_PRE_()
- }
- else {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, next->m_prio)
- QS_TIME_PRE_(); // timestamp
- // previous prio & current prio
- QS_2U8_PRE_(static_cast(p),
- QXK_attr_.curr->m_prio);
- QS_END_NOCRIT_PRE_()
- }
- }
- else { // resuming the idle thread
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_IDLE, 0U)
- QS_TIME_PRE_(); // timestamp
- QS_U8_PRE_(QXK_attr_.curr->m_prio); // previous prio
- QS_END_NOCRIT_PRE_()
- }
- #endif
+ // is the current thread different from the next?
+ if (curr != next) {
QXK_attr_.next = next;
- p = 0U; // no activation needed
QXK_CONTEXT_SWITCH_();
}
else { // next is the same as current
QXK_attr_.next = nullptr; // no need to context-switch
- p = 0U; // no activation needed
}
+ p = 0U; // no activation needed
}
return p;
}
//${QXK-extern-C::QXK_activate_} .............................................
-void QXK_activate_(std::uint_fast8_t const asynch) noexcept {
- Q_UNUSED_PAR(asynch); // unused when Q_SPY not defined
-
+void QXK_activate_() noexcept {
std::uint8_t const prio_in = QXK_attr_.actPrio;
- QP::QActive *a = QXK_attr_.next; // the next AO (basic-thread) to run
+ QP::QActive *next = QXK_attr_.next; // the next AO (basic-thread) to run
//! @pre QXK_attr_.next must be valid and the prio must be in range
- Q_REQUIRE_ID(700, (a != nullptr) && (prio_in <= QF_MAX_ACTIVE));
+ Q_REQUIRE_ID(700, (next != nullptr) && (prio_in <= QF_MAX_ACTIVE));
// QXK Context switch callback defined or QS tracing enabled?
#if (defined QXK_ON_CONTEXT_SW) || (defined Q_SPY)
- std::uint_fast8_t pprev = prio_in;
+ QXK_contextSw(next);
#endif // QXK_ON_CONTEXT_SW || Q_SPY
- // priority and preemption-threshold of the next AO
- std::uint_fast8_t p = static_cast(a->m_prio);
+ QXK_attr_.next = nullptr; // clear the next AO
+ QXK_attr_.curr = nullptr; // current is basic-thread
+
+ // priority of the next thread
+ std::uint_fast8_t p = static_cast(next->m_prio);
// loop until no more ready-to-run AOs of higher prio than the initial
do {
- a = QP::QActive::registry_[p]; // obtain the pointer to the AO
-
- QXK_attr_.actPrio = static_cast(p); // new active prio
- QXK_attr_.actThre = QP::QActive::registry_[p]->m_pthre; // new pthre
- QXK_attr_.next = nullptr; // clear the next AO
-
- #ifdef Q_SPY
- if ((asynch != 0U) && (pprev == prio_in)) {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_PREEMPT, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(p, pprev); // next prio & prev prio
- QS_END_NOCRIT_PRE_()
- }
- else {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(p, pprev); // next prio & prev prio
- QS_END_NOCRIT_PRE_()
- }
- #endif // Q_SPY
-
- #if (defined QXK_ON_CONTEXT_SW) || (defined Q_SPY)
- if (p != pprev) { // changing threads?
-
- #ifdef QXK_ON_CONTEXT_SW
- Q_ASSERT_ID(710, pprev <= QF_MAX_ACTIVE);
-
- // context-switch callback
- QXK_onContextSw(((pprev!=0U)
- ? QP::QActive::registry_[pprev]
- : nullptr),
- a);
- #endif // QXK_ON_CONTEXT_SW
-
- pprev = p; // update previous priority
- }
- #endif // QXK_ON_CONTEXT_SW || Q_SPY
+ QXK_attr_.actPrio = static_cast(p); // next active prio
QF_INT_ENABLE(); // unconditionally enable interrupts
@@ -432,103 +361,72 @@ void QXK_activate_(std::uint_fast8_t const asynch) noexcept {
// 2. dispatch the event to the AO's state machine.
// 3. determine if event is garbage and collect it if so
//
- QP::QEvt const * const e = a->get_();
- a->dispatch(e, a->m_prio);
+ QP::QEvt const * const e = next->get_();
+ next->dispatch(e, next->m_prio);
#if (QF_MAX_EPOOL > 0U)
QP::QF::gc(e);
#endif
+
QF_INT_DISABLE(); // unconditionally disable interrupts
- if (a->m_eQueue.isEmpty()) { // empty queue?
+ if (next->m_eQueue.isEmpty()) { // empty queue?
QP::QF::readySet_.remove(p);
}
- // find new highest-prio AO ready to run...
- p = QP::QF::readySet_.findMax();
- a = QP::QActive::registry_[p];
-
- // the AO must be registered in QF
- Q_ASSERT_ID(720, a != nullptr);
-
- // is the new priority below the lock ceiling?
- if (p <= static_cast(QXK_attr_.lockCeil)) {
- p = static_cast(QXK_attr_.lockHolder);
- if (p != 0U) {
- Q_ASSERT_ID(710, QP::QF::readySet_.hasElement(p));
- }
+ if (QP::QF::readySet_.isEmpty()) {
+ QXK_attr_.next = nullptr;
+ next = QP::QActive::registry_[0];
+ p = 0U; // no activation needed
}
+ else {
+ // find new highest-prio AO ready to run...
+ p = QP::QF::readySet_.findMax();
+ next = QP::QActive::registry_[p];
- // is the next a basic thread?
- if (a->m_osObject == nullptr) {
- // is the new priority above the initial pre-thre?
- if (p > QP::QActive::registry_[prio_in]->m_pthre) {
- QXK_attr_.next = a;
+ // the AO must be registered in QF
+ Q_ASSERT_ID(710, next != nullptr);
+
+ // is the new priority below the lock ceiling?
+ if (p <= static_cast(QXK_attr_.lockCeil)) {
+ p = static_cast(QXK_attr_.lockHolder);
+ if (p != 0U) {
+ Q_ASSERT_ID(720, QP::QF::readySet_.hasElement(p));
+ }
}
- else {
- QXK_attr_.next = nullptr;
+
+ // is the next a basic thread?
+ if (next->m_osObject == nullptr) {
+ // is the next priority above the initial priority?
+ if (p > QP::QActive::registry_[prio_in]->m_prio) {
+ #if (defined QXK_ON_CONTEXT_SW) || (defined Q_SPY)
+ if (p != QXK_attr_.actPrio) { // changing threads?
+ QXK_contextSw(next);
+ }
+ #endif // QXK_ON_CONTEXT_SW || Q_SPY
+ QXK_attr_.next = next;
+ }
+ else {
+ QXK_attr_.next = nullptr;
+ p = 0U; // no activation needed
+ }
+ }
+ else { // next is the extended-thread
+ QXK_attr_.next = next;
+ QXK_CONTEXT_SWITCH_();
p = 0U; // no activation needed
}
}
- else { // next is the extended thread
+ } while (p != 0U); // while activation needed
- #ifdef Q_SPY
- if (asynch != 0U) {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_PREEMPT, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(p, QXK_attr_.actPrio);
- QS_END_NOCRIT_PRE_()
- }
- else {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(p, QXK_attr_.actPrio);
- QS_END_NOCRIT_PRE_()
- }
- #endif // Q_SPY
-
- QXK_attr_.next = a;
- p = 0U; // no activation needed
- QXK_CONTEXT_SWITCH_();
- }
- } while (p != 0U); // while preemption needed
-
- // restore the active priority and preemption-threshold
+ // restore the active priority
QXK_attr_.actPrio = prio_in;
- QXK_attr_.actThre = QP::QActive::registry_[prio_in]->m_pthre;
#if (defined QXK_ON_CONTEXT_SW) || (defined Q_SPY)
- if (prio_in != 0U) { // resuming an active object?
- a = QP::QActive::registry_[prio_in]; // pointer to the preempted AO
-
- #ifdef Q_SPY
- if (asynch != 0U) {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_RESTORE, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(prio_in, pprev); // resumed prio & previous prio
- QS_END_NOCRIT_PRE_()
- }
- else {
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_RESUME, a->m_prio)
- QS_TIME_PRE_(); // timestamp
- QS_2U8_PRE_(prio_in, pprev); // resumed prio & previous prio
- QS_END_NOCRIT_PRE_()
- }
- #endif // Q_SPY
+ if (next->m_osObject == nullptr) {
+ QXK_contextSw((prio_in == 0U)
+ ? nullptr
+ : QP::QActive::registry_[prio_in]);
}
- else { // resuming priority==0 --> idle
- a = nullptr;
-
- QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_IDLE, 0U)
- QS_TIME_PRE_(); // timestamp
- QS_U8_PRE_(pprev); // previous prio
- QS_END_NOCRIT_PRE_()
- }
-
- #ifdef QXK_ON_CONTEXT_SW
- // context-switch callback
- QXK_onContextSw(QP::QActive::registry_[pprev], a);
- #endif // QXK_ON_CONTEXT_SW
-
#endif // QXK_ON_CONTEXT_SW || Q_SPY
}
@@ -552,6 +450,41 @@ QP::QActive * QXK_current() noexcept {
return curr;
}
+//${QXK-extern-C::QXK_contextSw} .............................................
+#if defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
+void QXK_contextSw(QP::QActive * const next) {
+ std::uint8_t const prev_prio = (QXK_attr_.prev != nullptr)
+ ? QXK_attr_.prev->m_prio
+ : 0U;
+ std::uint8_t const next_prio = (next != nullptr)
+ ? next->m_prio
+ : QXK_attr_.actPrio;
+
+ if (next_prio == 0U) { // going to idle?
+ QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_IDLE, 0U)
+ QS_TIME_PRE_(); // timestamp
+ QS_U8_PRE_(prev_prio);
+ QS_END_NOCRIT_PRE_()
+
+ #ifdef QXK_ON_CONTEXT_SW
+ QXK_onContextSw(QXK_attr_.prev, nullptr);
+ #endif // QXK_ON_CONTEXT_SW
+ }
+ else {
+ QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, next_prio)
+ QS_TIME_PRE_(); // timestamp
+ QS_2U8_PRE_(next_prio, prev_prio);
+ QS_END_NOCRIT_PRE_()
+
+ #ifdef QXK_ON_CONTEXT_SW
+ QXK_onContextSw(QXK_attr_.prev, next);
+ #endif // QXK_ON_CONTEXT_SW
+ }
+
+ QXK_attr_.prev = next; // update the previous thread
+}
+#endif // defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
+
//${QXK-extern-C::QXK_threadExit_} ...........................................
void QXK_threadExit_() {
QF_CRIT_STAT_
@@ -573,7 +506,7 @@ void QXK_threadExit_() {
// remove this thread from the QF
QP::QActive::registry_[p] = nullptr;
QP::QF::readySet_.remove(p);
- static_cast(QXK_sched_(0U)); // synchronous scheduling
+ static_cast(QXK_sched_()); // synchronous scheduling
QF_CRIT_X_();
}
//$enddef${QXK-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/qxk/qxk_mutex.cpp b/src/qxk/qxk_mutex.cpp
index 2eab986a..6123bfb4 100644
--- a/src/qxk/qxk_mutex.cpp
+++ b/src/qxk/qxk_mutex.cpp
@@ -79,8 +79,11 @@ QXMutex::QXMutex()
//${QXK::QXMutex::init} ......................................................
void QXMutex::init(QPrioSpec const prioSpec) noexcept {
+ //! @pre preemption-threshold must not be used
+ Q_REQUIRE_ID(100, (prioSpec & 0xFF00U) == 0U);
+
m_prio = static_cast(prioSpec & 0xFFU);
- m_pthre = static_cast(prioSpec >> 8U);
+ m_pthre = 0U; // preemption-threshold not used
if (prioSpec != 0U) { // priority-ceiling protocol used?
register_(); // register this mutex as AO
@@ -281,7 +284,7 @@ bool QXMutex::lock(std::uint_fast16_t const nTicks) noexcept {
// set the blocking object (this mutex)
curr->m_temp.obj = QXK_PTR_CAST_(QMState*, this);
- curr->teArm_(static_cast(QXK::MUTEX_SIG), nTicks);
+ curr->teArm_(static_cast(QXK::TIMEOUT_SIG), nTicks);
QS_BEGIN_NOCRIT_PRE_(QS_MTX_BLOCK, curr->m_prio)
QS_TIME_PRE_(); // timestamp
@@ -291,7 +294,7 @@ bool QXMutex::lock(std::uint_fast16_t const nTicks) noexcept {
QS_END_NOCRIT_PRE_()
// schedule the next thread if multitasking started
- static_cast(QXK_sched_(0U)); // synchronous scheduling
+ static_cast(QXK_sched_()); // synchronous scheduling
QF_CRIT_X_();
QF_CRIT_EXIT_NOP(); // BLOCK here !!!
@@ -432,8 +435,8 @@ void QXMutex::unlock() noexcept {
}
// schedule the next thread if multitasking started
- if (QXK_sched_(0U) != 0U) { // synchronous preemption needed?
- QXK_activate_(0U); // synchronously activate basic threads
+ if (QXK_sched_() != 0U) { // synchronous preemption needed?
+ QXK_activate_(); // synchronously activate basic threads
}
}
else { // releasing one level of nested mutex lock
diff --git a/src/qxk/qxk_sema.cpp b/src/qxk/qxk_sema.cpp
index 8d561deb..9914ee23 100644
--- a/src/qxk/qxk_sema.cpp
+++ b/src/qxk/qxk_sema.cpp
@@ -125,7 +125,7 @@ bool QXSemaphore::wait(std::uint_fast16_t const nTicks) noexcept {
// remember the blocking object (this semaphore)
curr->m_temp.obj = QXK_PTR_CAST_(QMState*, this);
- curr->teArm_(static_cast(QXK::SEMA_SIG), nTicks);
+ curr->teArm_(static_cast(QXK::TIMEOUT_SIG), nTicks);
QS_BEGIN_NOCRIT_PRE_(QS_SEM_BLOCK, curr->m_prio)
QS_TIME_PRE_(); // timestamp
@@ -134,7 +134,7 @@ bool QXSemaphore::wait(std::uint_fast16_t const nTicks) noexcept {
QS_END_NOCRIT_PRE_()
// schedule the next thread if multitasking started
- static_cast(QXK_sched_(0U)); // synchronous scheduling
+ static_cast(QXK_sched_()); // synchronous scheduling
QF_CRIT_X_();
QF_CRIT_EXIT_NOP(); // BLOCK here !!!
@@ -260,7 +260,7 @@ bool QXSemaphore::signal() noexcept {
QS_END_NOCRIT_PRE_()
if (!QXK_ISR_CONTEXT_()) { // not inside ISR?
- static_cast(QXK_sched_(0U)); // synchronous scheduling
+ static_cast(QXK_sched_()); // synchronous scheduling
}
}
}
diff --git a/src/qxk/qxk_xthr.cpp b/src/qxk/qxk_xthr.cpp
index ea2630b5..87f6520c 100644
--- a/src/qxk/qxk_xthr.cpp
+++ b/src/qxk/qxk_xthr.cpp
@@ -163,10 +163,10 @@ QEvt const * QXThread::queueGet(std::uint_fast16_t const nTicks) noexcept {
// remember the blocking object (the thread's queue)
thr->m_temp.obj = QXK_PTR_CAST_(QMState*, &thr->m_eQueue);
- thr->teArm_(static_cast(QXK::QUEUE_SIG), nTicks);
+ thr->teArm_(static_cast(QXK::TIMEOUT_SIG), nTicks);
QF::readySet_.remove(
static_cast(thr->m_prio));
- static_cast(QXK_sched_(0U)); // synchronous scheduling
+ static_cast(QXK_sched_()); // synchronous scheduling
QF_CRIT_X_();
QF_CRIT_EXIT_NOP(); // BLOCK here
@@ -269,10 +269,13 @@ void QXThread::start(
//! - NOT be called from an ISR;
//! - the stack storage must be provided;
//! - the thread must be instantiated (see #QXThread).
+ //! - preemption-threshold is NOT provided (because QXK kernel
+ //! does not support preemption-threshold scheduling)
Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_())
&& (stkSto != nullptr)
&& (stkSize != 0U)
- && (m_state.act == nullptr));
+ && (m_state.act == nullptr)
+ && ((prioSpec & 0xFF00U) == 0U));
// is storage for the queue buffer provided?
if (qSto != nullptr) {
@@ -284,7 +287,7 @@ void QXThread::start(
QXK_stackInit_(this, m_temp.thr, stkSto, stkSize);
m_prio = static_cast(prioSpec & 0xFFU); // QF-prio.
- m_pthre = static_cast(prioSpec >> 8U); // preemption-thre.
+ m_pthre = 0U; // preemption-threshold NOT used
register_(); // make QF aware of this AO
// the new thread is not blocked on any object
@@ -296,7 +299,9 @@ void QXThread::start(
QF::readySet_.insert(static_cast(m_prio));
// see if this thread needs to be scheduled in case QXK is running
- static_cast(QXK_sched_(0U)); // synchronous scheduling
+ if (QXK_attr_.lockCeil <= QF_MAX_ACTIVE) {
+ static_cast(QXK_sched_()); // synchronous scheduling
+ }
QF_CRIT_X_();
}
@@ -386,7 +391,7 @@ bool QXThread::post_(
QF::readySet_.insert(
static_cast(m_prio));
if (!QXK_ISR_CONTEXT_()) {
- static_cast(QXK_sched_(0U));
+ static_cast(QXK_sched_());
}
}
}
@@ -446,7 +451,7 @@ void QXThread::block_() const noexcept {
//! @pre the thread holding the lock cannot block!
Q_REQUIRE_ID(600, (QXK_attr_.lockHolder != m_prio));
QF::readySet_.remove(static_cast(m_prio));
- static_cast(QXK_sched_(0U)); // synchronous scheduling
+ static_cast(QXK_sched_()); // synchronous scheduling
}
//${QXK::QXThread::unblock_} .................................................
@@ -456,7 +461,7 @@ void QXThread::unblock_() const noexcept {
if ((!QXK_ISR_CONTEXT_()) // not inside ISR?
&& (QActive::registry_[0] != nullptr)) // kernel started?
{
- static_cast(QXK_sched_(0U)); // synchronous scheduling
+ static_cast(QXK_sched_()); // synchronous scheduling
}
}
diff --git a/test/qk/test_pts/test_pts.py b/test/qk/test_pts/test_pts.py
deleted file mode 100644
index fc24108b..00000000
--- a/test/qk/test_pts/test_pts.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# test-script for QUTest unit testing harness
-# see https://www.state-machine.com/qtools/qutest.html/qutest.html
-
-# preamble
-def on_reset():
- expect_pause()
-
-def Q_PRIO(prio, pthre):
- return prio | (pthre << 8)
-
-test("NO preemption-threshold (scheduler only)")
-continue_test()
-expect_run()
-#----
-glb_filter(GRP_SM, GRP_SC)
-current_obj(OBJ_AO, "ObjB::inst[1]")
-post("TRIG_SIG")
-expect("@timestamp Sch-Next Pri=0->2")
-expect("@timestamp Disp===> Obj=ObjB::inst[1],Sig=TRIG_SIG,State=ObjB::active")
-expect("@timestamp Sch-Pre Pri=2->4")
-expect("@timestamp Disp===> Obj=ObjA::inst,Sig=TEST_SIG,State=ObjA::active")
-expect("@timestamp =>Intern Obj=ObjA::inst,Sig=TEST_SIG,State=ObjA::active")
-expect("@timestamp Sch-Next Pri=4->3")
-expect("@timestamp Disp===> Obj=ObjB::inst[2],Sig=TEST_SIG,State=ObjB::active")
-expect("@timestamp =>Intern Obj=ObjB::inst[2],Sig=TEST_SIG,State=ObjB::active")
-expect("@timestamp Sch-Rest Pri=3->2")
-expect("@timestamp =>Intern Obj=ObjB::inst[1],Sig=TRIG_SIG,State=ObjB::active")
-expect("@timestamp Sch-Next Pri=2->2")
-expect("@timestamp Disp===> Obj=ObjB::inst[1],Sig=TEST_SIG,State=ObjB::active")
-expect("@timestamp =>Intern Obj=ObjB::inst[1],Sig=TEST_SIG,State=ObjB::active")
-expect("@timestamp Sch-Next Pri=2->1")
-expect("@timestamp Disp===> Obj=ObjB::inst[0],Sig=TEST_SIG,State=ObjB::active")
-expect("@timestamp =>Intern Obj=ObjB::inst[0],Sig=TEST_SIG,State=ObjB::active")
-expect("@timestamp Sch-Idle Pri=1->0")
-expect("@timestamp Trg-Done QS_RX_EVENT")
-
-test("preemption-threshold (scheduler only)")
-current_obj(OBJ_AP, "pspec")
-poke(0, 2, pack("2")
-expect("@timestamp Disp===> Obj=ObjB::inst[1],Sig=TRIG_SIG,State=ObjB::active")
-expect("@timestamp Sch-Pre Pri=2->4")
-expect("@timestamp Disp===> Obj=ObjA::inst,Sig=TEST_SIG,State=ObjA::active")
-expect("@timestamp =>Intern Obj=ObjA::inst,Sig=TEST_SIG,State=ObjA::active")
-expect("@timestamp Sch-Rest Pri=4->2")
-expect("@timestamp =>Intern Obj=ObjB::inst[1],Sig=TRIG_SIG,State=ObjB::active")
-expect("@timestamp Sch-Next Pri=2->3")
-expect("@timestamp Disp===> Obj=ObjB::inst[2],Sig=TEST_SIG,State=ObjB::active")
-expect("@timestamp =>Intern Obj=ObjB::inst[2],Sig=TEST_SIG,State=ObjB::active")
-expect("@timestamp Sch-Next Pri=3->2")
-expect("@timestamp Disp===> Obj=ObjB::inst[1],Sig=TEST_SIG,State=ObjB::active")
-expect("@timestamp =>Intern Obj=ObjB::inst[1],Sig=TEST_SIG,State=ObjB::active")
-expect("@timestamp Sch-Next Pri=2->1")
-expect("@timestamp Disp===> Obj=ObjB::inst[0],Sig=TEST_SIG,State=ObjB::active")
-expect("@timestamp =>Intern Obj=ObjB::inst[0],Sig=TEST_SIG,State=ObjB::active")
-expect("@timestamp Sch-Idle Pri=1->0")
-expect("@timestamp Trg-Done QS_RX_EVENT")
diff --git a/test/qk/src/bsp.hpp b/test/qk/test_sched/bsp.hpp
similarity index 90%
rename from test/qk/src/bsp.hpp
rename to test/qk/test_sched/bsp.hpp
index a6926e59..dab38994 100644
--- a/test/qk/src/bsp.hpp
+++ b/test/qk/test_sched/bsp.hpp
@@ -1,7 +1,7 @@
//============================================================================
// Product: BSP for system-testing QXK
-// Last updated for version 7.1.1
-// Last updated on 2022-09-04
+// Last updated for version 7.1.2
+// Last updated on 2022-10-06
//
// Q u a n t u m L e a P s
// ------------------------
@@ -36,12 +36,11 @@
namespace BSP {
-enum { TICKS_PER_SEC = 100 };
-
void init(void);
void terminate(int16_t const result);
// for testing...
+void trace(QP::QActive const *thr, char const *msg);
void wait4PB1(void);
void ledOn(void);
void ledOff(void);
@@ -50,11 +49,12 @@ void trigISR(void);
} // namespace BSP
enum TestSignals {
- TEST_SIG = QP::Q_USER_SIG,
+ TEST0_SIG = QP::Q_USER_SIG,
+ TEST1_SIG,
+ TEST2_SIG,
+ TEST3_SIG,
MAX_PUB_SIG, // the last published signal
- TIMEOUT_SIG,
- TRIG_SIG,
MAX_SIG // the last signal
};
diff --git a/test/qk/src/bsp_efm32.cpp b/test/qk/test_sched/bsp_efm32.cpp
similarity index 92%
rename from test/qk/src/bsp_efm32.cpp
rename to test/qk/test_sched/bsp_efm32.cpp
index 27c31df9..1c5bf961 100644
--- a/test/qk/src/bsp_efm32.cpp
+++ b/test/qk/test_sched/bsp_efm32.cpp
@@ -1,7 +1,7 @@
//============================================================================
// Product: BSP for system-testing QK, EFM32-SLSTK3401A board
-// Last updated for version 7.1.1
-// Last updated on 2022-09-04
+// Last updated for version 7.1.2
+// Last updated on 2022-10-06
//
// Q u a n t u m L e a P s
// ------------------------
@@ -60,11 +60,9 @@ namespace BSP {
static QP::QSpyId const l_SysTick_Handler = { 0U };
static QP::QSpyId const l_test_ISR = { 0U };
- static USART_TypeDef * const l_USART0 = ((USART_TypeDef *)(0x40010000UL));
-
enum AppRecords { // application-specific trace records
CONTEXT_SW = QP::QS_USER,
- COMMAND_STAT
+ TRACE_MSG
};
#endif
@@ -90,8 +88,8 @@ void GPIO_EVEN_IRQHandler(void) {
QK_ISR_ENTRY(); // inform QK about entering an ISR
// for testing...
- QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), // for testing...
- &BSP::l_test_ISR);
+ static QP::QEvt const t1 = { TEST1_SIG, 0U, 0U };
+ QP::QF::PUBLISH(&t1, &BSP::l_test_ISR);
QK_ISR_EXIT(); // inform QK about exiting an ISR
}
@@ -130,7 +128,11 @@ void BSP::init(void) {
QS_OBJ_DICTIONARY(&l_test_ISR);
QS_USR_DICTIONARY(CONTEXT_SW);
- QS_USR_DICTIONARY(COMMAND_STAT);
+ QS_USR_DICTIONARY(TRACE_MSG);
+}
+//............................................................................
+void BSP::terminate(int16_t result) {
+ Q_UNUSED_PAR(result);
}
//............................................................................
void BSP::ledOn(void) {
@@ -145,8 +147,11 @@ void BSP::trigISR(void) {
NVIC_SetPendingIRQ(GPIO_EVEN_IRQn);
}
//............................................................................
-void BSP::terminate(int16_t result) {
- (void)result;
+void BSP::trace(QP::QActive const *thr, char const *msg) {
+ QS_BEGIN_ID(TRACE_MSG, 0U)
+ QS_OBJ(thr);
+ QS_STR(msg);
+ QS_END()
}
// namespace QP ==============================================================
@@ -175,16 +180,6 @@ void QF::onStartup(void) {
void QF::onCleanup(void) {
}
//............................................................................
-#ifdef QK_ON_CONTEXT_SW
-// NOTE: the context-switch callback is called with interrupts DISABLED
-void QK::onContextSw(QActive *prev, QActive *next) {
- QS_BEGIN_NOCRIT(BSP::CONTEXT_SW, 0U) // no critical section!
- QS_OBJ(prev);
- QS_OBJ(next);
- QS_END_NOCRIT()
-}
-#endif // QK_ON_CONTEXT_SW
-//............................................................................
void QK::onIdle(void) {
#ifdef Q_SPY
QS::rxParse(); // parse all the received bytes
@@ -199,7 +194,6 @@ void QK::onIdle(void) {
}
// QS callbacks ==============================================================
-#ifdef Q_SPY
//............................................................................
void QTimeEvt::tick1_(
uint_fast8_t const tickRate,
@@ -211,8 +205,21 @@ void QTimeEvt::tick1_(
QF_INT_ENABLE();
}
-#endif // Q_SPY
//----------------------------------------------------------------------------
} // namespace QP
+extern "C" {
+//............................................................................
+#ifdef QK_ON_CONTEXT_SW
+// NOTE: the context-switch callback is called with interrupts DISABLED
+void QK_onContextSw(QP::QActive *prev, QP::QActive *next) {
+ QS_BEGIN_NOCRIT(BSP::CONTEXT_SW, 0U) // no critical section!
+ QS_OBJ(prev);
+ QS_OBJ(next);
+ QS_END_NOCRIT()
+}
+#endif // QK_ON_CONTEXT_SW
+
+} // extern "C"
+
diff --git a/test/qk/src/bsp_l053r8.cpp b/test/qk/test_sched/bsp_l053r8.cpp
similarity index 92%
rename from test/qk/src/bsp_l053r8.cpp
rename to test/qk/test_sched/bsp_l053r8.cpp
index 2bb31c84..59bb6dca 100644
--- a/test/qk/src/bsp_l053r8.cpp
+++ b/test/qk/test_sched/bsp_l053r8.cpp
@@ -1,7 +1,7 @@
//============================================================================
// Product: BSP for system-testing QK kernel, NUCLEO-L053R8 board
-// Last updated for version 7.1.1
-// Last updated on 2022-09-04
+// Last updated for version 7.1.2
+// Last updated on 2022-10-06
//
// Q u a n t u m L e a P s
// ------------------------
@@ -57,7 +57,7 @@ namespace BSP {
enum AppRecords { // application-specific trace records
CONTEXT_SW = QP::QS_USER,
- COMMAND_STAT
+ TRACE_MSG
};
#endif
@@ -83,8 +83,8 @@ void EXTI0_1_IRQHandler(void) {
QK_ISR_ENTRY(); // inform QK about entering an ISR
// for testing...
- QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), // for testing...
- &BSP::l_test_ISR);
+ static QP::QEvt const t1 = { TEST1_SIG, 0U, 0U };
+ QP::QF::PUBLISH(&t1, &BSP::l_test_ISR);
QK_ISR_EXIT(); // inform QK about exiting an ISR
}
@@ -125,7 +125,11 @@ void BSP::init(void) {
QS_OBJ_DICTIONARY(&l_test_ISR);
QS_USR_DICTIONARY(CONTEXT_SW);
- QS_USR_DICTIONARY(COMMAND_STAT);
+ QS_USR_DICTIONARY(TRACE_MSG);
+}
+//............................................................................
+void BSP::terminate(int16_t result) {
+ Q_UNUSED_PAR(result);
}
//............................................................................
void BSP::ledOn(void) {
@@ -140,8 +144,11 @@ void BSP::trigISR(void) {
NVIC_SetPendingIRQ(EXTI0_1_IRQn);
}
//............................................................................
-void BSP::terminate(int16_t result) {
- (void)result;
+void BSP::trace(QP::QActive const *thr, char const *msg) {
+ QS_BEGIN_ID(TRACE_MSG, 0U)
+ QS_OBJ(thr);
+ QS_STR(msg);
+ QS_END()
}
// namespace QP ==============================================================
@@ -170,16 +177,6 @@ void QF::onStartup(void) {
void QF::onCleanup(void) {
}
//............................................................................
-#ifdef QK_ON_CONTEXT_SW
-// NOTE: the context-switch callback is called with interrupts DISABLED
-void QK::onContextSw(QActive *prev, QActive *next) {
- QS_BEGIN_NOCRIT(BSP::CONTEXT_SW, 0U) // no critical section!
- QS_OBJ(prev);
- QS_OBJ(next);
- QS_END_NOCRIT()
-}
-#endif // QK_ON_CONTEXT_SW
-//............................................................................
void QK::onIdle(void) {
#ifdef Q_SPY
QS::rxParse(); // parse all the received bytes
@@ -194,7 +191,6 @@ void QK::onIdle(void) {
}
// QS callbacks ==============================================================
-#ifdef Q_SPY
//............................................................................
void QTimeEvt::tick1_(
uint_fast8_t const tickRate,
@@ -206,8 +202,21 @@ void QTimeEvt::tick1_(
QF_INT_ENABLE();
}
-#endif // Q_SPY
//----------------------------------------------------------------------------
} // namespace QP
+extern "C" {
+//............................................................................
+#ifdef QK_ON_CONTEXT_SW
+// NOTE: the context-switch callback is called with interrupts DISABLED
+void QK_onContextSw(QP::QActive *prev, QP::QActive *next) {
+ QS_BEGIN_NOCRIT(BSP::CONTEXT_SW, 0U) // no critical section!
+ QS_OBJ(prev);
+ QS_OBJ(next);
+ QS_END_NOCRIT()
+}
+#endif // QK_ON_CONTEXT_SW
+
+} // extern "C"
+
diff --git a/test/qk/test_pts/make_efm32 b/test/qk/test_sched/make_efm32
similarity index 94%
rename from test/qk/test_pts/make_efm32
rename to test/qk/test_sched/make_efm32
index c4387196..7c41ed73 100644
--- a/test/qk/test_pts/make_efm32
+++ b/test/qk/test_sched/make_efm32
@@ -1,7 +1,7 @@
##############################################################################
# Product: Makefile for SYSTEM-Level tests of QP/C++ on EMF32, GNU-ARM
-# Last Updated for Version: 7.1.1
-# Date of the Last Update: 2022-09-05
+# Last Updated for Version: 7.1.2
+# Date of the Last Update: 2022-10-05
#
# Q u a n t u m L e a P s
# ------------------------
@@ -38,6 +38,7 @@
# make -f make_efm32 HOST=localhost:7705 # connect to host:port
# make -f make_efm32 norun # only make but not run the tests
# make -f make_efm32 clean # cleanup the build
+# make -f make_efm32 debug # only run tests in DEBUG mode
#
# NOTE:
# To use this Makefile on Windows, you will need the GNU make utility, which
@@ -53,7 +54,7 @@ endif
#-----------------------------------------------------------------------------
# project name, target name, target directory:
#
-PROJECT := test_pts
+PROJECT := test_sched
TARGET := efm32
TARGET_DIR := $(QPCPP)/3rd_party/efm32pg1b/qutest
@@ -72,7 +73,6 @@ endif
# list of all source directories used by this project
VPATH := . \
- ../src \
$(QPCPP)/src/qf \
$(QPCPP)/src/qk \
$(QPCPP)/src/qs \
@@ -83,7 +83,6 @@ VPATH := . \
# list of all include directories needed by this project
INCLUDES = -I. \
- -I../src \
-I$(QPCPP)/include \
-I$(QP_PORT_DIR) \
-I$(TARGET_DIR) \
@@ -108,7 +107,7 @@ C_SRCS := \
# C++ source files
CPP_SRCS := \
- test_pts.cpp \
+ test_sched.cpp \
bsp_efm32.cpp
OUTPUT := $(PROJECT)
@@ -142,7 +141,8 @@ LIB_DIRS :=
LIBS :=
# defines
-DEFINES := -DEFM32PG1B200F256GM48=1
+DEFINES := -DEFM32PG1B200F256GM48=1 \
+ -DQK_ON_CONTEXT_SW
# ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]
@@ -247,7 +247,7 @@ endif
# rules
#
-.PHONY : run norun flash
+.PHONY : run norun debug flash
ifeq ($(MAKECMDGOALS),norun)
all : $(TARGET_BIN)
@@ -285,15 +285,23 @@ $(BIN_DIR)/%.o : %.c
$(BIN_DIR)/%.o : %.cpp
$(CPP) $(CPPFLAGS) $< -o $@
-.PHONY : clean show
-
-# include dependency files only if our goal depends on their existence
+# create BIN_DIR and include dependencies only if needed
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),show)
+ ifneq ($(MAKECMDGOALS),debug)
+ifeq ("$(wildcard $(BIN_DIR))","")
+$(shell $(MKDIR) $(BIN_DIR))
+endif
-include $(C_DEPS_EXT) $(CPP_DEPS_EXT)
+ endif
endif
endif
+debug :
+ $(QUTEST) $(TESTS) DEBUG $(HOST)
+
+.PHONY : clean show
+
clean :
-$(RM) $(BIN_DIR)/*.o \
$(BIN_DIR)/*.d \
diff --git a/test/qk/test_pts/make_nucleo-l053r8 b/test/qk/test_sched/make_nucleo-l053r8
similarity index 94%
rename from test/qk/test_pts/make_nucleo-l053r8
rename to test/qk/test_sched/make_nucleo-l053r8
index 7babadd9..236e09a2 100644
--- a/test/qk/test_pts/make_nucleo-l053r8
+++ b/test/qk/test_sched/make_nucleo-l053r8
@@ -1,7 +1,7 @@
##############################################################################
-# Product: Makefile for SYSTEM-Level tests of QP/C++ on NUCLEO-L053R8, GNU-ARM
-# Last Updated for Version: 7.1.1
-# Date of the Last Update: 2022-09-05
+# Product: Makefile for SYSTEM-Level tests of QP/C on NUCLEO-L053R8, GNU-ARM
+# Last Updated for Version: 7.1.2
+# Date of the Last Update: 2022-10-05
#
# Q u a n t u m L e a P s
# ------------------------
@@ -38,6 +38,7 @@
# make -f make_nucleo-l053r8 HOST=localhost:7705 # connect to host:port
# make -f make_nucleo-l053r8 norun # only make but not run the tests
# make -f make_nucleo-l053r8 clean # cleanup the build
+# make -f make_nucleo-l053r8 debug # only run tests in DEBUG mode
#
# NOTE:
# To use this Makefile on Windows, you will need the GNU make utility, which
@@ -53,7 +54,7 @@ endif
#-----------------------------------------------------------------------------
# project name, target name, target directory:
#
-PROJECT := test_pts
+PROJECT := test_sched
TARGET := nucleo-l053r8
TARGET_DIR := $(QPCPP)/3rd_party/nucleo-l053r8/qutest
@@ -72,7 +73,6 @@ endif
# list of all source directories used by this project
VPATH := . \
- ../src \
$(QPCPP)/src/qf \
$(QPCPP)/src/qk \
$(QPCPP)/src/qs \
@@ -83,7 +83,6 @@ VPATH := . \
# list of all include directories needed by this project
INCLUDES = -I. \
- -I../src \
-I$(QPCPP)/include \
-I$(QP_PORT_DIR) \
-I$(TARGET_DIR) \
@@ -104,7 +103,7 @@ C_SRCS := \
# C++ source files
CPP_SRCS := \
- test_pts.cpp \
+ test_sched.cpp \
bsp_l053r8.cpp
OUTPUT := $(PROJECT)
@@ -138,7 +137,8 @@ LIB_DIRS :=
LIBS :=
# defines
-DEFINES :=
+DEFINES := \
+ -DQK_ON_CONTEXT_SW
# ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]
@@ -247,7 +247,7 @@ endif
# rules
#
-.PHONY : run norun flash
+.PHONY : run norun debug flash
ifeq ($(MAKECMDGOALS),norun)
all : $(TARGET_BIN)
@@ -286,15 +286,23 @@ $(BIN_DIR)/%.o : %.c
$(BIN_DIR)/%.o : %.cpp
$(CPP) $(CPPFLAGS) $< -o $@
-.PHONY : clean show
-
-# include dependency files only if our goal depends on their existence
+# create BIN_DIR and include dependencies only if needed
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),show)
+ ifneq ($(MAKECMDGOALS),debug)
+ifeq ("$(wildcard $(BIN_DIR))","")
+$(shell $(MKDIR) $(BIN_DIR))
+endif
-include $(C_DEPS_EXT) $(CPP_DEPS_EXT)
+ endif
endif
endif
+debug :
+ $(QUTEST) $(TESTS) DEBUG $(HOST)
+
+.PHONY : clean show
+
clean :
-$(RM) $(BIN_DIR)/*.o \
$(BIN_DIR)/*.d \
@@ -323,6 +331,5 @@ show :
@echo QTOOLS = $(QTOOLS)
@echo HOST = $(HOST)
@echo QUTEST = $(QUTEST)
- @echo FLASH = $(FLASH)
@echo TESTS = $(TESTS)
diff --git a/test/qk/test_pts/test_pts.cpp b/test/qk/test_sched/test_sched.cpp
similarity index 54%
rename from test/qk/test_pts/test_pts.cpp
rename to test/qk/test_sched/test_sched.cpp
index a9796228..86affbb4 100644
--- a/test/qk/test_pts/test_pts.cpp
+++ b/test/qk/test_sched/test_sched.cpp
@@ -1,13 +1,13 @@
//============================================================================
-// System test fixture for QK kernel on the EFM32 target
-// Last updated for version 7.1.1
-// Last updated on 2022-09-05
+// Product: System test fixture for QK on the EFM32 target
+// Last updated for version 7.1.2
+// Last updated on 2022-10-06
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
-// Copyright (C) 2005-2020 Quantum Leaps. All rights reserved.
+// Copyright (C) 2005 Quantum Leaps. All rights reserved.
//
// 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
@@ -34,17 +34,18 @@
#include "qpcpp.hpp"
#include "bsp.hpp"
-namespace { // unnamed namespace
-
Q_DEFINE_THIS_FILE
-enum { NumB = 3 };
+namespace {
+//============================================================================
+// AO ObjB
+enum { NUM_B = 3 };
//............................................................................
// AO ObjB
class ObjB : public QP::QActive {
public:
- static ObjB inst[NumB];
+ static ObjB inst[NUM_B];
public:
ObjB() : QActive(&initial) {}
@@ -55,28 +56,37 @@ protected:
}; // class ObjB
Q_STATE_DEF(ObjB, initial) {
- for (std::uint8_t n = 0U; n < NumB; ++n) {
- QS_OBJ_ARR_DICTIONARY(&ObjB::inst[n], n);
+ static bool registered = false; // starts off with 0, per C-standard
+ if (!registered) {
+ registered = true;
+ QS_FUN_DICTIONARY(&ObjB::initial);
+ QS_FUN_DICTIONARY(&ObjB::active);
}
- QS_FUN_DICTIONARY(&ObjB::initial);
- QS_FUN_DICTIONARY(&ObjB::active);
-
+ subscribe(TEST1_SIG);
+ subscribe(TEST2_SIG);
return tran(&active);
}
Q_STATE_DEF(ObjB, active) {
QP::QState status_;
switch (e->sig) {
- case Q_ENTRY_SIG: {
- status_ = Q_RET_HANDLED;
- break;
- }
- case TRIG_SIG: {
+ case TEST0_SIG: {
+ BSP::trace(this, "TEST0 1of2");
BSP::trigISR();
+ BSP::trace(this, "TEST0 2of2");
status_ = Q_RET_HANDLED;
break;
}
- case TEST_SIG: {
+ case TEST1_SIG: {
+ static QP::QEvt const t2 = { TEST2_SIG, 0U, 0U };
+ BSP::trace(this, "TEST1 1of2");
+ QActive::PUBLISH(&t2, this);
+ BSP::trace(this, "TEST1 2of2");
+ status_ = Q_RET_HANDLED;
+ break;
+ }
+ case TEST2_SIG: {
+ BSP::trace(this, "TEST2 1of1");
status_ = Q_RET_HANDLED;
break;
}
@@ -87,111 +97,57 @@ Q_STATE_DEF(ObjB, active) {
}
return status_;
}
-//............................................................................
-// AO ObjA
-class ObjA : public QP::QActive {
-public:
- static ObjA inst;
-public:
- ObjA() : QActive(&initial) {}
-
-protected:
- Q_STATE_DECL(initial);
- Q_STATE_DECL(active);
-}; // class ObjA
-
-Q_STATE_DEF(ObjA, initial) {
- subscribe(TEST_SIG);
-
- QS_OBJ_DICTIONARY(&ObjA::inst);
- QS_FUN_DICTIONARY(&ObjA::initial);
- QS_FUN_DICTIONARY(&ObjA::active);
-
- return tran(&active);
-}
-
-Q_STATE_DEF(ObjA, active) {
- QP::QState status_;
- switch (e->sig) {
- case Q_ENTRY_SIG: {
- status_ = Q_RET_HANDLED;
- break;
- }
- case TRIG_SIG: {
- BSP::trigISR();
- status_ = Q_RET_HANDLED;
- break;
- }
- case TEST_SIG: {
- static QP::QEvt const tste = { TEST_SIG, 0U, 0U };
- BSP::ledOn();
- ObjB::inst[2].POST(&tste, this);
- ObjB::inst[1].POST(&tste, this);
- ObjB::inst[0].POST(&tste, this);
- BSP::ledOff();
- status_ = Q_RET_HANDLED;
- break;
- }
- default: {
- status_ = super(&top);
- break;
- }
- }
- return status_;
-}
+ObjB ObjB::inst[NUM_B];
} // unnamed namespace
//============================================================================
-ObjB ObjB::inst[NumB];
-ObjA ObjA::inst;
-
int main() {
- QP::QF::init(); // initialize the framework and the underlying QXK kernel
+
+ QP::QF::init(); // initialize the framework and the underlying QXK kernel
BSP::init(); // initialize the Board Support Package
- // dictionaries
- QS_FUN_DICTIONARY(&QP::QHsm::top);
- QS_SIG_DICTIONARY(TEST_SIG, nullptr);
- QS_SIG_DICTIONARY(TRIG_SIG, nullptr);
-
- static std::uint16_t pspec[NumB + 1] = {
- Q_PRIO(1U, 0U),
- Q_PRIO(2U, 0U),
- Q_PRIO(3U, 0U),
- Q_PRIO(4U, 0U)
- };
- QS_OBJ_DICTIONARY(pspec);
-
// initialize publish-subscribe...
static QP::QSubscrList subscrSto[MAX_PUB_SIG];
- QP::QF::psInit(subscrSto, Q_DIM(subscrSto));
+ QP::QActive::psInit(subscrSto, Q_DIM(subscrSto));
// initialize event pools...
static QF_MPOOL_EL(QP::QEvt) smlPoolSto[10]; // small pool
QP::QF::poolInit(smlPoolSto, sizeof(smlPoolSto), sizeof(smlPoolSto[0]));
- // pause execution of the test and wait for the test script to continue
- QS_TEST_PAUSE();
+ // dictionaries
+ QS_SIG_DICTIONARY(TEST0_SIG, nullptr);
+ QS_SIG_DICTIONARY(TEST1_SIG, nullptr);
+ QS_SIG_DICTIONARY(TEST2_SIG, nullptr);
+ QS_SIG_DICTIONARY(TEST3_SIG, nullptr);
- static QP::QEvt const *aoB_queueSto[NumB][5];
- for (std::uint8_t n = 0U; n < NumB; ++n) {
- ObjB::inst[n].start(
- pspec[n], // QP priority spec
- aoB_queueSto[n], // event queue storage
- Q_DIM(aoB_queueSto[n]), // event length [events]
- nullptr, // no stack storage
- 0U); // zero stack size [bytes]
+ // priority specifications for ObjBs...
+ static QP::QPrioSpec pspecB[NUM_B];
+ QS_OBJ_DICTIONARY(pspecB);
+
+ std::uint8_t n;
+
+ for (n = 0U; n < NUM_B; ++n) {
+ QS_OBJ_ARR_DICTIONARY(&ObjB::inst[n], n);
}
- static QP::QEvt const *aoA_queueSto[5];
- ObjA::inst.start(
- pspec[NumB], // QP priority spec
- aoA_queueSto, // event queue storage
- Q_DIM(aoA_queueSto), // event length [events]
- nullptr, // no stack storage
- 0U); // zero stack size [bytes]
+ // pause execution of the test and wait for the test script to continue
+ // NOTE:
+ // this pause gives the test-script a chance to poke pspecB and pspecX
+ // variables to start the threads with the desired prio-specifications.
+ QS_TEST_PAUSE();
+
+ static QP::QEvt const *aoB_queueSto[NUM_B][5];
+ for (n = 0U; n < NUM_B; ++n) {
+ if (pspecB[n] != 0U) {
+ ObjB::inst[n].start(pspecB[n], // QF-prio/p-thre.
+ aoB_queueSto[n], // event queue storage
+ Q_DIM(aoB_queueSto[n]), // event length [events]
+ nullptr, // no stack storage
+ 0U); // zero stack size [bytes]
+ }
+ }
return QP::QF::run(); // run the QF application
}
@@ -199,7 +155,6 @@ int main() {
//============================================================================
namespace QP {
-//............................................................................
void QS::onTestSetup(void) {
}
//............................................................................
@@ -215,18 +170,16 @@ void QS::onCommand(uint8_t cmdId,
Q_UNUSED_PAR(param2);
Q_UNUSED_PAR(param3);
}
-//............................................................................
+
+//============================================================================
//! Host callback function to "massage" the event, if necessary
void QS::onTestEvt(QEvt *e) {
- Q_UNUSED_PAR(e);
+ (void)e;
}
//............................................................................
//! callback function to output the posted QP events (not used here)
void QS::onTestPost(void const *sender, QActive *recipient,
QEvt const *e, bool status)
-{
- Q_UNUSED_PAR(sender);
- Q_UNUSED_PAR(status);
-}
+{}
} // namespace QP
diff --git a/test/qk/test_sched/test_sched.py b/test/qk/test_sched/test_sched.py
new file mode 100644
index 00000000..31e7c48f
--- /dev/null
+++ b/test/qk/test_sched/test_sched.py
@@ -0,0 +1,173 @@
+# test-script for QUTest unit testing harness
+# see https://www.state-machine.com/qtools/qutest.html/qutest.html
+
+# preamble
+def on_reset():
+ expect_pause()
+
+def Q_PRIO(prio, pthre):
+ return prio | (pthre << 8)
+
+test("ao->ao->ao (NO PTS)")
+current_obj(OBJ_AP, "pspecB")
+poke(0, 2, pack("2")
+expect("@timestamp CONTEXT_SW NULL ObjB::inst[1]")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST0 1of2")
+expect("@timestamp Sch-Next Pri=2->3")
+expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[2]")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST1 1of2")
+expect("@timestamp Sch-Lock Ceil=0->3")
+expect("@timestamp Sch-Unlk Ceil=3->0")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST1 2of2")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=3->2")
+expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST0 2of2")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST1 1of2")
+expect("@timestamp Sch-Lock Ceil=0->3")
+expect("@timestamp Sch-Unlk Ceil=3->0")
+expect("@timestamp Sch-Next Pri=2->3")
+expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[2]")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=3->2")
+expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST1 2of2")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=2->1")
+expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[0]")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 1of2")
+expect("@timestamp Sch-Lock Ceil=0->3")
+expect("@timestamp Sch-Unlk Ceil=3->0")
+expect("@timestamp Sch-Next Pri=1->3")
+expect("@timestamp CONTEXT_SW ObjB::inst[0] ObjB::inst[2]")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=3->2")
+expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=2->1")
+expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[0]")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 2of2")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1")
+expect("@timestamp Sch-Idle Pri=1->0")
+expect("@timestamp CONTEXT_SW ObjB::inst[0] NULL")
+expect("@timestamp Trg-Done QS_RX_EVENT")
+
+
+test("ao->ao->ao (PTS1)")
+current_obj(OBJ_AP, "pspecB")
+poke(0, 2, pack("2")
+expect("@timestamp CONTEXT_SW NULL ObjB::inst[1]")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST0 1of2")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST0 2of2")
+expect("@timestamp Sch-Next Pri=2->3")
+expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[2]")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST1 1of2")
+expect("@timestamp Sch-Lock Ceil=0->3")
+expect("@timestamp Sch-Unlk Ceil=3->0")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST1 2of2")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=3->2")
+expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST1 1of2")
+expect("@timestamp Sch-Lock Ceil=0->3")
+expect("@timestamp Sch-Unlk Ceil=3->0")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST1 2of2")
+expect("@timestamp Sch-Next Pri=2->3")
+expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[2]")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=3->2")
+expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=2->1")
+expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[0]")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 1of2")
+expect("@timestamp Sch-Lock Ceil=0->3")
+expect("@timestamp Sch-Unlk Ceil=3->0")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 2of2")
+expect("@timestamp Sch-Next Pri=1->3")
+expect("@timestamp CONTEXT_SW ObjB::inst[0] ObjB::inst[2]")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=3->2")
+expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=2->1")
+expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[0]")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1")
+expect("@timestamp Sch-Idle Pri=1->0")
+expect("@timestamp CONTEXT_SW ObjB::inst[0] NULL")
+expect("@timestamp Trg-Done QS_RX_EVENT")
+
+
+test("ao->ao->ao (PTS2)")
+current_obj(OBJ_AP, "pspecB")
+poke(0, 2, pack("2")
+expect("@timestamp CONTEXT_SW NULL ObjB::inst[1]")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST0 1of2")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST0 2of2")
+expect("@timestamp Sch-Next Pri=2->3")
+expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[2]")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST1 1of2")
+expect("@timestamp Sch-Lock Ceil=0->3")
+expect("@timestamp Sch-Unlk Ceil=3->0")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST1 2of2")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=3->2")
+expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST1 1of2")
+expect("@timestamp Sch-Lock Ceil=0->3")
+expect("@timestamp Sch-Unlk Ceil=3->0")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST1 2of2")
+expect("@timestamp Sch-Next Pri=2->3")
+expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[2]")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=3->2")
+expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=2->1")
+expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[0]")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 1of2")
+expect("@timestamp Sch-Lock Ceil=0->3")
+expect("@timestamp Sch-Unlk Ceil=3->0")
+expect("@timestamp Sch-Next Pri=1->3")
+expect("@timestamp CONTEXT_SW ObjB::inst[0] ObjB::inst[2]")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=3->2")
+expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=2->1")
+expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[0]")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 2of2")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1")
+expect("@timestamp Sch-Idle Pri=1->0")
+expect("@timestamp CONTEXT_SW ObjB::inst[0] NULL")
+expect("@timestamp Trg-Done QS_RX_EVENT")
diff --git a/test/qk/test_sched/uvision_efm32.uvoptx b/test/qk/test_sched/uvision_efm32.uvoptx
new file mode 100644
index 00000000..9bb06f26
--- /dev/null
+++ b/test/qk/test_sched/uvision_efm32.uvoptx
@@ -0,0 +1,754 @@
+
+
+
+ 1.0
+
+ ### uVision Project, (C) Keil Software
+
+
+ *.c
+ *.s*; *.src; *.a*
+ *.obj; *.o
+ *.lib
+ *.txt; *.h; *.inc; *.md
+ *.plm
+ *.cpp
+ 0
+
+
+
+ 0
+ 0
+
+
+
+ qutest
+ 0x4
+ ARM-ADS
+
+ 12000000
+
+ 1
+ 1
+ 1
+ 0
+ 0
+
+
+ 1
+ 65535
+ 0
+ 0
+ 0
+
+
+ 79
+ 66
+ 8
+ .\uvision_emf32\
+
+
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+
+
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+
+
+ 1
+ 0
+ 1
+
+ 3
+
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 1
+ 0
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ 0
+ 4
+
+
+
+
+
+
+
+
+
+
+ Segger\JL2CM3.dll
+
+
+
+ 0
+ DLGUARM
+
+
+
+ 0
+ JL2CM3
+ -U440060969 -O206 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO7 -FD20000000 -FC8000 -FN1 -FF0GECKOP2.FLM -FS00 -FL020000 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM)
+
+
+ 0
+ ARMRTXEVENTFLAGS
+ -L70 -Z18 -C0 -M0 -T1
+
+
+ 0
+ UL2CM3
+ UL2CM3(-O207 -S0 -C0 -FO7 -FN1 -FC8000 -FD20000000 -FF0GECKOP2 -FL020000 -FS00 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM)
+
+
+ 0
+ DLGTARM
+ (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)
+
+
+ 0
+ ARMDBGFLAGS
+
+
+
+ 0
+ lmidk-agdi
+ -U0E2006F4 -O4622 -S4 -FO61
+
+
+
+
+ 0
+ 0
+ 112
+ 1
+ 25212
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ ..\..\..\src\qs\qutest.c
+
+ \\test\../../../src/qs/qutest.c\112
+
+
+ 1
+ 0
+ 142
+ 1
+ 136
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ ..\..\..\src\qs\qs.c
+
+ \\test\../../../src/qs/qs.c\142
+
+
+ 2
+ 0
+ 180
+ 1
+ 27402
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ .\test_pts.c
+
+ \\test\test_pts.c\180
+
+
+
+
+ 0
+ 1
+ QF_readySet_
+
+
+ 1
+ 1
+ QK_attr_
+
+
+ 2
+ 1
+ QActive_registry_
+
+
+ 3
+ 1
+ QS_rxPriv_
+
+
+ 4
+ 1
+ pspec
+
+
+
+
+ 1
+ 2
+ 0x20000200
+ 0
+
+
+
+
+ 2
+ 0
+ 0x400
+ 0
+
+
+
+ 0
+
+
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+ Applicatioin
+ 1
+ 0
+ 0
+ 0
+
+ 1
+ 1
+ 5
+ 0
+ 0
+ 0
+ .\bsp.h
+ bsp.h
+ 0
+ 0
+
+
+ 1
+ 2
+ 1
+ 0
+ 0
+ 0
+ .\bsp_efm32.c
+ bsp_efm32.c
+ 0
+ 0
+
+
+ 1
+ 3
+ 1
+ 0
+ 0
+ 0
+ .\test_pts.c
+ test_pts.c
+ 0
+ 0
+
+
+
+
+ efm32pg1b
+ 1
+ 0
+ 0
+ 0
+
+ 2
+ 4
+ 2
+ 0
+ 0
+ 0
+ ..\..\..\..\3rd_party\efm32pg1b\arm\startup_efm32pg1b.s
+ startup_efm32pg1b.s
+ 0
+ 0
+
+
+ 2
+ 5
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\3rd_party\efm32pg1b\em_cmu.c
+ em_cmu.c
+ 0
+ 0
+
+
+ 2
+ 6
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\3rd_party\efm32pg1b\em_emu.c
+ em_emu.c
+ 0
+ 0
+
+
+ 2
+ 7
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\3rd_party\efm32pg1b\em_gpio.c
+ em_gpio.c
+ 0
+ 0
+
+
+ 2
+ 8
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c
+ system_efm32pg1b.c
+ 0
+ 0
+
+
+ 2
+ 9
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\3rd_party\efm32pg1b\em_system.c
+ em_system.c
+ 0
+ 0
+
+
+ 2
+ 10
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\3rd_party\efm32pg1b\em_usart.c
+ em_usart.c
+ 0
+ 0
+
+
+
+
+ QP
+ 1
+ 0
+ 0
+ 0
+
+ 3
+ 11
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qep_hsm.c
+ qep_hsm.c
+ 0
+ 0
+
+
+ 3
+ 12
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qep_msm.c
+ qep_msm.c
+ 0
+ 0
+
+
+ 3
+ 13
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_act.c
+ qf_act.c
+ 0
+ 0
+
+
+ 3
+ 14
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_actq.c
+ qf_actq.c
+ 0
+ 0
+
+
+ 3
+ 15
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_defer.c
+ qf_defer.c
+ 0
+ 0
+
+
+ 3
+ 16
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_dyn.c
+ qf_dyn.c
+ 0
+ 0
+
+
+ 3
+ 17
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_mem.c
+ qf_mem.c
+ 0
+ 0
+
+
+ 3
+ 18
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_ps.c
+ qf_ps.c
+ 0
+ 0
+
+
+ 3
+ 19
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_qact.c
+ qf_qact.c
+ 0
+ 0
+
+
+ 3
+ 20
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_qeq.c
+ qf_qeq.c
+ 0
+ 0
+
+
+ 3
+ 21
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_qmact.c
+ qf_qmact.c
+ 0
+ 0
+
+
+ 3
+ 22
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_time.c
+ qf_time.c
+ 0
+ 0
+
+
+ 3
+ 23
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\include\qstamp.c
+ qstamp.c
+ 0
+ 0
+
+
+ 3
+ 24
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qk\qk.c
+ qk.c
+ 0
+ 0
+
+
+
+
+ QP_port
+ 1
+ 0
+ 0
+ 0
+
+ 4
+ 25
+ 5
+ 0
+ 0
+ 0
+ ..\..\..\ports\arm-cm\qxk\armclang\qep_port.h
+ qep_port.h
+ 0
+ 0
+
+
+ 4
+ 26
+ 5
+ 0
+ 0
+ 0
+ ..\..\..\ports\arm-cm\qxk\armclang\qf_port.h
+ qf_port.h
+ 0
+ 0
+
+
+ 4
+ 27
+ 5
+ 0
+ 0
+ 0
+ ..\..\..\ports\arm-cm\qk\armclang\qk_port.h
+ qk_port.h
+ 0
+ 0
+
+
+ 4
+ 28
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\ports\arm-cm\qk\armclang\qk_port.c
+ qk_port.c
+ 0
+ 0
+
+
+ 4
+ 29
+ 5
+ 0
+ 0
+ 0
+ ..\..\..\ports\arm-cm\qxk\armclang\qs_port.h
+ qs_port.h
+ 0
+ 0
+
+
+ 4
+ 30
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\3rd_party\efm32pg1b\qutest\qutest_port.c
+ qutest_port.c
+ 0
+ 0
+
+
+
+
+ QS
+ 1
+ 0
+ 0
+ 0
+
+ 5
+ 31
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qs\qs.c
+ qs.c
+ 0
+ 0
+
+
+ 5
+ 32
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qs\qs_64bit.c
+ qs_64bit.c
+ 0
+ 0
+
+
+ 5
+ 33
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qs\qs_fp.c
+ qs_fp.c
+ 0
+ 0
+
+
+ 5
+ 34
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qs\qs_rx.c
+ qs_rx.c
+ 0
+ 0
+
+
+ 5
+ 35
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qs\qutest.c
+ qutest.c
+ 0
+ 0
+
+
+
+
diff --git a/test/qk/test_sched/uvision_efm32.uvprojx b/test/qk/test_sched/uvision_efm32.uvprojx
new file mode 100644
index 00000000..65e7f24b
--- /dev/null
+++ b/test/qk/test_sched/uvision_efm32.uvprojx
@@ -0,0 +1,602 @@
+
+
+
+ 2.1
+
+ ### uVision Project, (C) Keil Software
+
+
+
+ qutest
+ 0x4
+ ARM-ADS
+ 6160000::V6.16::ARMCLANG
+ 1
+
+
+ EFM32PG1B200F256GM48
+ Silicon Labs
+ SiliconLabs.GeckoPlatform_EFM32PG1B_DFP.4.0.0
+ https://www.silabs.com/documents/public/cmsis-packs/
+ IRAM(0x20000000,0x00008000) IROM(0x00000000,0x00020000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE
+
+
+ UL2CM3(-S0 -C0 -P0 -FD20000000 -FC8000 -FN1 -FF0GECKOP2 -FS00 -FL020000 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM))
+ 0
+ $$Device:EFM32PG1B200F256GM48$Device\EFM32PG1B\Include\em_device.h
+
+
+
+
+
+
+
+
+
+ $$Device:EFM32PG1B200F256GM48$SVD\EFM32PG1B\EFM32PG1B200F256GM48.svd
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+ 1
+
+ .\uvision_emf32\
+ test
+ 1
+ 0
+ 0
+ 1
+ 1
+ .\uvision_emf32\
+ 1
+ 0
+ 0
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+ 1
+ 0
+ cmd /c "del .\uvision_em32\qstamp.o"
+
+ 0
+ 0
+ 0
+ 0
+
+
+ 1
+ 0
+ fromelf --bin --output .\uvision_em32\test.bin .\uvision_em32\test.axf
+
+ 0
+ 0
+ 0
+ 0
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 3
+
+
+ 1
+
+
+ SARMCM3.DLL
+ -MPU
+ DCM.DLL
+ -pCM4
+ SARMCM3.DLL
+ -MPU
+ TCM.DLL
+ -pCM4
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 16
+
+
+
+
+ 1
+ 0
+ 0
+ 1
+ 1
+ 4096
+
+ 1
+ BIN\UL2CM3.DLL
+ "" ()
+
+
+
+
+ 0
+
+
+
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ "Cortex-M4"
+
+ 0
+ 0
+ 0
+ 1
+ 1
+ 0
+ 0
+ 2
+ 0
+ 0
+ 0
+ 0
+ 8
+ 0
+ 0
+ 0
+ 0
+ 3
+ 3
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x20000000
+ 0x8000
+
+
+ 1
+ 0x0
+ 0x20000
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x20000
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x20000000
+ 0x8000
+
+
+ 0
+ 0x0
+ 0x0
+
+
+
+
+
+ 0
+ 1
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 3
+ 0
+ 1
+ 1
+ 0
+ 0
+ 3
+ 3
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+ Q_SPY, Q_UTEST=0
+
+ .;..\..\..\include;..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\3rd_party\efm32pg1b
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 4
+
+
+ Stack_Size=2048 Heap_Size=16
+
+
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0x00000000
+ 0x20000000
+
+
+
+
+ --entry Reset_Handler
+
+
+
+
+
+
+
+ Applicatioin
+
+
+ bsp.h
+ 5
+ .\bsp.h
+
+
+ bsp_efm32.c
+ 1
+ .\bsp_efm32.c
+
+
+ test_pts.c
+ 1
+ .\test_pts.c
+
+
+
+
+ efm32pg1b
+
+
+ startup_efm32pg1b.s
+ 2
+ ..\..\..\..\3rd_party\efm32pg1b\arm\startup_efm32pg1b.s
+
+
+ em_cmu.c
+ 1
+ ..\..\..\..\3rd_party\efm32pg1b\em_cmu.c
+
+
+ em_emu.c
+ 1
+ ..\..\..\..\3rd_party\efm32pg1b\em_emu.c
+
+
+ em_gpio.c
+ 1
+ ..\..\..\..\3rd_party\efm32pg1b\em_gpio.c
+
+
+ system_efm32pg1b.c
+ 1
+ ..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c
+
+
+ em_system.c
+ 1
+ ..\..\..\..\3rd_party\efm32pg1b\em_system.c
+
+
+ em_usart.c
+ 1
+ ..\..\..\..\3rd_party\efm32pg1b\em_usart.c
+
+
+
+
+ QP
+
+
+ qep_hsm.c
+ 1
+ ..\..\..\src\qf\qep_hsm.c
+
+
+ qep_msm.c
+ 1
+ ..\..\..\src\qf\qep_msm.c
+
+
+ qf_act.c
+ 1
+ ..\..\..\src\qf\qf_act.c
+
+
+ qf_actq.c
+ 1
+ ..\..\..\src\qf\qf_actq.c
+
+
+ qf_defer.c
+ 1
+ ..\..\..\src\qf\qf_defer.c
+
+
+ qf_dyn.c
+ 1
+ ..\..\..\src\qf\qf_dyn.c
+
+
+ qf_mem.c
+ 1
+ ..\..\..\src\qf\qf_mem.c
+
+
+ qf_ps.c
+ 1
+ ..\..\..\src\qf\qf_ps.c
+
+
+ qf_qact.c
+ 1
+ ..\..\..\src\qf\qf_qact.c
+
+
+ qf_qeq.c
+ 1
+ ..\..\..\src\qf\qf_qeq.c
+
+
+ qf_qmact.c
+ 1
+ ..\..\..\src\qf\qf_qmact.c
+
+
+ qf_time.c
+ 1
+ ..\..\..\src\qf\qf_time.c
+
+
+ qstamp.c
+ 1
+ ..\..\..\include\qstamp.c
+
+
+ qk.c
+ 1
+ ..\..\..\src\qk\qk.c
+
+
+
+
+ QP_port
+
+
+ qep_port.h
+ 5
+ ..\..\..\ports\arm-cm\qxk\armclang\qep_port.h
+
+
+ qf_port.h
+ 5
+ ..\..\..\ports\arm-cm\qxk\armclang\qf_port.h
+
+
+ qk_port.h
+ 5
+ ..\..\..\ports\arm-cm\qk\armclang\qk_port.h
+
+
+ qk_port.c
+ 1
+ ..\..\..\ports\arm-cm\qk\armclang\qk_port.c
+
+
+ qs_port.h
+ 5
+ ..\..\..\ports\arm-cm\qxk\armclang\qs_port.h
+
+
+ qutest_port.c
+ 1
+ ..\..\..\3rd_party\efm32pg1b\qutest\qutest_port.c
+
+
+
+
+ QS
+
+
+ qs.c
+ 1
+ ..\..\..\src\qs\qs.c
+
+
+ qs_64bit.c
+ 1
+ ..\..\..\src\qs\qs_64bit.c
+
+
+ qs_fp.c
+ 1
+ ..\..\..\src\qs\qs_fp.c
+
+
+ qs_rx.c
+ 1
+ ..\..\..\src\qs\qs_rx.c
+
+
+ qutest.c
+ 1
+ ..\..\..\src\qs\qutest.c
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test
+ 1
+
+
+
+
+
diff --git a/test/qxk/src/bsp.hpp b/test/qxk/test_sched/bsp.hpp
similarity index 90%
rename from test/qxk/src/bsp.hpp
rename to test/qxk/test_sched/bsp.hpp
index a6926e59..dab38994 100644
--- a/test/qxk/src/bsp.hpp
+++ b/test/qxk/test_sched/bsp.hpp
@@ -1,7 +1,7 @@
//============================================================================
// Product: BSP for system-testing QXK
-// Last updated for version 7.1.1
-// Last updated on 2022-09-04
+// Last updated for version 7.1.2
+// Last updated on 2022-10-06
//
// Q u a n t u m L e a P s
// ------------------------
@@ -36,12 +36,11 @@
namespace BSP {
-enum { TICKS_PER_SEC = 100 };
-
void init(void);
void terminate(int16_t const result);
// for testing...
+void trace(QP::QActive const *thr, char const *msg);
void wait4PB1(void);
void ledOn(void);
void ledOff(void);
@@ -50,11 +49,12 @@ void trigISR(void);
} // namespace BSP
enum TestSignals {
- TEST_SIG = QP::Q_USER_SIG,
+ TEST0_SIG = QP::Q_USER_SIG,
+ TEST1_SIG,
+ TEST2_SIG,
+ TEST3_SIG,
MAX_PUB_SIG, // the last published signal
- TIMEOUT_SIG,
- TRIG_SIG,
MAX_SIG // the last signal
};
diff --git a/test/qxk/src/bsp_efm32.cpp b/test/qxk/test_sched/bsp_efm32.cpp
similarity index 92%
rename from test/qxk/src/bsp_efm32.cpp
rename to test/qxk/test_sched/bsp_efm32.cpp
index d36f7faa..3f354958 100644
--- a/test/qxk/src/bsp_efm32.cpp
+++ b/test/qxk/test_sched/bsp_efm32.cpp
@@ -1,7 +1,7 @@
//============================================================================
// Product: BSP for system-testing QXK, EFM32-SLSTK3401A board
-// Last updated for version 7.1.1
-// Last updated on 2022-09-04
+// Last updated for version 7.1.2
+// Last updated on 2022-10-06
//
// Q u a n t u m L e a P s
// ------------------------
@@ -60,11 +60,9 @@ namespace BSP {
static QP::QSpyId const l_SysTick_Handler = { 0U };
static QP::QSpyId const l_test_ISR = { 0U };
- static USART_TypeDef * const l_USART0 = ((USART_TypeDef *)(0x40010000UL));
-
enum AppRecords { // application-specific trace records
CONTEXT_SW = QP::QS_USER,
- COMMAND_STAT
+ TRACE_MSG
};
#endif
@@ -90,8 +88,8 @@ void GPIO_EVEN_IRQHandler(void) {
QXK_ISR_ENTRY(); // inform QXK about entering an ISR
// for testing...
- QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), // for testing...
- &BSP::l_test_ISR);
+ static QP::QEvt const t1 = { TEST1_SIG, 0U, 0U };
+ QP::QF::PUBLISH(&t1, &BSP::l_test_ISR);
QXK_ISR_EXIT(); // inform QXK about exiting an ISR
}
@@ -130,7 +128,11 @@ void BSP::init(void) {
QS_OBJ_DICTIONARY(&l_test_ISR);
QS_USR_DICTIONARY(CONTEXT_SW);
- QS_USR_DICTIONARY(COMMAND_STAT);
+ QS_USR_DICTIONARY(TRACE_MSG);
+}
+//............................................................................
+void BSP::terminate(int16_t result) {
+ Q_UNUSED_PAR(result);
}
//............................................................................
void BSP::ledOn(void) {
@@ -145,8 +147,11 @@ void BSP::trigISR(void) {
NVIC_SetPendingIRQ(GPIO_EVEN_IRQn);
}
//............................................................................
-void BSP::terminate(int16_t result) {
- (void)result;
+void BSP::trace(QP::QActive const *thr, char const *msg) {
+ QS_BEGIN_ID(TRACE_MSG, 0U)
+ QS_OBJ(thr);
+ QS_STR(msg);
+ QS_END()
}
// namespace QP ==============================================================
@@ -175,16 +180,6 @@ void QF::onStartup(void) {
void QF::onCleanup(void) {
}
//............................................................................
-#ifdef QXK_ON_CONTEXT_SW
-// NOTE: the context-switch callback is called with interrupts DISABLED
-void QXK::onContextSw(QActive *prev, QActive *next) {
- QS_BEGIN_NOCRIT(BSP::CONTEXT_SW, 0U) // no critical section!
- QS_OBJ(prev);
- QS_OBJ(next);
- QS_END_NOCRIT()
-}
-#endif // QXK_ON_CONTEXT_SW
-//............................................................................
void QXK::onIdle(void) {
#ifdef Q_SPY
QS::rxParse(); // parse all the received bytes
@@ -199,7 +194,6 @@ void QXK::onIdle(void) {
}
// QS callbacks ==============================================================
-#ifdef Q_SPY
//............................................................................
void QTimeEvt::tick1_(
uint_fast8_t const tickRate,
@@ -211,8 +205,21 @@ void QTimeEvt::tick1_(
QF_INT_ENABLE();
}
-#endif // Q_SPY
//----------------------------------------------------------------------------
} // namespace QP
+extern "C" {
+//............................................................................
+#ifdef QXK_ON_CONTEXT_SW
+// NOTE: the context-switch callback is called with interrupts DISABLED
+void QXK_onContextSw(QP::QActive *prev, QP::QActive *next) {
+ QS_BEGIN_NOCRIT(BSP::CONTEXT_SW, 0U) // no critical section!
+ QS_OBJ(prev);
+ QS_OBJ(next);
+ QS_END_NOCRIT()
+}
+#endif // QXK_ON_CONTEXT_SW
+
+} // extern "C"
+
diff --git a/test/qxk/src/bsp_l053r8.cpp b/test/qxk/test_sched/bsp_l053r8.cpp
similarity index 92%
rename from test/qxk/src/bsp_l053r8.cpp
rename to test/qxk/test_sched/bsp_l053r8.cpp
index 6ed640ba..0475c8a4 100644
--- a/test/qxk/src/bsp_l053r8.cpp
+++ b/test/qxk/test_sched/bsp_l053r8.cpp
@@ -1,7 +1,7 @@
//============================================================================
// Product: BSP for system-testing QXK kernel, NUCLEO-L053R8 board
-// Last updated for version 7.1.1
-// Last updated on 2022-09-04
+// Last updated for version 7.1.2
+// Last updated on 2022-10-06
//
// Q u a n t u m L e a P s
// ------------------------
@@ -57,7 +57,7 @@ namespace BSP {
enum AppRecords { // application-specific trace records
CONTEXT_SW = QP::QS_USER,
- COMMAND_STAT
+ TRACE_MSG
};
#endif
@@ -83,8 +83,8 @@ void EXTI0_1_IRQHandler(void) {
QXK_ISR_ENTRY(); // inform QXK about entering an ISR
// for testing...
- QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), // for testing...
- &BSP::l_test_ISR);
+ static QP::QEvt const t1 = { TEST1_SIG, 0U, 0U };
+ QP::QF::PUBLISH(&t1, &BSP::l_test_ISR);
QXK_ISR_EXIT(); // inform QXK about exiting an ISR
}
@@ -125,7 +125,11 @@ void BSP::init(void) {
QS_OBJ_DICTIONARY(&l_test_ISR);
QS_USR_DICTIONARY(CONTEXT_SW);
- QS_USR_DICTIONARY(COMMAND_STAT);
+ QS_USR_DICTIONARY(TRACE_MSG);
+}
+//............................................................................
+void BSP::terminate(int16_t result) {
+ Q_UNUSED_PAR(result);
}
//............................................................................
void BSP::ledOn(void) {
@@ -140,8 +144,11 @@ void BSP::trigISR(void) {
NVIC_SetPendingIRQ(EXTI0_1_IRQn);
}
//............................................................................
-void BSP::terminate(int16_t result) {
- (void)result;
+void BSP::trace(QP::QActive const *thr, char const *msg) {
+ QS_BEGIN_ID(TRACE_MSG, 0U)
+ QS_OBJ(thr);
+ QS_STR(msg);
+ QS_END()
}
// namespace QP ==============================================================
@@ -170,16 +177,6 @@ void QF::onStartup(void) {
void QF::onCleanup(void) {
}
//............................................................................
-#ifdef QXK_ON_CONTEXT_SW
-// NOTE: the context-switch callback is called with interrupts DISABLED
-void QXK::onContextSw(QActive *prev, QActive *next) {
- QS_BEGIN_NOCRIT(BSP::CONTEXT_SW, 0U) // no critical section!
- QS_OBJ(prev);
- QS_OBJ(next);
- QS_END_NOCRIT()
-}
-#endif // QXK_ON_CONTEXT_SW
-//............................................................................
void QXK::onIdle(void) {
#ifdef Q_SPY
QS::rxParse(); // parse all the received bytes
@@ -194,7 +191,6 @@ void QXK::onIdle(void) {
}
// QS callbacks ==============================================================
-#ifdef Q_SPY
//............................................................................
void QTimeEvt::tick1_(
uint_fast8_t const tickRate,
@@ -206,8 +202,21 @@ void QTimeEvt::tick1_(
QF_INT_ENABLE();
}
-#endif // Q_SPY
//----------------------------------------------------------------------------
} // namespace QP
+extern "C" {
+//............................................................................
+#ifdef QXK_ON_CONTEXT_SW
+// NOTE: the context-switch callback is called with interrupts DISABLED
+void QXK_onContextSw(QP::QActive *prev, QP::QActive *next) {
+ QS_BEGIN_NOCRIT(BSP::CONTEXT_SW, 0U) // no critical section!
+ QS_OBJ(prev);
+ QS_OBJ(next);
+ QS_END_NOCRIT()
+}
+#endif // QXK_ON_CONTEXT_SW
+
+} // extern "C"
+
diff --git a/test/qxk/test_xthr/make_efm32 b/test/qxk/test_sched/make_efm32
similarity index 94%
rename from test/qxk/test_xthr/make_efm32
rename to test/qxk/test_sched/make_efm32
index ae802155..4f810e9b 100644
--- a/test/qxk/test_xthr/make_efm32
+++ b/test/qxk/test_sched/make_efm32
@@ -1,7 +1,7 @@
##############################################################################
# Product: Makefile for SYSTEM-Level tests of QP/C++ on EMF32, GNU-ARM
-# Last Updated for Version: 7.1.1
-# Date of the Last Update: 2022-09-05
+# Last Updated for Version: 7.1.2
+# Date of the Last Update: 2022-10-05
#
# Q u a n t u m L e a P s
# ------------------------
@@ -38,6 +38,7 @@
# make -f make_efm32 HOST=localhost:7705 # connect to host:port
# make -f make_efm32 norun # only make but not run the tests
# make -f make_efm32 clean # cleanup the build
+# make -f make_efm32 debug # only run tests in DEBUG mode
#
# NOTE:
# To use this Makefile on Windows, you will need the GNU make utility, which
@@ -53,7 +54,7 @@ endif
#-----------------------------------------------------------------------------
# project name, target name, target directory:
#
-PROJECT := test_xthr
+PROJECT := test_sched
TARGET := efm32
TARGET_DIR := $(QPCPP)/3rd_party/efm32pg1b/qutest
@@ -72,7 +73,6 @@ endif
# list of all source directories used by this project
VPATH := . \
- ../src \
$(QPCPP)/src/qf \
$(QPCPP)/src/qxk \
$(QPCPP)/src/qs \
@@ -83,7 +83,6 @@ VPATH := . \
# list of all include directories needed by this project
INCLUDES = -I. \
- -I../src \
-I$(QPCPP)/include \
-I$(QP_PORT_DIR) \
-I$(TARGET_DIR) \
@@ -108,7 +107,7 @@ C_SRCS := \
# C++ source files
CPP_SRCS := \
- test_xthr.cpp \
+ test_sched.cpp \
bsp_efm32.cpp
OUTPUT := $(PROJECT)
@@ -145,7 +144,8 @@ LIB_DIRS :=
LIBS :=
# defines
-DEFINES := -DEFM32PG1B200F256GM48=1
+DEFINES := -DEFM32PG1B200F256GM48=1 \
+ -DQXK_ON_CONTEXT_SW
# ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]
@@ -250,7 +250,7 @@ endif
# rules
#
-.PHONY : run norun flash
+.PHONY : run norun debug flash
ifeq ($(MAKECMDGOALS),norun)
all : $(TARGET_BIN)
@@ -288,15 +288,23 @@ $(BIN_DIR)/%.o : %.c
$(BIN_DIR)/%.o : %.cpp
$(CPP) $(CPPFLAGS) $< -o $@
-.PHONY : clean show
-
-# include dependency files only if our goal depends on their existence
+# create BIN_DIR and include dependencies only if needed
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),show)
+ ifneq ($(MAKECMDGOALS),debug)
+ifeq ("$(wildcard $(BIN_DIR))","")
+$(shell $(MKDIR) $(BIN_DIR))
+endif
-include $(C_DEPS_EXT) $(CPP_DEPS_EXT)
+ endif
endif
endif
+debug :
+ $(QUTEST) $(TESTS) DEBUG $(HOST)
+
+.PHONY : clean show
+
clean :
-$(RM) $(BIN_DIR)/*.o \
$(BIN_DIR)/*.d \
diff --git a/test/qxk/test_xthr/make_nucleo-l053r8 b/test/qxk/test_sched/make_nucleo-l053r8
similarity index 94%
rename from test/qxk/test_xthr/make_nucleo-l053r8
rename to test/qxk/test_sched/make_nucleo-l053r8
index 6bb3d797..364dacb3 100644
--- a/test/qxk/test_xthr/make_nucleo-l053r8
+++ b/test/qxk/test_sched/make_nucleo-l053r8
@@ -1,7 +1,7 @@
##############################################################################
-# Product: Makefile for SYSTEM-Level tests of QP/C++ on NUCLEO-L053R8, GNU-ARM
-# Last Updated for Version: 7.1.1
-# Date of the Last Update: 2022-09-05
+# Product: Makefile for SYSTEM-Level tests of QP/C on NUCLEO-L053R8, GNU-ARM
+# Last Updated for Version: 7.1.2
+# Date of the Last Update: 2022-10-05
#
# Q u a n t u m L e a P s
# ------------------------
@@ -38,6 +38,7 @@
# make -f make_nucleo-l053r8 HOST=localhost:7705 # connect to host:port
# make -f make_nucleo-l053r8 norun # only make but not run the tests
# make -f make_nucleo-l053r8 clean # cleanup the build
+# make -f make_nucleo-l053r8 debug # only run tests in DEBUG mode
#
# NOTE:
# To use this Makefile on Windows, you will need the GNU make utility, which
@@ -53,7 +54,7 @@ endif
#-----------------------------------------------------------------------------
# project name, target name, target directory:
#
-PROJECT := test_xthr
+PROJECT := test_sched
TARGET := nucleo-l053r8
TARGET_DIR := $(QPCPP)/3rd_party/nucleo-l053r8/qutest
@@ -72,7 +73,6 @@ endif
# list of all source directories used by this project
VPATH := . \
- ../src \
$(QPCPP)/src/qf \
$(QPCPP)/src/qxk \
$(QPCPP)/src/qs \
@@ -83,7 +83,6 @@ VPATH := . \
# list of all include directories needed by this project
INCLUDES = -I. \
- -I../src \
-I$(QPCPP)/include \
-I$(QP_PORT_DIR) \
-I$(TARGET_DIR) \
@@ -104,7 +103,7 @@ C_SRCS := \
# C++ source files
CPP_SRCS := \
- test_xthr.cpp \
+ test_sched.cpp \
bsp_l053r8.cpp
OUTPUT := $(PROJECT)
@@ -141,7 +140,8 @@ LIB_DIRS :=
LIBS :=
# defines
-DEFINES :=
+DEFINES := \
+ -DQXK_ON_CONTEXT_SW
# ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]
@@ -250,7 +250,7 @@ endif
# rules
#
-.PHONY : run norun flash
+.PHONY : run norun debug flash
ifeq ($(MAKECMDGOALS),norun)
all : $(TARGET_BIN)
@@ -289,15 +289,23 @@ $(BIN_DIR)/%.o : %.c
$(BIN_DIR)/%.o : %.cpp
$(CPP) $(CPPFLAGS) $< -o $@
-.PHONY : clean show
-
-# include dependency files only if our goal depends on their existence
+# create BIN_DIR and include dependencies only if needed
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),show)
+ ifneq ($(MAKECMDGOALS),debug)
+ifeq ("$(wildcard $(BIN_DIR))","")
+$(shell $(MKDIR) $(BIN_DIR))
+endif
-include $(C_DEPS_EXT) $(CPP_DEPS_EXT)
+ endif
endif
endif
+debug :
+ $(QUTEST) $(TESTS) DEBUG $(HOST)
+
+.PHONY : clean show
+
clean :
-$(RM) $(BIN_DIR)/*.o \
$(BIN_DIR)/*.d \
@@ -326,6 +334,5 @@ show :
@echo QTOOLS = $(QTOOLS)
@echo HOST = $(HOST)
@echo QUTEST = $(QUTEST)
- @echo FLASH = $(FLASH)
@echo TESTS = $(TESTS)
diff --git a/test/qxk/test_sched/test_sched.cpp b/test/qxk/test_sched/test_sched.cpp
new file mode 100644
index 00000000..58fad133
--- /dev/null
+++ b/test/qxk/test_sched/test_sched.cpp
@@ -0,0 +1,245 @@
+//============================================================================
+// Product: System test fixture for QXK on the EFM32 target
+// Last updated for version 7.1.2
+// Last updated on 2022-10-06
+//
+// Q u a n t u m L e a P s
+// ------------------------
+// Modern Embedded Software
+//
+// Copyright (C) 2005 Quantum Leaps. All rights reserved.
+//
+// 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.
+//
+// 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
+// along with this program. If not, see .
+//
+// Contact information:
+//
+//
+//============================================================================
+#include "qpcpp.hpp"
+#include "bsp.hpp"
+
+Q_DEFINE_THIS_FILE
+
+namespace {
+//============================================================================
+// AO ObjB
+enum { NUM_B = 3 };
+
+//............................................................................
+// AO ObjB
+class ObjB : public QP::QActive {
+public:
+ static ObjB inst[NUM_B];
+
+public:
+ ObjB() : QActive(&initial) {}
+
+protected:
+ Q_STATE_DECL(initial);
+ Q_STATE_DECL(active);
+}; // class ObjB
+
+Q_STATE_DEF(ObjB, initial) {
+ static bool registered = false; // starts off with 0, per C-standard
+ if (!registered) {
+ registered = true;
+ QS_FUN_DICTIONARY(&ObjB::initial);
+ QS_FUN_DICTIONARY(&ObjB::active);
+ }
+ subscribe(TEST1_SIG);
+ subscribe(TEST2_SIG);
+ return tran(&active);
+}
+
+Q_STATE_DEF(ObjB, active) {
+ QP::QState status_;
+ switch (e->sig) {
+ case TEST0_SIG: {
+ BSP::trace(this, "TEST0 1of2");
+ BSP::trigISR();
+ BSP::trace(this, "TEST0 2of2");
+ status_ = Q_RET_HANDLED;
+ break;
+ }
+ case TEST1_SIG: {
+ BSP::trace(this, "TEST1 1of1");
+ status_ = Q_RET_HANDLED;
+ break;
+ }
+ case TEST2_SIG: {
+ BSP::trace(this, "TEST2 1of1");
+ status_ = Q_RET_HANDLED;
+ break;
+ }
+ default: {
+ status_ = super(&top);
+ break;
+ }
+ }
+ return status_;
+}
+
+ObjB ObjB::inst[NUM_B];
+
+/*==========================================================================*/
+enum { NUM_X = 3 };
+
+static void ThrX_run(QP::QXThread * const me) {
+ me->subscribe(TEST1_SIG);
+ me->subscribe(TEST2_SIG);
+
+ for (;;) {
+ QP::QEvt const *e = me->queueGet(QP::QXTHREAD_NO_TIMEOUT);
+ switch (e->sig) {
+ case TEST0_SIG: {
+ BSP::trace(me, "TEST0 1of2");
+ BSP::trigISR();
+ BSP::trace(me, "TEST0 2of2");
+ break;
+ }
+ case TEST1_SIG: {
+ static QP::QEvt const t2 = { TEST2_SIG, 0U, 0U };
+ BSP::trace(me, "TEST1 1of2");
+ QP::QActive::PUBLISH(&t2, me);
+ BSP::trace(me, "TEST1 2of2");
+ break;
+ }
+ case TEST2_SIG: {
+ BSP::trace(me, "TEST2 1of1");
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+}
+
+class ThrX : public QP::QXThread {
+public:
+ static ThrX inst[NUM_X];
+
+public:
+ ThrX() : QXThread(&ThrX_run) {}
+};
+
+ThrX ThrX::inst[NUM_X];
+
+} // unnamed namespace
+
+//============================================================================
+int main() {
+
+ QP::QF::init(); // initialize the framework and the underlying QXK kernel
+ BSP::init(); // initialize the Board Support Package
+
+ // initialize publish-subscribe...
+ static QP::QSubscrList subscrSto[MAX_PUB_SIG];
+ QP::QActive::psInit(subscrSto, Q_DIM(subscrSto));
+
+ // initialize event pools...
+ static QF_MPOOL_EL(QP::QEvt) smlPoolSto[10]; // small pool
+ QP::QF::poolInit(smlPoolSto, sizeof(smlPoolSto), sizeof(smlPoolSto[0]));
+
+ // dictionaries
+ QS_SIG_DICTIONARY(TEST0_SIG, nullptr);
+ QS_SIG_DICTIONARY(TEST1_SIG, nullptr);
+ QS_SIG_DICTIONARY(TEST2_SIG, nullptr);
+ QS_SIG_DICTIONARY(TEST3_SIG, nullptr);
+
+ // priority specifications for ObjBs...
+ static QP::QPrioSpec pspecB[NUM_B];
+ QS_OBJ_DICTIONARY(pspecB);
+
+ // priority specifications for ThrXs...
+ static QP::QPrioSpec pspecX[NUM_X];
+ QS_OBJ_DICTIONARY(pspecX);
+
+ std::uint8_t n;
+
+ for (n = 0U; n < NUM_B; ++n) {
+ QS_OBJ_ARR_DICTIONARY(&ObjB::inst[n], n);
+ }
+ for (n = 0U; n < NUM_X; ++n) {
+ QS_OBJ_ARR_DICTIONARY(&ThrX::inst[n], n);
+ }
+
+ // pause execution of the test and wait for the test script to continue
+ // NOTE:
+ // this pause gives the test-script a chance to poke pspecB and pspecX
+ // variables to start the threads with the desired prio-specifications.
+ QS_TEST_PAUSE();
+
+ static QP::QEvt const *aoB_queueSto[NUM_B][5];
+ for (n = 0U; n < NUM_B; ++n) {
+ if (pspecB[n] != 0U) {
+ ObjB::inst[n].start(pspecB[n], // QF-prio/p-thre.
+ aoB_queueSto[n], // event queue storage
+ Q_DIM(aoB_queueSto[n]), // event length [events]
+ nullptr, // no stack storage
+ 0U); // zero stack size [bytes]
+ }
+ }
+
+ static QP::QEvt const *thrX_queueSto[NUM_X][5];
+ static std::uint64_t thrXStackSto[NUM_X][32];
+ for (n = 0U; n < NUM_X; ++n) {
+ if (pspecX[n] != 0U) {
+ ThrX::inst[n].start(pspecX[n], // QF-prio/p-thre.
+ thrX_queueSto[n], // event queue storage
+ Q_DIM(thrX_queueSto[n]), // event length [events]
+ thrXStackSto[n], // stack storage
+ sizeof(thrXStackSto[n]));// stack size [bytes]
+ }
+ }
+
+ return QP::QF::run(); // run the QF application
+}
+
+//============================================================================
+namespace QP {
+
+void QS::onTestSetup(void) {
+}
+//............................................................................
+void QS::onTestTeardown(void) {
+}
+//............................................................................
+//! callback function to execute user commands
+void QS::onCommand(uint8_t cmdId,
+ uint32_t param1, uint32_t param2, uint32_t param3)
+{
+ Q_UNUSED_PAR(cmdId);
+ Q_UNUSED_PAR(param1);
+ Q_UNUSED_PAR(param2);
+ Q_UNUSED_PAR(param3);
+}
+
+//============================================================================
+//! Host callback function to "massage" the event, if necessary
+void QS::onTestEvt(QEvt *e) {
+ (void)e;
+}
+//............................................................................
+//! callback function to output the posted QP events (not used here)
+void QS::onTestPost(void const *sender, QActive *recipient,
+ QEvt const *e, bool status)
+{}
+
+} // namespace QP
diff --git a/test/qxk/test_sched/test_sched.py b/test/qxk/test_sched/test_sched.py
new file mode 100644
index 00000000..7f56e362
--- /dev/null
+++ b/test/qxk/test_sched/test_sched.py
@@ -0,0 +1,141 @@
+# test-script for QUTest unit testing harness
+# see https://www.state-machine.com/qtools/qutest.html/qutest.html
+
+# preamble
+def on_reset():
+ expect_pause()
+
+test("extened->basic")
+current_obj(OBJ_AP, "pspecB")
+poke(0, 2, pack("1")
+expect("@timestamp CONTEXT_SW NULL ThrX::inst[0]")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST0 1of2")
+expect("@timestamp Sch-Next Pri=1->4")
+expect("@timestamp CONTEXT_SW ThrX::inst[0] ObjB::inst[0]")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 1of1")
+expect("@timestamp Sch-Next Pri=4->1")
+expect("@timestamp CONTEXT_SW ObjB::inst[0] ThrX::inst[0]")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST0 2of2")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST1 1of2")
+expect("@timestamp Sch-Lock Ceil=0->4")
+expect("@timestamp Sch-Unlk Ceil=4->0")
+expect("@timestamp Sch-Next Pri=1->4")
+expect("@timestamp CONTEXT_SW ThrX::inst[0] ObjB::inst[0]")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=4->1")
+expect("@timestamp CONTEXT_SW ObjB::inst[0] ThrX::inst[0]")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST1 2of2")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST2 1of1")
+expect("@timestamp Sch-Idle Pri=1->0")
+expect("@timestamp CONTEXT_SW ThrX::inst[0] NULL")
+expect("@timestamp Trg-Done QS_RX_EVENT")
+
+test("extended->extened->basic")
+current_obj(OBJ_AP, "pspecB")
+poke(0, 2, pack("4")
+expect("@timestamp CONTEXT_SW NULL ThrX::inst[0]")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST0 1of2")
+expect("@timestamp Sch-Next Pri=4->5")
+expect("@timestamp CONTEXT_SW ThrX::inst[0] ThrX::inst[1]")
+expect("@timestamp TRACE_MSG ThrX::inst[1] TEST1 1of2")
+expect("@timestamp Sch-Lock Ceil=0->5")
+expect("@timestamp Sch-Unlk Ceil=5->0")
+expect("@timestamp TRACE_MSG ThrX::inst[1] TEST1 2of2")
+expect("@timestamp TRACE_MSG ThrX::inst[1] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=5->4")
+expect("@timestamp CONTEXT_SW ThrX::inst[1] ThrX::inst[0]")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST0 2of2")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST1 1of2")
+expect("@timestamp Sch-Lock Ceil=0->5")
+expect("@timestamp Sch-Unlk Ceil=5->0")
+expect("@timestamp Sch-Next Pri=4->5")
+expect("@timestamp CONTEXT_SW ThrX::inst[0] ThrX::inst[1]")
+expect("@timestamp TRACE_MSG ThrX::inst[1] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=5->4")
+expect("@timestamp CONTEXT_SW ThrX::inst[1] ThrX::inst[0]")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST1 2of2")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST2 1of1")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=4->3")
+expect("@timestamp CONTEXT_SW ThrX::inst[0] ObjB::inst[2]")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST1 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=3->2")
+expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST1 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=2->1")
+expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[0]")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1")
+expect("@timestamp Sch-Idle Pri=1->0")
+expect("@timestamp CONTEXT_SW ObjB::inst[0] NULL")
+expect("@timestamp Trg-Done QS_RX_EVENT")
+
+
+test("extened->basic->extended")
+current_obj(OBJ_AP, "pspecB")
+poke(0, 2, pack("1")
+expect("@timestamp CONTEXT_SW NULL ThrX::inst[0]")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST0 1of2")
+expect("@timestamp Sch-Next Pri=1->5")
+expect("@timestamp CONTEXT_SW ThrX::inst[0] ThrX::inst[1]")
+expect("@timestamp TRACE_MSG ThrX::inst[1] TEST1 1of2")
+expect("@timestamp Sch-Lock Ceil=0->5")
+expect("@timestamp Sch-Unlk Ceil=5->0")
+expect("@timestamp TRACE_MSG ThrX::inst[1] TEST1 2of2")
+expect("@timestamp TRACE_MSG ThrX::inst[1] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=5->4")
+expect("@timestamp CONTEXT_SW ThrX::inst[1] ObjB::inst[0]")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 1of1")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=4->1")
+expect("@timestamp CONTEXT_SW ObjB::inst[0] ThrX::inst[0]")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST0 2of2")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST1 1of2")
+expect("@timestamp Sch-Lock Ceil=0->5")
+expect("@timestamp Sch-Unlk Ceil=5->0")
+expect("@timestamp Sch-Next Pri=1->5")
+expect("@timestamp CONTEXT_SW ThrX::inst[0] ThrX::inst[1]")
+expect("@timestamp TRACE_MSG ThrX::inst[1] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=5->4")
+expect("@timestamp CONTEXT_SW ThrX::inst[1] ObjB::inst[0]")
+expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1")
+expect("@timestamp Sch-Next Pri=4->1")
+expect("@timestamp CONTEXT_SW ObjB::inst[0] ThrX::inst[0]")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST1 2of2")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST2 1of1")
+expect("@timestamp TRACE_MSG ThrX::inst[0] TEST2 1of1")
+expect("@timestamp Sch-Idle Pri=1->0")
+expect("@timestamp CONTEXT_SW ThrX::inst[0] NULL")
+expect("@timestamp Trg-Done QS_RX_EVENT")
diff --git a/test/qxk/test_sched/uvision_efm32.uvoptx b/test/qxk/test_sched/uvision_efm32.uvoptx
new file mode 100644
index 00000000..f802e499
--- /dev/null
+++ b/test/qxk/test_sched/uvision_efm32.uvoptx
@@ -0,0 +1,801 @@
+
+
+
+ 1.0
+
+ ### uVision Project, (C) Keil Software
+
+
+ *.c
+ *.s*; *.src; *.a*
+ *.obj; *.o
+ *.lib
+ *.txt; *.h; *.inc; *.md
+ *.plm
+ *.cpp
+ 0
+
+
+
+ 0
+ 0
+
+
+
+ qutest
+ 0x4
+ ARM-ADS
+
+ 12000000
+
+ 1
+ 1
+ 1
+ 0
+ 0
+
+
+ 1
+ 65535
+ 0
+ 0
+ 0
+
+
+ 79
+ 66
+ 8
+ .\uvision_emf32\
+
+
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+
+
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+
+
+ 1
+ 0
+ 1
+
+ 3
+
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 1
+ 0
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ 0
+ 4
+
+
+
+
+
+
+
+
+
+
+ Segger\JL2CM3.dll
+
+
+
+ 0
+ DLGUARM
+
+
+
+ 0
+ JL2CM3
+ -U440060969 -O206 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO7 -FD20000000 -FC8000 -FN1 -FF0GECKOP2.FLM -FS00 -FL020000 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM)
+
+
+ 0
+ ARMRTXEVENTFLAGS
+ -L70 -Z18 -C0 -M0 -T1
+
+
+ 0
+ UL2CM3
+ UL2CM3(-O207 -S0 -C0 -FO7 -FN1 -FC8000 -FD20000000 -FF0GECKOP2 -FL020000 -FS00 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM)
+
+
+ 0
+ DLGTARM
+ (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)
+
+
+ 0
+ ARMDBGFLAGS
+
+
+
+ 0
+ lmidk-agdi
+ -U0E2006F4 -O4622 -S4 -FO61
+
+
+
+
+ 0
+ 0
+ 142
+ 1
+ 136
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ ..\..\..\src\qs\qs.c
+
+ \\test\../../../src/qs/qs.c\142
+
+
+ 1
+ 0
+ 113
+ 1
+ 29538
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ ..\..\..\src\qs\qutest.c
+
+ \\test\../../../src/qs/qutest.c\113
+
+
+ 2
+ 0
+ 259
+ 1
+ 26664
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ ..\..\..\src\qxk\qxk.c
+
+ \\test\../../../src/qxk/qxk.c\259
+
+
+ 3
+ 0
+ 103
+ 1
+ 29984
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ .\test_sched.c
+
+ \\test\test_sched.c\103
+
+
+
+
+ 0
+ 1
+ QF_readySet_
+
+
+ 1
+ 1
+ QXK_attr_
+
+
+ 2
+ 1
+ QActive_registry_
+
+
+ 3
+ 1
+ QS_rxPriv_
+
+
+
+
+ 1
+ 2
+ 0x20000200
+ 0
+
+
+
+
+ 2
+ 0
+ 0x400
+ 0
+
+
+
+ 0
+
+
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+ Applicatioin
+ 1
+ 0
+ 0
+ 0
+
+ 1
+ 1
+ 5
+ 0
+ 0
+ 0
+ .\bsp.h
+ bsp.h
+ 0
+ 0
+
+
+ 1
+ 2
+ 1
+ 0
+ 0
+ 0
+ .\bsp_efm32.c
+ bsp_efm32.c
+ 0
+ 0
+
+
+ 1
+ 3
+ 1
+ 0
+ 0
+ 0
+ .\test_sched.c
+ test_sched.c
+ 0
+ 0
+
+
+
+
+ efm32pg1b
+ 1
+ 0
+ 0
+ 0
+
+ 2
+ 4
+ 2
+ 0
+ 0
+ 0
+ ..\..\..\..\3rd_party\efm32pg1b\arm\startup_efm32pg1b.s
+ startup_efm32pg1b.s
+ 0
+ 0
+
+
+ 2
+ 5
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\3rd_party\efm32pg1b\em_cmu.c
+ em_cmu.c
+ 0
+ 0
+
+
+ 2
+ 6
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\3rd_party\efm32pg1b\em_emu.c
+ em_emu.c
+ 0
+ 0
+
+
+ 2
+ 7
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\3rd_party\efm32pg1b\em_gpio.c
+ em_gpio.c
+ 0
+ 0
+
+
+ 2
+ 8
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c
+ system_efm32pg1b.c
+ 0
+ 0
+
+
+ 2
+ 9
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\3rd_party\efm32pg1b\em_system.c
+ em_system.c
+ 0
+ 0
+
+
+ 2
+ 10
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\3rd_party\efm32pg1b\em_usart.c
+ em_usart.c
+ 0
+ 0
+
+
+
+
+ QP
+ 1
+ 0
+ 0
+ 0
+
+ 3
+ 11
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qep_hsm.c
+ qep_hsm.c
+ 0
+ 0
+
+
+ 3
+ 12
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qep_msm.c
+ qep_msm.c
+ 0
+ 0
+
+
+ 3
+ 13
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_act.c
+ qf_act.c
+ 0
+ 0
+
+
+ 3
+ 14
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_actq.c
+ qf_actq.c
+ 0
+ 0
+
+
+ 3
+ 15
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_defer.c
+ qf_defer.c
+ 0
+ 0
+
+
+ 3
+ 16
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_dyn.c
+ qf_dyn.c
+ 0
+ 0
+
+
+ 3
+ 17
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_mem.c
+ qf_mem.c
+ 0
+ 0
+
+
+ 3
+ 18
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_ps.c
+ qf_ps.c
+ 0
+ 0
+
+
+ 3
+ 19
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_qact.c
+ qf_qact.c
+ 0
+ 0
+
+
+ 3
+ 20
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_qeq.c
+ qf_qeq.c
+ 0
+ 0
+
+
+ 3
+ 21
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_qmact.c
+ qf_qmact.c
+ 0
+ 0
+
+
+ 3
+ 22
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qf\qf_time.c
+ qf_time.c
+ 0
+ 0
+
+
+ 3
+ 23
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qxk\qxk.c
+ qxk.c
+ 0
+ 0
+
+
+ 3
+ 24
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qxk\qxk_mutex.c
+ qxk_mutex.c
+ 0
+ 0
+
+
+ 3
+ 25
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qxk\qxk_sema.c
+ qxk_sema.c
+ 0
+ 0
+
+
+ 3
+ 26
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qxk\qxk_xthr.c
+ qxk_xthr.c
+ 0
+ 0
+
+
+ 3
+ 27
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\include\qstamp.c
+ qstamp.c
+ 0
+ 0
+
+
+
+
+ QP_port
+ 1
+ 0
+ 0
+ 0
+
+ 4
+ 28
+ 5
+ 0
+ 0
+ 0
+ ..\..\..\ports\arm-cm\qxk\armclang\qep_port.h
+ qep_port.h
+ 0
+ 0
+
+
+ 4
+ 29
+ 5
+ 0
+ 0
+ 0
+ ..\..\..\ports\arm-cm\qxk\armclang\qf_port.h
+ qf_port.h
+ 0
+ 0
+
+
+ 4
+ 30
+ 5
+ 0
+ 0
+ 0
+ ..\..\..\ports\arm-cm\qxk\armclang\qs_port.h
+ qs_port.h
+ 0
+ 0
+
+
+ 4
+ 31
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\ports\arm-cm\qxk\armclang\qxk_port.c
+ qxk_port.c
+ 0
+ 0
+
+
+ 4
+ 32
+ 5
+ 0
+ 0
+ 0
+ ..\..\..\ports\arm-cm\qxk\armclang\qxk_port.h
+ qxk_port.h
+ 0
+ 0
+
+
+ 4
+ 33
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\3rd_party\efm32pg1b\qutest\qutest_port.c
+ qutest_port.c
+ 0
+ 0
+
+
+
+
+ QS
+ 1
+ 0
+ 0
+ 0
+
+ 5
+ 34
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qs\qs.c
+ qs.c
+ 0
+ 0
+
+
+ 5
+ 35
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qs\qs_64bit.c
+ qs_64bit.c
+ 0
+ 0
+
+
+ 5
+ 36
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qs\qs_fp.c
+ qs_fp.c
+ 0
+ 0
+
+
+ 5
+ 37
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qs\qs_rx.c
+ qs_rx.c
+ 0
+ 0
+
+
+ 5
+ 38
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\src\qs\qutest.c
+ qutest.c
+ 0
+ 0
+
+
+
+
diff --git a/test/qxk/test_sched/uvision_efm32.uvprojx b/test/qxk/test_sched/uvision_efm32.uvprojx
new file mode 100644
index 00000000..8c1c944b
--- /dev/null
+++ b/test/qxk/test_sched/uvision_efm32.uvprojx
@@ -0,0 +1,617 @@
+
+
+
+ 2.1
+
+ ### uVision Project, (C) Keil Software
+
+
+
+ qutest
+ 0x4
+ ARM-ADS
+ 6160000::V6.16::ARMCLANG
+ 1
+
+
+ EFM32PG1B200F256GM48
+ Silicon Labs
+ SiliconLabs.GeckoPlatform_EFM32PG1B_DFP.4.0.0
+ https://www.silabs.com/documents/public/cmsis-packs/
+ IRAM(0x20000000,0x00008000) IROM(0x00000000,0x00020000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE
+
+
+ UL2CM3(-S0 -C0 -P0 -FD20000000 -FC8000 -FN1 -FF0GECKOP2 -FS00 -FL020000 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM))
+ 0
+ $$Device:EFM32PG1B200F256GM48$Device\EFM32PG1B\Include\em_device.h
+
+
+
+
+
+
+
+
+
+ $$Device:EFM32PG1B200F256GM48$SVD\EFM32PG1B\EFM32PG1B200F256GM48.svd
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+ 1
+
+ .\uvision_emf32\
+ test
+ 1
+ 0
+ 0
+ 1
+ 1
+ .\uvision_emf32\
+ 1
+ 0
+ 0
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+ 1
+ 0
+ cmd /c "del .\uvision_em32\qstamp.o"
+
+ 0
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 3
+
+
+ 1
+
+
+ SARMCM3.DLL
+ -MPU
+ DCM.DLL
+ -pCM4
+ SARMCM3.DLL
+ -MPU
+ TCM.DLL
+ -pCM4
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 16
+
+
+
+
+ 1
+ 0
+ 0
+ 1
+ 1
+ 4096
+
+ 1
+ BIN\UL2CM3.DLL
+ "" ()
+
+
+
+
+ 0
+
+
+
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ "Cortex-M4"
+
+ 0
+ 0
+ 0
+ 1
+ 1
+ 0
+ 0
+ 2
+ 0
+ 0
+ 0
+ 0
+ 8
+ 0
+ 0
+ 0
+ 0
+ 3
+ 3
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x20000000
+ 0x8000
+
+
+ 1
+ 0x0
+ 0x20000
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x20000
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x20000000
+ 0x8000
+
+
+ 0
+ 0x0
+ 0x0
+
+
+
+
+
+ 0
+ 1
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 3
+ 0
+ 1
+ 1
+ 0
+ 0
+ 3
+ 3
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+ Q_SPY, Q_UTEST=0, QXK_ON_CONTEXT_SW
+
+ .;..\..\..\include;..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\3rd_party\efm32pg1b
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 4
+
+
+ Stack_Size=2048 Heap_Size=16
+
+
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0x00000000
+ 0x20000000
+
+
+
+
+ --entry Reset_Handler
+
+
+
+
+
+
+
+ Applicatioin
+
+
+ bsp.h
+ 5
+ .\bsp.h
+
+
+ bsp_efm32.c
+ 1
+ .\bsp_efm32.c
+
+
+ test_sched.c
+ 1
+ .\test_sched.c
+
+
+
+
+ efm32pg1b
+
+
+ startup_efm32pg1b.s
+ 2
+ ..\..\..\..\3rd_party\efm32pg1b\arm\startup_efm32pg1b.s
+
+
+ em_cmu.c
+ 1
+ ..\..\..\..\3rd_party\efm32pg1b\em_cmu.c
+
+
+ em_emu.c
+ 1
+ ..\..\..\..\3rd_party\efm32pg1b\em_emu.c
+
+
+ em_gpio.c
+ 1
+ ..\..\..\..\3rd_party\efm32pg1b\em_gpio.c
+
+
+ system_efm32pg1b.c
+ 1
+ ..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c
+
+
+ em_system.c
+ 1
+ ..\..\..\..\3rd_party\efm32pg1b\em_system.c
+
+
+ em_usart.c
+ 1
+ ..\..\..\..\3rd_party\efm32pg1b\em_usart.c
+
+
+
+
+ QP
+
+
+ qep_hsm.c
+ 1
+ ..\..\..\src\qf\qep_hsm.c
+
+
+ qep_msm.c
+ 1
+ ..\..\..\src\qf\qep_msm.c
+
+
+ qf_act.c
+ 1
+ ..\..\..\src\qf\qf_act.c
+
+
+ qf_actq.c
+ 1
+ ..\..\..\src\qf\qf_actq.c
+
+
+ qf_defer.c
+ 1
+ ..\..\..\src\qf\qf_defer.c
+
+
+ qf_dyn.c
+ 1
+ ..\..\..\src\qf\qf_dyn.c
+
+
+ qf_mem.c
+ 1
+ ..\..\..\src\qf\qf_mem.c
+
+
+ qf_ps.c
+ 1
+ ..\..\..\src\qf\qf_ps.c
+
+
+ qf_qact.c
+ 1
+ ..\..\..\src\qf\qf_qact.c
+
+
+ qf_qeq.c
+ 1
+ ..\..\..\src\qf\qf_qeq.c
+
+
+ qf_qmact.c
+ 1
+ ..\..\..\src\qf\qf_qmact.c
+
+
+ qf_time.c
+ 1
+ ..\..\..\src\qf\qf_time.c
+
+
+ qxk.c
+ 1
+ ..\..\..\src\qxk\qxk.c
+
+
+ qxk_mutex.c
+ 1
+ ..\..\..\src\qxk\qxk_mutex.c
+
+
+ qxk_sema.c
+ 1
+ ..\..\..\src\qxk\qxk_sema.c
+
+
+ qxk_xthr.c
+ 1
+ ..\..\..\src\qxk\qxk_xthr.c
+
+
+ qstamp.c
+ 1
+ ..\..\..\include\qstamp.c
+
+
+
+
+ QP_port
+
+
+ qep_port.h
+ 5
+ ..\..\..\ports\arm-cm\qxk\armclang\qep_port.h
+
+
+ qf_port.h
+ 5
+ ..\..\..\ports\arm-cm\qxk\armclang\qf_port.h
+
+
+ qs_port.h
+ 5
+ ..\..\..\ports\arm-cm\qxk\armclang\qs_port.h
+
+
+ qxk_port.c
+ 1
+ ..\..\..\ports\arm-cm\qxk\armclang\qxk_port.c
+
+
+ qxk_port.h
+ 5
+ ..\..\..\ports\arm-cm\qxk\armclang\qxk_port.h
+
+
+ qutest_port.c
+ 1
+ ..\..\..\3rd_party\efm32pg1b\qutest\qutest_port.c
+
+
+
+
+ QS
+
+
+ qs.c
+ 1
+ ..\..\..\src\qs\qs.c
+
+
+ qs_64bit.c
+ 1
+ ..\..\..\src\qs\qs_64bit.c
+
+
+ qs_fp.c
+ 1
+ ..\..\..\src\qs\qs_fp.c
+
+
+ qs_rx.c
+ 1
+ ..\..\..\src\qs\qs_rx.c
+
+
+ qutest.c
+ 1
+ ..\..\..\src\qs\qutest.c
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test
+ 1
+
+
+
+
+
diff --git a/test/qxk/test_xthr/test_xthr.cpp b/test/qxk/test_xthr/test_xthr.cpp
deleted file mode 100644
index c4eddc0f..00000000
--- a/test/qxk/test_xthr/test_xthr.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-//============================================================================
-// Product: System test fixture for QXK on the EFM32 target
-// Last updated for version 7.1.1
-// Last updated on 2022-09-23
-//
-// Q u a n t u m L e a P s
-// ------------------------
-// Modern Embedded Software
-//
-// Copyright (C) 2005 Quantum Leaps. All rights reserved.
-//
-// 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.
-//
-// 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
-// along with this program. If not, see .
-//
-// Contact information:
-//
-//
-//============================================================================
-#include "qpcpp.hpp"
-#include "bsp.hpp"
-
-Q_DEFINE_THIS_FILE
-
-//============================================================================
-namespace {
-static void Thread1_run(QP::QXThread * const me) {
-
- for (;;) {
- BSP::ledOn();
- QP::QXThread::delay(1U); // BLOCK!
- BSP::ledOff();
- QP::QXThread::delay(1U); // BLOCK!
- }
-}
-static QP::QXThread thr1(&Thread1_run, 0U);
-}
-
-//============================================================================
-namespace QP {
-
-void QS::onTestSetup(void) {
-}
-//............................................................................
-void QS::onTestTeardown(void) {
-}
-//............................................................................
-//! callback function to execute user commands
-void QS::onCommand(uint8_t cmdId,
- uint32_t param1, uint32_t param2, uint32_t param3)
-{
- switch (cmdId) {
- case 0U: {
- break;
- }
- case 1U: {
- break;
- }
- default:
- break;
- }
-}
-
-//============================================================================
-//! Host callback function to "massage" the event, if necessary
-void QS::onTestEvt(QEvt *e) {
- (void)e;
-}
-//............................................................................
-//! callback function to output the posted QP events (not used here)
-void QS::onTestPost(void const *sender, QActive *recipient,
- QEvt const *e, bool status)
-{
-}
-
-} // namespace QP
-
-//============================================================================
-int main() {
-
- QP::QF::init(); // initialize the framework and the underlying QXK kernel
- BSP::init(); // initialize the Board Support Package
-
- // dictionaries
- QS_OBJ_DICTIONARY(&thr1);
- QS_OBJ_DICTIONARY(thr1.getTimeEvt());
- QS_SIG_DICTIONARY(TEST_SIG, nullptr);
- QS_SIG_DICTIONARY(TRIG_SIG, nullptr);
- QS_SIG_DICTIONARY(TIMEOUT_SIG, nullptr);
-
- // setup the QS filters...
- QS_GLB_FILTER(QP::QS_ALL_RECORDS); // all records
-
- // initialize publish-subscribe...
- static QP::QSubscrList subscrSto[MAX_PUB_SIG];
- QP::QActive::psInit(subscrSto, Q_DIM(subscrSto));
-
- // initialize event pools...
- static QF_MPOOL_EL(QP::QEvt) smlPoolSto[10]; // small pool
- QP::QF::poolInit(smlPoolSto, sizeof(smlPoolSto), sizeof(smlPoolSto[0]));
-
- // start the extended thread1
- static QP::QEvt const *test1QueueSto[5];
- static uint64_t test1StackSto[64];
- thr1.start(1U, // QF-priority/preemption-threshold
- test1QueueSto, // message queue storage
- Q_DIM(test1QueueSto), // message length [events]
- test1StackSto, // stack storage
- sizeof(test1StackSto)); // stack size [bytes]
-
- return QP::QF::run(); // run the QF application
-}
diff --git a/test/qxk/test_xthr/tick_tick.py b/test/qxk/test_xthr/tick_tick.py
deleted file mode 100644
index a9b6fc7a..00000000
--- a/test/qxk/test_xthr/tick_tick.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# test-script for QUTest unit testing harness
-# see https://www.state-machine.com/qtools/qutest.html/qutest.html
-
-# preamble...
-def on_reset():
- expect("@timestamp Sch-Next Pri=0->1")
- expect_run()
- expect("@timestamp Sch-Idle Pri=1->0")
-
-test("extended thread tick-tick")
-current_obj(OBJ_AP,"thr1")
-query_curr(OBJ_AP)
-expect("@timestamp Query-AP Obj=thr1")
-tick()
-expect(" Tick<0> Ctr=0000000001")
-expect(" TE0-ADis Obj=thr1.getTimeEvt(),AO=thr1")
-expect("@timestamp TE0-Post Obj=thr1.getTimeEvt(),Sig=TEST_SIG,AO=thr1")
-expect("@timestamp Sch-Pre Pri=0->1")
-expect("@timestamp Sch-Idle Pri=1->0")
-expect("@timestamp Trg-Done QS_RX_TICK")
-tick()
-expect(" Tick<0> Ctr=0000000002")
-expect(" TE0-ADis Obj=thr1.getTimeEvt(),AO=thr1")
-expect("@timestamp TE0-Post Obj=thr1.getTimeEvt(),Sig=TEST_SIG,AO=thr1")
-expect("@timestamp Sch-Pre Pri=0->1")
-expect("@timestamp Sch-Idle Pri=1->0")
-expect("@timestamp Trg-Done QS_RX_TICK")