This commit is contained in:
MMS 2022-10-06 20:29:33 -04:00
parent 6e08c71866
commit 119ddd7c79
61 changed files with 4408 additions and 1439 deletions

View File

@ -5,7 +5,7 @@
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8 DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = QP/C++ PROJECT_NAME = QP/C++
PROJECT_NUMBER = 7.1.1 PROJECT_NUMBER = 7.1.2
PROJECT_BRIEF = "Real-Time Embedded Framework" PROJECT_BRIEF = "Real-Time Embedded Framework"
PROJECT_LOGO = ../../ql-doxygen/images/logo_ql.png PROJECT_LOGO = ../../ql-doxygen/images/logo_ql.png
OUTPUT_DIRECTORY = OUTPUT_DIRECTORY =

View File

@ -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}. 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 @note

View File

@ -1,33 +1,23 @@
/** @page history Revision History /** @page history Revision History
@section qpcpp_7_1_1 Version 7.1.1, 2022-09-30 @section qpcpp_7_1_2 Version 7.1.2, 2022-10-07
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. 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.
@note
The QP framework "knows" the type of preemption (synchronous/asynchronous) and this information is now provided in the software trace to the user.
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. 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__ __Source__
- Added new pre-defined QS trace records: - Modified QK_sched_() and QK_activate_()
+ QP::QS_SCHED_PREEMPT - for reporting *asynchronous* preemption - Modified QXK_sched_() and QXK_activate_()
+ QP::QS_SCHED_RESTORE - for reporting restoring the context - Added QXK_contextSw() to handle context switching (generation of software tracing information and invoking of the QXK_onContextSw() callback, if configured
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);
- increased default for #QF_TIMEEVT_CTR_SIZE 4 - 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. - 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__ __Ports__
- All QK ports have been updated to set the `asynch` parameter for calling QK_activate_() - Modified QXK ports (assembly) to call QXK_contextSw()
- All QXK ports have been updated to set the `asynch` parameter for calling QXK_sched_()/XK_activate_() - Added port to RISC-V with the cooperative @ref srs_qvk "QV" kernel
__Testing__ __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 QK: `qpcpp/test/qk`
- Added new tests for QXK: `qpcpp/test/qutest/qxk` - 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`. 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 @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 @section qpcpp_7_1_0 Version 7.1.0, 2022-08-30

View File

@ -66,8 +66,8 @@
14 3 70 1 14 QP::QS::rxPut@805-818@..\include\qs.hpp 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 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 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 3 1 11 0 3 QP::QXThread::getTimeEvt@208-210@..\include\qxk.hpp
9 1 49 5 9 QP::QXThread::start@312-320@..\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 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 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 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 25 0.0 0.0 0.0 0 ..\include\qs_pkg.hpp
9 0.0 0.0 0.0 0 ..\include\quit.hpp 9 0.0 0.0 0.0 0 ..\include\quit.hpp
8 0.0 0.0 0.0 0 ..\include\qv.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 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 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 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 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 @endcode
*/ */

View File

@ -1,6 +1,6 @@
#include "qpc.h" #include "qpcpp.hpp"
#include "dpp.h" #include "dpp.hpp"
#include "bsp.h" #include "bsp.hpp"
namespace DPP { namespace DPP {
@ -12,14 +12,13 @@ int_t main(void) {
// object dictionaries... // object dictionaries...
QS_OBJ_DICTIONARY(AO_Table); QS_OBJ_DICTIONARY(AO_Table);
QS_OBJ_DICTIONARY(AO_Philo[0]); for (std::uint8_t n = 0U; n < N_PHILO; ++n) {
QS_OBJ_DICTIONARY(AO_Philo[1]); QS_OBJ_ARR_DICTIONARY(AO_Philo[n], n);
QS_OBJ_DICTIONARY(AO_Philo[2]); }
QS_OBJ_DICTIONARY(AO_Philo[3]);
QS_OBJ_DICTIONARY(AO_Philo[4]);
// initialize publish-subscribe...
static QP::QSubscrList subscrSto[MAX_PUB_SIG]; 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... // initialize event pools...
static QF_MPOOL_EL(TableEvt) smlPoolSto[2*N_PHILO]; static QF_MPOOL_EL(TableEvt) smlPoolSto[2*N_PHILO];
@ -29,15 +28,21 @@ int_t main(void) {
// start the active objects... // start the active objects...
static QP::QEvt const *philoQueueSto[N_PHILO][N_PHILO]; static QP::QEvt const *philoQueueSto[N_PHILO][N_PHILO];
for (std::uint8_t n = 0U; n < N_PHILO; ++n) { for (std::uint8_t n = 0U; n < N_PHILO; ++n) {
AO_Philo[n]->start(n + 1U, AO_Philo[n]->start(
philoQueueSto[n], Q_DIM(philoQueueSto[n]), Q_PRIO(n + 1U, N_PHILO), // QF-priority/preemption-threshold
nullptr, 0U); 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]; static QP::QEvt const *tableQueueSto[N_PHILO];
AO_Table->start(N_PHILO + 1U, AO_Table->start(
tableQueueSto, Q_DIM(tableQueueSto), N_PHILO + 1U,
nullptr, 0U); tableQueueSto,
Q_DIM(tableQueueSto),
nullptr,
0U);
return QP::QF::run(); // run the QF application return QP::QF::run(); // run the QF application
} }

View File

@ -1,11 +1,11 @@
//============================================================================ //============================================================================
// DPP example // DPP example
// Last updated for version 7.1.1 // Last updated for version 7.1.2
// Last updated on 2022-09-23 // Last updated on 2022-10-05
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ------------------------
// innovating embedded systems // Modern Embedded Software
// //
// Copyright (C) Quantum Leaps, LLC. All rights reserved. // Copyright (C) Quantum Leaps, LLC. All rights reserved.
// //
@ -65,11 +65,11 @@ int main() {
} }
// example of prioritizing the Ticker0 active object // 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); 0, 0, 0, 0);
DPP::AO_Table->start( DPP::AO_Table->start(
(N_PHILO + 2U, // QF-prio/preempt-thre. N_PHILO + 2U, // QF-prio/preempt-thre.
tableQueueSto, // event queue storage tableQueueSto, // event queue storage
Q_DIM(tableQueueSto), // queue length [events] Q_DIM(tableQueueSto), // queue length [events]
nullptr, 0U); // no stack storage nullptr, 0U); // no stack storage

View File

@ -152,9 +152,9 @@
<Bp> <Bp>
<Number>0</Number> <Number>0</Number>
<Type>0</Type> <Type>0</Type>
<LineNumber>355</LineNumber> <LineNumber>362</LineNumber>
<EnabledFlag>1</EnabledFlag> <EnabledFlag>1</EnabledFlag>
<Address>2142</Address> <Address>2144</Address>
<ByteObject>0</ByteObject> <ByteObject>0</ByteObject>
<HtxType>0</HtxType> <HtxType>0</HtxType>
<ManyObjects>0</ManyObjects> <ManyObjects>0</ManyObjects>
@ -163,39 +163,23 @@
<BreakIfRCount>1</BreakIfRCount> <BreakIfRCount>1</BreakIfRCount>
<Filename>..\bsp.cpp</Filename> <Filename>..\bsp.cpp</Filename>
<ExecCommand></ExecCommand> <ExecCommand></ExecCommand>
<Expression>\\dpp_qxk\../bsp.cpp\355</Expression> <Expression>\\dpp_qxk\../bsp.cpp\362</Expression>
</Bp> </Bp>
<Bp> <Bp>
<Number>1</Number> <Number>1</Number>
<Type>0</Type> <Type>0</Type>
<LineNumber>292</LineNumber> <LineNumber>355</LineNumber>
<EnabledFlag>1</EnabledFlag> <EnabledFlag>1</EnabledFlag>
<Address>7064</Address> <Address>0</Address>
<ByteObject>0</ByteObject> <ByteObject>0</ByteObject>
<HtxType>0</HtxType> <HtxType>0</HtxType>
<ManyObjects>0</ManyObjects> <ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject> <SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess> <BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount> <BreakIfRCount>0</BreakIfRCount>
<Filename>..\..\..\..\..\src\qf\qf_time.cpp</Filename> <Filename>..\bsp.cpp</Filename>
<ExecCommand></ExecCommand> <ExecCommand></ExecCommand>
<Expression>\\dpp_qxk\../../../../../src/qf/qf_time.cpp\292</Expression> <Expression></Expression>
</Bp>
<Bp>
<Number>2</Number>
<Type>0</Type>
<LineNumber>112</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>6920</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>..\..\..\..\..\src\qf\qf_time.cpp</Filename>
<ExecCommand></ExecCommand>
<Expression>\\dpp_qxk\../../../../../src/qf/qf_time.cpp\112</Expression>
</Bp> </Bp>
</Breakpoint> </Breakpoint>
<WatchWindow1> <WatchWindow1>
@ -753,7 +737,7 @@
<Group> <Group>
<GroupName>QP</GroupName> <GroupName>QP</GroupName>
<tvExp>0</tvExp> <tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel> <cbSel>0</cbSel>
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>

View File

@ -1,7 +1,7 @@
//============================================================================ //============================================================================
// DPP example for QXK // DPP example for QXK
// Last updated for version 7.1.1 // Last updated for version 7.1.2
// Last updated on 2022-09-23 // Last updated on 2022-10-05
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ---------------------------
@ -78,7 +78,7 @@ int main() {
// start the Philo active objects... // start the Philo active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) { for (uint8_t n = 0U; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start( 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 philoQueueSto[n], // event queue storage
Q_DIM(philoQueueSto[n]), // queue length [events] Q_DIM(philoQueueSto[n]), // queue length [events]
nullptr, 0U); // no stack storage nullptr, 0U); // no stack storage

View File

@ -1,11 +1,11 @@
//============================================================================ //============================================================================
// DPP example // DPP example
// Last updated for version 6.3.3 // Last updated for version 7.1.2
// Last updated on 2018-06-23 // Last updated on 2022-10-05
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ------------------------
// innovating embedded systems // Modern Embedded Software
// //
// Copyright (C) Quantum Leaps, LLC. All rights reserved. // Copyright (C) Quantum Leaps, LLC. All rights reserved.
// //
@ -57,17 +57,18 @@ int main() {
// start the active objects... // start the active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) { for (uint8_t n = 0U; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start((uint_fast8_t)(n + 1U), // priority DPP::AO_Philo[n]->start(
Q_PRIO(n + 1U, N_PHILO), // QF-prio/preempt-thre.
philoQueueSto[n], Q_DIM(philoQueueSto[n]), philoQueueSto[n], Q_DIM(philoQueueSto[n]),
nullptr, 0U); nullptr, 0U);
} }
// example of prioritizing the Ticker0 active object // 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,
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), tableQueueSto, Q_DIM(tableQueueSto),
nullptr, 0U); nullptr, 0U);

View File

@ -1,13 +1,13 @@
//============================================================================ //============================================================================
// DPP example // DPP example
// Last updated for: @qpcpp_7_0_0 // Last updated for version 7.1.2
// Last updated on 2022-02-28 // Last updated on 2022-10-05
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ------------------------
// innovating embedded systems // 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 // 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 // modify it under the terms of the GNU General Public License as published
@ -25,7 +25,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <www.gnu.org/licenses>. // along with this program. If not, see <www.gnu.org/licenses/>.
// //
// Contact information: // Contact information:
// <www.state-machine.com/licensing> // <www.state-machine.com/licensing>
@ -54,12 +54,15 @@ int main() {
// start the active objects... // start the active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) { for (uint8_t n = 0U; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start((uint_fast8_t)(n + 1U), // priority DPP::AO_Philo[n]->start(
philoQueueSto[n], Q_DIM(philoQueueSto[n]), Q_PRIO(n + 1U, N_PHILO), // QF-prio/preempt-thre.
nullptr, 0U); 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), tableQueueSto, Q_DIM(tableQueueSto),
nullptr, 0U); nullptr, 0U);

View File

@ -1,11 +1,11 @@
//============================================================================ //============================================================================
// DPP example // DPP example
// Last updated for version 6.3.3 // Last updated for version 7.1.2
// Last updated on 2018-06-23 // Last updated on 2022-10-05
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ------------------------
// innovating embedded systems // Modern Embedded Software
// //
// Copyright (C) Quantum Leaps, LLC. All rights reserved. // Copyright (C) Quantum Leaps, LLC. All rights reserved.
// //
@ -55,14 +55,20 @@ int main() {
// start the active objects... // start the active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) { for (uint8_t n = 0U; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start((uint8_t)(n + 1U), DPP::AO_Philo[n]->start(
philoQueueSto[n], Q_DIM(philoQueueSto[n]), Q_PRIO(n + 1U, N_PHILO), // QF-prio/preempt-thre.
nullptr, 0U); 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 // 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), DPP::AO_Table->start(
nullptr, 0U); 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 return QP::QF::run(); // run the QF application
} }

View File

@ -1,13 +1,13 @@
//============================================================================ //============================================================================
// DPP example // DPP example
// Last updated for version 6.3.3 // Last updated for version 7.1.2
// Last updated on 2018-06-23 // Last updated on 2022-10-05
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ------------------------
// innovating embedded systems // 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 // 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 // modify it under the terms of the GNU General Public License as published
@ -56,13 +56,17 @@ int main() {
// start the active objects... // start the active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) { for (uint8_t n = 0U; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start((uint8_t)(n + 1U), DPP::AO_Philo[n]->start(
philoQueueSto[n], Q_DIM(philoQueueSto[n]), Q_PRIO(n + 1U, N_PHILO), // QF-prio/preempt-thre.
nullptr, 0U); 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), DPP::AO_Table->start(
tableQueueSto, Q_DIM(tableQueueSto), N_PHILO + 1U, // QF-prio/preempt-thre.
nullptr, 0U); tableQueueSto, // event queue storage
Q_DIM(tableQueueSto), // queue length [events]
nullptr, 0U); // no stack storage
return QP::QF::run(); // run the QF application return QP::QF::run(); // run the QF application
} }

View File

@ -1,13 +1,13 @@
//============================================================================ //============================================================================
// DPP example // DPP example
// Last updated for: @qpcpp_7_0_0 // Last updated for version 7.1.2
// Last updated on 2022-02-28 // Last updated on 2022-10-05
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ------------------------
// innovating embedded systems // 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 // 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 // modify it under the terms of the GNU General Public License as published
@ -25,7 +25,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <www.gnu.org/licenses>. // along with this program. If not, see <www.gnu.org/licenses/>.
// //
// Contact information: // Contact information:
// <www.state-machine.com/licensing> // <www.state-machine.com/licensing>
@ -54,14 +54,18 @@ int main() {
// start the active objects... // start the active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) { for (uint8_t n = 0U; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start((uint_fast8_t)(n + 1U), // priority DPP::AO_Philo[n]->start(
philoQueueSto[n], Q_DIM(philoQueueSto[n]), Q_PRIO(n + 1U, N_PHILO), // QF-prio/preempt-thre.
nullptr, 0U); 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(
tableQueueSto, Q_DIM(tableQueueSto), N_PHILO + 1U, // QF-prio/preempt-thre.
nullptr, 0U); tableQueueSto, // event queue storage
Q_DIM(tableQueueSto), // queue length [events]
nullptr, 0U); // no stack storage
return QP::QF::run(); // run the QF application return QP::QF::run(); // run the QF application
} }

View File

@ -1,11 +1,11 @@
//============================================================================ //============================================================================
// DPP example // DPP example
// Last updated for version 6.0.4 // Last updated for version 7.1.2
// Last updated on 2018-01-07 // Last updated on 2022-10-05
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ------------------------
// innovating embedded systems // Modern Embedded Software
// //
// Copyright (C) Quantum Leaps, LLC. All rights reserved. // Copyright (C) Quantum Leaps, LLC. All rights reserved.
// //
@ -64,19 +64,24 @@ int main() {
// start the active objects... // start the active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) { for (uint8_t n = 0U; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start((uint_fast8_t)(n + 1U), // priority DPP::AO_Philo[n]->start(
philoQueueSto[n], Q_DIM(philoQueueSto[n]), Q_PRIO(n + 1U, N_PHILO), // QF-prio/preempt-thre.
nullptr, 0U); philoQueueSto[n], // event queue storage
Q_DIM(philoQueueSto[n]), // queue length [events]
nullptr, 0U); // no stack storage
} }
// example of prioritizing the Ticker0 active object // 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, (QP::QEvt const **)0, 0U,
nullptr, 0U); nullptr, 0U);
DPP::AO_Table->start((uint_fast8_t)(N_PHILO + 2U), // priority DPP::AO_Table->start(
tableQueueSto, Q_DIM(tableQueueSto), N_PHILO + 2U, // QF-prio/preempt-thre.
nullptr, 0U); tableQueueSto, // event queue storage
Q_DIM(tableQueueSto), // queue length [events]
nullptr, 0U); // no stack storage
return QP::QF::run(); // run the QF application return QP::QF::run(); // run the QF application
} }

View File

@ -1,11 +1,11 @@
//============================================================================ //============================================================================
// DPP example // DPP example
// Last updated for version 5.6.2 // Last updated for version 7.1.2
// Last updated on 2016-03-31 // Last updated on 2022-10-05
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// --------------------------- // ------------------------
// innovating embedded systems // Modern Embedded Software
// //
// Copyright (C) Quantum Leaps, LLC. All rights reserved. // Copyright (C) Quantum Leaps, LLC. All rights reserved.
// //
@ -28,7 +28,7 @@
// along with this program. If not, see <www.gnu.org/licenses/>. // along with this program. If not, see <www.gnu.org/licenses/>.
// //
// Contact information: // Contact information:
// https://state-machine.com // <www.state-machine.com/licensing>
// <info@state-machine.com> // <info@state-machine.com>
//============================================================================ //============================================================================
#include "qpcpp.hpp" #include "qpcpp.hpp"
@ -48,7 +48,8 @@ int main() {
DPP::BSP::init(); // initialize the BSP 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... // initialize event pools...
QP::QF::poolInit(smlPoolSto, QP::QF::poolInit(smlPoolSto,
@ -56,13 +57,17 @@ int main() {
// start the active objects... // start the active objects...
for (uint8_t n = 0U; n < N_PHILO; ++n) { for (uint8_t n = 0U; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start((uint_fast8_t)(n + 1U), DPP::AO_Philo[n]->start(
philoQueueSto[n], Q_DIM(philoQueueSto[n]), Q_PRIO(n + 1U, N_PHILO), // QF-prio/preempt-thre.
nullptr, 0U); 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), DPP::AO_Table->start(
tableQueueSto, Q_DIM(tableQueueSto), N_PHILO + 1U, // QF-prio/preempt-thre.
nullptr, 0U); tableQueueSto, // event queue storage
Q_DIM(tableQueueSto), // queue length [events]
nullptr, 0U); // no stack storage
return QP::QF::run(); // run the QF application return QP::QF::run(); // run the QF application
} }

View File

@ -52,7 +52,7 @@
// major version number, Y is a 1-digit minor version number, and Z is // major version number, Y is a 1-digit minor version number, and Z is
// a 1-digit release number. // a 1-digit release number.
// //
#define QP_VERSION 710U #define QP_VERSION 712U
//! The current QP version as a zero terminated string literal. //! 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 // major version number, Y is a 1-digit minor version number, and Z is
// a 1-digit release number. // 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) //! Encrypted current QP release (7.1.2) and date (2022-10-07)
#define QP_RELEASE 0x7C600159U #define QP_RELEASE 0x7C44FF47U
//============================================================================ //============================================================================
// Global namespace... // Global namespace...

View File

@ -201,7 +201,7 @@ using QTimeEvtCtr = std::uint32_t;
//! When QP runs on top of 3rd-party kernels/RTOSes or general-purpose //! When QP runs on top of 3rd-party kernels/RTOSes or general-purpose
//! operating systems, sthe second priority can have different meaning, //! operating systems, sthe second priority can have different meaning,
//! depending on the specific RTOS/GPOS used. //! depending on the specific RTOS/GPOS used.
using QPrioSpec = std::uint_fast16_t; using QPrioSpec = std::uint16_t;
//${QF-types::QSchedStatus} .................................................. //${QF-types::QSchedStatus} ..................................................
//! The scheduler lock status used in some real-time kernels //! The scheduler lock status used in some real-time kernels

View File

@ -150,8 +150,9 @@ extern QK_Attr QK_attr_;
//! that (1) has events to process and (2) has priority that is above the //! that (1) has events to process and (2) has priority that is above the
//! current priority. //! current priority.
//! //!
//! @returns the 1-based priority of the the active object, or zero if //! @returns
//! no eligible active object is ready to run. //! The QF-priority of the next active object to activate, or zero
//! if no activation of AO is needed.
//! //!
//! @attention //! @attention
//! QK_sched_() must be always called with interrupts **disabled** and //! 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 //! QK activator activates the next active object. The activated AO preempts
//! the currently executing AOs //! the currently executing AOs
//! //!
//! @param[in] asynch flag conveying the type of activation:
//! != 0 for asynchronous activation and
//! == 0 for synchronous activation
//! @details //! @details
//! QK_activate_() activates ready-to run AOs that are above the initial //! QK_activate_() activates ready-to run AOs that are above the initial
//! active priority (QK_attr_.actPrio). //! preemption-threshold.
//! //!
//! @note //! @note
//! The activator might enable interrupts internally, but always returns with //! The activator might enable interrupts internally, but always returns with
//! interrupts **disabled**. //! interrupts **disabled**.
void QK_activate_(std::uint_fast8_t const asynch) noexcept; void QK_activate_() noexcept;
//${QK-extern-C::QK_onContextSw} ............................................. //${QK-extern-C::QK_onContextSw} .............................................
#ifdef QK_ON_CONTEXT_SW #ifdef QK_ON_CONTEXT_SW
@ -251,7 +249,7 @@ void QK_onContextSw(
static_cast<std::uint_fast8_t>((me_)->m_prio)); \ static_cast<std::uint_fast8_t>((me_)->m_prio)); \
if (!QK_ISR_CONTEXT_()) { \ if (!QK_ISR_CONTEXT_()) { \
if (QK_sched_() != 0U) { \ if (QK_sched_() != 0U) { \
QK_activate_(0U); \ QK_activate_(); \
} \ } \
} \ } \
} while (false) } while (false)

View File

@ -205,7 +205,7 @@ enum QSpyPre : std::int8_t {
QS_SCHED_UNLOCK, //!< scheduler was unlocked QS_SCHED_UNLOCK, //!< scheduler was unlocked
QS_SCHED_NEXT, //!< scheduler found next task to execute QS_SCHED_NEXT, //!< scheduler found next task to execute
QS_SCHED_IDLE, //!< scheduler became idle 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 // [55] Additional QEP records
QS_QEP_TRAN_HIST, //!< a tran to history was taken QS_QEP_TRAN_HIST, //!< a tran to history was taken

View File

@ -145,10 +145,8 @@ void schedUnlock(QSchedStatus const stat) noexcept;
//${QXK::QXK-base::Timeouts} ................................................. //${QXK::QXK-base::Timeouts} .................................................
//! timeout signals for extended threads //! timeout signals for extended threads
enum Timeouts : enum_t { enum Timeouts : enum_t {
DELAY_SIG = Q_USER_SIG, DELAY_SIG = 1,
QUEUE_SIG, TIMEOUT_SIG
SEMA_SIG,
MUTEX_SIG
}; };
} // namespace QXK } // namespace QXK
@ -600,15 +598,9 @@ public:
//! the priority and priority-threshold of the holding thread to the //! the priority and priority-threshold of the holding thread to the
//! priority specification in `prioSpec` (see QP::QPrioSpec). //! 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 //! @usage
//! @include qxk_mutex.cpp //! @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 //! try to lock the QXK priority-ceiling mutex QP::QXMutex
//! //!
@ -684,8 +676,8 @@ extern "C" {
struct QXK_Attr { struct QXK_Attr {
QP::QActive * volatile curr; //!< currently executing thread QP::QActive * volatile curr; //!< currently executing thread
QP::QActive * volatile next; //!< next thread to execute QP::QActive * volatile next; //!< next thread to execute
std::uint8_t volatile actPrio; //!< prio of the active AO QP::QActive * volatile prev; //!< previous thread
std::uint8_t volatile actThre; //!< active preemption-threshold 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 lockCeil; //!< lock preemption-ceiling (0==no-lock)
std::uint8_t volatile lockHolder; //!< prio of the lock holder 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-extern-C::QXK_sched_} ................................................
//! QXK scheduler finds the highest-priority thread ready to run //! 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 //! @details
//! The QXK scheduler finds the priority of the highest-priority thread //! The QXK scheduler finds the priority of the highest-priority thread
//! that is ready to run. //! that is ready to run.
@ -710,15 +699,12 @@ extern QXK_Attr QXK_attr_;
//! @attention //! @attention
//! QXK_sched_() must be always called with interrupts **disabled** and //! QXK_sched_() must be always called with interrupts **disabled** and
//! returns with interrupts **disabled**. //! 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-extern-C::QXK_activate_} .............................................
//! QXK activator activates the next active object. The activated AO preempts //! QXK activator activates the next active object. The activated AO preempts
//! the currently executing AOs //! the currently executing AOs
//! //!
//! @param[in] asynch flag conveying the type of activation:
//! != 0 for asynchronous activation and
//! == 0 for synchronous activation
//! @attention //! @attention
//! QXK_activate_() must be always called with interrupts **disabled** and //! QXK_activate_() must be always called with interrupts **disabled** and
//! returns with interrupts **disabled**. //! returns with interrupts **disabled**.
@ -726,10 +712,13 @@ std::uint_fast8_t QXK_sched_(std::uint_fast8_t const asynch) noexcept;
//! @note //! @note
//! The activate function might enable interrupts internally, but it always //! The activate function might enable interrupts internally, but it always
//! returns with interrupts **disabled**. //! returns with interrupts **disabled**.
void QXK_activate_(std::uint_fast8_t const asynch) noexcept; void QXK_activate_() noexcept;
//${QXK-extern-C::QXK_current} ............................................... //${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; QP::QActive * QXK_current() noexcept;
//${QXK-extern-C::QXK_stackInit_} ............................................ //${QXK-extern-C::QXK_stackInit_} ............................................
@ -740,6 +729,22 @@ void QXK_stackInit_(
void * const stkSto, void * const stkSto,
std::uint_fast16_t const stkSize) noexcept; 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} ........................................... //${QXK-extern-C::QXK_onContextSw} ...........................................
#ifdef QXK_ON_CONTEXT_SW #ifdef QXK_ON_CONTEXT_SW
//! QXK context switch callback (customized in BSPs for QXK) //! QXK context switch callback (customized in BSPs for QXK)
@ -856,8 +861,8 @@ void QXK_threadExit_();
QF::readySet_.insert( \ QF::readySet_.insert( \
static_cast<std::uint_fast8_t>((me_)->m_prio)); \ static_cast<std::uint_fast8_t>((me_)->m_prio)); \
if (!QXK_ISR_CONTEXT_()) { \ if (!QXK_ISR_CONTEXT_()) { \
if (QXK_sched_(0U) != 0U) { \ if (QXK_sched_() != 0U) { \
QXK_activate_(0U); \ QXK_activate_(); \
} \ } \
} \ } \
} while (false) } while (false)

View File

@ -23,8 +23,8 @@
* <info@state-machine.com> * <info@state-machine.com>
============================================================================*/ ============================================================================*/
/*! /*!
* @date Last updated on: 2022-09-04 * @date Last updated on: 2022-10-04
* @version Last updated for: @ref qpcpp_7_1_1 * @version Last updated for: @ref qpcpp_7_1_2
* *
* @file * @file
* @brief QXK/C++ port to ARM Cortex-M, ARM-CLANG toolset * @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" !!! */ /* NOTE: keep in synch with struct QXK_Attr in "qxk.hpp" !!! */
#define QXK_CURR 0 #define QXK_CURR 0
#define QXK_NEXT 4 #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" */ /* 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_CURR == offsetof(QXK_Attr, curr));
Q_ASSERT_STATIC(QXK_NEXT == offsetof(QXK_Attr, next)); 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" !!! */ /* offsets within struct QActive; NOTE: keep in synch with "qf.hpp" !!! */
#define QACTIVE_OSOBJ 28 #define QACTIVE_OSOBJ 28
#define QACTIVE_PRIO 36 #define QACTIVE_PRIO 36
#define QACTIVE_PTHRE 37
/* make sure that the offsets match the QXK declaration in "qf.hpp" */ /* 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_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 */ /* helper macros to "stringify" values */
#define VAL(x) #x #define VAL(x) #x
@ -273,11 +273,6 @@ __asm volatile (
" ADD r0,sp,#(5*4) \n" /* r0 := 5 registers below the top of stack */ " ADD r0,sp,#(5*4) \n" /* r0 := 5 registers below the top of stack */
" STM r0!,{r1-r3} \n" /* save xpsr,pc,lr */ " 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" " MOVS r0,#6 \n"
" MVNS r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */ " MVNS r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */
#if (__ARM_ARCH != 6) /* ARMv7-M or higher */ #if (__ARM_ARCH != 6) /* ARMv7-M or higher */
@ -328,9 +323,9 @@ __asm volatile (
* r12 -> QXK_attr_.next / basic-thread * r12 -> QXK_attr_.next / basic-thread
*/ */
"PendSV_restore_ao: \n" "PendSV_restore_ao: \n"
" MOVS r0,#0 \n" /* don NOT clear QXK_attr_.curr or QXK_attr_.next,
" STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := 0 */ * as they might be needed for AO activation
/* don't clear QXK_attr_.next, as it might be needed for AO activation */ */
#if (__ARM_ARCH == 6) /* if ARMv6-M... */ #if (__ARM_ARCH == 6) /* if ARMv6-M... */
" MOV r0,sp \n" /* r0 := top of stack */ " MOV r0,sp \n" /* r0 := top of stack */
@ -361,26 +356,25 @@ __asm volatile (
#endif /* ARMv7-M or higher */ #endif /* ARMv7-M or higher */
" MOV r0,r12 \n" /* r0 := QXK_attr_.next */ " MOV r0,r12 \n" /* r0 := QXK_attr_.next */
" MOVS r2,#" STRINGIFY(QACTIVE_PTHRE) "\n" /* r2 := offset of .pthre */ " MOVS r2,#" STRINGIFY(QACTIVE_PRIO) "\n" /* r2 := offset of .prio */
" LDRB r0,[r0,r2] \n" /* r0 := QXK_attr_.next->pthre */ " LDRB r0,[r0,r2] \n" /* r0 := QXK_attr_.next->prio */
" LDRB r2,[r3,#" STRINGIFY(QXK_ACT_THRE) "]\n" /* r2 := QXK_attr_.actThre */ " LDRB r2,[r3,#" STRINGIFY(QXK_ACT_PRIO) "]\n" /* r2 := QXK_attr_.actPrio */
" CMP r2,r0 \n" " 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... */ /* otherwise no activation needed... */
" MOVS r0,#0 \n" " MOVS r0,#0 \n"
" STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* QXK_attr_.next := 0 (clear the next) */ " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := 0 */
" MOV r12,r0 \n" /* also clear r12==QXK_attr_.next */ " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* QXK_attr_.next := 0 */
#ifdef QXK_ON_CONTEXT_SW #if defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
" MOVS r0,r1 \n" /* r0 := QXK_attr_.curr / basic */ " MOVS r0,#0 \n" /* r0 := 0 (next is basic) */
" MOV r1,r12 \n" /* r1 := QXK_attr_.next / basic */ " PUSH {r3,lr} \n" /* save QXK_attr_ + exception lr */
" LDR r2,=QXK_onContextSw \n" " LDR r3,=QXK_contextSw \n"
" PUSH {r1,lr} \n" /* save the aligner + exception lr */ " BLX r3 \n" /* call QXK_contextSw() */
" BLX r2 \n" /* call QXK_onContextSw() */ " POP {r0,r1} \n" /* restore the aligner + lr into r1 */
" POP {r1,r2} \n" /* restore the aligner + lr into r2 */ " MOV lr,r1 \n" /* restore the exception lr */
" MOV lr,r2 \n" /* restore the exception lr */ #endif /* defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW) */
#endif /* QXK_ON_CONTEXT_SW */
/* re-enable interrupts and return from PendSV */ /* re-enable interrupts and return from PendSV */
"PendSV_return: \n" "PendSV_return: \n"
@ -395,7 +389,7 @@ __asm volatile (
" BX lr \n" /* return to the preempted AO-thread */ " BX lr \n" /* return to the preempted AO-thread */
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* Saving extended-thread before crossing to AO-thread * Saving extended-thread
* expected register contents: * expected register contents:
* r0 -> QXK_attr_.next / basic-thread * r0 -> QXK_attr_.next / basic-thread
* r1 -> QXK_attr_.curr / basic-thread * r1 -> QXK_attr_.curr / basic-thread
@ -437,7 +431,7 @@ __asm volatile (
/* otherwise continue to restoring next extended-thread... */ /* otherwise continue to restoring next extended-thread... */
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* Restoring extended-thread after crossing from AO-thread * Restoring extended-thread
* expected register contents: * expected register contents:
* r0 -> QXK_attr_.next / basic-thread * r0 -> QXK_attr_.next / basic-thread
* r1 -> QXK_attr_.curr / basic-thread * r1 -> QXK_attr_.curr / basic-thread
@ -446,20 +440,19 @@ __asm volatile (
* r12 -> QXK_attr_.next / basic-thread * r12 -> QXK_attr_.next / basic-thread
*/ */
"PendSV_restore_ex: \n" "PendSV_restore_ex: \n"
#ifdef QXK_ON_CONTEXT_SW #if defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
" MOVS r0,r1 \n" /* r0 := QXK_attr_.curr / basic */ " MOV r0,r12 \n" /* r0 := next */
" MOV r1,r12 \n" /* r1 := QXK_attr_.next / basic */ " PUSH {r3,lr} \n" /* save QXK_attr_ + exception lr */
" LDR r2,=QXK_onContextSw \n" " LDR r3,=QXK_contextSw \n"
" PUSH {r1,lr} \n" /* save the aligner + exception lr */ " BLX r3 \n" /* call QXK_contextSw() */
" BLX r2 \n" /* call QXK_onContextSw() */ " POP {r0,r1} \n" /* restore the aligner + lr into r1 */
" POP {r1,r2} \n" /* restore the aligner + lr into r2 */ " MOV lr,r1 \n" /* restore the exception lr */
" MOV lr,r2 \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... */ /* 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 r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* r0 := QXK_attr_.next */
" LDR r2,[r0,#" STRINGIFY(QACTIVE_OSOBJ) "]\n" /* r2 := QXK_attr_.curr->osObject */ " 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) */ " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := r0 (QXK_attr_.next) */
" MOVS r0,#0 \n" " MOVS r0,#0 \n"

View File

@ -21,8 +21,8 @@
// <www.state-machine.com> // <www.state-machine.com>
// <info@state-machine.com> // <info@state-machine.com>
//============================================================================ //============================================================================
//! @date Last updated on: 2022-09-04 //! @date Last updated on: 2022-10-04
//! @version Last updated for: @ref qpcpp_7_1_1 //! @version Last updated for: @ref qpcpp_7_1_2
//! //!
//! @file //! @file
//! @brief QXK/C++ port to ARM Cortex-M, ARM-CLANG toolset //! @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 { \ #define QXK_ISR_EXIT() do { \
QF_INT_DISABLE(); \ QF_INT_DISABLE(); \
if (QXK_sched_(1U) != 0U) {\ if (QXK_sched_() != 0U) { \
QXK_CONTEXT_SWITCH_(); \ QXK_CONTEXT_SWITCH_(); \
} \ } \
QF_INT_ENABLE(); \ QF_INT_ENABLE(); \

View File

@ -23,8 +23,8 @@
* <info@state-machine.com> * <info@state-machine.com>
============================================================================*/ ============================================================================*/
/*! /*!
* @date Last updated on: 2022-09-20 * @date Last updated on: 2022-10-04
* @version Last updated for: @ref qpcpp_7_1_1 * @version Last updated for: @ref qpcpp_7_1_2
* *
* @file * @file
* @brief QXK/C++ port to ARM Cortex-M, GNU-ARM toolset * @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" !!! */ /* NOTE: keep in synch with struct QXK_Attr in "qxk.hpp" !!! */
#define QXK_CURR 0 #define QXK_CURR 0
#define QXK_NEXT 4 #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" */ /* 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_CURR == offsetof(QXK_Attr, curr));
//Q_ASSERT_STATIC(QXK_NEXT == offsetof(QXK_Attr, next)); //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" !!! */ /* offsets within struct QActive; NOTE: keep in synch with "qf.hpp" !!! */
#define QACTIVE_OSOBJ 28 #define QACTIVE_OSOBJ 28
#define QACTIVE_PRIO 36 #define QACTIVE_PRIO 36
#define QACTIVE_PTHRE 37
/* make sure that the offsets match the QXK declaration in "qf.hpp" */ /* 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_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 */ /* helper macros to "stringify" values */
#define VAL(x) #x #define VAL(x) #x
@ -278,11 +278,6 @@ __asm volatile (
" ADD r0,sp,#(5*4) \n" /* r0 := 5 registers below the top of stack */ " ADD r0,sp,#(5*4) \n" /* r0 := 5 registers below the top of stack */
" STM r0!,{r1-r3} \n" /* save xpsr,pc,lr */ " 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" " MOV r0,#6 \n"
" MVN r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */ " MVN r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */
#if (__ARM_ARCH != 6) /* ARMv7-M or higher */ #if (__ARM_ARCH != 6) /* ARMv7-M or higher */
@ -333,9 +328,9 @@ __asm volatile (
* r12 -> QXK_attr_.next / basic-thread * r12 -> QXK_attr_.next / basic-thread
*/ */
"PendSV_restore_ao: \n" "PendSV_restore_ao: \n"
" MOV r0,#0 \n" /* don NOT clear QXK_attr_.curr or QXK_attr_.next,
" STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := 0 */ * as they might be needed for AO activation
/* don't clear QXK_attr_.next, as it might be needed for AO activation */ */
#if (__ARM_ARCH == 6) /* if ARMv6-M... */ #if (__ARM_ARCH == 6) /* if ARMv6-M... */
" MOV r0,sp \n" /* r0 := top of stack */ " MOV r0,sp \n" /* r0 := top of stack */
@ -366,26 +361,25 @@ __asm volatile (
#endif /* ARMv7-M or higher */ #endif /* ARMv7-M or higher */
" MOV r0,r12 \n" /* r0 := QXK_attr_.next */ " MOV r0,r12 \n" /* r0 := QXK_attr_.next */
" MOV r2,#" STRINGIFY(QACTIVE_PTHRE) "\n" /* r2 := offset of .pthre */ " MOV r2,#" STRINGIFY(QACTIVE_PRIO) "\n" /* r2 := offset of .prio */
" LDRB r0,[r0,r2] \n" /* r0 := QXK_attr_.next->pthre */ " LDRB r0,[r0,r2] \n" /* r0 := QXK_attr_.next->prio */
" LDRB r2,[r3,#" STRINGIFY(QXK_ACT_THRE) "]\n" /* r2 := QXK_attr_.actThre */ " LDRB r2,[r3,#" STRINGIFY(QXK_ACT_PRIO) "]\n" /* r2 := QXK_attr_.actPrio */
" CMP r2,r0 \n" " 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... */ /* otherwise no activation needed... */
" MOV r0,#0 \n" " MOV r0,#0 \n"
" STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* QXK_attr_.next := 0 (clear the next) */ " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := 0 */
" MOV r12,r0 \n" /* also clear r12==QXK_attr_.next */ " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* QXK_attr_.next := 0 */
#ifdef QXK_ON_CONTEXT_SW #if defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
" MOV r0,r1 \n" /* r0 := QXK_attr_.curr / basic */ " MOV r0,#0 \n" /* r0 := 0 (next is basic) */
" MOV r1,r12 \n" /* r1 := QXK_attr_.next / basic */ " PUSH {r3,lr} \n" /* save QXK_attr_ + exception lr */
" LDR r2,=QXK_onContextSw \n" " LDR r3,=QXK_contextSw \n"
" PUSH {r1,lr} \n" /* save the aligner + exception lr */ " BLX r3 \n" /* call QXK_contextSw() */
" BLX r2 \n" /* call QXK_onContextSw() */ " POP {r0,r1} \n" /* restore the aligner + lr into r1 */
" POP {r1,r2} \n" /* restore the aligner + lr into r2 */ " MOV lr,r1 \n" /* restore the exception lr */
" MOV lr,r2 \n" /* restore the exception lr */ #endif /* defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW) */
#endif /* QXK_ON_CONTEXT_SW */
/* re-enable interrupts and return from PendSV */ /* re-enable interrupts and return from PendSV */
"PendSV_return: \n" "PendSV_return: \n"
@ -400,7 +394,7 @@ __asm volatile (
" BX lr \n" /* return to the preempted AO-thread */ " BX lr \n" /* return to the preempted AO-thread */
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* Saving extended-thread before crossing to AO-thread * Saving extended-thread
* expected register contents: * expected register contents:
* r0 -> QXK_attr_.next / basic-thread * r0 -> QXK_attr_.next / basic-thread
* r1 -> QXK_attr_.curr / basic-thread * r1 -> QXK_attr_.curr / basic-thread
@ -442,7 +436,7 @@ __asm volatile (
/* otherwise continue to restoring next extended-thread... */ /* otherwise continue to restoring next extended-thread... */
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* Restoring extended-thread after crossing from AO-thread * Restoring extended-thread
* expected register contents: * expected register contents:
* r0 -> QXK_attr_.next / basic-thread * r0 -> QXK_attr_.next / basic-thread
* r1 -> QXK_attr_.curr / basic-thread * r1 -> QXK_attr_.curr / basic-thread
@ -451,20 +445,19 @@ __asm volatile (
* r12 -> QXK_attr_.next / basic-thread * r12 -> QXK_attr_.next / basic-thread
*/ */
"PendSV_restore_ex: \n" "PendSV_restore_ex: \n"
#ifdef QXK_ON_CONTEXT_SW #if defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
" MOV r0,r1 \n" /* r0 := QXK_attr_.curr / basic */ " MOV r0,r12 \n" /* r0 := next */
" MOV r1,r12 \n" /* r1 := QXK_attr_.next / basic */ " PUSH {r3,lr} \n" /* save QXK_attr_ + exception lr */
" LDR r2,=QXK_onContextSw \n" " LDR r3,=QXK_contextSw \n"
" PUSH {r1,lr} \n" /* save the aligner + exception lr */ " BLX r3 \n" /* call QXK_contextSw() */
" BLX r2 \n" /* call QXK_onContextSw() */ " POP {r0,r1} \n" /* restore the aligner + lr into r1 */
" POP {r1,r2} \n" /* restore the aligner + lr into r2 */ " MOV lr,r1 \n" /* restore the exception lr */
" MOV lr,r2 \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... */ /* 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 r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* r0 := QXK_attr_.next */
" LDR r2,[r0,#" STRINGIFY(QACTIVE_OSOBJ) "]\n" /* r2 := QXK_attr_.curr->osObject */ " 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) */ " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := r0 (QXK_attr_.next) */
" MOV r0,#0 \n" " MOV r0,#0 \n"
@ -539,7 +532,7 @@ __asm volatile (
" ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */ " ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */
#endif /*--------- VFP available */ #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 */ " LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */
" MOV r1,#1 \n" " MOV r1,#1 \n"
" LSL r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */ " LSL r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */

View File

@ -21,8 +21,8 @@
// <www.state-machine.com> // <www.state-machine.com>
// <info@state-machine.com> // <info@state-machine.com>
//============================================================================ //============================================================================
//! @date Last updated on: 2022-09-04 //! @date Last updated on: 2022-10-04
//! @version Last updated for: @ref qpcpp_7_1_1 //! @version Last updated for: @ref qpcpp_7_1_2
//! //!
//! @file //! @file
//! @brief QXK/C++ port to ARM Cortex-M, GNU-ARM toolset //! @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 { \ #define QXK_ISR_EXIT() do { \
QF_INT_DISABLE(); \ QF_INT_DISABLE(); \
if (QXK_sched_(1U) != 0U) {\ if (QXK_sched_() != 0U) { \
QXK_CONTEXT_SWITCH_(); \ QXK_CONTEXT_SWITCH_(); \
} \ } \
QF_INT_ENABLE(); \ QF_INT_ENABLE(); \

View File

@ -23,8 +23,8 @@
* <info@state-machine.com> * <info@state-machine.com>
============================================================================*/ ============================================================================*/
/*! /*!
* @date Last updated on: 2022-09-20 * @date Last updated on: 2022-10-04
* @version Last updated for: @ref qpcpp_7_1_1 * @version Last updated for: @ref qpcpp_7_1_2
* *
* @file * @file
* @brief QXK/C++ port to ARM Cortex-M, IAR-ARM toolset * @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" !!! */ /* NOTE: keep in synch with struct QXK_Attr in "qxk.hpp" !!! */
#define QXK_CURR 0 #define QXK_CURR 0
#define QXK_NEXT 4 #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" */ /* 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_CURR == offsetof(QXK_Attr, curr));
Q_ASSERT_STATIC(QXK_NEXT == offsetof(QXK_Attr, next)); 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" !!! */ /* offsets within struct QActive; NOTE: keep in synch with "qf.hpp" !!! */
#define QACTIVE_OSOBJ 28 #define QACTIVE_OSOBJ 28
#define QACTIVE_PRIO 36 #define QACTIVE_PRIO 36
#define QACTIVE_PTHRE 37
/* make sure that the offsets match the QXK declaration in "qf.hpp" */ /* 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_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 */ /* helper macros to "stringify" values */
#define VAL(x) #x #define VAL(x) #x
@ -273,11 +273,6 @@ __asm volatile (
" ADD r0,sp,#(5*4) \n" /* r0 := 5 registers below the top of stack */ " ADD r0,sp,#(5*4) \n" /* r0 := 5 registers below the top of stack */
" STM r0!,{r1-r3} \n" /* save xpsr,pc,lr */ " 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" " MOVS r0,#6 \n"
" MVNS r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */ " MVNS r0,r0 \n" /* r0 := ~6 == 0xFFFFFFF9 */
#if (__ARM_ARCH != 6) /* ARMv7-M or higher */ #if (__ARM_ARCH != 6) /* ARMv7-M or higher */
@ -328,9 +323,9 @@ __asm volatile (
* r12 -> QXK_attr_.next / basic-thread * r12 -> QXK_attr_.next / basic-thread
*/ */
"PendSV_restore_ao: \n" "PendSV_restore_ao: \n"
" MOVS r0,#0 \n" /* don NOT clear QXK_attr_.curr or QXK_attr_.next,
" STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := 0 */ * as they might be needed for AO activation
/* don't clear QXK_attr_.next, as it might be needed for AO activation */ */
#if (__ARM_ARCH == 6) /* if ARMv6-M... */ #if (__ARM_ARCH == 6) /* if ARMv6-M... */
" MOV r0,sp \n" /* r0 := top of stack */ " MOV r0,sp \n" /* r0 := top of stack */
@ -361,26 +356,25 @@ __asm volatile (
#endif /* ARMv7-M or higher */ #endif /* ARMv7-M or higher */
" MOV r0,r12 \n" /* r0 := QXK_attr_.next */ " MOV r0,r12 \n" /* r0 := QXK_attr_.next */
" MOVS r2,#" STRINGIFY(QACTIVE_PTHRE) "\n" /* r2 := offset of .pthre */ " MOVS r2,#" STRINGIFY(QACTIVE_PRIO) "\n" /* r2 := offset of .prio */
" LDRB r0,[r0,r2] \n" /* r0 := QXK_attr_.next->pthre */ " LDRB r0,[r0,r2] \n" /* r0 := QXK_attr_.next->prio */
" LDRB r2,[r3,#" STRINGIFY(QXK_ACT_THRE) "]\n" /* r2 := QXK_attr_.actThre */ " LDRB r2,[r3,#" STRINGIFY(QXK_ACT_PRIO) "]\n" /* r2 := QXK_attr_.actPrio */
" CMP r2,r0 \n" " 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... */ /* otherwise no activation needed... */
" MOVS r0,#0 \n" " MOVS r0,#0 \n"
" STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* QXK_attr_.next := 0 (clear the next) */ " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := 0 */
" MOV r12,r0 \n" /* also clear r12==QXK_attr_.next */ " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* QXK_attr_.next := 0 */
#ifdef QXK_ON_CONTEXT_SW #if defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
" MOVS r0,r1 \n" /* r0 := QXK_attr_.curr / basic */ " MOVS r0,#0 \n" /* r0 := 0 (next is basic) */
" MOV r1,r12 \n" /* r1 := QXK_attr_.next / basic */ " PUSH {r3,lr} \n" /* save QXK_attr_ + exception lr */
" LDR r2,=QXK_onContextSw \n" " LDR r3,=QXK_contextSw \n"
" PUSH {r1,lr} \n" /* save the aligner + exception lr */ " BLX r3 \n" /* call QXK_contextSw() */
" BLX r2 \n" /* call QXK_onContextSw() */ " POP {r0,r1} \n" /* restore the aligner + lr into r1 */
" POP {r1,r2} \n" /* restore the aligner + lr into r2 */ " MOV lr,r1 \n" /* restore the exception lr */
" MOV lr,r2 \n" /* restore the exception lr */ #endif /* defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW) */
#endif /* QXK_ON_CONTEXT_SW */
/* re-enable interrupts and return from PendSV */ /* re-enable interrupts and return from PendSV */
"PendSV_return: \n" "PendSV_return: \n"
@ -395,7 +389,7 @@ __asm volatile (
" BX lr \n" /* return to the preempted AO-thread */ " BX lr \n" /* return to the preempted AO-thread */
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* Saving extended-thread before crossing to AO-thread * Saving extended-thread
* expected register contents: * expected register contents:
* r0 -> QXK_attr_.next / basic-thread * r0 -> QXK_attr_.next / basic-thread
* r1 -> QXK_attr_.curr / basic-thread * r1 -> QXK_attr_.curr / basic-thread
@ -437,7 +431,7 @@ __asm volatile (
/* otherwise continue to restoring next extended-thread... */ /* otherwise continue to restoring next extended-thread... */
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* Restoring extended-thread after crossing from AO-thread * Restoring extended-thread
* expected register contents: * expected register contents:
* r0 -> QXK_attr_.next / basic-thread * r0 -> QXK_attr_.next / basic-thread
* r1 -> QXK_attr_.curr / basic-thread * r1 -> QXK_attr_.curr / basic-thread
@ -446,20 +440,19 @@ __asm volatile (
* r12 -> QXK_attr_.next / basic-thread * r12 -> QXK_attr_.next / basic-thread
*/ */
"PendSV_restore_ex: \n" "PendSV_restore_ex: \n"
#ifdef QXK_ON_CONTEXT_SW #if defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)
" MOVS r0,r1 \n" /* r0 := QXK_attr_.curr / basic */ " MOV r0,r12 \n" /* r0 := next */
" MOV r1,r12 \n" /* r1 := QXK_attr_.next / basic */ " PUSH {r3,lr} \n" /* save QXK_attr_ + exception lr */
" LDR r2,=QXK_onContextSw \n" " LDR r3,=QXK_contextSw \n"
" PUSH {r1,lr} \n" /* save the aligner + exception lr */ " BLX r3 \n" /* call QXK_contextSw() */
" BLX r2 \n" /* call QXK_onContextSw() */ " POP {r0,r1} \n" /* restore the aligner + lr into r1 */
" POP {r1,r2} \n" /* restore the aligner + lr into r2 */ " MOV lr,r1 \n" /* restore the exception lr */
" MOV lr,r2 \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... */ /* 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 r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" /* r0 := QXK_attr_.next */
" LDR r2,[r0,#" STRINGIFY(QACTIVE_OSOBJ) "]\n" /* r2 := QXK_attr_.curr->osObject */ " 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) */ " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" /* QXK_attr_.curr := r0 (QXK_attr_.next) */
" MOVS r0,#0 \n" " MOVS r0,#0 \n"

View File

@ -21,8 +21,8 @@
// <www.state-machine.com> // <www.state-machine.com>
// <info@state-machine.com> // <info@state-machine.com>
//============================================================================ //============================================================================
//! @date Last updated on: 2022-09-04 //! @date Last updated on: 2022-10-04
//! @version Last updated for: @ref qpcpp_7_1_1 //! @version Last updated for: @ref qpcpp_7_1_2
//! //!
//! @file //! @file
//! @brief QXK/C++ port to ARM Cortex-M, QXK kernel, IAR-ARM toolset //! @brief QXK/C++ port to ARM Cortex-M, QXK kernel, IAR-ARM toolset
@ -42,7 +42,7 @@
#define QXK_ISR_EXIT() do { \ #define QXK_ISR_EXIT() do { \
QF_INT_DISABLE(); \ QF_INT_DISABLE(); \
if (QXK_sched_(1U) != 0U) {\ if (QXK_sched_() != 0U) { \
QXK_CONTEXT_SWITCH_(); \ QXK_CONTEXT_SWITCH_(); \
} \ } \
QF_INT_ENABLE(); \ QF_INT_ENABLE(); \

View File

@ -22,8 +22,8 @@
// <www.state-machine.com> // <www.state-machine.com>
// <info@state-machine.com> // <info@state-machine.com>
//============================================================================ //============================================================================
//! @date Last updated on: 2022-09-04 //! @date Last updated on: 2022-10-04
//! @version Last updated for: @ref qpcpp_7_1_1 //! @version Last updated for: @ref qpcpp_7_1_2
//! //!
//! @file //! @file
//! @brief QK/C++ port to ARM Cortex-R, preemptive QK kernel, GNU-ARM toolset //! @brief QK/C++ port to ARM Cortex-R, preemptive QK kernel, GNU-ARM toolset
@ -71,7 +71,7 @@
} --QP::QF::intNest_; \ } --QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) { \ if (QP::QF::intNest_ == 0U) { \
if (QK_sched_() != 0U) { \ if (QK_sched_() != 0U) { \
QK_activate_(1U); \ QK_activate_(); \
} \ } \
} \ } \
__asm volatile (" POP {R3, LR}\n" \ __asm volatile (" POP {R3, LR}\n" \
@ -89,7 +89,7 @@
} --QP::QF::intNest_; \ } --QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) { \ if (QP::QF::intNest_ == 0U) { \
if (QK_sched_() != 0U) { \ if (QK_sched_() != 0U) { \
QK_activate_(1U); \ QK_activate_(); \
} \ } \
} \ } \
__asm volatile (" POP {R3, LR}\n" \ __asm volatile (" POP {R3, LR}\n" \

View File

@ -22,8 +22,8 @@
// <www.state-machine.com> // <www.state-machine.com>
// <info@state-machine.com> // <info@state-machine.com>
//============================================================================ //============================================================================
//! @date Last updated on: 2022-09-04 //! @date Last updated on: 2022-10-04
//! @version Last updated for: @ref qpcpp_7_1_1 //! @version Last updated for: @ref qpcpp_7_1_2
//! //!
//! @file //! @file
//! @brief QK/C++ port to ARM Cortex-R, preemptive QK kernel, IAR-ARM toolset //! @brief QK/C++ port to ARM Cortex-R, preemptive QK kernel, IAR-ARM toolset
@ -67,7 +67,7 @@
} --QP::QF::intNest_; \ } --QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) { \ if (QP::QF::intNest_ == 0U) { \
if (QK_sched_() != 0U) { \ if (QK_sched_() != 0U) { \
QK_activate_(1U); \ QK_activate_(); \
} \ } \
} \ } \
__asm(" POP {R3, LR}\n" \ __asm(" POP {R3, LR}\n" \
@ -85,7 +85,7 @@
} --QP::QF::intNest_; \ } --QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) { \ if (QP::QF::intNest_ == 0U) { \
if (QK_sched_() != 0U) { \ if (QK_sched_() != 0U) { \
QK_activate_(1U); \ QK_activate_(); \
} \ } \
} \ } \
__asm(" POP {R3, LR}\n" \ __asm(" POP {R3, LR}\n" \

View File

@ -22,8 +22,8 @@
// <www.state-machine.com> // <www.state-machine.com>
// <info@state-machine.com> // <info@state-machine.com>
//============================================================================ //============================================================================
//! @date Last updated on: 2022-09-04 //! @date Last updated on: 2022-10-04
//! @version Last updated for: @ref qpcpp_7_1_1 //! @version Last updated for: @ref qpcpp_7_1_2
//! //!
//! @file //! @file
//! @brief QK/C++ port to ARM Cortex-R, preemptive QK kernel, TI-ARM toolset //! @brief QK/C++ port to ARM Cortex-R, preemptive QK kernel, TI-ARM toolset
@ -73,7 +73,7 @@
} --QP::QF::intNest_; \ } --QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) { \ if (QP::QF::intNest_ == 0U) { \
if (QK_sched_() != 0U) { \ if (QK_sched_() != 0U) { \
QK_activate_(1U); \ QK_activate_(); \
} \ } \
} \ } \
} }

View File

@ -22,8 +22,8 @@
// <www.state-machine.com> // <www.state-machine.com>
// <info@state-machine.com> // <info@state-machine.com>
//============================================================================ //============================================================================
//! @date Last updated on: 2022-09-04 //! @date Last updated on: 2022-10-04
//! @version Last updated for: @ref qpcpp_7_1_1 //! @version Last updated for: @ref qpcpp_7_1_2
//! //!
//! @file //! @file
//! @brief QK/C++ port to Lint, Generic C++ compiler //! @brief QK/C++ port to Lint, Generic C++ compiler
@ -60,7 +60,7 @@
--QP::QF::intNest_; \ --QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) {\ if (QP::QF::intNest_ == 0U) {\
if (QK_sched_() != 0U) { \ if (QK_sched_() != 0U) { \
QK_activate_(1U); \ QK_activate_(); \
} \ } \
} \ } \
else { \ else { \

View File

@ -22,8 +22,8 @@
// <www.state-machine.com> // <www.state-machine.com>
// <info@state-machine.com> // <info@state-machine.com>
//============================================================================ //============================================================================
//! @date Last updated on: 2022-09-04 //! @date Last updated on: 2022-10-04
//! @version Last updated for: @ref qpcpp_7_1_1 //! @version Last updated for: @ref qpcpp_7_1_2
//! //!
//! @file //! @file
//! @brief QXK/C++ port example, Generic C++ compiler //! @brief QXK/C++ port example, Generic C++ compiler
@ -70,8 +70,8 @@
#define QXK_ISR_EXIT() do { \ #define QXK_ISR_EXIT() do { \
--QP::QF::intNest_; \ --QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) { \ if (QP::QF::intNest_ == 0U) { \
if (QXK_sched_(1U) != 0U) {\ if (QXK_sched_() != 0U) { \
QXK_activate_(1U); \ QXK_activate_(); \
} \ } \
} \ } \
else { \ else { \

View File

@ -22,8 +22,8 @@
// <www.state-machine.com> // <www.state-machine.com>
// <info@state-machine.com> // <info@state-machine.com>
//============================================================================ //============================================================================
//! @date Last updated on: 2022-09-04 //! @date Last updated on: 2022-10-04
//! @version Last updated for: @ref qpcpp_7_1_1 //! @version Last updated for: @ref qpcpp_7_1_2
//! //!
//! @file //! @file
//! @brief QK/C++ port to MSP430 //! @brief QK/C++ port to MSP430
@ -38,7 +38,7 @@
--QP::QF::intNest_; \ --QP::QF::intNest_; \
if (QP::QF::intNest_ == 0U) {\ if (QP::QF::intNest_ == 0U) {\
if (QK_sched_() != 0U) { \ if (QK_sched_() != 0U) { \
QK_activate_(1U); \ QK_activate_(); \
} \ } \
} \ } \
else { \ else { \

View File

@ -22,8 +22,8 @@
// <www.state-machine.com> // <www.state-machine.com>
// <info@state-machine.com> // <info@state-machine.com>
//============================================================================ //============================================================================
//! @date Last updated on: 2022-09-04 //! @date Last updated on: 2022-10-04
//! @version Last updated for: @ref qpcpp_7_1_1 //! @version Last updated for: @ref qpcpp_7_1_2
//! //!
//! @file //! @file
//! @brief QK/C++ port to PIC32, preemptive QK kernel, XC32 toolchain //! @brief QK/C++ port to PIC32, preemptive QK kernel, XC32 toolchain
@ -49,7 +49,7 @@ void QK_isr_(void) { // see NOTE2
QF_INT_DISABLE(); QF_INT_DISABLE();
_mtc0(_CP0_STATUS, _CP0_STATUS_SELECT, 0U); // drop IPL to 0 _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 _mtc0(_CP0_STATUS, _CP0_STATUS_SELECT, 1U << 10); //restore IPL to 1
QF_INT_ENABLE(); QF_INT_ENABLE();
} }

496
qpcpp.qm
View File

@ -2323,7 +2323,7 @@ return r;</code>
//! When QP runs on top of 3rd-party kernels/RTOSes or general-purpose //! When QP runs on top of 3rd-party kernels/RTOSes or general-purpose
//! operating systems, sthe second priority can have different meaning, //! operating systems, sthe second priority can have different meaning,
//! depending on the specific RTOS/GPOS used.</documentation> //! depending on the specific RTOS/GPOS used.</documentation>
<code>= std::uint_fast16_t;</code> <code>= std::uint16_t;</code>
</attribute> </attribute>
<!--${QF-types::QSchedStatus}--> <!--${QF-types::QSchedStatus}-->
<attribute name="QSchedStatus" type="using" visibility="0x04" properties="0x00"> <attribute name="QSchedStatus" type="using" visibility="0x04" properties="0x00">
@ -3759,7 +3759,7 @@ QF_QMACTIVE_TO_QMSM_CAST_(this)-&gt;QMsm::init(qs_id);</code>
m_interval(0U) m_interval(0U)
//! @pre The signal must be valid and the tick rate in range //! @pre The signal must be valid and the tick rate in range
Q_REQUIRE_ID(300, (sgnl &gt;= Q_USER_SIG) Q_REQUIRE_ID(300, (sgnl != 0)
&amp;&amp; (tickRate &lt; QF_MAX_TICK_RATE)); &amp;&amp; (tickRate &lt; QF_MAX_TICK_RATE));
#ifndef Q_EVT_CTOR #ifndef Q_EVT_CTOR
@ -6560,7 +6560,7 @@ if (QS_GLB_CHECK_(rec_) &amp;&amp; QS_LOC_CHECK_(qs_id_)) { \
QS_SCHED_UNLOCK, //!&lt; scheduler was unlocked QS_SCHED_UNLOCK, //!&lt; scheduler was unlocked
QS_SCHED_NEXT, //!&lt; scheduler found next task to execute QS_SCHED_NEXT, //!&lt; scheduler found next task to execute
QS_SCHED_IDLE, //!&lt; scheduler became idle QS_SCHED_IDLE, //!&lt; scheduler became idle
QS_SCHED_RESUME, //!&lt; scheduler resumed previous task (not idle) QS_SCHED_RESUME, //!&lt; scheduler resumed a (blocked) task
// [55] Additional QEP records // [55] Additional QEP records
QS_QEP_TRAN_HIST, //!&lt; a tran to history was taken QS_QEP_TRAN_HIST, //!&lt; a tran to history was taken
@ -9637,8 +9637,8 @@ if (stat != 0xFFU) {
QS_BEGIN_NOCRIT_PRE_(QS_SCHED_UNLOCK, 0U) QS_BEGIN_NOCRIT_PRE_(QS_SCHED_UNLOCK, 0U)
QS_TIME_PRE_(); // timestamp QS_TIME_PRE_(); // timestamp
QS_2U8_PRE_(lockCeil, // current lock ceiling (old) // current lock ceiling (old), previous lock ceiling (new)
prevCeil); // previous lock ceiling (new) QS_2U8_PRE_(lockCeil, prevCeil);
QS_END_NOCRIT_PRE_() QS_END_NOCRIT_PRE_()
// restore the previous lock ceiling and lock holder // 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 // find if any AOs should be run after unlocking the scheduler
if (QK_sched_() != 0U) { // synchronous preemption needed? 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_(); QF_CRIT_X_();
@ -9691,7 +9691,7 @@ QK_attr_.lockCeil = 0U; // scheduler unlocked
// any active objects need to be scheduled before starting event loop? // any active objects need to be scheduled before starting event loop?
if (QK_sched_() != 0U) { // synchronous preemption needed? 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 onStartup(); // application-specific startup callback
@ -9752,7 +9752,7 @@ QS_FLUSH(); // flush the trace buffer to the host
QF_CRIT_STAT_ QF_CRIT_STAT_
QF_CRIT_E_(); QF_CRIT_E_();
if (QK_sched_() != 0U) { // synchronous preemption needed? if (QK_sched_() != 0U) { // synchronous preemption needed?
QK_activate_(0U); // synchronously activate AOs QK_activate_(); // synchronously activate AOs
} }
QF_CRIT_X_();</code> QF_CRIT_X_();</code>
</operation> </operation>
@ -9785,26 +9785,33 @@ QF_CRIT_X_();</code>
//! that (1) has events to process and (2) has priority that is above the //! that (1) has events to process and (2) has priority that is above the
//! current priority. //! current priority.
//! //!
//! @returns the 1-based priority of the the active object, or zero if //! @returns
//! no eligible active object is ready to run. //! The QF-priority of the next active object to activate, or zero
//! if no activation of AO is needed.
//! //!
//! @attention //! @attention
//! QK_sched_() must be always called with interrupts **disabled** and //! QK_sched_() must be always called with interrupts **disabled** and
//! returns with interrupts **disabled**.</documentation> //! returns with interrupts **disabled**.</documentation>
<code>// find the highest-prio AO with non-empty event queue <code>std::uint_fast8_t p;
std::uint_fast8_t p = QP::QF::readySet_.findMax();
if (QP::QF::readySet_.isEmpty()) {
p = 0U; // no activation needed
}
else {
// 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? // is the AO's priority below the active preemption-threshold?
if (p &lt;= QK_attr_.actThre) { if (p &lt;= QK_attr_.actThre) {
p = 0U; // no preemption needed p = 0U; // no activation needed
} }
// is the AO's priority below the lock preemption-ceiling? // is the AO's priority below the lock preemption-ceiling?
else if (p &lt;= QK_attr_.lockCeil) { else if (p &lt;= QK_attr_.lockCeil) {
p = 0U; // no preemption needed p = 0U; // no activation needed
} }
else { else {
Q_ASSERT_ID(410, p &lt;= QF_MAX_ACTIVE); QK_attr_.nextPrio = static_cast&lt;std::uint8_t&gt;(p);
QK_attr_.nextPrio = static_cast&lt;std::uint8_t&gt;(p); // next AO to run }
} }
return p;</code> return p;</code>
</operation> </operation>
@ -9814,21 +9821,14 @@ return p;</code>
<documentation>//! QK activator activates the next active object. The activated AO preempts <documentation>//! QK activator activates the next active object. The activated AO preempts
//! the currently executing AOs //! the currently executing AOs
//! //!
//! @param[in] asynch flag conveying the type of activation:
//! != 0 for asynchronous activation and
//! == 0 for synchronous activation
//! @details //! @details
//! QK_activate_() activates ready-to run AOs that are above the initial //! QK_activate_() activates ready-to run AOs that are above the initial
//! active priority (QK_attr_.actPrio). //! preemption-threshold.
//! //!
//! @note //! @note
//! The activator might enable interrupts internally, but always returns with //! The activator might enable interrupts internally, but always returns with
//! interrupts **disabled**.</documentation> //! interrupts **disabled**.</documentation>
<!--${QK-extern-C::QK_activate_::asynch}--> <code>std::uint8_t const prio_in = QK_attr_.actPrio; // saved initial priority
<parameter name="asynch" type="std::uint_fast8_t const"/>
<code>Q_UNUSED_PAR(asynch); // unused when Q_SPY not defined
std::uint8_t const prio_in = QK_attr_.actPrio; // saved initial priority
std::uint_fast8_t p = QK_attr_.nextPrio; // next prio to run std::uint_fast8_t p = QK_attr_.nextPrio; // next prio to run
QK_attr_.nextPrio = 0U; // clear for the next time QK_attr_.nextPrio = 0U; // clear for the next time
@ -9849,25 +9849,14 @@ do {
QK_attr_.actPrio = static_cast&lt;std::uint8_t&gt;(p); QK_attr_.actPrio = static_cast&lt;std::uint8_t&gt;(p);
QK_attr_.actThre = QP::QActive::registry_[p]-&gt;m_pthre; QK_attr_.actThre = QP::QActive::registry_[p]-&gt;m_pthre;
#ifdef Q_SPY #if (defined QK_ON_CONTEXT_SW) || (defined Q_SPY)
if ((asynch != 0U) &amp;&amp; (pprev == prio_in)) { if (p != pprev) { // changing threads?
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_PREEMPT, a-&gt;m_prio)
QS_TIME_PRE_(); // timestamp
QS_2U8_PRE_(p, // priority of the scheduled AO
pprev); // previous priority
QS_END_NOCRIT_PRE_()
}
else {
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a-&gt;m_prio) QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a-&gt;m_prio)
QS_TIME_PRE_(); // timestamp QS_TIME_PRE_(); // timestamp
QS_2U8_PRE_(p, // priority of the scheduled AO QS_2U8_PRE_(p, // priority of the scheduled AO
pprev); // previous priority pprev); // previous priority
QS_END_NOCRIT_PRE_() 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 #ifdef QK_ON_CONTEXT_SW
// context-switch callback // context-switch callback
@ -9892,6 +9881,7 @@ do {
#if (QF_MAX_EPOOL &gt; 0U) #if (QF_MAX_EPOOL &gt; 0U)
QP::QF::gc(e); QP::QF::gc(e);
#endif #endif
// determine the next highest-priority AO ready to run... // determine the next highest-priority AO ready to run...
QF_INT_DISABLE(); // unconditionally disable interrupts QF_INT_DISABLE(); // unconditionally disable interrupts
@ -9899,20 +9889,25 @@ do {
QP::QF::readySet_.remove(p); QP::QF::readySet_.remove(p);
} }
if (QP::QF::readySet_.isEmpty()) {
p = 0U; // no activation needed
}
else {
// find new highest-prio AO ready to run... // find new highest-prio AO ready to run...
p = QP::QF::readySet_.findMax(); p = QP::QF::readySet_.findMax();
// is the new priority below the initial preemption-threshold? // is the new priority below the initial preemption-threshold?
if (p &lt;= QP::QActive::registry_[prio_in]-&gt;m_pthre) { if (p &lt;= QP::QActive::registry_[prio_in]-&gt;m_pthre) {
p = 0U; // no preemption needed p = 0U; // no activation needed
} }
// is the AO's priority below the lock preemption-ceiling? // is the AO's priority below the lock preemption-ceiling?
else if (p &lt;= QK_attr_.lockCeil) { else if (p &lt;= QK_attr_.lockCeil) {
p = 0U; // no preemption needed p = 0U; // no activation needed
} }
else { else {
Q_ASSERT_ID(510, p &lt;= QF_MAX_ACTIVE); Q_ASSERT_ID(510, p &lt;= QF_MAX_ACTIVE);
} }
}
} while (p != 0U); } while (p != 0U);
// restore the active priority and preemption-threshold // restore the active priority and preemption-threshold
@ -9923,23 +9918,12 @@ QK_attr_.actThre = QP::QActive::registry_[prio_in]-&gt;m_pthre;
if (prio_in != 0U) { // resuming an active object? if (prio_in != 0U) { // resuming an active object?
a = QP::QActive::registry_[prio_in]; // pointer to preempted AO a = QP::QActive::registry_[prio_in]; // pointer to preempted AO
#ifdef Q_SPY QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a-&gt;m_prio)
if (asynch != 0U) {
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_RESTORE, a-&gt;m_prio)
QS_TIME_PRE_(); // timestamp QS_TIME_PRE_(); // timestamp
QS_2U8_PRE_(prio_in, // priority of the resumed AO // priority of the resumed AO, previous priority
pprev); // previous priority QS_2U8_PRE_(prio_in, pprev);
QS_END_NOCRIT_PRE_() QS_END_NOCRIT_PRE_()
} }
else {
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_RESUME, a-&gt;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
}
else { // resuming priority==0 --&gt; idle else { // resuming priority==0 --&gt; idle
a = nullptr; // QK idle loop a = nullptr; // QK idle loop
@ -10038,7 +10022,7 @@ QK_onContextSw(QP::QActive::registry_[pprev], a);
static_cast&lt;std::uint_fast8_t&gt;((me_)-&gt;m_prio)); \ static_cast&lt;std::uint_fast8_t&gt;((me_)-&gt;m_prio)); \
if (!QK_ISR_CONTEXT_()) { \ if (!QK_ISR_CONTEXT_()) { \
if (QK_sched_() != 0U) { \ if (QK_sched_() != 0U) { \
QK_activate_(0U); \ QK_activate_(); \
} \ } \
} \ } \
} while (false)</code> } while (false)</code>
@ -10174,8 +10158,8 @@ if (stat != 0xFFU) {
QXK_attr_.lockHolder = static_cast&lt;std::uint8_t&gt;(stat &amp; 0xFFU); QXK_attr_.lockHolder = static_cast&lt;std::uint8_t&gt;(stat &amp; 0xFFU);
// find the highest-prio thread ready to run // find the highest-prio thread ready to run
if (QXK_sched_(0U) != 0U) { // synchronous preemption needed? if (QXK_sched_() != 0U) { // synchronous preemption needed?
QXK_activate_(0U); // synchronously activate unlocked AOs QXK_activate_(); // synchronously activate unlocked AOs
} }
QF_CRIT_X_(); QF_CRIT_X_();
@ -10185,10 +10169,8 @@ if (stat != 0xFFU) {
<attribute name="Timeouts" type="enum" visibility="0x04" properties="0x00"> <attribute name="Timeouts" type="enum" visibility="0x04" properties="0x00">
<documentation>//! timeout signals for extended threads</documentation> <documentation>//! timeout signals for extended threads</documentation>
<code>: enum_t { <code>: enum_t {
DELAY_SIG = Q_USER_SIG, DELAY_SIG = 1,
QUEUE_SIG, TIMEOUT_SIG
SEMA_SIG,
MUTEX_SIG
};</code> };</code>
</attribute> </attribute>
</package> </package>
@ -10386,10 +10368,10 @@ if (thr-&gt;m_eQueue.m_frontEvt == nullptr) {
// remember the blocking object (the thread's queue) // remember the blocking object (the thread's queue)
thr-&gt;m_temp.obj = QXK_PTR_CAST_(QMState*, &amp;thr-&gt;m_eQueue); thr-&gt;m_temp.obj = QXK_PTR_CAST_(QMState*, &amp;thr-&gt;m_eQueue);
thr-&gt;teArm_(static_cast&lt;enum_t&gt;(QXK::QUEUE_SIG), nTicks); thr-&gt;teArm_(static_cast&lt;enum_t&gt;(QXK::TIMEOUT_SIG), nTicks);
QF::readySet_.remove( QF::readySet_.remove(
static_cast&lt;std::uint_fast8_t&gt;(thr-&gt;m_prio)); static_cast&lt;std::uint_fast8_t&gt;(thr-&gt;m_prio));
static_cast&lt;void&gt;(QXK_sched_(0U)); // synchronous scheduling static_cast&lt;void&gt;(QXK_sched_()); // synchronous scheduling
QF_CRIT_X_(); QF_CRIT_X_();
QF_CRIT_EXIT_NOP(); // BLOCK here QF_CRIT_EXIT_NOP(); // BLOCK here
@ -10527,10 +10509,13 @@ Q_ERROR_ID(120);</code>
//! - NOT be called from an ISR; //! - NOT be called from an ISR;
//! - the stack storage must be provided; //! - the stack storage must be provided;
//! - the thread must be instantiated (see #QXThread). //! - 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_()) Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_())
&amp;&amp; (stkSto != nullptr) &amp;&amp; (stkSto != nullptr)
&amp;&amp; (stkSize != 0U) &amp;&amp; (stkSize != 0U)
&amp;&amp; (m_state.act == nullptr)); &amp;&amp; (m_state.act == nullptr)
&amp;&amp; ((prioSpec &amp; 0xFF00U) == 0U));
// is storage for the queue buffer provided? // is storage for the queue buffer provided?
if (qSto != nullptr) { if (qSto != nullptr) {
@ -10542,7 +10527,7 @@ if (qSto != nullptr) {
QXK_stackInit_(this, m_temp.thr, stkSto, stkSize); QXK_stackInit_(this, m_temp.thr, stkSto, stkSize);
m_prio = static_cast&lt;std::uint8_t&gt;(prioSpec &amp; 0xFFU); // QF-prio. m_prio = static_cast&lt;std::uint8_t&gt;(prioSpec &amp; 0xFFU); // QF-prio.
m_pthre = static_cast&lt;std::uint8_t&gt;(prioSpec &gt;&gt; 8U); // preemption-thre. m_pthre = 0U; // preemption-threshold NOT used
register_(); // make QF aware of this AO register_(); // make QF aware of this AO
// the new thread is not blocked on any object // the new thread is not blocked on any object
@ -10554,7 +10539,9 @@ QF_CRIT_E_();
QF::readySet_.insert(static_cast&lt;std::uint_fast8_t&gt;(m_prio)); QF::readySet_.insert(static_cast&lt;std::uint_fast8_t&gt;(m_prio));
// see if this thread needs to be scheduled in case QXK is running // see if this thread needs to be scheduled in case QXK is running
static_cast&lt;void&gt;(QXK_sched_(0U)); // synchronous scheduling if (QXK_attr_.lockCeil &lt;= QF_MAX_ACTIVE) {
static_cast&lt;void&gt;(QXK_sched_()); // synchronous scheduling
}
QF_CRIT_X_();</code> QF_CRIT_X_();</code>
</operation> </operation>
<!--${QXK::QXThread::start}--> <!--${QXK::QXThread::start}-->
@ -10691,7 +10678,7 @@ else if (m_eQueue.m_end != 0U) {
QF::readySet_.insert( QF::readySet_.insert(
static_cast&lt;std::uint_fast8_t&gt;(m_prio)); static_cast&lt;std::uint_fast8_t&gt;(m_prio));
if (!QXK_ISR_CONTEXT_()) { if (!QXK_ISR_CONTEXT_()) {
static_cast&lt;void&gt;(QXK_sched_(0U)); static_cast&lt;void&gt;(QXK_sched_());
} }
} }
} }
@ -10770,7 +10757,7 @@ Q_ERROR_ID(410);</code>
<code>//! @pre the thread holding the lock cannot block! <code>//! @pre the thread holding the lock cannot block!
Q_REQUIRE_ID(600, (QXK_attr_.lockHolder != m_prio)); Q_REQUIRE_ID(600, (QXK_attr_.lockHolder != m_prio));
QF::readySet_.remove(static_cast&lt;std::uint_fast8_t&gt;(m_prio)); QF::readySet_.remove(static_cast&lt;std::uint_fast8_t&gt;(m_prio));
static_cast&lt;void&gt;(QXK_sched_(0U)); // synchronous scheduling</code> static_cast&lt;void&gt;(QXK_sched_()); // synchronous scheduling</code>
</operation> </operation>
<!--${QXK::QXThread::unblock_}--> <!--${QXK::QXThread::unblock_}-->
<operation name="unblock_" type="void" visibility="0x02" properties="0x00"> <operation name="unblock_" type="void" visibility="0x02" properties="0x00">
@ -10787,7 +10774,7 @@ static_cast&lt;void&gt;(QXK_sched_(0U)); // synchronous scheduling</code>
if ((!QXK_ISR_CONTEXT_()) // not inside ISR? if ((!QXK_ISR_CONTEXT_()) // not inside ISR?
&amp;&amp; (QActive::registry_[0] != nullptr)) // kernel started? &amp;&amp; (QActive::registry_[0] != nullptr)) // kernel started?
{ {
static_cast&lt;void&gt;(QXK_sched_(0U)); // synchronous scheduling static_cast&lt;void&gt;(QXK_sched_()); // synchronous scheduling
}</code> }</code>
</operation> </operation>
<!--${QXK::QXThread::teArm_}--> <!--${QXK::QXThread::teArm_}-->
@ -10992,7 +10979,7 @@ else {
// remember the blocking object (this semaphore) // remember the blocking object (this semaphore)
curr-&gt;m_temp.obj = QXK_PTR_CAST_(QMState*, this); curr-&gt;m_temp.obj = QXK_PTR_CAST_(QMState*, this);
curr-&gt;teArm_(static_cast&lt;enum_t&gt;(QXK::SEMA_SIG), nTicks); curr-&gt;teArm_(static_cast&lt;enum_t&gt;(QXK::TIMEOUT_SIG), nTicks);
QS_BEGIN_NOCRIT_PRE_(QS_SEM_BLOCK, curr-&gt;m_prio) QS_BEGIN_NOCRIT_PRE_(QS_SEM_BLOCK, curr-&gt;m_prio)
QS_TIME_PRE_(); // timestamp QS_TIME_PRE_(); // timestamp
@ -11001,7 +10988,7 @@ else {
QS_END_NOCRIT_PRE_() QS_END_NOCRIT_PRE_()
// schedule the next thread if multitasking started // schedule the next thread if multitasking started
static_cast&lt;void&gt;(QXK_sched_(0U)); // synchronous scheduling static_cast&lt;void&gt;(QXK_sched_()); // synchronous scheduling
QF_CRIT_X_(); QF_CRIT_X_();
QF_CRIT_EXIT_NOP(); // BLOCK here !!! QF_CRIT_EXIT_NOP(); // BLOCK here !!!
@ -11157,7 +11144,7 @@ if (m_count &lt; m_max_count) {
QS_END_NOCRIT_PRE_() QS_END_NOCRIT_PRE_()
if (!QXK_ISR_CONTEXT_()) { // not inside ISR? if (!QXK_ISR_CONTEXT_()) { // not inside ISR?
static_cast&lt;void&gt;(QXK_sched_(0U)); // synchronous scheduling static_cast&lt;void&gt;(QXK_sched_()); // synchronous scheduling
} }
} }
} }
@ -11218,7 +11205,7 @@ return signaled;</code>
</operation> </operation>
<!--${QXK::QXMutex::init}--> <!--${QXK::QXMutex::init}-->
<operation name="init" type="void" visibility="0x00" properties="0x00"> <operation name="init" type="void" visibility="0x00" properties="0x00">
<specifiers>noexcept override</specifiers> <specifiers>noexcept</specifiers>
<documentation>//! initialize the QXK priority-ceiling mutex QP::QXMutex <documentation>//! initialize the QXK priority-ceiling mutex QP::QXMutex
//! //!
//! @details //! @details
@ -11242,18 +11229,15 @@ return signaled;</code>
//! the priority and priority-threshold of the holding thread to the //! the priority and priority-threshold of the holding thread to the
//! priority specification in `prioSpec` (see QP::QPrioSpec). //! 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 //! @usage
//! @include qxk_mutex.cpp</documentation> //! @include qxk_mutex.cpp</documentation>
<!--${QXK::QXMutex::init::prioSpec}--> <!--${QXK::QXMutex::init::prioSpec}-->
<parameter name="prioSpec" type="QPrioSpec const"/> <parameter name="prioSpec" type="QPrioSpec const"/>
<code>m_prio = static_cast&lt;std::uint8_t&gt;(prioSpec &amp; 0xFFU); <code>//! @pre preemption-threshold must not be used
m_pthre = static_cast&lt;std::uint8_t&gt;(prioSpec &gt;&gt; 8U); Q_REQUIRE_ID(100, (prioSpec &amp; 0xFF00U) == 0U);
m_prio = static_cast&lt;std::uint8_t&gt;(prioSpec &amp; 0xFFU);
m_pthre = 0U; // preemption-threshold not used
if (prioSpec != 0U) { // priority-ceiling protocol used? if (prioSpec != 0U) { // priority-ceiling protocol used?
register_(); // register this mutex as AO 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) // set the blocking object (this mutex)
curr-&gt;m_temp.obj = QXK_PTR_CAST_(QMState*, this); curr-&gt;m_temp.obj = QXK_PTR_CAST_(QMState*, this);
curr-&gt;teArm_(static_cast&lt;enum_t&gt;(QXK::MUTEX_SIG), nTicks); curr-&gt;teArm_(static_cast&lt;enum_t&gt;(QXK::TIMEOUT_SIG), nTicks);
QS_BEGIN_NOCRIT_PRE_(QS_MTX_BLOCK, curr-&gt;m_prio) QS_BEGIN_NOCRIT_PRE_(QS_MTX_BLOCK, curr-&gt;m_prio)
QS_TIME_PRE_(); // timestamp QS_TIME_PRE_(); // timestamp
@ -11505,7 +11489,7 @@ else { // the mutex is already locked by a different thread
QS_END_NOCRIT_PRE_() QS_END_NOCRIT_PRE_()
// schedule the next thread if multitasking started // schedule the next thread if multitasking started
static_cast&lt;void&gt;(QXK_sched_(0U)); // synchronous scheduling static_cast&lt;void&gt;(QXK_sched_()); // synchronous scheduling
QF_CRIT_X_(); QF_CRIT_X_();
QF_CRIT_EXIT_NOP(); // BLOCK here !!! QF_CRIT_EXIT_NOP(); // BLOCK here !!!
@ -11663,8 +11647,8 @@ if (m_eQueue.m_nFree == 1U) {
} }
// schedule the next thread if multitasking started // schedule the next thread if multitasking started
if (QXK_sched_(0U) != 0U) { // synchronous preemption needed? if (QXK_sched_() != 0U) { // synchronous preemption needed?
QXK_activate_(0U); // synchronously activate basic threads QXK_activate_(); // synchronously activate basic threads
} }
} }
else { // releasing one level of nested mutex lock else { // releasing one level of nested mutex lock
@ -11699,11 +11683,11 @@ bzero(&amp;QXK_attr_, sizeof(QXK_attr_));
QXK_attr_.lockCeil = (QF_MAX_ACTIVE + 1U); // scheduler locked QXK_attr_.lockCeil = (QF_MAX_ACTIVE + 1U); // scheduler locked
// QXK idle AO object (const in ROM) // 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 }; = { nullptr };
// register the idle AO object (cast 'const' away) // register the idle AO object (cast 'const' away)
QActive::registry_[0] = QF_CONST_CAST_(QActive*, QActive::registry_[0] = QF_CONST_CAST_(QActive*,
QXK_PTR_CAST_(QActive const*, &amp;idle_obj[0])); QXK_PTR_CAST_(QActive const*, &amp;idle_ao[0]));
#ifdef QXK_INIT #ifdef QXK_INIT
QXK_INIT(); // port-specific initialization of the QXK kernel 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 QXK_attr_.lockCeil = 0U; // unlock the scheduler
// any active objects need to be scheduled before starting event loop? // any active objects need to be scheduled before starting event loop?
if (QXK_sched_(0U) != 0U) { // synchronous preemption needed? if (QXK_sched_() != 0U) { // synchronous preemption needed?
QXK_activate_(0U); // synchronously activate AOs to process events QXK_activate_(); // synchronously activate AOs to process events
} }
onStartup(); // application-specific startup callback onStartup(); // application-specific startup callback
// produce the QS_QF_RUN trace record // produce the QS_QF_RUN trace record
@ -11735,6 +11720,9 @@ QS_END_NOCRIT_PRE_()
QF_INT_ENABLE(); QF_INT_ENABLE();
QS_SIG_DICTIONARY(QP::QXK::DELAY_SIG, nullptr);
QS_SIG_DICTIONARY(QP::QXK::TIMEOUT_SIG, nullptr);
// the QXK idle loop... // the QXK idle loop...
for (;;) { for (;;) {
QXK::onIdle(); // application-specific QXK idle callback QXK::onIdle(); // application-specific QXK idle callback
@ -11770,15 +11758,18 @@ Q_UNUSED_PAR(stkSize); // not needed in QXK
//! @pre AO cannot be started: //! @pre AO cannot be started:
//! - from an ISR; //! - from an ISR;
//! - the stack storage must NOT be provided //! - 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_()) Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_())
&amp;&amp; (stkSto == nullptr)); &amp;&amp; (stkSto == nullptr)
&amp;&amp; ((prioSpec &amp; 0xFF00U) == 0U));
m_prio = static_cast&lt;std::uint8_t&gt;(prioSpec &amp; 0xFFU); // QF-prio. m_prio = static_cast&lt;std::uint8_t&gt;(prioSpec &amp; 0xFFU); // QF-prio.
m_pthre = static_cast&lt;std::uint8_t&gt;(prioSpec &gt;&gt; 8U); // preemption-thre. m_pthre = 0U; // preemption-threshold NOT used
register_(); // make QF aware of this AO 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_eQueue.init(qSto, qLen); // initialize QEQueue of this AO
m_osObject = nullptr; // no private stack for AO
this-&gt;init(par, m_prio); // take the top-most initial tran. (virtual) this-&gt;init(par, m_prio); // take the top-most initial tran. (virtual)
QS_FLUSH(); // flush the trace buffer to the host 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 // see if this AO needs to be scheduled in case QXK is running
QF_CRIT_STAT_ QF_CRIT_STAT_
QF_CRIT_E_(); QF_CRIT_E_();
if (QXK_sched_(0U) != 0U) { // synchronous preemption needed? if (QXK_attr_.lockCeil &lt;= QF_MAX_ACTIVE) { // scheduler running?
QXK_activate_(0U); // synchronously activate basic threads if (QXK_sched_() != 0U) { // synchronous preemption needed?
QXK_activate_(); // synchronously activate basic threads
}
} }
QF_CRIT_X_();</code> QF_CRIT_X_();</code>
</operation> </operation>
@ -11806,8 +11799,8 @@ QF_CRIT_X_();</code>
<code>{ <code>{
QP::QActive * volatile curr; //!&lt; currently executing thread QP::QActive * volatile curr; //!&lt; currently executing thread
QP::QActive * volatile next; //!&lt; next thread to execute QP::QActive * volatile next; //!&lt; next thread to execute
std::uint8_t volatile actPrio; //!&lt; prio of the active AO QP::QActive * volatile prev; //!&lt; previous thread
std::uint8_t volatile actThre; //!&lt; active preemption-threshold std::uint8_t volatile actPrio; //!&lt; QF-prio of the active AO
std::uint8_t volatile lockCeil; //!&lt; lock preemption-ceiling (0==no-lock) std::uint8_t volatile lockCeil; //!&lt; lock preemption-ceiling (0==no-lock)
std::uint8_t volatile lockHolder; //!&lt; prio of the lock holder std::uint8_t volatile lockHolder; //!&lt; prio of the lock holder
};</code> };</code>
@ -11821,9 +11814,6 @@ QF_CRIT_X_();</code>
<specifiers>noexcept</specifiers> <specifiers>noexcept</specifiers>
<documentation>//! QXK scheduler finds the highest-priority thread ready to run <documentation>//! 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 //! @details
//! The QXK scheduler finds the priority of the highest-priority thread //! The QXK scheduler finds the priority of the highest-priority thread
//! that is ready to run. //! that is ready to run.
@ -11834,13 +11824,14 @@ QF_CRIT_X_();</code>
//! @attention //! @attention
//! QXK_sched_() must be always called with interrupts **disabled** and //! QXK_sched_() must be always called with interrupts **disabled** and
//! returns with interrupts **disabled**.</documentation> //! returns with interrupts **disabled**.</documentation>
<!--${QXK-extern-C::QXK_sched_::asynch}--> <code>std::uint_fast8_t p;
<parameter name="asynch" type="std::uint_fast8_t const"/>
<code>Q_UNUSED_PAR(asynch); // unused when Q_SPY not defined
if (QP::QF::readySet_.isEmpty()) {
p = 0U; // no activation needed
}
else {
// find the highest-prio thread ready to run // find the highest-prio thread ready to run
std::uint_fast8_t p = QP::QF::readySet_.findMax(); p = QP::QF::readySet_.findMax();
if (p &lt;= QXK_attr_.lockCeil) { if (p &lt;= QXK_attr_.lockCeil) {
// priority of the thread holding the lock // priority of the thread holding the lock
p = static_cast&lt;std::uint_fast8_t&gt;( p = static_cast&lt;std::uint_fast8_t&gt;(
@ -11849,88 +11840,40 @@ if (p &lt;= QXK_attr_.lockCeil) {
Q_ASSERT_ID(610, QP::QF::readySet_.hasElement(p)); 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]; QP::QActive * const next = QP::QActive::registry_[p];
// the thread found must be registered in QF // the thread found must be registered in QF
Q_ASSERT_ID(620, next != nullptr); Q_ASSERT_ID(620, next != nullptr);
// is the current thread a basic-thread? // is the current thread a basic-thread?
if (QXK_attr_.curr == nullptr) { if (curr == nullptr) {
// is next a basic-thread? // is the new priority above the active priority?
if (next-&gt;m_osObject == nullptr) { if (p &gt; QXK_attr_.actPrio) {
// is the new priority above the actvie pre-thre?
if (p &gt; QXK_attr_.actThre) {
QXK_attr_.next = next; // set the next AO to activate QXK_attr_.next = next; // set the next AO to activate
if (next-&gt;m_osObject != nullptr) { // is next extended?
QXK_CONTEXT_SWITCH_();
p = 0U; // no activation needed
} }
else { }
else { // below the pre-thre
QXK_attr_.next = nullptr; QXK_attr_.next = nullptr;
p = 0U; // no activation needed 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-&gt;m_prio)
QS_TIME_PRE_(); // timestamp
// prio of the next AO &amp; 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-&gt;m_prio)
QS_TIME_PRE_(); // timestamp
// prio of the next AO &amp; prio of the curr AO
QS_2U8_PRE_(p, QXK_attr_.actPrio);
QS_END_NOCRIT_PRE_()
}
#endif // Q_SPY
QXK_attr_.next = next;
p = 0U; // no activation needed
QXK_CONTEXT_SWITCH_();
}
}
else { // currently executing an extended-thread else { // currently executing an extended-thread
// is the current thread different from the next?
// is the next thread different from the current? if (curr != next) {
if (next != QXK_attr_.curr) {
#ifdef Q_SPY
if (next-&gt;m_prio != 0U) {
if (asynch != 0U) {
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_PREEMPT, next-&gt;m_prio)
QS_TIME_PRE_(); // timestamp
// previous prio &amp; current prio
QS_2U8_PRE_(static_cast&lt;std::uint8_t&gt;(p),
QXK_attr_.curr-&gt;m_prio);
QS_END_NOCRIT_PRE_()
}
else {
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, next-&gt;m_prio)
QS_TIME_PRE_(); // timestamp
// previous prio &amp; current prio
QS_2U8_PRE_(static_cast&lt;std::uint8_t&gt;(p),
QXK_attr_.curr-&gt;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-&gt;m_prio); // previous prio
QS_END_NOCRIT_PRE_()
}
#endif
QXK_attr_.next = next; QXK_attr_.next = next;
p = 0U; // no activation needed
QXK_CONTEXT_SWITCH_(); QXK_CONTEXT_SWITCH_();
} }
else { // next is the same as current else { // next is the same as current
QXK_attr_.next = nullptr; // no need to context-switch QXK_attr_.next = nullptr; // no need to context-switch
p = 0U; // no activation needed
} }
p = 0U; // no activation needed
} }
return p;</code> return p;</code>
</operation> </operation>
@ -11940,9 +11883,6 @@ return p;</code>
<documentation>//! QXK activator activates the next active object. The activated AO preempts <documentation>//! QXK activator activates the next active object. The activated AO preempts
//! the currently executing AOs //! the currently executing AOs
//! //!
//! @param[in] asynch flag conveying the type of activation:
//! != 0 for asynchronous activation and
//! == 0 for synchronous activation
//! @attention //! @attention
//! QXK_activate_() must be always called with interrupts **disabled** and //! QXK_activate_() must be always called with interrupts **disabled** and
//! returns with interrupts **disabled**. //! returns with interrupts **disabled**.
@ -11950,63 +11890,26 @@ return p;</code>
//! @note //! @note
//! The activate function might enable interrupts internally, but it always //! The activate function might enable interrupts internally, but it always
//! returns with interrupts **disabled**.</documentation> //! returns with interrupts **disabled**.</documentation>
<!--${QXK-extern-C::QXK_activate_::asynch}--> <code>std::uint8_t const prio_in = QXK_attr_.actPrio;
<parameter name="asynch" type="std::uint_fast8_t const"/> QP::QActive *next = QXK_attr_.next; // the next AO (basic-thread) to run
<code>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
//! @pre QXK_attr_.next must be valid and the prio must be in range //! @pre QXK_attr_.next must be valid and the prio must be in range
Q_REQUIRE_ID(700, (a != nullptr) &amp;&amp; (prio_in &lt;= QF_MAX_ACTIVE)); Q_REQUIRE_ID(700, (next != nullptr) &amp;&amp; (prio_in &lt;= QF_MAX_ACTIVE));
// QXK Context switch callback defined or QS tracing enabled? // QXK Context switch callback defined or QS tracing enabled?
#if (defined QXK_ON_CONTEXT_SW) || (defined Q_SPY) #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 #endif // QXK_ON_CONTEXT_SW || Q_SPY
// priority and preemption-threshold of the next AO QXK_attr_.next = nullptr; // clear the next AO
std::uint_fast8_t p = static_cast&lt;std::uint_fast8_t&gt;(a-&gt;m_prio); QXK_attr_.curr = nullptr; // current is basic-thread
// priority of the next thread
std::uint_fast8_t p = static_cast&lt;std::uint_fast8_t&gt;(next-&gt;m_prio);
// loop until no more ready-to-run AOs of higher prio than the initial // loop until no more ready-to-run AOs of higher prio than the initial
do { do {
a = QP::QActive::registry_[p]; // obtain the pointer to the AO QXK_attr_.actPrio = static_cast&lt;std::uint8_t&gt;(p); // next active prio
QXK_attr_.actPrio = static_cast&lt;std::uint8_t&gt;(p); // new active prio
QXK_attr_.actThre = QP::QActive::registry_[p]-&gt;m_pthre; // new pthre
QXK_attr_.next = nullptr; // clear the next AO
#ifdef Q_SPY
if ((asynch != 0U) &amp;&amp; (pprev == prio_in)) {
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_PREEMPT, a-&gt;m_prio)
QS_TIME_PRE_(); // timestamp
QS_2U8_PRE_(p, pprev); // next prio &amp; prev prio
QS_END_NOCRIT_PRE_()
}
else {
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a-&gt;m_prio)
QS_TIME_PRE_(); // timestamp
QS_2U8_PRE_(p, pprev); // next prio &amp; 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 &lt;= 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
QF_INT_ENABLE(); // unconditionally enable interrupts QF_INT_ENABLE(); // unconditionally enable interrupts
@ -12016,109 +11919,81 @@ do {
// 2. dispatch the event to the AO's state machine. // 2. dispatch the event to the AO's state machine.
// 3. determine if event is garbage and collect it if so // 3. determine if event is garbage and collect it if so
// //
QP::QEvt const * const e = a-&gt;get_(); QP::QEvt const * const e = next-&gt;get_();
a-&gt;dispatch(e, a-&gt;m_prio); next-&gt;dispatch(e, next-&gt;m_prio);
#if (QF_MAX_EPOOL &gt; 0U) #if (QF_MAX_EPOOL &gt; 0U)
QP::QF::gc(e); QP::QF::gc(e);
#endif #endif
QF_INT_DISABLE(); // unconditionally disable interrupts QF_INT_DISABLE(); // unconditionally disable interrupts
if (a-&gt;m_eQueue.isEmpty()) { // empty queue? if (next-&gt;m_eQueue.isEmpty()) { // empty queue?
QP::QF::readySet_.remove(p); QP::QF::readySet_.remove(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... // find new highest-prio AO ready to run...
p = QP::QF::readySet_.findMax(); p = QP::QF::readySet_.findMax();
a = QP::QActive::registry_[p]; next = QP::QActive::registry_[p];
// the AO must be registered in QF // the AO must be registered in QF
Q_ASSERT_ID(720, a != nullptr); Q_ASSERT_ID(710, next != nullptr);
// is the new priority below the lock ceiling? // is the new priority below the lock ceiling?
if (p &lt;= static_cast&lt;std::uint_fast8_t&gt;(QXK_attr_.lockCeil)) { if (p &lt;= static_cast&lt;std::uint_fast8_t&gt;(QXK_attr_.lockCeil)) {
p = static_cast&lt;std::uint_fast8_t&gt;(QXK_attr_.lockHolder); p = static_cast&lt;std::uint_fast8_t&gt;(QXK_attr_.lockHolder);
if (p != 0U) { if (p != 0U) {
Q_ASSERT_ID(710, QP::QF::readySet_.hasElement(p)); Q_ASSERT_ID(720, QP::QF::readySet_.hasElement(p));
} }
} }
// is the next a basic thread? // is the next a basic thread?
if (a-&gt;m_osObject == nullptr) { if (next-&gt;m_osObject == nullptr) {
// is the new priority above the initial pre-thre? // is the next priority above the initial priority?
if (p &gt; QP::QActive::registry_[prio_in]-&gt;m_pthre) { if (p &gt; QP::QActive::registry_[prio_in]-&gt;m_prio) {
QXK_attr_.next = a; #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 { else {
QXK_attr_.next = nullptr; QXK_attr_.next = nullptr;
p = 0U; // no activation needed p = 0U; // no activation needed
} }
} }
else { // next is the extended thread else { // next is the extended-thread
QXK_attr_.next = next;
#ifdef Q_SPY
if (asynch != 0U) {
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_PREEMPT, a-&gt;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-&gt;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_(); QXK_CONTEXT_SWITCH_();
p = 0U; // no activation needed
} }
} while (p != 0U); // while preemption needed }
} while (p != 0U); // while activation needed
// restore the active priority and preemption-threshold // restore the active priority
QXK_attr_.actPrio = prio_in; QXK_attr_.actPrio = prio_in;
QXK_attr_.actThre = QP::QActive::registry_[prio_in]-&gt;m_pthre;
#if (defined QXK_ON_CONTEXT_SW) || (defined Q_SPY) #if (defined QXK_ON_CONTEXT_SW) || (defined Q_SPY)
if (prio_in != 0U) { // resuming an active object? if (next-&gt;m_osObject == nullptr) {
a = QP::QActive::registry_[prio_in]; // pointer to the preempted AO QXK_contextSw((prio_in == 0U)
? nullptr
#ifdef Q_SPY : QP::QActive::registry_[prio_in]);
if (asynch != 0U) {
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_RESTORE, a-&gt;m_prio)
QS_TIME_PRE_(); // timestamp
QS_2U8_PRE_(prio_in, pprev); // resumed prio &amp; previous prio
QS_END_NOCRIT_PRE_()
} }
else {
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_RESUME, a-&gt;m_prio)
QS_TIME_PRE_(); // timestamp
QS_2U8_PRE_(prio_in, pprev); // resumed prio &amp; previous prio
QS_END_NOCRIT_PRE_()
}
#endif // Q_SPY
}
else { // resuming priority==0 --&gt; 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</code> #endif // QXK_ON_CONTEXT_SW || Q_SPY</code>
</operation> </operation>
<!--${QXK-extern-C::QXK_current}--> <!--${QXK-extern-C::QXK_current}-->
<operation name="QXK_current" type="QP::QActive *" visibility="0x00" properties="0x00"> <operation name="QXK_current" type="QP::QActive *" visibility="0x00" properties="0x00">
<specifiers>noexcept</specifiers> <specifiers>noexcept</specifiers>
<documentation>//! return the currently executing active-object/thread</documentation> <documentation>//! obtain the currently executing active-object/thread
//!
//! @returns
//! pointer to the currently executing active-object/thread</documentation>
<code>//! @pre the QXK kernel must be running <code>//! @pre the QXK kernel must be running
Q_REQUIRE_ID(800, QXK_attr_.lockCeil &lt;= QF_MAX_ACTIVE); Q_REQUIRE_ID(800, QXK_attr_.lockCeil &lt;= QF_MAX_ACTIVE);
@ -12149,6 +12024,51 @@ return curr;</code>
<!--${QXK-extern-C::QXK_stackInit_::stkSize}--> <!--${QXK-extern-C::QXK_stackInit_::stkSize}-->
<parameter name="stkSize" type="std::uint_fast16_t const"/> <parameter name="stkSize" type="std::uint_fast16_t const"/>
</operation> </operation>
<!--${QXK-extern-C::QXK_contextSw}-->
<operation name="QXK_contextSw? defined(Q_SPY) || defined(QXK_ON_CONTEXT_SW)" type="void" visibility="0x00" properties="0x00">
<documentation>//! 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**.</documentation>
<!--${QXK-extern-C::QXK_contextSw::next}-->
<parameter name="next" type="QP::QActive * const"/>
<code>std::uint8_t const prev_prio = (QXK_attr_.prev != nullptr)
? QXK_attr_.prev-&gt;m_prio
: 0U;
std::uint8_t const next_prio = (next != nullptr)
? next-&gt;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</code>
</operation>
<!--${QXK-extern-C::QXK_onContextSw}--> <!--${QXK-extern-C::QXK_onContextSw}-->
<operation name="QXK_onContextSw?def QXK_ON_CONTEXT_SW" type="void" visibility="0x00" properties="0x00"> <operation name="QXK_onContextSw?def QXK_ON_CONTEXT_SW" type="void" visibility="0x00" properties="0x00">
<documentation>//! QXK context switch callback (customized in BSPs for QXK) <documentation>//! 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 // remove this thread from the QF
QP::QActive::registry_[p] = nullptr; QP::QActive::registry_[p] = nullptr;
QP::QF::readySet_.remove(p); QP::QF::readySet_.remove(p);
static_cast&lt;void&gt;(QXK_sched_(0U)); // synchronous scheduling static_cast&lt;void&gt;(QXK_sched_()); // synchronous scheduling
QF_CRIT_X_();</code> QF_CRIT_X_();</code>
</operation> </operation>
<!--${QXK-extern-C::QXK_PTR_CAST_}--> <!--${QXK-extern-C::QXK_PTR_CAST_}-->
@ -12301,8 +12221,8 @@ QF_CRIT_X_();</code>
QF::readySet_.insert( \ QF::readySet_.insert( \
static_cast&lt;std::uint_fast8_t&gt;((me_)-&gt;m_prio)); \ static_cast&lt;std::uint_fast8_t&gt;((me_)-&gt;m_prio)); \
if (!QXK_ISR_CONTEXT_()) { \ if (!QXK_ISR_CONTEXT_()) { \
if (QXK_sched_(0U) != 0U) { \ if (QXK_sched_() != 0U) { \
QXK_activate_(0U); \ QXK_activate_(); \
} \ } \
} \ } \
} while (false)</code> } while (false)</code>
@ -12328,7 +12248,7 @@ QF_CRIT_X_();</code>
// major version number, Y is a 1-digit minor version number, and Z is // major version number, Y is a 1-digit minor version number, and Z is
// a 1-digit release number. // a 1-digit release number.
// //
#define QP_VERSION 710U #define QP_VERSION 712U
//! The current QP version as a zero terminated string literal. //! The current QP version as a zero terminated string literal.
// //
@ -12337,10 +12257,10 @@ QF_CRIT_X_();</code>
// major version number, Y is a 1-digit minor version number, and Z is // major version number, Y is a 1-digit minor version number, and Z is
// a 1-digit release number. // a 1-digit release number.
// //
#define QP_VERSION_STR &quot;7.1.0&quot; #define QP_VERSION_STR &quot;7.1.2&quot;
//! Encrypted current QP release (7.1.0) and date (2022-08-30) //! Encrypted current QP release (7.1.2) and date (2022-10-07)
#define QP_RELEASE 0x7C600159U #define QP_RELEASE 0x7C44FF47U
//============================================================================ //============================================================================
// Global namespace... // Global namespace...

View File

@ -85,7 +85,7 @@ QTimeEvt::QTimeEvt(
m_interval(0U) m_interval(0U)
{ {
//! @pre The signal must be valid and the tick rate in range //! @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)); && (tickRate < QF_MAX_TICK_RATE));
#ifndef Q_EVT_CTOR #ifndef Q_EVT_CTOR

View File

@ -123,8 +123,8 @@ void schedUnlock(QSchedStatus const stat) noexcept {
QS_BEGIN_NOCRIT_PRE_(QS_SCHED_UNLOCK, 0U) QS_BEGIN_NOCRIT_PRE_(QS_SCHED_UNLOCK, 0U)
QS_TIME_PRE_(); // timestamp QS_TIME_PRE_(); // timestamp
QS_2U8_PRE_(lockCeil, // current lock ceiling (old) // current lock ceiling (old), previous lock ceiling (new)
prevCeil); // previous lock ceiling (new) QS_2U8_PRE_(lockCeil, prevCeil);
QS_END_NOCRIT_PRE_() QS_END_NOCRIT_PRE_()
// restore the previous lock ceiling and lock holder // 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 // find if any AOs should be run after unlocking the scheduler
if (QK_sched_() != 0U) { // synchronous preemption needed? 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_(); QF_CRIT_X_();
@ -179,7 +179,7 @@ int_t run() {
// any active objects need to be scheduled before starting event loop? // any active objects need to be scheduled before starting event loop?
if (QK_sched_() != 0U) { // synchronous preemption needed? 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 onStartup(); // application-specific startup callback
@ -238,7 +238,7 @@ void QActive::start(
QF_CRIT_STAT_ QF_CRIT_STAT_
QF_CRIT_E_(); QF_CRIT_E_();
if (QK_sched_() != 0U) { // synchronous preemption needed? if (QK_sched_() != 0U) { // synchronous preemption needed?
QK_activate_(0U); // synchronously activate AOs QK_activate_(); // synchronously activate AOs
} }
QF_CRIT_X_(); QF_CRIT_X_();
} }
@ -255,28 +255,32 @@ QK_Attr QK_attr_;
//${QK-extern-C::QK_sched_} .................................................. //${QK-extern-C::QK_sched_} ..................................................
std::uint_fast8_t QK_sched_() noexcept { std::uint_fast8_t QK_sched_() noexcept {
std::uint_fast8_t p;
if (QP::QF::readySet_.isEmpty()) {
p = 0U; // no activation needed
}
else {
// find the highest-prio AO with non-empty event queue // find the highest-prio AO with non-empty event queue
std::uint_fast8_t p = QP::QF::readySet_.findMax(); p = QP::QF::readySet_.findMax();
// is the AO's priority below the active preemption-threshold? // is the AO's priority below the active preemption-threshold?
if (p <= QK_attr_.actThre) { if (p <= QK_attr_.actThre) {
p = 0U; // no preemption needed p = 0U; // no activation needed
} }
// is the AO's priority below the lock preemption-ceiling? // is the AO's priority below the lock preemption-ceiling?
else if (p <= QK_attr_.lockCeil) { else if (p <= QK_attr_.lockCeil) {
p = 0U; // no preemption needed p = 0U; // no activation needed
} }
else { else {
Q_ASSERT_ID(410, p <= QF_MAX_ACTIVE); QK_attr_.nextPrio = static_cast<std::uint8_t>(p);
QK_attr_.nextPrio = static_cast<std::uint8_t>(p); // next AO to run }
} }
return p; return p;
} }
//${QK-extern-C::QK_activate_} ............................................... //${QK-extern-C::QK_activate_} ...............................................
void QK_activate_(std::uint_fast8_t const asynch) noexcept { void QK_activate_() noexcept {
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 std::uint_fast8_t p = QK_attr_.nextPrio; // next prio to run
QK_attr_.nextPrio = 0U; // clear for the next time 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<std::uint8_t>(p); QK_attr_.actPrio = static_cast<std::uint8_t>(p);
QK_attr_.actThre = QP::QActive::registry_[p]->m_pthre; QK_attr_.actThre = QP::QActive::registry_[p]->m_pthre;
#ifdef Q_SPY #if (defined QK_ON_CONTEXT_SW) || (defined Q_SPY)
if ((asynch != 0U) && (pprev == prio_in)) { if (p != pprev) { // changing threads?
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 {
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a->m_prio) QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a->m_prio)
QS_TIME_PRE_(); // timestamp QS_TIME_PRE_(); // timestamp
QS_2U8_PRE_(p, // priority of the scheduled AO QS_2U8_PRE_(p, // priority of the scheduled AO
pprev); // previous priority pprev); // previous priority
QS_END_NOCRIT_PRE_() 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 #ifdef QK_ON_CONTEXT_SW
// context-switch callback // context-switch callback
@ -341,6 +334,7 @@ void QK_activate_(std::uint_fast8_t const asynch) noexcept {
#if (QF_MAX_EPOOL > 0U) #if (QF_MAX_EPOOL > 0U)
QP::QF::gc(e); QP::QF::gc(e);
#endif #endif
// determine the next highest-priority AO ready to run... // determine the next highest-priority AO ready to run...
QF_INT_DISABLE(); // unconditionally disable interrupts QF_INT_DISABLE(); // unconditionally disable interrupts
@ -348,20 +342,25 @@ void QK_activate_(std::uint_fast8_t const asynch) noexcept {
QP::QF::readySet_.remove(p); QP::QF::readySet_.remove(p);
} }
if (QP::QF::readySet_.isEmpty()) {
p = 0U; // no activation needed
}
else {
// find new highest-prio AO ready to run... // find new highest-prio AO ready to run...
p = QP::QF::readySet_.findMax(); p = QP::QF::readySet_.findMax();
// is the new priority below the initial preemption-threshold? // is the new priority below the initial preemption-threshold?
if (p <= QP::QActive::registry_[prio_in]->m_pthre) { if (p <= QP::QActive::registry_[prio_in]->m_pthre) {
p = 0U; // no preemption needed p = 0U; // no activation needed
} }
// is the AO's priority below the lock preemption-ceiling? // is the AO's priority below the lock preemption-ceiling?
else if (p <= QK_attr_.lockCeil) { else if (p <= QK_attr_.lockCeil) {
p = 0U; // no preemption needed p = 0U; // no activation needed
} }
else { else {
Q_ASSERT_ID(510, p <= QF_MAX_ACTIVE); Q_ASSERT_ID(510, p <= QF_MAX_ACTIVE);
} }
}
} while (p != 0U); } while (p != 0U);
// restore the active priority and preemption-threshold // restore the active priority and preemption-threshold
@ -372,23 +371,12 @@ void QK_activate_(std::uint_fast8_t const asynch) noexcept {
if (prio_in != 0U) { // resuming an active object? if (prio_in != 0U) { // resuming an active object?
a = QP::QActive::registry_[prio_in]; // pointer to preempted AO a = QP::QActive::registry_[prio_in]; // pointer to preempted AO
#ifdef Q_SPY QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_NEXT, a->m_prio)
if (asynch != 0U) {
QS_BEGIN_NOCRIT_PRE_(QP::QS_SCHED_RESTORE, a->m_prio)
QS_TIME_PRE_(); // timestamp QS_TIME_PRE_(); // timestamp
QS_2U8_PRE_(prio_in, // priority of the resumed AO // priority of the resumed AO, previous priority
pprev); // previous priority QS_2U8_PRE_(prio_in, pprev);
QS_END_NOCRIT_PRE_() 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
}
else { // resuming priority==0 --> idle else { // resuming priority==0 --> idle
a = nullptr; // QK idle loop a = nullptr; // QK idle loop

View File

@ -136,8 +136,8 @@ void schedUnlock(QSchedStatus const stat) noexcept {
QXK_attr_.lockHolder = static_cast<std::uint8_t>(stat & 0xFFU); QXK_attr_.lockHolder = static_cast<std::uint8_t>(stat & 0xFFU);
// find the highest-prio thread ready to run // find the highest-prio thread ready to run
if (QXK_sched_(0U) != 0U) { // synchronous preemption needed? if (QXK_sched_() != 0U) { // synchronous preemption needed?
QXK_activate_(0U); // synchronously activate unlocked AOs QXK_activate_(); // synchronously activate unlocked AOs
} }
QF_CRIT_X_(); QF_CRIT_X_();
@ -166,11 +166,11 @@ void init() {
QXK_attr_.lockCeil = (QF_MAX_ACTIVE + 1U); // scheduler locked QXK_attr_.lockCeil = (QF_MAX_ACTIVE + 1U); // scheduler locked
// QXK idle AO object (const in ROM) // 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 }; = { nullptr };
// register the idle AO object (cast 'const' away) // register the idle AO object (cast 'const' away)
QActive::registry_[0] = QF_CONST_CAST_(QActive*, 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 #ifdef QXK_INIT
QXK_INIT(); // port-specific initialization of the QXK kernel QXK_INIT(); // port-specific initialization of the QXK kernel
@ -189,9 +189,10 @@ int_t run() {
QXK_attr_.lockCeil = 0U; // unlock the scheduler QXK_attr_.lockCeil = 0U; // unlock the scheduler
// any active objects need to be scheduled before starting event loop? // any active objects need to be scheduled before starting event loop?
if (QXK_sched_(0U) != 0U) { // synchronous preemption needed? if (QXK_sched_() != 0U) { // synchronous preemption needed?
QXK_activate_(0U); // synchronously activate AOs to process events QXK_activate_(); // synchronously activate AOs to process events
} }
onStartup(); // application-specific startup callback onStartup(); // application-specific startup callback
// produce the QS_QF_RUN trace record // produce the QS_QF_RUN trace record
@ -200,6 +201,9 @@ int_t run() {
QF_INT_ENABLE(); QF_INT_ENABLE();
QS_SIG_DICTIONARY(QP::QXK::DELAY_SIG, nullptr);
QS_SIG_DICTIONARY(QP::QXK::TIMEOUT_SIG, nullptr);
// the QXK idle loop... // the QXK idle loop...
for (;;) { for (;;) {
QXK::onIdle(); // application-specific QXK idle callback QXK::onIdle(); // application-specific QXK idle callback
@ -233,15 +237,18 @@ void QActive::start(
//! @pre AO cannot be started: //! @pre AO cannot be started:
//! - from an ISR; //! - from an ISR;
//! - the stack storage must NOT be provided //! - 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_()) 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_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 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_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) this->init(par, m_prio); // take the top-most initial tran. (virtual)
QS_FLUSH(); // flush the trace buffer to the host 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 // see if this AO needs to be scheduled in case QXK is running
QF_CRIT_STAT_ QF_CRIT_STAT_
QF_CRIT_E_(); QF_CRIT_E_();
if (QXK_sched_(0U) != 0U) { // synchronous preemption needed? if (QXK_attr_.lockCeil <= QF_MAX_ACTIVE) { // scheduler running?
QXK_activate_(0U); // synchronously activate basic threads if (QXK_sched_() != 0U) { // synchronous preemption needed?
QXK_activate_(); // synchronously activate basic threads
}
} }
QF_CRIT_X_(); QF_CRIT_X_();
} }
@ -266,12 +275,15 @@ extern "C" {
QXK_Attr QXK_attr_; QXK_Attr QXK_attr_;
//${QXK-extern-C::QXK_sched_} ................................................ //${QXK-extern-C::QXK_sched_} ................................................
std::uint_fast8_t QXK_sched_(std::uint_fast8_t const asynch) noexcept { std::uint_fast8_t QXK_sched_() noexcept {
Q_UNUSED_PAR(asynch); // unused when Q_SPY not defined std::uint_fast8_t p;
if (QP::QF::readySet_.isEmpty()) {
p = 0U; // no activation needed
}
else {
// find the highest-prio thread ready to run // find the highest-prio thread ready to run
std::uint_fast8_t p = QP::QF::readySet_.findMax(); p = QP::QF::readySet_.findMax();
if (p <= QXK_attr_.lockCeil) { if (p <= QXK_attr_.lockCeil) {
// priority of the thread holding the lock // priority of the thread holding the lock
p = static_cast<std::uint_fast8_t>( p = static_cast<std::uint_fast8_t>(
@ -280,149 +292,66 @@ std::uint_fast8_t QXK_sched_(std::uint_fast8_t const asynch) noexcept {
Q_ASSERT_ID(610, QP::QF::readySet_.hasElement(p)); 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]; QP::QActive * const next = QP::QActive::registry_[p];
// the thread found must be registered in QF // the thread found must be registered in QF
Q_ASSERT_ID(620, next != nullptr); Q_ASSERT_ID(620, next != nullptr);
// is the current thread a basic-thread? // is the current thread a basic-thread?
if (QXK_attr_.curr == nullptr) { if (curr == nullptr) {
// is next a basic-thread? // is the new priority above the active priority?
if (next->m_osObject == nullptr) { if (p > QXK_attr_.actPrio) {
// is the new priority above the actvie pre-thre?
if (p > QXK_attr_.actThre) {
QXK_attr_.next = next; // set the next AO to activate 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 { }
else { // below the pre-thre
QXK_attr_.next = nullptr; QXK_attr_.next = nullptr;
p = 0U; // no activation needed 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;
p = 0U; // no activation needed
QXK_CONTEXT_SWITCH_();
}
}
else { // currently executing an extended-thread else { // currently executing an extended-thread
// is the current thread different from the next?
// is the next thread different from the current? if (curr != next) {
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
QXK_attr_.next = next; QXK_attr_.next = next;
p = 0U; // no activation needed
QXK_CONTEXT_SWITCH_(); QXK_CONTEXT_SWITCH_();
} }
else { // next is the same as current else { // next is the same as current
QXK_attr_.next = nullptr; // no need to context-switch QXK_attr_.next = nullptr; // no need to context-switch
p = 0U; // no activation needed
} }
p = 0U; // no activation needed
} }
return p; return p;
} }
//${QXK-extern-C::QXK_activate_} ............................................. //${QXK-extern-C::QXK_activate_} .............................................
void QXK_activate_(std::uint_fast8_t const asynch) noexcept { void QXK_activate_() noexcept {
Q_UNUSED_PAR(asynch); // unused when Q_SPY not defined
std::uint8_t const prio_in = QXK_attr_.actPrio; 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 //! @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? // QXK Context switch callback defined or QS tracing enabled?
#if (defined QXK_ON_CONTEXT_SW) || (defined Q_SPY) #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 #endif // QXK_ON_CONTEXT_SW || Q_SPY
// priority and preemption-threshold of the next AO QXK_attr_.next = nullptr; // clear the next AO
std::uint_fast8_t p = static_cast<std::uint_fast8_t>(a->m_prio); 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 // loop until no more ready-to-run AOs of higher prio than the initial
do { do {
a = QP::QActive::registry_[p]; // obtain the pointer to the AO QXK_attr_.actPrio = static_cast<std::uint8_t>(p); // next active prio
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
QF_INT_ENABLE(); // unconditionally enable interrupts 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. // 2. dispatch the event to the AO's state machine.
// 3. determine if event is garbage and collect it if so // 3. determine if event is garbage and collect it if so
// //
QP::QEvt const * const e = a->get_(); QP::QEvt const * const e = next->get_();
a->dispatch(e, a->m_prio); next->dispatch(e, next->m_prio);
#if (QF_MAX_EPOOL > 0U) #if (QF_MAX_EPOOL > 0U)
QP::QF::gc(e); QP::QF::gc(e);
#endif #endif
QF_INT_DISABLE(); // unconditionally disable interrupts 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); QP::QF::readySet_.remove(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... // find new highest-prio AO ready to run...
p = QP::QF::readySet_.findMax(); p = QP::QF::readySet_.findMax();
a = QP::QActive::registry_[p]; next = QP::QActive::registry_[p];
// the AO must be registered in QF // the AO must be registered in QF
Q_ASSERT_ID(720, a != nullptr); Q_ASSERT_ID(710, next != nullptr);
// is the new priority below the lock ceiling? // is the new priority below the lock ceiling?
if (p <= static_cast<std::uint_fast8_t>(QXK_attr_.lockCeil)) { if (p <= static_cast<std::uint_fast8_t>(QXK_attr_.lockCeil)) {
p = static_cast<std::uint_fast8_t>(QXK_attr_.lockHolder); p = static_cast<std::uint_fast8_t>(QXK_attr_.lockHolder);
if (p != 0U) { if (p != 0U) {
Q_ASSERT_ID(710, QP::QF::readySet_.hasElement(p)); Q_ASSERT_ID(720, QP::QF::readySet_.hasElement(p));
} }
} }
// is the next a basic thread? // is the next a basic thread?
if (a->m_osObject == nullptr) { if (next->m_osObject == nullptr) {
// is the new priority above the initial pre-thre? // is the next priority above the initial priority?
if (p > QP::QActive::registry_[prio_in]->m_pthre) { if (p > QP::QActive::registry_[prio_in]->m_prio) {
QXK_attr_.next = a; #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 { else {
QXK_attr_.next = nullptr; QXK_attr_.next = nullptr;
p = 0U; // no activation needed p = 0U; // no activation needed
} }
} }
else { // next is the extended thread else { // next is the extended-thread
QXK_attr_.next = next;
#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_(); QXK_CONTEXT_SWITCH_();
p = 0U; // no activation needed
} }
} while (p != 0U); // while preemption needed }
} while (p != 0U); // while activation needed
// restore the active priority and preemption-threshold // restore the active priority
QXK_attr_.actPrio = prio_in; 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 (defined QXK_ON_CONTEXT_SW) || (defined Q_SPY)
if (prio_in != 0U) { // resuming an active object? if (next->m_osObject == nullptr) {
a = QP::QActive::registry_[prio_in]; // pointer to the preempted AO QXK_contextSw((prio_in == 0U)
? nullptr
#ifdef Q_SPY : QP::QActive::registry_[prio_in]);
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
}
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 #endif // QXK_ON_CONTEXT_SW || Q_SPY
} }
@ -552,6 +450,41 @@ QP::QActive * QXK_current() noexcept {
return curr; 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_} ........................................... //${QXK-extern-C::QXK_threadExit_} ...........................................
void QXK_threadExit_() { void QXK_threadExit_() {
QF_CRIT_STAT_ QF_CRIT_STAT_
@ -573,7 +506,7 @@ void QXK_threadExit_() {
// remove this thread from the QF // remove this thread from the QF
QP::QActive::registry_[p] = nullptr; QP::QActive::registry_[p] = nullptr;
QP::QF::readySet_.remove(p); QP::QF::readySet_.remove(p);
static_cast<void>(QXK_sched_(0U)); // synchronous scheduling static_cast<void>(QXK_sched_()); // synchronous scheduling
QF_CRIT_X_(); QF_CRIT_X_();
} }
//$enddef${QXK-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //$enddef${QXK-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -79,8 +79,11 @@ QXMutex::QXMutex()
//${QXK::QXMutex::init} ...................................................... //${QXK::QXMutex::init} ......................................................
void QXMutex::init(QPrioSpec const prioSpec) noexcept { 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<std::uint8_t>(prioSpec & 0xFFU); m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU);
m_pthre = static_cast<std::uint8_t>(prioSpec >> 8U); m_pthre = 0U; // preemption-threshold not used
if (prioSpec != 0U) { // priority-ceiling protocol used? if (prioSpec != 0U) { // priority-ceiling protocol used?
register_(); // register this mutex as AO 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) // set the blocking object (this mutex)
curr->m_temp.obj = QXK_PTR_CAST_(QMState*, this); 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_BEGIN_NOCRIT_PRE_(QS_MTX_BLOCK, curr->m_prio)
QS_TIME_PRE_(); // timestamp QS_TIME_PRE_(); // timestamp
@ -291,7 +294,7 @@ bool QXMutex::lock(std::uint_fast16_t const nTicks) noexcept {
QS_END_NOCRIT_PRE_() QS_END_NOCRIT_PRE_()
// schedule the next thread if multitasking started // 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_X_();
QF_CRIT_EXIT_NOP(); // BLOCK here !!! QF_CRIT_EXIT_NOP(); // BLOCK here !!!
@ -432,8 +435,8 @@ void QXMutex::unlock() noexcept {
} }
// schedule the next thread if multitasking started // schedule the next thread if multitasking started
if (QXK_sched_(0U) != 0U) { // synchronous preemption needed? if (QXK_sched_() != 0U) { // synchronous preemption needed?
QXK_activate_(0U); // synchronously activate basic threads QXK_activate_(); // synchronously activate basic threads
} }
} }
else { // releasing one level of nested mutex lock else { // releasing one level of nested mutex lock

View File

@ -125,7 +125,7 @@ bool QXSemaphore::wait(std::uint_fast16_t const nTicks) noexcept {
// remember the blocking object (this semaphore) // remember the blocking object (this semaphore)
curr->m_temp.obj = QXK_PTR_CAST_(QMState*, this); 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_BEGIN_NOCRIT_PRE_(QS_SEM_BLOCK, curr->m_prio)
QS_TIME_PRE_(); // timestamp QS_TIME_PRE_(); // timestamp
@ -134,7 +134,7 @@ bool QXSemaphore::wait(std::uint_fast16_t const nTicks) noexcept {
QS_END_NOCRIT_PRE_() QS_END_NOCRIT_PRE_()
// schedule the next thread if multitasking started // 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_X_();
QF_CRIT_EXIT_NOP(); // BLOCK here !!! QF_CRIT_EXIT_NOP(); // BLOCK here !!!
@ -260,7 +260,7 @@ bool QXSemaphore::signal() noexcept {
QS_END_NOCRIT_PRE_() QS_END_NOCRIT_PRE_()
if (!QXK_ISR_CONTEXT_()) { // not inside ISR? if (!QXK_ISR_CONTEXT_()) { // not inside ISR?
static_cast<void>(QXK_sched_(0U)); // synchronous scheduling static_cast<void>(QXK_sched_()); // synchronous scheduling
} }
} }
} }

View File

@ -163,10 +163,10 @@ QEvt const * QXThread::queueGet(std::uint_fast16_t const nTicks) noexcept {
// remember the blocking object (the thread's queue) // remember the blocking object (the thread's queue)
thr->m_temp.obj = QXK_PTR_CAST_(QMState*, &thr->m_eQueue); 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( QF::readySet_.remove(
static_cast<std::uint_fast8_t>(thr->m_prio)); 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_X_();
QF_CRIT_EXIT_NOP(); // BLOCK here QF_CRIT_EXIT_NOP(); // BLOCK here
@ -269,10 +269,13 @@ void QXThread::start(
//! - NOT be called from an ISR; //! - NOT be called from an ISR;
//! - the stack storage must be provided; //! - the stack storage must be provided;
//! - the thread must be instantiated (see #QXThread). //! - 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_()) Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_())
&& (stkSto != nullptr) && (stkSto != nullptr)
&& (stkSize != 0U) && (stkSize != 0U)
&& (m_state.act == nullptr)); && (m_state.act == nullptr)
&& ((prioSpec & 0xFF00U) == 0U));
// is storage for the queue buffer provided? // is storage for the queue buffer provided?
if (qSto != nullptr) { if (qSto != nullptr) {
@ -284,7 +287,7 @@ void QXThread::start(
QXK_stackInit_(this, m_temp.thr, stkSto, stkSize); QXK_stackInit_(this, m_temp.thr, stkSto, stkSize);
m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU); // QF-prio. 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 register_(); // make QF aware of this AO
// the new thread is not blocked on any object // the new thread is not blocked on any object
@ -296,7 +299,9 @@ void QXThread::start(
QF::readySet_.insert(static_cast<std::uint_fast8_t>(m_prio)); QF::readySet_.insert(static_cast<std::uint_fast8_t>(m_prio));
// see if this thread needs to be scheduled in case QXK is running // 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_(); QF_CRIT_X_();
} }
@ -386,7 +391,7 @@ bool QXThread::post_(
QF::readySet_.insert( QF::readySet_.insert(
static_cast<std::uint_fast8_t>(m_prio)); static_cast<std::uint_fast8_t>(m_prio));
if (!QXK_ISR_CONTEXT_()) { if (!QXK_ISR_CONTEXT_()) {
static_cast<void>(QXK_sched_(0U)); static_cast<void>(QXK_sched_());
} }
} }
} }
@ -446,7 +451,7 @@ void QXThread::block_() const noexcept {
//! @pre the thread holding the lock cannot block! //! @pre the thread holding the lock cannot block!
Q_REQUIRE_ID(600, (QXK_attr_.lockHolder != m_prio)); Q_REQUIRE_ID(600, (QXK_attr_.lockHolder != m_prio));
QF::readySet_.remove(static_cast<std::uint_fast8_t>(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
} }
//${QXK::QXThread::unblock_} ................................................. //${QXK::QXThread::unblock_} .................................................
@ -456,7 +461,7 @@ void QXThread::unblock_() const noexcept {
if ((!QXK_ISR_CONTEXT_()) // not inside ISR? if ((!QXK_ISR_CONTEXT_()) // not inside ISR?
&& (QActive::registry_[0] != nullptr)) // kernel started? && (QActive::registry_[0] != nullptr)) // kernel started?
{ {
static_cast<void>(QXK_sched_(0U)); // synchronous scheduling static_cast<void>(QXK_sched_()); // synchronous scheduling
} }
} }

View File

@ -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("<HHHH",
Q_PRIO(1,3), Q_PRIO(2,3), Q_PRIO(3,3), Q_PRIO(4,4)))
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-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")

View File

@ -1,7 +1,7 @@
//============================================================================ //============================================================================
// Product: BSP for system-testing QXK // Product: BSP for system-testing QXK
// Last updated for version 7.1.1 // Last updated for version 7.1.2
// Last updated on 2022-09-04 // Last updated on 2022-10-06
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// ------------------------ // ------------------------
@ -36,12 +36,11 @@
namespace BSP { namespace BSP {
enum { TICKS_PER_SEC = 100 };
void init(void); void init(void);
void terminate(int16_t const result); void terminate(int16_t const result);
// for testing... // for testing...
void trace(QP::QActive const *thr, char const *msg);
void wait4PB1(void); void wait4PB1(void);
void ledOn(void); void ledOn(void);
void ledOff(void); void ledOff(void);
@ -50,11 +49,12 @@ void trigISR(void);
} // namespace BSP } // namespace BSP
enum TestSignals { 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 MAX_PUB_SIG, // the last published signal
TIMEOUT_SIG,
TRIG_SIG,
MAX_SIG // the last signal MAX_SIG // the last signal
}; };

View File

@ -1,7 +1,7 @@
//============================================================================ //============================================================================
// Product: BSP for system-testing QK, EFM32-SLSTK3401A board // Product: BSP for system-testing QK, EFM32-SLSTK3401A board
// Last updated for version 7.1.1 // Last updated for version 7.1.2
// Last updated on 2022-09-04 // Last updated on 2022-10-06
// //
// Q u a n t u m L e a P s // 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_SysTick_Handler = { 0U };
static QP::QSpyId const l_test_ISR = { 0U }; static QP::QSpyId const l_test_ISR = { 0U };
static USART_TypeDef * const l_USART0 = ((USART_TypeDef *)(0x40010000UL));
enum AppRecords { // application-specific trace records enum AppRecords { // application-specific trace records
CONTEXT_SW = QP::QS_USER, CONTEXT_SW = QP::QS_USER,
COMMAND_STAT TRACE_MSG
}; };
#endif #endif
@ -90,8 +88,8 @@ void GPIO_EVEN_IRQHandler(void) {
QK_ISR_ENTRY(); // inform QK about entering an ISR QK_ISR_ENTRY(); // inform QK about entering an ISR
// for testing... // for testing...
QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), // for testing... static QP::QEvt const t1 = { TEST1_SIG, 0U, 0U };
&BSP::l_test_ISR); QP::QF::PUBLISH(&t1, &BSP::l_test_ISR);
QK_ISR_EXIT(); // inform QK about exiting an 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_OBJ_DICTIONARY(&l_test_ISR);
QS_USR_DICTIONARY(CONTEXT_SW); 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) { void BSP::ledOn(void) {
@ -145,8 +147,11 @@ void BSP::trigISR(void) {
NVIC_SetPendingIRQ(GPIO_EVEN_IRQn); NVIC_SetPendingIRQ(GPIO_EVEN_IRQn);
} }
//............................................................................ //............................................................................
void BSP::terminate(int16_t result) { void BSP::trace(QP::QActive const *thr, char const *msg) {
(void)result; QS_BEGIN_ID(TRACE_MSG, 0U)
QS_OBJ(thr);
QS_STR(msg);
QS_END()
} }
// namespace QP ============================================================== // namespace QP ==============================================================
@ -175,16 +180,6 @@ void QF::onStartup(void) {
void QF::onCleanup(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) { void QK::onIdle(void) {
#ifdef Q_SPY #ifdef Q_SPY
QS::rxParse(); // parse all the received bytes QS::rxParse(); // parse all the received bytes
@ -199,7 +194,6 @@ void QK::onIdle(void) {
} }
// QS callbacks ============================================================== // QS callbacks ==============================================================
#ifdef Q_SPY
//............................................................................ //............................................................................
void QTimeEvt::tick1_( void QTimeEvt::tick1_(
uint_fast8_t const tickRate, uint_fast8_t const tickRate,
@ -211,8 +205,21 @@ void QTimeEvt::tick1_(
QF_INT_ENABLE(); QF_INT_ENABLE();
} }
#endif // Q_SPY
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
} // namespace QP } // 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"

View File

@ -1,7 +1,7 @@
//============================================================================ //============================================================================
// Product: BSP for system-testing QK kernel, NUCLEO-L053R8 board // Product: BSP for system-testing QK kernel, NUCLEO-L053R8 board
// Last updated for version 7.1.1 // Last updated for version 7.1.2
// Last updated on 2022-09-04 // Last updated on 2022-10-06
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// ------------------------ // ------------------------
@ -57,7 +57,7 @@ namespace BSP {
enum AppRecords { // application-specific trace records enum AppRecords { // application-specific trace records
CONTEXT_SW = QP::QS_USER, CONTEXT_SW = QP::QS_USER,
COMMAND_STAT TRACE_MSG
}; };
#endif #endif
@ -83,8 +83,8 @@ void EXTI0_1_IRQHandler(void) {
QK_ISR_ENTRY(); // inform QK about entering an ISR QK_ISR_ENTRY(); // inform QK about entering an ISR
// for testing... // for testing...
QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), // for testing... static QP::QEvt const t1 = { TEST1_SIG, 0U, 0U };
&BSP::l_test_ISR); QP::QF::PUBLISH(&t1, &BSP::l_test_ISR);
QK_ISR_EXIT(); // inform QK about exiting an 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_OBJ_DICTIONARY(&l_test_ISR);
QS_USR_DICTIONARY(CONTEXT_SW); 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) { void BSP::ledOn(void) {
@ -140,8 +144,11 @@ void BSP::trigISR(void) {
NVIC_SetPendingIRQ(EXTI0_1_IRQn); NVIC_SetPendingIRQ(EXTI0_1_IRQn);
} }
//............................................................................ //............................................................................
void BSP::terminate(int16_t result) { void BSP::trace(QP::QActive const *thr, char const *msg) {
(void)result; QS_BEGIN_ID(TRACE_MSG, 0U)
QS_OBJ(thr);
QS_STR(msg);
QS_END()
} }
// namespace QP ============================================================== // namespace QP ==============================================================
@ -170,16 +177,6 @@ void QF::onStartup(void) {
void QF::onCleanup(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) { void QK::onIdle(void) {
#ifdef Q_SPY #ifdef Q_SPY
QS::rxParse(); // parse all the received bytes QS::rxParse(); // parse all the received bytes
@ -194,7 +191,6 @@ void QK::onIdle(void) {
} }
// QS callbacks ============================================================== // QS callbacks ==============================================================
#ifdef Q_SPY
//............................................................................ //............................................................................
void QTimeEvt::tick1_( void QTimeEvt::tick1_(
uint_fast8_t const tickRate, uint_fast8_t const tickRate,
@ -206,8 +202,21 @@ void QTimeEvt::tick1_(
QF_INT_ENABLE(); QF_INT_ENABLE();
} }
#endif // Q_SPY
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
} // namespace QP } // 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"

View File

@ -1,7 +1,7 @@
############################################################################## ##############################################################################
# Product: Makefile for SYSTEM-Level tests of QP/C++ on EMF32, GNU-ARM # Product: Makefile for SYSTEM-Level tests of QP/C++ on EMF32, GNU-ARM
# Last Updated for Version: 7.1.1 # Last Updated for Version: 7.1.2
# Date of the Last Update: 2022-09-05 # Date of the Last Update: 2022-10-05
# #
# Q u a n t u m L e a P s # 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 HOST=localhost:7705 # connect to host:port
# make -f make_efm32 norun # only make but not run the tests # make -f make_efm32 norun # only make but not run the tests
# make -f make_efm32 clean # cleanup the build # make -f make_efm32 clean # cleanup the build
# make -f make_efm32 debug # only run tests in DEBUG mode
# #
# NOTE: # NOTE:
# To use this Makefile on Windows, you will need the GNU make utility, which # 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 name, target name, target directory:
# #
PROJECT := test_pts PROJECT := test_sched
TARGET := efm32 TARGET := efm32
TARGET_DIR := $(QPCPP)/3rd_party/efm32pg1b/qutest TARGET_DIR := $(QPCPP)/3rd_party/efm32pg1b/qutest
@ -72,7 +73,6 @@ endif
# list of all source directories used by this project # list of all source directories used by this project
VPATH := . \ VPATH := . \
../src \
$(QPCPP)/src/qf \ $(QPCPP)/src/qf \
$(QPCPP)/src/qk \ $(QPCPP)/src/qk \
$(QPCPP)/src/qs \ $(QPCPP)/src/qs \
@ -83,7 +83,6 @@ VPATH := . \
# list of all include directories needed by this project # list of all include directories needed by this project
INCLUDES = -I. \ INCLUDES = -I. \
-I../src \
-I$(QPCPP)/include \ -I$(QPCPP)/include \
-I$(QP_PORT_DIR) \ -I$(QP_PORT_DIR) \
-I$(TARGET_DIR) \ -I$(TARGET_DIR) \
@ -108,7 +107,7 @@ C_SRCS := \
# C++ source files # C++ source files
CPP_SRCS := \ CPP_SRCS := \
test_pts.cpp \ test_sched.cpp \
bsp_efm32.cpp bsp_efm32.cpp
OUTPUT := $(PROJECT) OUTPUT := $(PROJECT)
@ -142,7 +141,8 @@ LIB_DIRS :=
LIBS := LIBS :=
# defines # defines
DEFINES := -DEFM32PG1B200F256GM48=1 DEFINES := -DEFM32PG1B200F256GM48=1 \
-DQK_ON_CONTEXT_SW
# ARM CPU, ARCH, FPU, and Float-ABI types... # ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] # ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]
@ -247,7 +247,7 @@ endif
# rules # rules
# #
.PHONY : run norun flash .PHONY : run norun debug flash
ifeq ($(MAKECMDGOALS),norun) ifeq ($(MAKECMDGOALS),norun)
all : $(TARGET_BIN) all : $(TARGET_BIN)
@ -285,14 +285,22 @@ $(BIN_DIR)/%.o : %.c
$(BIN_DIR)/%.o : %.cpp $(BIN_DIR)/%.o : %.cpp
$(CPP) $(CPPFLAGS) $< -o $@ $(CPP) $(CPPFLAGS) $< -o $@
.PHONY : clean show # create BIN_DIR and include dependencies only if needed
# include dependency files only if our goal depends on their existence
ifneq ($(MAKECMDGOALS),clean) ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),show) ifneq ($(MAKECMDGOALS),show)
ifneq ($(MAKECMDGOALS),debug)
ifeq ("$(wildcard $(BIN_DIR))","")
$(shell $(MKDIR) $(BIN_DIR))
endif
-include $(C_DEPS_EXT) $(CPP_DEPS_EXT) -include $(C_DEPS_EXT) $(CPP_DEPS_EXT)
endif endif
endif endif
endif
debug :
$(QUTEST) $(TESTS) DEBUG $(HOST)
.PHONY : clean show
clean : clean :
-$(RM) $(BIN_DIR)/*.o \ -$(RM) $(BIN_DIR)/*.o \

View File

@ -1,7 +1,7 @@
############################################################################## ##############################################################################
# Product: Makefile for SYSTEM-Level tests of QP/C++ on NUCLEO-L053R8, GNU-ARM # Product: Makefile for SYSTEM-Level tests of QP/C on NUCLEO-L053R8, GNU-ARM
# Last Updated for Version: 7.1.1 # Last Updated for Version: 7.1.2
# Date of the Last Update: 2022-09-05 # Date of the Last Update: 2022-10-05
# #
# Q u a n t u m L e a P s # 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 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 norun # only make but not run the tests
# make -f make_nucleo-l053r8 clean # cleanup the build # make -f make_nucleo-l053r8 clean # cleanup the build
# make -f make_nucleo-l053r8 debug # only run tests in DEBUG mode
# #
# NOTE: # NOTE:
# To use this Makefile on Windows, you will need the GNU make utility, which # 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 name, target name, target directory:
# #
PROJECT := test_pts PROJECT := test_sched
TARGET := nucleo-l053r8 TARGET := nucleo-l053r8
TARGET_DIR := $(QPCPP)/3rd_party/nucleo-l053r8/qutest TARGET_DIR := $(QPCPP)/3rd_party/nucleo-l053r8/qutest
@ -72,7 +73,6 @@ endif
# list of all source directories used by this project # list of all source directories used by this project
VPATH := . \ VPATH := . \
../src \
$(QPCPP)/src/qf \ $(QPCPP)/src/qf \
$(QPCPP)/src/qk \ $(QPCPP)/src/qk \
$(QPCPP)/src/qs \ $(QPCPP)/src/qs \
@ -83,7 +83,6 @@ VPATH := . \
# list of all include directories needed by this project # list of all include directories needed by this project
INCLUDES = -I. \ INCLUDES = -I. \
-I../src \
-I$(QPCPP)/include \ -I$(QPCPP)/include \
-I$(QP_PORT_DIR) \ -I$(QP_PORT_DIR) \
-I$(TARGET_DIR) \ -I$(TARGET_DIR) \
@ -104,7 +103,7 @@ C_SRCS := \
# C++ source files # C++ source files
CPP_SRCS := \ CPP_SRCS := \
test_pts.cpp \ test_sched.cpp \
bsp_l053r8.cpp bsp_l053r8.cpp
OUTPUT := $(PROJECT) OUTPUT := $(PROJECT)
@ -138,7 +137,8 @@ LIB_DIRS :=
LIBS := LIBS :=
# defines # defines
DEFINES := DEFINES := \
-DQK_ON_CONTEXT_SW
# ARM CPU, ARCH, FPU, and Float-ABI types... # ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] # ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]
@ -247,7 +247,7 @@ endif
# rules # rules
# #
.PHONY : run norun flash .PHONY : run norun debug flash
ifeq ($(MAKECMDGOALS),norun) ifeq ($(MAKECMDGOALS),norun)
all : $(TARGET_BIN) all : $(TARGET_BIN)
@ -286,14 +286,22 @@ $(BIN_DIR)/%.o : %.c
$(BIN_DIR)/%.o : %.cpp $(BIN_DIR)/%.o : %.cpp
$(CPP) $(CPPFLAGS) $< -o $@ $(CPP) $(CPPFLAGS) $< -o $@
.PHONY : clean show # create BIN_DIR and include dependencies only if needed
# include dependency files only if our goal depends on their existence
ifneq ($(MAKECMDGOALS),clean) ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),show) ifneq ($(MAKECMDGOALS),show)
ifneq ($(MAKECMDGOALS),debug)
ifeq ("$(wildcard $(BIN_DIR))","")
$(shell $(MKDIR) $(BIN_DIR))
endif
-include $(C_DEPS_EXT) $(CPP_DEPS_EXT) -include $(C_DEPS_EXT) $(CPP_DEPS_EXT)
endif endif
endif endif
endif
debug :
$(QUTEST) $(TESTS) DEBUG $(HOST)
.PHONY : clean show
clean : clean :
-$(RM) $(BIN_DIR)/*.o \ -$(RM) $(BIN_DIR)/*.o \
@ -323,6 +331,5 @@ show :
@echo QTOOLS = $(QTOOLS) @echo QTOOLS = $(QTOOLS)
@echo HOST = $(HOST) @echo HOST = $(HOST)
@echo QUTEST = $(QUTEST) @echo QUTEST = $(QUTEST)
@echo FLASH = $(FLASH)
@echo TESTS = $(TESTS) @echo TESTS = $(TESTS)

View File

@ -1,13 +1,13 @@
//============================================================================ //============================================================================
// System test fixture for QK kernel on the EFM32 target // Product: System test fixture for QK on the EFM32 target
// Last updated for version 7.1.1 // Last updated for version 7.1.2
// Last updated on 2022-09-05 // Last updated on 2022-10-06
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// ------------------------ // ------------------------
// Modern Embedded Software // 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 // 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 // modify it under the terms of the GNU General Public License as published
@ -34,17 +34,18 @@
#include "qpcpp.hpp" #include "qpcpp.hpp"
#include "bsp.hpp" #include "bsp.hpp"
namespace { // unnamed namespace
Q_DEFINE_THIS_FILE Q_DEFINE_THIS_FILE
enum { NumB = 3 }; namespace {
//============================================================================
// AO ObjB
enum { NUM_B = 3 };
//............................................................................ //............................................................................
// AO ObjB // AO ObjB
class ObjB : public QP::QActive { class ObjB : public QP::QActive {
public: public:
static ObjB inst[NumB]; static ObjB inst[NUM_B];
public: public:
ObjB() : QActive(&initial) {} ObjB() : QActive(&initial) {}
@ -55,28 +56,37 @@ protected:
}; // class ObjB }; // class ObjB
Q_STATE_DEF(ObjB, initial) { Q_STATE_DEF(ObjB, initial) {
for (std::uint8_t n = 0U; n < NumB; ++n) { static bool registered = false; // starts off with 0, per C-standard
QS_OBJ_ARR_DICTIONARY(&ObjB::inst[n], n); if (!registered) {
} registered = true;
QS_FUN_DICTIONARY(&ObjB::initial); QS_FUN_DICTIONARY(&ObjB::initial);
QS_FUN_DICTIONARY(&ObjB::active); QS_FUN_DICTIONARY(&ObjB::active);
}
subscribe(TEST1_SIG);
subscribe(TEST2_SIG);
return tran(&active); return tran(&active);
} }
Q_STATE_DEF(ObjB, active) { Q_STATE_DEF(ObjB, active) {
QP::QState status_; QP::QState status_;
switch (e->sig) { switch (e->sig) {
case Q_ENTRY_SIG: { case TEST0_SIG: {
status_ = Q_RET_HANDLED; BSP::trace(this, "TEST0 1of2");
break;
}
case TRIG_SIG: {
BSP::trigISR(); BSP::trigISR();
BSP::trace(this, "TEST0 2of2");
status_ = Q_RET_HANDLED; status_ = Q_RET_HANDLED;
break; 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; status_ = Q_RET_HANDLED;
break; break;
} }
@ -87,111 +97,57 @@ Q_STATE_DEF(ObjB, active) {
} }
return status_; return status_;
} }
//............................................................................
// AO ObjA
class ObjA : public QP::QActive {
public:
static ObjA inst;
public: ObjB ObjB::inst[NUM_B];
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_;
}
} // unnamed namespace } // unnamed namespace
//============================================================================ //============================================================================
ObjB ObjB::inst[NumB];
ObjA ObjA::inst;
int main() { 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 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... // initialize publish-subscribe...
static QP::QSubscrList subscrSto[MAX_PUB_SIG]; static QP::QSubscrList subscrSto[MAX_PUB_SIG];
QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); QP::QActive::psInit(subscrSto, Q_DIM(subscrSto));
// initialize event pools... // initialize event pools...
static QF_MPOOL_EL(QP::QEvt) smlPoolSto[10]; // small pool static QF_MPOOL_EL(QP::QEvt) smlPoolSto[10]; // small pool
QP::QF::poolInit(smlPoolSto, sizeof(smlPoolSto), sizeof(smlPoolSto[0])); 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);
std::uint8_t n;
for (n = 0U; n < NUM_B; ++n) {
QS_OBJ_ARR_DICTIONARY(&ObjB::inst[n], n);
}
// pause execution of the test and wait for the test script to continue // 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(); QS_TEST_PAUSE();
static QP::QEvt const *aoB_queueSto[NumB][5]; static QP::QEvt const *aoB_queueSto[NUM_B][5];
for (std::uint8_t n = 0U; n < NumB; ++n) { for (n = 0U; n < NUM_B; ++n) {
ObjB::inst[n].start( if (pspecB[n] != 0U) {
pspec[n], // QP priority spec ObjB::inst[n].start(pspecB[n], // QF-prio/p-thre.
aoB_queueSto[n], // event queue storage aoB_queueSto[n], // event queue storage
Q_DIM(aoB_queueSto[n]), // event length [events] Q_DIM(aoB_queueSto[n]), // event length [events]
nullptr, // no stack storage nullptr, // no stack storage
0U); // zero stack size [bytes] 0U); // zero stack size [bytes]
} }
}
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]
return QP::QF::run(); // run the QF application return QP::QF::run(); // run the QF application
} }
@ -199,7 +155,6 @@ int main() {
//============================================================================ //============================================================================
namespace QP { namespace QP {
//............................................................................
void QS::onTestSetup(void) { void QS::onTestSetup(void) {
} }
//............................................................................ //............................................................................
@ -215,18 +170,16 @@ void QS::onCommand(uint8_t cmdId,
Q_UNUSED_PAR(param2); Q_UNUSED_PAR(param2);
Q_UNUSED_PAR(param3); Q_UNUSED_PAR(param3);
} }
//............................................................................
//============================================================================
//! Host callback function to "massage" the event, if necessary //! Host callback function to "massage" the event, if necessary
void QS::onTestEvt(QEvt *e) { void QS::onTestEvt(QEvt *e) {
Q_UNUSED_PAR(e); (void)e;
} }
//............................................................................ //............................................................................
//! callback function to output the posted QP events (not used here) //! callback function to output the posted QP events (not used here)
void QS::onTestPost(void const *sender, QActive *recipient, void QS::onTestPost(void const *sender, QActive *recipient,
QEvt const *e, bool status) QEvt const *e, bool status)
{ {}
Q_UNUSED_PAR(sender);
Q_UNUSED_PAR(status);
}
} // namespace QP } // namespace QP

View File

@ -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("<HHH", Q_PRIO(1,0), Q_PRIO(2,0), Q_PRIO(3,0)))
continue_test()
expect_run()
#----
glb_filter(GRP_SC, GRP_UA)
current_obj(OBJ_AO, "ObjB::inst[1]")
post("TEST0_SIG")
expect("@timestamp Sch-Next Pri=0->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("<HHH", Q_PRIO(1,3), Q_PRIO(2,3), Q_PRIO(3,0)))
continue_test()
expect_run()
#----
glb_filter(GRP_SC, GRP_UA)
current_obj(OBJ_AO, "ObjB::inst[1]")
post("TEST0_SIG")
expect("@timestamp Sch-Next Pri=0->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("<HHH", Q_PRIO(1,0), Q_PRIO(2,3), Q_PRIO(3,0)))
continue_test()
expect_run()
#----
glb_filter(GRP_SC, GRP_UA)
current_obj(OBJ_AO, "ObjB::inst[1]")
post("TEST0_SIG")
expect("@timestamp Sch-Next Pri=0->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")

View File

@ -0,0 +1,754 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<ProjectOpt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_optx.xsd">
<SchemaVersion>1.0</SchemaVersion>
<Header>### uVision Project, (C) Keil Software</Header>
<Extensions>
<cExt>*.c</cExt>
<aExt>*.s*; *.src; *.a*</aExt>
<oExt>*.obj; *.o</oExt>
<lExt>*.lib</lExt>
<tExt>*.txt; *.h; *.inc; *.md</tExt>
<pExt>*.plm</pExt>
<CppX>*.cpp</CppX>
<nMigrate>0</nMigrate>
</Extensions>
<DaveTm>
<dwLowDateTime>0</dwLowDateTime>
<dwHighDateTime>0</dwHighDateTime>
</DaveTm>
<Target>
<TargetName>qutest</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<TargetOption>
<CLKADS>12000000</CLKADS>
<OPTTT>
<gFlags>1</gFlags>
<BeepAtEnd>1</BeepAtEnd>
<RunSim>1</RunSim>
<RunTarget>0</RunTarget>
<RunAbUc>0</RunAbUc>
</OPTTT>
<OPTHX>
<HexSelection>1</HexSelection>
<FlashByte>65535</FlashByte>
<HexRangeLowAddress>0</HexRangeLowAddress>
<HexRangeHighAddress>0</HexRangeHighAddress>
<HexOffset>0</HexOffset>
</OPTHX>
<OPTLEX>
<PageWidth>79</PageWidth>
<PageLength>66</PageLength>
<TabStop>8</TabStop>
<ListingPath>.\uvision_emf32\</ListingPath>
</OPTLEX>
<ListingPage>
<CreateCListing>1</CreateCListing>
<CreateAListing>1</CreateAListing>
<CreateLListing>1</CreateLListing>
<CreateIListing>0</CreateIListing>
<AsmCond>1</AsmCond>
<AsmSymb>1</AsmSymb>
<AsmXref>0</AsmXref>
<CCond>1</CCond>
<CCode>0</CCode>
<CListInc>0</CListInc>
<CSymb>0</CSymb>
<LinkerCodeListing>0</LinkerCodeListing>
</ListingPage>
<OPTXL>
<LMap>1</LMap>
<LComments>1</LComments>
<LGenerateSymbols>1</LGenerateSymbols>
<LLibSym>1</LLibSym>
<LLines>1</LLines>
<LLocSym>1</LLocSym>
<LPubSym>1</LPubSym>
<LXref>0</LXref>
<LExpSel>0</LExpSel>
</OPTXL>
<OPTFL>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<IsCurrentTarget>1</IsCurrentTarget>
</OPTFL>
<CpuCode>3</CpuCode>
<DebugOpt>
<uSim>0</uSim>
<uTrg>1</uTrg>
<sLdApp>1</sLdApp>
<sGomain>1</sGomain>
<sRbreak>1</sRbreak>
<sRwatch>1</sRwatch>
<sRmem>1</sRmem>
<sRfunc>1</sRfunc>
<sRbox>1</sRbox>
<tLdApp>1</tLdApp>
<tGomain>1</tGomain>
<tRbreak>1</tRbreak>
<tRwatch>1</tRwatch>
<tRmem>1</tRmem>
<tRfunc>0</tRfunc>
<tRbox>1</tRbox>
<tRtrace>0</tRtrace>
<sRSysVw>1</sRSysVw>
<tRSysVw>1</tRSysVw>
<sRunDeb>0</sRunDeb>
<sLrtime>0</sLrtime>
<bEvRecOn>1</bEvRecOn>
<bSchkAxf>0</bSchkAxf>
<bTchkAxf>0</bTchkAxf>
<nTsel>4</nTsel>
<sDll></sDll>
<sDllPa></sDllPa>
<sDlgDll></sDlgDll>
<sDlgPa></sDlgPa>
<sIfile></sIfile>
<tDll></tDll>
<tDllPa></tDllPa>
<tDlgDll></tDlgDll>
<tDlgPa></tDlgPa>
<tIfile></tIfile>
<pMon>Segger\JL2CM3.dll</pMon>
</DebugOpt>
<TargetDriverDllRegistry>
<SetRegEntry>
<Number>0</Number>
<Key>DLGUARM</Key>
<Name></Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>JL2CM3</Key>
<Name>-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)</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>ARMRTXEVENTFLAGS</Key>
<Name>-L70 -Z18 -C0 -M0 -T1</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>UL2CM3</Key>
<Name>UL2CM3(-O207 -S0 -C0 -FO7 -FN1 -FC8000 -FD20000000 -FF0GECKOP2 -FL020000 -FS00 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM)</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>DLGTARM</Key>
<Name>(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)</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>ARMDBGFLAGS</Key>
<Name></Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>lmidk-agdi</Key>
<Name>-U0E2006F4 -O4622 -S4 -FO61</Name>
</SetRegEntry>
</TargetDriverDllRegistry>
<Breakpoint>
<Bp>
<Number>0</Number>
<Type>0</Type>
<LineNumber>112</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>25212</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>..\..\..\src\qs\qutest.c</Filename>
<ExecCommand></ExecCommand>
<Expression>\\test\../../../src/qs/qutest.c\112</Expression>
</Bp>
<Bp>
<Number>1</Number>
<Type>0</Type>
<LineNumber>142</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>136</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>..\..\..\src\qs\qs.c</Filename>
<ExecCommand></ExecCommand>
<Expression>\\test\../../../src/qs/qs.c\142</Expression>
</Bp>
<Bp>
<Number>2</Number>
<Type>0</Type>
<LineNumber>180</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>27402</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>.\test_pts.c</Filename>
<ExecCommand></ExecCommand>
<Expression>\\test\test_pts.c\180</Expression>
</Bp>
</Breakpoint>
<WatchWindow1>
<Ww>
<count>0</count>
<WinNumber>1</WinNumber>
<ItemText>QF_readySet_</ItemText>
</Ww>
<Ww>
<count>1</count>
<WinNumber>1</WinNumber>
<ItemText>QK_attr_</ItemText>
</Ww>
<Ww>
<count>2</count>
<WinNumber>1</WinNumber>
<ItemText>QActive_registry_</ItemText>
</Ww>
<Ww>
<count>3</count>
<WinNumber>1</WinNumber>
<ItemText>QS_rxPriv_</ItemText>
</Ww>
<Ww>
<count>4</count>
<WinNumber>1</WinNumber>
<ItemText>pspec</ItemText>
</Ww>
</WatchWindow1>
<MemoryWindow1>
<Mm>
<WinNumber>1</WinNumber>
<SubType>2</SubType>
<ItemText>0x20000200</ItemText>
<AccSizeX>0</AccSizeX>
</Mm>
</MemoryWindow1>
<MemoryWindow2>
<Mm>
<WinNumber>2</WinNumber>
<SubType>0</SubType>
<ItemText>0x400</ItemText>
<AccSizeX>0</AccSizeX>
</Mm>
</MemoryWindow2>
<Tracepoint>
<THDelay>0</THDelay>
</Tracepoint>
<DebugFlag>
<trace>0</trace>
<periodic>0</periodic>
<aLwin>1</aLwin>
<aCover>0</aCover>
<aSer1>0</aSer1>
<aSer2>0</aSer2>
<aPa>0</aPa>
<viewmode>1</viewmode>
<vrSel>0</vrSel>
<aSym>0</aSym>
<aTbox>0</aTbox>
<AscS1>0</AscS1>
<AscS2>0</AscS2>
<AscS3>0</AscS3>
<aSer3>0</aSer3>
<eProf>0</eProf>
<aLa>0</aLa>
<aPa1>0</aPa1>
<AscS4>0</AscS4>
<aSer4>0</aSer4>
<StkLoc>0</StkLoc>
<TrcWin>0</TrcWin>
<newCpu>0</newCpu>
<uProt>0</uProt>
</DebugFlag>
<LintExecutable></LintExecutable>
<LintConfigFile></LintConfigFile>
<bLintAuto>0</bLintAuto>
<bAutoGenD>0</bAutoGenD>
<LntExFlags>0</LntExFlags>
<pMisraName></pMisraName>
<pszMrule></pszMrule>
<pSingCmds></pSingCmds>
<pMultCmds></pMultCmds>
<pMisraNamep></pMisraNamep>
<pszMrulep></pszMrulep>
<pSingCmdsp></pSingCmdsp>
<pMultCmdsp></pMultCmdsp>
</TargetOption>
</Target>
<Group>
<GroupName>Applicatioin</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>1</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\bsp.h</PathWithFileName>
<FilenameWithoutPath>bsp.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>2</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\bsp_efm32.c</PathWithFileName>
<FilenameWithoutPath>bsp_efm32.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>3</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\test_pts.c</PathWithFileName>
<FilenameWithoutPath>test_pts.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>efm32pg1b</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>4</FileNumber>
<FileType>2</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\3rd_party\efm32pg1b\arm\startup_efm32pg1b.s</PathWithFileName>
<FilenameWithoutPath>startup_efm32pg1b.s</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>5</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\3rd_party\efm32pg1b\em_cmu.c</PathWithFileName>
<FilenameWithoutPath>em_cmu.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>6</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\3rd_party\efm32pg1b\em_emu.c</PathWithFileName>
<FilenameWithoutPath>em_emu.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>7</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\3rd_party\efm32pg1b\em_gpio.c</PathWithFileName>
<FilenameWithoutPath>em_gpio.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>8</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c</PathWithFileName>
<FilenameWithoutPath>system_efm32pg1b.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>9</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\3rd_party\efm32pg1b\em_system.c</PathWithFileName>
<FilenameWithoutPath>em_system.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>10</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\3rd_party\efm32pg1b\em_usart.c</PathWithFileName>
<FilenameWithoutPath>em_usart.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>QP</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>11</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qep_hsm.c</PathWithFileName>
<FilenameWithoutPath>qep_hsm.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>12</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qep_msm.c</PathWithFileName>
<FilenameWithoutPath>qep_msm.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>13</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_act.c</PathWithFileName>
<FilenameWithoutPath>qf_act.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>14</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_actq.c</PathWithFileName>
<FilenameWithoutPath>qf_actq.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>15</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_defer.c</PathWithFileName>
<FilenameWithoutPath>qf_defer.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>16</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_dyn.c</PathWithFileName>
<FilenameWithoutPath>qf_dyn.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>17</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_mem.c</PathWithFileName>
<FilenameWithoutPath>qf_mem.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>18</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_ps.c</PathWithFileName>
<FilenameWithoutPath>qf_ps.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>19</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_qact.c</PathWithFileName>
<FilenameWithoutPath>qf_qact.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>20</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_qeq.c</PathWithFileName>
<FilenameWithoutPath>qf_qeq.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>21</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_qmact.c</PathWithFileName>
<FilenameWithoutPath>qf_qmact.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>22</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_time.c</PathWithFileName>
<FilenameWithoutPath>qf_time.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>23</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\include\qstamp.c</PathWithFileName>
<FilenameWithoutPath>qstamp.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>24</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qk\qk.c</PathWithFileName>
<FilenameWithoutPath>qk.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>QP_port</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>25</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\ports\arm-cm\qxk\armclang\qep_port.h</PathWithFileName>
<FilenameWithoutPath>qep_port.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>26</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\ports\arm-cm\qxk\armclang\qf_port.h</PathWithFileName>
<FilenameWithoutPath>qf_port.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>27</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\ports\arm-cm\qk\armclang\qk_port.h</PathWithFileName>
<FilenameWithoutPath>qk_port.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>28</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\ports\arm-cm\qk\armclang\qk_port.c</PathWithFileName>
<FilenameWithoutPath>qk_port.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>29</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\ports\arm-cm\qxk\armclang\qs_port.h</PathWithFileName>
<FilenameWithoutPath>qs_port.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>30</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\3rd_party\efm32pg1b\qutest\qutest_port.c</PathWithFileName>
<FilenameWithoutPath>qutest_port.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>QS</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>31</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qs\qs.c</PathWithFileName>
<FilenameWithoutPath>qs.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>32</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qs\qs_64bit.c</PathWithFileName>
<FilenameWithoutPath>qs_64bit.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>33</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qs\qs_fp.c</PathWithFileName>
<FilenameWithoutPath>qs_fp.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>34</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qs\qs_rx.c</PathWithFileName>
<FilenameWithoutPath>qs_rx.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>35</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qs\qutest.c</PathWithFileName>
<FilenameWithoutPath>qutest.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
</ProjectOpt>

View File

@ -0,0 +1,602 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_projx.xsd">
<SchemaVersion>2.1</SchemaVersion>
<Header>### uVision Project, (C) Keil Software</Header>
<Targets>
<Target>
<TargetName>qutest</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>6160000::V6.16::ARMCLANG</pCCUsed>
<uAC6>1</uAC6>
<TargetOption>
<TargetCommonOption>
<Device>EFM32PG1B200F256GM48</Device>
<Vendor>Silicon Labs</Vendor>
<PackID>SiliconLabs.GeckoPlatform_EFM32PG1B_DFP.4.0.0</PackID>
<PackURL>https://www.silabs.com/documents/public/cmsis-packs/</PackURL>
<Cpu>IRAM(0x20000000,0x00008000) IROM(0x00000000,0x00020000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE</Cpu>
<FlashUtilSpec></FlashUtilSpec>
<StartupFile></StartupFile>
<FlashDriverDll>UL2CM3(-S0 -C0 -P0 -FD20000000 -FC8000 -FN1 -FF0GECKOP2 -FS00 -FL020000 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM))</FlashDriverDll>
<DeviceId>0</DeviceId>
<RegisterFile>$$Device:EFM32PG1B200F256GM48$Device\EFM32PG1B\Include\em_device.h</RegisterFile>
<MemoryEnv></MemoryEnv>
<Cmp></Cmp>
<Asm></Asm>
<Linker></Linker>
<OHString></OHString>
<InfinionOptionDll></InfinionOptionDll>
<SLE66CMisc></SLE66CMisc>
<SLE66AMisc></SLE66AMisc>
<SLE66LinkerMisc></SLE66LinkerMisc>
<SFDFile>$$Device:EFM32PG1B200F256GM48$SVD\EFM32PG1B\EFM32PG1B200F256GM48.svd</SFDFile>
<bCustSvd>0</bCustSvd>
<UseEnv>0</UseEnv>
<BinPath></BinPath>
<IncludePath></IncludePath>
<LibPath></LibPath>
<RegisterFilePath></RegisterFilePath>
<DBRegisterFilePath></DBRegisterFilePath>
<TargetStatus>
<Error>0</Error>
<ExitCodeStop>0</ExitCodeStop>
<ButtonStop>0</ButtonStop>
<NotGenerated>0</NotGenerated>
<InvalidFlash>1</InvalidFlash>
</TargetStatus>
<OutputDirectory>.\uvision_emf32\</OutputDirectory>
<OutputName>test</OutputName>
<CreateExecutable>1</CreateExecutable>
<CreateLib>0</CreateLib>
<CreateHexFile>0</CreateHexFile>
<DebugInformation>1</DebugInformation>
<BrowseInformation>1</BrowseInformation>
<ListingPath>.\uvision_emf32\</ListingPath>
<HexFormatSelection>1</HexFormatSelection>
<Merge32K>0</Merge32K>
<CreateBatchFile>0</CreateBatchFile>
<BeforeCompile>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopU1X>0</nStopU1X>
<nStopU2X>0</nStopU2X>
</BeforeCompile>
<BeforeMake>
<RunUserProg1>1</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name>cmd /c "del .\uvision_em32\qstamp.o"</UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopB1X>0</nStopB1X>
<nStopB2X>0</nStopB2X>
</BeforeMake>
<AfterMake>
<RunUserProg1>1</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name>fromelf --bin --output .\uvision_em32\test.bin .\uvision_em32\test.axf</UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopA1X>0</nStopA1X>
<nStopA2X>0</nStopA2X>
</AfterMake>
<SelectedForBatchBuild>1</SelectedForBatchBuild>
<SVCSIdString></SVCSIdString>
</TargetCommonOption>
<CommonProperty>
<UseCPPCompiler>0</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>0</AlwaysBuild>
<GenerateAssemblyFile>0</GenerateAssemblyFile>
<AssembleAssemblyFile>0</AssembleAssemblyFile>
<PublicsOnly>0</PublicsOnly>
<StopOnExitCode>3</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<DllOption>
<SimDllName>SARMCM3.DLL</SimDllName>
<SimDllArguments> -MPU</SimDllArguments>
<SimDlgDll>DCM.DLL</SimDlgDll>
<SimDlgDllArguments>-pCM4</SimDlgDllArguments>
<TargetDllName>SARMCM3.DLL</TargetDllName>
<TargetDllArguments> -MPU</TargetDllArguments>
<TargetDlgDll>TCM.DLL</TargetDlgDll>
<TargetDlgDllArguments>-pCM4</TargetDlgDllArguments>
</DllOption>
<DebugOption>
<OPTHX>
<HexSelection>1</HexSelection>
<HexRangeLowAddress>0</HexRangeLowAddress>
<HexRangeHighAddress>0</HexRangeHighAddress>
<HexOffset>0</HexOffset>
<Oh166RecLen>16</Oh166RecLen>
</OPTHX>
</DebugOption>
<Utilities>
<Flash1>
<UseTargetDll>1</UseTargetDll>
<UseExternalTool>0</UseExternalTool>
<RunIndependent>0</RunIndependent>
<UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
<Capability>1</Capability>
<DriverSelection>4096</DriverSelection>
</Flash1>
<bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2CM3.DLL</Flash2>
<Flash3>"" ()</Flash3>
<Flash4></Flash4>
<pFcarmOut></pFcarmOut>
<pFcarmGrp></pFcarmGrp>
<pFcArmRoot></pFcArmRoot>
<FcArmLst>0</FcArmLst>
</Utilities>
<TargetArmAds>
<ArmAdsMisc>
<GenerateListings>0</GenerateListings>
<asHll>1</asHll>
<asAsm>1</asAsm>
<asMacX>1</asMacX>
<asSyms>1</asSyms>
<asFals>1</asFals>
<asDbgD>1</asDbgD>
<asForm>1</asForm>
<ldLst>0</ldLst>
<ldmm>1</ldmm>
<ldXref>1</ldXref>
<BigEnd>0</BigEnd>
<AdsALst>0</AdsALst>
<AdsACrf>0</AdsACrf>
<AdsANop>0</AdsANop>
<AdsANot>0</AdsANot>
<AdsLLst>1</AdsLLst>
<AdsLmap>1</AdsLmap>
<AdsLcgr>1</AdsLcgr>
<AdsLsym>1</AdsLsym>
<AdsLszi>1</AdsLszi>
<AdsLtoi>1</AdsLtoi>
<AdsLsun>1</AdsLsun>
<AdsLven>1</AdsLven>
<AdsLsxf>1</AdsLsxf>
<RvctClst>0</RvctClst>
<GenPPlst>0</GenPPlst>
<AdsCpuType>"Cortex-M4"</AdsCpuType>
<RvctDeviceName></RvctDeviceName>
<mOS>0</mOS>
<uocRom>0</uocRom>
<uocRam>0</uocRam>
<hadIROM>1</hadIROM>
<hadIRAM>1</hadIRAM>
<hadXRAM>0</hadXRAM>
<uocXRam>0</uocXRam>
<RvdsVP>2</RvdsVP>
<RvdsMve>0</RvdsMve>
<RvdsCdeCp>0</RvdsCdeCp>
<hadIRAM2>0</hadIRAM2>
<hadIROM2>0</hadIROM2>
<StupSel>8</StupSel>
<useUlib>0</useUlib>
<EndSel>0</EndSel>
<uLtcg>0</uLtcg>
<nSecure>0</nSecure>
<RoSelD>3</RoSelD>
<RwSelD>3</RwSelD>
<CodeSel>0</CodeSel>
<OptFeed>0</OptFeed>
<NoZi1>0</NoZi1>
<NoZi2>0</NoZi2>
<NoZi3>0</NoZi3>
<NoZi4>0</NoZi4>
<NoZi5>0</NoZi5>
<Ro1Chk>0</Ro1Chk>
<Ro2Chk>0</Ro2Chk>
<Ro3Chk>0</Ro3Chk>
<Ir1Chk>1</Ir1Chk>
<Ir2Chk>0</Ir2Chk>
<Ra1Chk>0</Ra1Chk>
<Ra2Chk>0</Ra2Chk>
<Ra3Chk>0</Ra3Chk>
<Im1Chk>1</Im1Chk>
<Im2Chk>0</Im2Chk>
<OnChipMemories>
<Ocm1>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm1>
<Ocm2>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm2>
<Ocm3>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm3>
<Ocm4>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm4>
<Ocm5>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm5>
<Ocm6>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm6>
<IRAM>
<Type>0</Type>
<StartAddress>0x20000000</StartAddress>
<Size>0x8000</Size>
</IRAM>
<IROM>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x20000</Size>
</IROM>
<XRAM>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</XRAM>
<OCR_RVCT1>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT1>
<OCR_RVCT2>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT2>
<OCR_RVCT3>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT3>
<OCR_RVCT4>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x20000</Size>
</OCR_RVCT4>
<OCR_RVCT5>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT5>
<OCR_RVCT6>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT6>
<OCR_RVCT7>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT7>
<OCR_RVCT8>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT8>
<OCR_RVCT9>
<Type>0</Type>
<StartAddress>0x20000000</StartAddress>
<Size>0x8000</Size>
</OCR_RVCT9>
<OCR_RVCT10>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT10>
</OnChipMemories>
<RvctStartVector></RvctStartVector>
</ArmAdsMisc>
<Cads>
<interw>0</interw>
<Optim>1</Optim>
<oTime>0</oTime>
<SplitLS>0</SplitLS>
<OneElfS>1</OneElfS>
<Strict>0</Strict>
<EnumInt>0</EnumInt>
<PlainCh>0</PlainCh>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<wLevel>3</wLevel>
<uThumb>0</uThumb>
<uSurpInc>1</uSurpInc>
<uC99>1</uC99>
<uGnu>0</uGnu>
<useXO>0</useXO>
<v6Lang>3</v6Lang>
<v6LangP>3</v6LangP>
<vShortEn>0</vShortEn>
<vShortWch>0</vShortWch>
<v6Lto>0</v6Lto>
<v6WtE>0</v6WtE>
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>Q_SPY, Q_UTEST=0</Define>
<Undefine></Undefine>
<IncludePath>.;..\..\..\include;..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls>
</Cads>
<Aads>
<interw>1</interw>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<thumb>0</thumb>
<SplitLS>0</SplitLS>
<SwStkChk>0</SwStkChk>
<NoWarn>0</NoWarn>
<uSurpInc>1</uSurpInc>
<useXO>0</useXO>
<ClangAsOpt>4</ClangAsOpt>
<VariousControls>
<MiscControls></MiscControls>
<Define>Stack_Size=2048 Heap_Size=16</Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Aads>
<LDads>
<umfTarg>1</umfTarg>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<noStLib>0</noStLib>
<RepFail>1</RepFail>
<useFile>0</useFile>
<TextAddressRange>0x00000000</TextAddressRange>
<DataAddressRange>0x20000000</DataAddressRange>
<pXoBase></pXoBase>
<ScatterFile></ScatterFile>
<IncludeLibs></IncludeLibs>
<IncludeLibsPath></IncludeLibsPath>
<Misc>--entry Reset_Handler</Misc>
<LinkerInputFile></LinkerInputFile>
<DisabledWarnings></DisabledWarnings>
</LDads>
</TargetArmAds>
</TargetOption>
<Groups>
<Group>
<GroupName>Applicatioin</GroupName>
<Files>
<File>
<FileName>bsp.h</FileName>
<FileType>5</FileType>
<FilePath>.\bsp.h</FilePath>
</File>
<File>
<FileName>bsp_efm32.c</FileName>
<FileType>1</FileType>
<FilePath>.\bsp_efm32.c</FilePath>
</File>
<File>
<FileName>test_pts.c</FileName>
<FileType>1</FileType>
<FilePath>.\test_pts.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>efm32pg1b</GroupName>
<Files>
<File>
<FileName>startup_efm32pg1b.s</FileName>
<FileType>2</FileType>
<FilePath>..\..\..\..\3rd_party\efm32pg1b\arm\startup_efm32pg1b.s</FilePath>
</File>
<File>
<FileName>em_cmu.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\3rd_party\efm32pg1b\em_cmu.c</FilePath>
</File>
<File>
<FileName>em_emu.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\3rd_party\efm32pg1b\em_emu.c</FilePath>
</File>
<File>
<FileName>em_gpio.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\3rd_party\efm32pg1b\em_gpio.c</FilePath>
</File>
<File>
<FileName>system_efm32pg1b.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c</FilePath>
</File>
<File>
<FileName>em_system.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\3rd_party\efm32pg1b\em_system.c</FilePath>
</File>
<File>
<FileName>em_usart.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\3rd_party\efm32pg1b\em_usart.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>QP</GroupName>
<Files>
<File>
<FileName>qep_hsm.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qep_hsm.c</FilePath>
</File>
<File>
<FileName>qep_msm.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qep_msm.c</FilePath>
</File>
<File>
<FileName>qf_act.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_act.c</FilePath>
</File>
<File>
<FileName>qf_actq.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_actq.c</FilePath>
</File>
<File>
<FileName>qf_defer.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_defer.c</FilePath>
</File>
<File>
<FileName>qf_dyn.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_dyn.c</FilePath>
</File>
<File>
<FileName>qf_mem.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_mem.c</FilePath>
</File>
<File>
<FileName>qf_ps.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_ps.c</FilePath>
</File>
<File>
<FileName>qf_qact.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_qact.c</FilePath>
</File>
<File>
<FileName>qf_qeq.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_qeq.c</FilePath>
</File>
<File>
<FileName>qf_qmact.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_qmact.c</FilePath>
</File>
<File>
<FileName>qf_time.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_time.c</FilePath>
</File>
<File>
<FileName>qstamp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\include\qstamp.c</FilePath>
</File>
<File>
<FileName>qk.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qk\qk.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>QP_port</GroupName>
<Files>
<File>
<FileName>qep_port.h</FileName>
<FileType>5</FileType>
<FilePath>..\..\..\ports\arm-cm\qxk\armclang\qep_port.h</FilePath>
</File>
<File>
<FileName>qf_port.h</FileName>
<FileType>5</FileType>
<FilePath>..\..\..\ports\arm-cm\qxk\armclang\qf_port.h</FilePath>
</File>
<File>
<FileName>qk_port.h</FileName>
<FileType>5</FileType>
<FilePath>..\..\..\ports\arm-cm\qk\armclang\qk_port.h</FilePath>
</File>
<File>
<FileName>qk_port.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\ports\arm-cm\qk\armclang\qk_port.c</FilePath>
</File>
<File>
<FileName>qs_port.h</FileName>
<FileType>5</FileType>
<FilePath>..\..\..\ports\arm-cm\qxk\armclang\qs_port.h</FilePath>
</File>
<File>
<FileName>qutest_port.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\3rd_party\efm32pg1b\qutest\qutest_port.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>QS</GroupName>
<Files>
<File>
<FileName>qs.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qs\qs.c</FilePath>
</File>
<File>
<FileName>qs_64bit.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qs\qs_64bit.c</FilePath>
</File>
<File>
<FileName>qs_fp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qs\qs_fp.c</FilePath>
</File>
<File>
<FileName>qs_rx.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qs\qs_rx.c</FilePath>
</File>
<File>
<FileName>qutest.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qs\qutest.c</FilePath>
</File>
</Files>
</Group>
</Groups>
</Target>
</Targets>
<RTE>
<apis/>
<components/>
<files/>
</RTE>
<LayerInfo>
<Layers>
<Layer>
<LayName>test</LayName>
<LayPrjMark>1</LayPrjMark>
</Layer>
</Layers>
</LayerInfo>
</Project>

View File

@ -1,7 +1,7 @@
//============================================================================ //============================================================================
// Product: BSP for system-testing QXK // Product: BSP for system-testing QXK
// Last updated for version 7.1.1 // Last updated for version 7.1.2
// Last updated on 2022-09-04 // Last updated on 2022-10-06
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// ------------------------ // ------------------------
@ -36,12 +36,11 @@
namespace BSP { namespace BSP {
enum { TICKS_PER_SEC = 100 };
void init(void); void init(void);
void terminate(int16_t const result); void terminate(int16_t const result);
// for testing... // for testing...
void trace(QP::QActive const *thr, char const *msg);
void wait4PB1(void); void wait4PB1(void);
void ledOn(void); void ledOn(void);
void ledOff(void); void ledOff(void);
@ -50,11 +49,12 @@ void trigISR(void);
} // namespace BSP } // namespace BSP
enum TestSignals { 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 MAX_PUB_SIG, // the last published signal
TIMEOUT_SIG,
TRIG_SIG,
MAX_SIG // the last signal MAX_SIG // the last signal
}; };

View File

@ -1,7 +1,7 @@
//============================================================================ //============================================================================
// Product: BSP for system-testing QXK, EFM32-SLSTK3401A board // Product: BSP for system-testing QXK, EFM32-SLSTK3401A board
// Last updated for version 7.1.1 // Last updated for version 7.1.2
// Last updated on 2022-09-04 // Last updated on 2022-10-06
// //
// Q u a n t u m L e a P s // 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_SysTick_Handler = { 0U };
static QP::QSpyId const l_test_ISR = { 0U }; static QP::QSpyId const l_test_ISR = { 0U };
static USART_TypeDef * const l_USART0 = ((USART_TypeDef *)(0x40010000UL));
enum AppRecords { // application-specific trace records enum AppRecords { // application-specific trace records
CONTEXT_SW = QP::QS_USER, CONTEXT_SW = QP::QS_USER,
COMMAND_STAT TRACE_MSG
}; };
#endif #endif
@ -90,8 +88,8 @@ void GPIO_EVEN_IRQHandler(void) {
QXK_ISR_ENTRY(); // inform QXK about entering an ISR QXK_ISR_ENTRY(); // inform QXK about entering an ISR
// for testing... // for testing...
QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), // for testing... static QP::QEvt const t1 = { TEST1_SIG, 0U, 0U };
&BSP::l_test_ISR); QP::QF::PUBLISH(&t1, &BSP::l_test_ISR);
QXK_ISR_EXIT(); // inform QXK about exiting an 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_OBJ_DICTIONARY(&l_test_ISR);
QS_USR_DICTIONARY(CONTEXT_SW); 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) { void BSP::ledOn(void) {
@ -145,8 +147,11 @@ void BSP::trigISR(void) {
NVIC_SetPendingIRQ(GPIO_EVEN_IRQn); NVIC_SetPendingIRQ(GPIO_EVEN_IRQn);
} }
//............................................................................ //............................................................................
void BSP::terminate(int16_t result) { void BSP::trace(QP::QActive const *thr, char const *msg) {
(void)result; QS_BEGIN_ID(TRACE_MSG, 0U)
QS_OBJ(thr);
QS_STR(msg);
QS_END()
} }
// namespace QP ============================================================== // namespace QP ==============================================================
@ -175,16 +180,6 @@ void QF::onStartup(void) {
void QF::onCleanup(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) { void QXK::onIdle(void) {
#ifdef Q_SPY #ifdef Q_SPY
QS::rxParse(); // parse all the received bytes QS::rxParse(); // parse all the received bytes
@ -199,7 +194,6 @@ void QXK::onIdle(void) {
} }
// QS callbacks ============================================================== // QS callbacks ==============================================================
#ifdef Q_SPY
//............................................................................ //............................................................................
void QTimeEvt::tick1_( void QTimeEvt::tick1_(
uint_fast8_t const tickRate, uint_fast8_t const tickRate,
@ -211,8 +205,21 @@ void QTimeEvt::tick1_(
QF_INT_ENABLE(); QF_INT_ENABLE();
} }
#endif // Q_SPY
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
} // namespace QP } // 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"

View File

@ -1,7 +1,7 @@
//============================================================================ //============================================================================
// Product: BSP for system-testing QXK kernel, NUCLEO-L053R8 board // Product: BSP for system-testing QXK kernel, NUCLEO-L053R8 board
// Last updated for version 7.1.1 // Last updated for version 7.1.2
// Last updated on 2022-09-04 // Last updated on 2022-10-06
// //
// Q u a n t u m L e a P s // Q u a n t u m L e a P s
// ------------------------ // ------------------------
@ -57,7 +57,7 @@ namespace BSP {
enum AppRecords { // application-specific trace records enum AppRecords { // application-specific trace records
CONTEXT_SW = QP::QS_USER, CONTEXT_SW = QP::QS_USER,
COMMAND_STAT TRACE_MSG
}; };
#endif #endif
@ -83,8 +83,8 @@ void EXTI0_1_IRQHandler(void) {
QXK_ISR_ENTRY(); // inform QXK about entering an ISR QXK_ISR_ENTRY(); // inform QXK about entering an ISR
// for testing... // for testing...
QP::QF::PUBLISH(Q_NEW(QP::QEvt, TEST_SIG), // for testing... static QP::QEvt const t1 = { TEST1_SIG, 0U, 0U };
&BSP::l_test_ISR); QP::QF::PUBLISH(&t1, &BSP::l_test_ISR);
QXK_ISR_EXIT(); // inform QXK about exiting an 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_OBJ_DICTIONARY(&l_test_ISR);
QS_USR_DICTIONARY(CONTEXT_SW); 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) { void BSP::ledOn(void) {
@ -140,8 +144,11 @@ void BSP::trigISR(void) {
NVIC_SetPendingIRQ(EXTI0_1_IRQn); NVIC_SetPendingIRQ(EXTI0_1_IRQn);
} }
//............................................................................ //............................................................................
void BSP::terminate(int16_t result) { void BSP::trace(QP::QActive const *thr, char const *msg) {
(void)result; QS_BEGIN_ID(TRACE_MSG, 0U)
QS_OBJ(thr);
QS_STR(msg);
QS_END()
} }
// namespace QP ============================================================== // namespace QP ==============================================================
@ -170,16 +177,6 @@ void QF::onStartup(void) {
void QF::onCleanup(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) { void QXK::onIdle(void) {
#ifdef Q_SPY #ifdef Q_SPY
QS::rxParse(); // parse all the received bytes QS::rxParse(); // parse all the received bytes
@ -194,7 +191,6 @@ void QXK::onIdle(void) {
} }
// QS callbacks ============================================================== // QS callbacks ==============================================================
#ifdef Q_SPY
//............................................................................ //............................................................................
void QTimeEvt::tick1_( void QTimeEvt::tick1_(
uint_fast8_t const tickRate, uint_fast8_t const tickRate,
@ -206,8 +202,21 @@ void QTimeEvt::tick1_(
QF_INT_ENABLE(); QF_INT_ENABLE();
} }
#endif // Q_SPY
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
} // namespace QP } // 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"

View File

@ -1,7 +1,7 @@
############################################################################## ##############################################################################
# Product: Makefile for SYSTEM-Level tests of QP/C++ on EMF32, GNU-ARM # Product: Makefile for SYSTEM-Level tests of QP/C++ on EMF32, GNU-ARM
# Last Updated for Version: 7.1.1 # Last Updated for Version: 7.1.2
# Date of the Last Update: 2022-09-05 # Date of the Last Update: 2022-10-05
# #
# Q u a n t u m L e a P s # 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 HOST=localhost:7705 # connect to host:port
# make -f make_efm32 norun # only make but not run the tests # make -f make_efm32 norun # only make but not run the tests
# make -f make_efm32 clean # cleanup the build # make -f make_efm32 clean # cleanup the build
# make -f make_efm32 debug # only run tests in DEBUG mode
# #
# NOTE: # NOTE:
# To use this Makefile on Windows, you will need the GNU make utility, which # 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 name, target name, target directory:
# #
PROJECT := test_xthr PROJECT := test_sched
TARGET := efm32 TARGET := efm32
TARGET_DIR := $(QPCPP)/3rd_party/efm32pg1b/qutest TARGET_DIR := $(QPCPP)/3rd_party/efm32pg1b/qutest
@ -72,7 +73,6 @@ endif
# list of all source directories used by this project # list of all source directories used by this project
VPATH := . \ VPATH := . \
../src \
$(QPCPP)/src/qf \ $(QPCPP)/src/qf \
$(QPCPP)/src/qxk \ $(QPCPP)/src/qxk \
$(QPCPP)/src/qs \ $(QPCPP)/src/qs \
@ -83,7 +83,6 @@ VPATH := . \
# list of all include directories needed by this project # list of all include directories needed by this project
INCLUDES = -I. \ INCLUDES = -I. \
-I../src \
-I$(QPCPP)/include \ -I$(QPCPP)/include \
-I$(QP_PORT_DIR) \ -I$(QP_PORT_DIR) \
-I$(TARGET_DIR) \ -I$(TARGET_DIR) \
@ -108,7 +107,7 @@ C_SRCS := \
# C++ source files # C++ source files
CPP_SRCS := \ CPP_SRCS := \
test_xthr.cpp \ test_sched.cpp \
bsp_efm32.cpp bsp_efm32.cpp
OUTPUT := $(PROJECT) OUTPUT := $(PROJECT)
@ -145,7 +144,8 @@ LIB_DIRS :=
LIBS := LIBS :=
# defines # defines
DEFINES := -DEFM32PG1B200F256GM48=1 DEFINES := -DEFM32PG1B200F256GM48=1 \
-DQXK_ON_CONTEXT_SW
# ARM CPU, ARCH, FPU, and Float-ABI types... # ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] # ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]
@ -250,7 +250,7 @@ endif
# rules # rules
# #
.PHONY : run norun flash .PHONY : run norun debug flash
ifeq ($(MAKECMDGOALS),norun) ifeq ($(MAKECMDGOALS),norun)
all : $(TARGET_BIN) all : $(TARGET_BIN)
@ -288,14 +288,22 @@ $(BIN_DIR)/%.o : %.c
$(BIN_DIR)/%.o : %.cpp $(BIN_DIR)/%.o : %.cpp
$(CPP) $(CPPFLAGS) $< -o $@ $(CPP) $(CPPFLAGS) $< -o $@
.PHONY : clean show # create BIN_DIR and include dependencies only if needed
# include dependency files only if our goal depends on their existence
ifneq ($(MAKECMDGOALS),clean) ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),show) ifneq ($(MAKECMDGOALS),show)
ifneq ($(MAKECMDGOALS),debug)
ifeq ("$(wildcard $(BIN_DIR))","")
$(shell $(MKDIR) $(BIN_DIR))
endif
-include $(C_DEPS_EXT) $(CPP_DEPS_EXT) -include $(C_DEPS_EXT) $(CPP_DEPS_EXT)
endif endif
endif endif
endif
debug :
$(QUTEST) $(TESTS) DEBUG $(HOST)
.PHONY : clean show
clean : clean :
-$(RM) $(BIN_DIR)/*.o \ -$(RM) $(BIN_DIR)/*.o \

View File

@ -1,7 +1,7 @@
############################################################################## ##############################################################################
# Product: Makefile for SYSTEM-Level tests of QP/C++ on NUCLEO-L053R8, GNU-ARM # Product: Makefile for SYSTEM-Level tests of QP/C on NUCLEO-L053R8, GNU-ARM
# Last Updated for Version: 7.1.1 # Last Updated for Version: 7.1.2
# Date of the Last Update: 2022-09-05 # Date of the Last Update: 2022-10-05
# #
# Q u a n t u m L e a P s # 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 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 norun # only make but not run the tests
# make -f make_nucleo-l053r8 clean # cleanup the build # make -f make_nucleo-l053r8 clean # cleanup the build
# make -f make_nucleo-l053r8 debug # only run tests in DEBUG mode
# #
# NOTE: # NOTE:
# To use this Makefile on Windows, you will need the GNU make utility, which # 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 name, target name, target directory:
# #
PROJECT := test_xthr PROJECT := test_sched
TARGET := nucleo-l053r8 TARGET := nucleo-l053r8
TARGET_DIR := $(QPCPP)/3rd_party/nucleo-l053r8/qutest TARGET_DIR := $(QPCPP)/3rd_party/nucleo-l053r8/qutest
@ -72,7 +73,6 @@ endif
# list of all source directories used by this project # list of all source directories used by this project
VPATH := . \ VPATH := . \
../src \
$(QPCPP)/src/qf \ $(QPCPP)/src/qf \
$(QPCPP)/src/qxk \ $(QPCPP)/src/qxk \
$(QPCPP)/src/qs \ $(QPCPP)/src/qs \
@ -83,7 +83,6 @@ VPATH := . \
# list of all include directories needed by this project # list of all include directories needed by this project
INCLUDES = -I. \ INCLUDES = -I. \
-I../src \
-I$(QPCPP)/include \ -I$(QPCPP)/include \
-I$(QP_PORT_DIR) \ -I$(QP_PORT_DIR) \
-I$(TARGET_DIR) \ -I$(TARGET_DIR) \
@ -104,7 +103,7 @@ C_SRCS := \
# C++ source files # C++ source files
CPP_SRCS := \ CPP_SRCS := \
test_xthr.cpp \ test_sched.cpp \
bsp_l053r8.cpp bsp_l053r8.cpp
OUTPUT := $(PROJECT) OUTPUT := $(PROJECT)
@ -141,7 +140,8 @@ LIB_DIRS :=
LIBS := LIBS :=
# defines # defines
DEFINES := DEFINES := \
-DQXK_ON_CONTEXT_SW
# ARM CPU, ARCH, FPU, and Float-ABI types... # ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] # ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]
@ -250,7 +250,7 @@ endif
# rules # rules
# #
.PHONY : run norun flash .PHONY : run norun debug flash
ifeq ($(MAKECMDGOALS),norun) ifeq ($(MAKECMDGOALS),norun)
all : $(TARGET_BIN) all : $(TARGET_BIN)
@ -289,14 +289,22 @@ $(BIN_DIR)/%.o : %.c
$(BIN_DIR)/%.o : %.cpp $(BIN_DIR)/%.o : %.cpp
$(CPP) $(CPPFLAGS) $< -o $@ $(CPP) $(CPPFLAGS) $< -o $@
.PHONY : clean show # create BIN_DIR and include dependencies only if needed
# include dependency files only if our goal depends on their existence
ifneq ($(MAKECMDGOALS),clean) ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),show) ifneq ($(MAKECMDGOALS),show)
ifneq ($(MAKECMDGOALS),debug)
ifeq ("$(wildcard $(BIN_DIR))","")
$(shell $(MKDIR) $(BIN_DIR))
endif
-include $(C_DEPS_EXT) $(CPP_DEPS_EXT) -include $(C_DEPS_EXT) $(CPP_DEPS_EXT)
endif endif
endif endif
endif
debug :
$(QUTEST) $(TESTS) DEBUG $(HOST)
.PHONY : clean show
clean : clean :
-$(RM) $(BIN_DIR)/*.o \ -$(RM) $(BIN_DIR)/*.o \
@ -326,6 +334,5 @@ show :
@echo QTOOLS = $(QTOOLS) @echo QTOOLS = $(QTOOLS)
@echo HOST = $(HOST) @echo HOST = $(HOST)
@echo QUTEST = $(QUTEST) @echo QUTEST = $(QUTEST)
@echo FLASH = $(FLASH)
@echo TESTS = $(TESTS) @echo TESTS = $(TESTS)

View File

@ -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 <www.gnu.org/licenses>.
//
// Contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
#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

View File

@ -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("<HHH", 4, 0, 0))
current_obj(OBJ_AP, "pspecX")
poke(0, 2, pack("<HHH", 1, 0, 0))
continue_test()
expect_run()
#----
glb_filter(GRP_SC, GRP_UA)
current_obj(OBJ_AO, "ThrX::inst[0]")
post("TEST0_SIG")
expect("@timestamp Sch-Next Pri=0->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("<HHH", 1, 2, 3))
current_obj(OBJ_AP, "pspecX")
poke(0, 2, pack("<HHH", 4, 5, 0))
continue_test()
expect_run()
#----
glb_filter(GRP_SC, GRP_UA)
current_obj(OBJ_AO, "ThrX::inst[0]")
post("TEST0_SIG")
expect("@timestamp Sch-Next Pri=0->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("<HHH", 4, 0, 0))
current_obj(OBJ_AP, "pspecX")
poke(0, 2, pack("<HHH", 1, 5, 0))
continue_test()
expect_run()
#----
glb_filter(GRP_SC, GRP_UA)
current_obj(OBJ_AO, "ThrX::inst[0]")
post("TEST0_SIG")
expect("@timestamp Sch-Next Pri=0->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")

View File

@ -0,0 +1,801 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<ProjectOpt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_optx.xsd">
<SchemaVersion>1.0</SchemaVersion>
<Header>### uVision Project, (C) Keil Software</Header>
<Extensions>
<cExt>*.c</cExt>
<aExt>*.s*; *.src; *.a*</aExt>
<oExt>*.obj; *.o</oExt>
<lExt>*.lib</lExt>
<tExt>*.txt; *.h; *.inc; *.md</tExt>
<pExt>*.plm</pExt>
<CppX>*.cpp</CppX>
<nMigrate>0</nMigrate>
</Extensions>
<DaveTm>
<dwLowDateTime>0</dwLowDateTime>
<dwHighDateTime>0</dwHighDateTime>
</DaveTm>
<Target>
<TargetName>qutest</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<TargetOption>
<CLKADS>12000000</CLKADS>
<OPTTT>
<gFlags>1</gFlags>
<BeepAtEnd>1</BeepAtEnd>
<RunSim>1</RunSim>
<RunTarget>0</RunTarget>
<RunAbUc>0</RunAbUc>
</OPTTT>
<OPTHX>
<HexSelection>1</HexSelection>
<FlashByte>65535</FlashByte>
<HexRangeLowAddress>0</HexRangeLowAddress>
<HexRangeHighAddress>0</HexRangeHighAddress>
<HexOffset>0</HexOffset>
</OPTHX>
<OPTLEX>
<PageWidth>79</PageWidth>
<PageLength>66</PageLength>
<TabStop>8</TabStop>
<ListingPath>.\uvision_emf32\</ListingPath>
</OPTLEX>
<ListingPage>
<CreateCListing>1</CreateCListing>
<CreateAListing>1</CreateAListing>
<CreateLListing>1</CreateLListing>
<CreateIListing>0</CreateIListing>
<AsmCond>1</AsmCond>
<AsmSymb>1</AsmSymb>
<AsmXref>0</AsmXref>
<CCond>1</CCond>
<CCode>0</CCode>
<CListInc>0</CListInc>
<CSymb>0</CSymb>
<LinkerCodeListing>0</LinkerCodeListing>
</ListingPage>
<OPTXL>
<LMap>1</LMap>
<LComments>1</LComments>
<LGenerateSymbols>1</LGenerateSymbols>
<LLibSym>1</LLibSym>
<LLines>1</LLines>
<LLocSym>1</LLocSym>
<LPubSym>1</LPubSym>
<LXref>0</LXref>
<LExpSel>0</LExpSel>
</OPTXL>
<OPTFL>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<IsCurrentTarget>1</IsCurrentTarget>
</OPTFL>
<CpuCode>3</CpuCode>
<DebugOpt>
<uSim>0</uSim>
<uTrg>1</uTrg>
<sLdApp>1</sLdApp>
<sGomain>1</sGomain>
<sRbreak>1</sRbreak>
<sRwatch>1</sRwatch>
<sRmem>1</sRmem>
<sRfunc>1</sRfunc>
<sRbox>1</sRbox>
<tLdApp>1</tLdApp>
<tGomain>1</tGomain>
<tRbreak>1</tRbreak>
<tRwatch>1</tRwatch>
<tRmem>1</tRmem>
<tRfunc>0</tRfunc>
<tRbox>1</tRbox>
<tRtrace>0</tRtrace>
<sRSysVw>1</sRSysVw>
<tRSysVw>1</tRSysVw>
<sRunDeb>0</sRunDeb>
<sLrtime>0</sLrtime>
<bEvRecOn>1</bEvRecOn>
<bSchkAxf>0</bSchkAxf>
<bTchkAxf>0</bTchkAxf>
<nTsel>4</nTsel>
<sDll></sDll>
<sDllPa></sDllPa>
<sDlgDll></sDlgDll>
<sDlgPa></sDlgPa>
<sIfile></sIfile>
<tDll></tDll>
<tDllPa></tDllPa>
<tDlgDll></tDlgDll>
<tDlgPa></tDlgPa>
<tIfile></tIfile>
<pMon>Segger\JL2CM3.dll</pMon>
</DebugOpt>
<TargetDriverDllRegistry>
<SetRegEntry>
<Number>0</Number>
<Key>DLGUARM</Key>
<Name></Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>JL2CM3</Key>
<Name>-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)</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>ARMRTXEVENTFLAGS</Key>
<Name>-L70 -Z18 -C0 -M0 -T1</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>UL2CM3</Key>
<Name>UL2CM3(-O207 -S0 -C0 -FO7 -FN1 -FC8000 -FD20000000 -FF0GECKOP2 -FL020000 -FS00 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM)</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>DLGTARM</Key>
<Name>(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)</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>ARMDBGFLAGS</Key>
<Name></Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>lmidk-agdi</Key>
<Name>-U0E2006F4 -O4622 -S4 -FO61</Name>
</SetRegEntry>
</TargetDriverDllRegistry>
<Breakpoint>
<Bp>
<Number>0</Number>
<Type>0</Type>
<LineNumber>142</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>136</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>..\..\..\src\qs\qs.c</Filename>
<ExecCommand></ExecCommand>
<Expression>\\test\../../../src/qs/qs.c\142</Expression>
</Bp>
<Bp>
<Number>1</Number>
<Type>0</Type>
<LineNumber>113</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>29538</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>..\..\..\src\qs\qutest.c</Filename>
<ExecCommand></ExecCommand>
<Expression>\\test\../../../src/qs/qutest.c\113</Expression>
</Bp>
<Bp>
<Number>2</Number>
<Type>0</Type>
<LineNumber>259</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>26664</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>..\..\..\src\qxk\qxk.c</Filename>
<ExecCommand></ExecCommand>
<Expression>\\test\../../../src/qxk/qxk.c\259</Expression>
</Bp>
<Bp>
<Number>3</Number>
<Type>0</Type>
<LineNumber>103</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>29984</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>.\test_sched.c</Filename>
<ExecCommand></ExecCommand>
<Expression>\\test\test_sched.c\103</Expression>
</Bp>
</Breakpoint>
<WatchWindow1>
<Ww>
<count>0</count>
<WinNumber>1</WinNumber>
<ItemText>QF_readySet_</ItemText>
</Ww>
<Ww>
<count>1</count>
<WinNumber>1</WinNumber>
<ItemText>QXK_attr_</ItemText>
</Ww>
<Ww>
<count>2</count>
<WinNumber>1</WinNumber>
<ItemText>QActive_registry_</ItemText>
</Ww>
<Ww>
<count>3</count>
<WinNumber>1</WinNumber>
<ItemText>QS_rxPriv_</ItemText>
</Ww>
</WatchWindow1>
<MemoryWindow1>
<Mm>
<WinNumber>1</WinNumber>
<SubType>2</SubType>
<ItemText>0x20000200</ItemText>
<AccSizeX>0</AccSizeX>
</Mm>
</MemoryWindow1>
<MemoryWindow2>
<Mm>
<WinNumber>2</WinNumber>
<SubType>0</SubType>
<ItemText>0x400</ItemText>
<AccSizeX>0</AccSizeX>
</Mm>
</MemoryWindow2>
<Tracepoint>
<THDelay>0</THDelay>
</Tracepoint>
<DebugFlag>
<trace>0</trace>
<periodic>0</periodic>
<aLwin>1</aLwin>
<aCover>0</aCover>
<aSer1>0</aSer1>
<aSer2>0</aSer2>
<aPa>0</aPa>
<viewmode>1</viewmode>
<vrSel>0</vrSel>
<aSym>0</aSym>
<aTbox>0</aTbox>
<AscS1>0</AscS1>
<AscS2>0</AscS2>
<AscS3>0</AscS3>
<aSer3>0</aSer3>
<eProf>0</eProf>
<aLa>0</aLa>
<aPa1>0</aPa1>
<AscS4>0</AscS4>
<aSer4>0</aSer4>
<StkLoc>0</StkLoc>
<TrcWin>0</TrcWin>
<newCpu>0</newCpu>
<uProt>0</uProt>
</DebugFlag>
<LintExecutable></LintExecutable>
<LintConfigFile></LintConfigFile>
<bLintAuto>0</bLintAuto>
<bAutoGenD>0</bAutoGenD>
<LntExFlags>0</LntExFlags>
<pMisraName></pMisraName>
<pszMrule></pszMrule>
<pSingCmds></pSingCmds>
<pMultCmds></pMultCmds>
<pMisraNamep></pMisraNamep>
<pszMrulep></pszMrulep>
<pSingCmdsp></pSingCmdsp>
<pMultCmdsp></pMultCmdsp>
</TargetOption>
</Target>
<Group>
<GroupName>Applicatioin</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>1</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\bsp.h</PathWithFileName>
<FilenameWithoutPath>bsp.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>2</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\bsp_efm32.c</PathWithFileName>
<FilenameWithoutPath>bsp_efm32.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>3</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\test_sched.c</PathWithFileName>
<FilenameWithoutPath>test_sched.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>efm32pg1b</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>4</FileNumber>
<FileType>2</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\3rd_party\efm32pg1b\arm\startup_efm32pg1b.s</PathWithFileName>
<FilenameWithoutPath>startup_efm32pg1b.s</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>5</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\3rd_party\efm32pg1b\em_cmu.c</PathWithFileName>
<FilenameWithoutPath>em_cmu.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>6</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\3rd_party\efm32pg1b\em_emu.c</PathWithFileName>
<FilenameWithoutPath>em_emu.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>7</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\3rd_party\efm32pg1b\em_gpio.c</PathWithFileName>
<FilenameWithoutPath>em_gpio.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>8</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c</PathWithFileName>
<FilenameWithoutPath>system_efm32pg1b.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>9</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\3rd_party\efm32pg1b\em_system.c</PathWithFileName>
<FilenameWithoutPath>em_system.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>10</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\..\3rd_party\efm32pg1b\em_usart.c</PathWithFileName>
<FilenameWithoutPath>em_usart.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>QP</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>11</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qep_hsm.c</PathWithFileName>
<FilenameWithoutPath>qep_hsm.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>12</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qep_msm.c</PathWithFileName>
<FilenameWithoutPath>qep_msm.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>13</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_act.c</PathWithFileName>
<FilenameWithoutPath>qf_act.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>14</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_actq.c</PathWithFileName>
<FilenameWithoutPath>qf_actq.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>15</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_defer.c</PathWithFileName>
<FilenameWithoutPath>qf_defer.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>16</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_dyn.c</PathWithFileName>
<FilenameWithoutPath>qf_dyn.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>17</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_mem.c</PathWithFileName>
<FilenameWithoutPath>qf_mem.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>18</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_ps.c</PathWithFileName>
<FilenameWithoutPath>qf_ps.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>19</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_qact.c</PathWithFileName>
<FilenameWithoutPath>qf_qact.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>20</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_qeq.c</PathWithFileName>
<FilenameWithoutPath>qf_qeq.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>21</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_qmact.c</PathWithFileName>
<FilenameWithoutPath>qf_qmact.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>22</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qf\qf_time.c</PathWithFileName>
<FilenameWithoutPath>qf_time.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>23</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qxk\qxk.c</PathWithFileName>
<FilenameWithoutPath>qxk.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>24</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qxk\qxk_mutex.c</PathWithFileName>
<FilenameWithoutPath>qxk_mutex.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>25</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qxk\qxk_sema.c</PathWithFileName>
<FilenameWithoutPath>qxk_sema.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>26</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qxk\qxk_xthr.c</PathWithFileName>
<FilenameWithoutPath>qxk_xthr.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>27</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\include\qstamp.c</PathWithFileName>
<FilenameWithoutPath>qstamp.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>QP_port</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>28</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\ports\arm-cm\qxk\armclang\qep_port.h</PathWithFileName>
<FilenameWithoutPath>qep_port.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>29</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\ports\arm-cm\qxk\armclang\qf_port.h</PathWithFileName>
<FilenameWithoutPath>qf_port.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>30</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\ports\arm-cm\qxk\armclang\qs_port.h</PathWithFileName>
<FilenameWithoutPath>qs_port.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>31</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\ports\arm-cm\qxk\armclang\qxk_port.c</PathWithFileName>
<FilenameWithoutPath>qxk_port.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>32</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\ports\arm-cm\qxk\armclang\qxk_port.h</PathWithFileName>
<FilenameWithoutPath>qxk_port.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>33</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\3rd_party\efm32pg1b\qutest\qutest_port.c</PathWithFileName>
<FilenameWithoutPath>qutest_port.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>QS</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>34</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qs\qs.c</PathWithFileName>
<FilenameWithoutPath>qs.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>35</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qs\qs_64bit.c</PathWithFileName>
<FilenameWithoutPath>qs_64bit.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>36</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qs\qs_fp.c</PathWithFileName>
<FilenameWithoutPath>qs_fp.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>37</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qs\qs_rx.c</PathWithFileName>
<FilenameWithoutPath>qs_rx.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>38</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\..\..\src\qs\qutest.c</PathWithFileName>
<FilenameWithoutPath>qutest.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
</ProjectOpt>

View File

@ -0,0 +1,617 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_projx.xsd">
<SchemaVersion>2.1</SchemaVersion>
<Header>### uVision Project, (C) Keil Software</Header>
<Targets>
<Target>
<TargetName>qutest</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>6160000::V6.16::ARMCLANG</pCCUsed>
<uAC6>1</uAC6>
<TargetOption>
<TargetCommonOption>
<Device>EFM32PG1B200F256GM48</Device>
<Vendor>Silicon Labs</Vendor>
<PackID>SiliconLabs.GeckoPlatform_EFM32PG1B_DFP.4.0.0</PackID>
<PackURL>https://www.silabs.com/documents/public/cmsis-packs/</PackURL>
<Cpu>IRAM(0x20000000,0x00008000) IROM(0x00000000,0x00020000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE</Cpu>
<FlashUtilSpec></FlashUtilSpec>
<StartupFile></StartupFile>
<FlashDriverDll>UL2CM3(-S0 -C0 -P0 -FD20000000 -FC8000 -FN1 -FF0GECKOP2 -FS00 -FL020000 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM))</FlashDriverDll>
<DeviceId>0</DeviceId>
<RegisterFile>$$Device:EFM32PG1B200F256GM48$Device\EFM32PG1B\Include\em_device.h</RegisterFile>
<MemoryEnv></MemoryEnv>
<Cmp></Cmp>
<Asm></Asm>
<Linker></Linker>
<OHString></OHString>
<InfinionOptionDll></InfinionOptionDll>
<SLE66CMisc></SLE66CMisc>
<SLE66AMisc></SLE66AMisc>
<SLE66LinkerMisc></SLE66LinkerMisc>
<SFDFile>$$Device:EFM32PG1B200F256GM48$SVD\EFM32PG1B\EFM32PG1B200F256GM48.svd</SFDFile>
<bCustSvd>0</bCustSvd>
<UseEnv>0</UseEnv>
<BinPath></BinPath>
<IncludePath></IncludePath>
<LibPath></LibPath>
<RegisterFilePath></RegisterFilePath>
<DBRegisterFilePath></DBRegisterFilePath>
<TargetStatus>
<Error>0</Error>
<ExitCodeStop>0</ExitCodeStop>
<ButtonStop>0</ButtonStop>
<NotGenerated>0</NotGenerated>
<InvalidFlash>1</InvalidFlash>
</TargetStatus>
<OutputDirectory>.\uvision_emf32\</OutputDirectory>
<OutputName>test</OutputName>
<CreateExecutable>1</CreateExecutable>
<CreateLib>0</CreateLib>
<CreateHexFile>0</CreateHexFile>
<DebugInformation>1</DebugInformation>
<BrowseInformation>1</BrowseInformation>
<ListingPath>.\uvision_emf32\</ListingPath>
<HexFormatSelection>1</HexFormatSelection>
<Merge32K>0</Merge32K>
<CreateBatchFile>0</CreateBatchFile>
<BeforeCompile>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopU1X>0</nStopU1X>
<nStopU2X>0</nStopU2X>
</BeforeCompile>
<BeforeMake>
<RunUserProg1>1</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name>cmd /c "del .\uvision_em32\qstamp.o"</UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopB1X>0</nStopB1X>
<nStopB2X>0</nStopB2X>
</BeforeMake>
<AfterMake>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopA1X>0</nStopA1X>
<nStopA2X>0</nStopA2X>
</AfterMake>
<SelectedForBatchBuild>1</SelectedForBatchBuild>
<SVCSIdString></SVCSIdString>
</TargetCommonOption>
<CommonProperty>
<UseCPPCompiler>0</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>0</AlwaysBuild>
<GenerateAssemblyFile>0</GenerateAssemblyFile>
<AssembleAssemblyFile>0</AssembleAssemblyFile>
<PublicsOnly>0</PublicsOnly>
<StopOnExitCode>3</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<DllOption>
<SimDllName>SARMCM3.DLL</SimDllName>
<SimDllArguments> -MPU</SimDllArguments>
<SimDlgDll>DCM.DLL</SimDlgDll>
<SimDlgDllArguments>-pCM4</SimDlgDllArguments>
<TargetDllName>SARMCM3.DLL</TargetDllName>
<TargetDllArguments> -MPU</TargetDllArguments>
<TargetDlgDll>TCM.DLL</TargetDlgDll>
<TargetDlgDllArguments>-pCM4</TargetDlgDllArguments>
</DllOption>
<DebugOption>
<OPTHX>
<HexSelection>1</HexSelection>
<HexRangeLowAddress>0</HexRangeLowAddress>
<HexRangeHighAddress>0</HexRangeHighAddress>
<HexOffset>0</HexOffset>
<Oh166RecLen>16</Oh166RecLen>
</OPTHX>
</DebugOption>
<Utilities>
<Flash1>
<UseTargetDll>1</UseTargetDll>
<UseExternalTool>0</UseExternalTool>
<RunIndependent>0</RunIndependent>
<UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
<Capability>1</Capability>
<DriverSelection>4096</DriverSelection>
</Flash1>
<bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2CM3.DLL</Flash2>
<Flash3>"" ()</Flash3>
<Flash4></Flash4>
<pFcarmOut></pFcarmOut>
<pFcarmGrp></pFcarmGrp>
<pFcArmRoot></pFcArmRoot>
<FcArmLst>0</FcArmLst>
</Utilities>
<TargetArmAds>
<ArmAdsMisc>
<GenerateListings>0</GenerateListings>
<asHll>1</asHll>
<asAsm>1</asAsm>
<asMacX>1</asMacX>
<asSyms>1</asSyms>
<asFals>1</asFals>
<asDbgD>1</asDbgD>
<asForm>1</asForm>
<ldLst>0</ldLst>
<ldmm>1</ldmm>
<ldXref>1</ldXref>
<BigEnd>0</BigEnd>
<AdsALst>0</AdsALst>
<AdsACrf>0</AdsACrf>
<AdsANop>0</AdsANop>
<AdsANot>0</AdsANot>
<AdsLLst>1</AdsLLst>
<AdsLmap>1</AdsLmap>
<AdsLcgr>1</AdsLcgr>
<AdsLsym>1</AdsLsym>
<AdsLszi>1</AdsLszi>
<AdsLtoi>1</AdsLtoi>
<AdsLsun>1</AdsLsun>
<AdsLven>1</AdsLven>
<AdsLsxf>1</AdsLsxf>
<RvctClst>0</RvctClst>
<GenPPlst>0</GenPPlst>
<AdsCpuType>"Cortex-M4"</AdsCpuType>
<RvctDeviceName></RvctDeviceName>
<mOS>0</mOS>
<uocRom>0</uocRom>
<uocRam>0</uocRam>
<hadIROM>1</hadIROM>
<hadIRAM>1</hadIRAM>
<hadXRAM>0</hadXRAM>
<uocXRam>0</uocXRam>
<RvdsVP>2</RvdsVP>
<RvdsMve>0</RvdsMve>
<RvdsCdeCp>0</RvdsCdeCp>
<hadIRAM2>0</hadIRAM2>
<hadIROM2>0</hadIROM2>
<StupSel>8</StupSel>
<useUlib>0</useUlib>
<EndSel>0</EndSel>
<uLtcg>0</uLtcg>
<nSecure>0</nSecure>
<RoSelD>3</RoSelD>
<RwSelD>3</RwSelD>
<CodeSel>0</CodeSel>
<OptFeed>0</OptFeed>
<NoZi1>0</NoZi1>
<NoZi2>0</NoZi2>
<NoZi3>0</NoZi3>
<NoZi4>0</NoZi4>
<NoZi5>0</NoZi5>
<Ro1Chk>0</Ro1Chk>
<Ro2Chk>0</Ro2Chk>
<Ro3Chk>0</Ro3Chk>
<Ir1Chk>1</Ir1Chk>
<Ir2Chk>0</Ir2Chk>
<Ra1Chk>0</Ra1Chk>
<Ra2Chk>0</Ra2Chk>
<Ra3Chk>0</Ra3Chk>
<Im1Chk>1</Im1Chk>
<Im2Chk>0</Im2Chk>
<OnChipMemories>
<Ocm1>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm1>
<Ocm2>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm2>
<Ocm3>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm3>
<Ocm4>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm4>
<Ocm5>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm5>
<Ocm6>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm6>
<IRAM>
<Type>0</Type>
<StartAddress>0x20000000</StartAddress>
<Size>0x8000</Size>
</IRAM>
<IROM>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x20000</Size>
</IROM>
<XRAM>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</XRAM>
<OCR_RVCT1>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT1>
<OCR_RVCT2>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT2>
<OCR_RVCT3>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT3>
<OCR_RVCT4>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x20000</Size>
</OCR_RVCT4>
<OCR_RVCT5>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT5>
<OCR_RVCT6>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT6>
<OCR_RVCT7>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT7>
<OCR_RVCT8>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT8>
<OCR_RVCT9>
<Type>0</Type>
<StartAddress>0x20000000</StartAddress>
<Size>0x8000</Size>
</OCR_RVCT9>
<OCR_RVCT10>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT10>
</OnChipMemories>
<RvctStartVector></RvctStartVector>
</ArmAdsMisc>
<Cads>
<interw>0</interw>
<Optim>1</Optim>
<oTime>0</oTime>
<SplitLS>0</SplitLS>
<OneElfS>1</OneElfS>
<Strict>0</Strict>
<EnumInt>0</EnumInt>
<PlainCh>0</PlainCh>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<wLevel>3</wLevel>
<uThumb>0</uThumb>
<uSurpInc>1</uSurpInc>
<uC99>1</uC99>
<uGnu>0</uGnu>
<useXO>0</useXO>
<v6Lang>3</v6Lang>
<v6LangP>3</v6LangP>
<vShortEn>0</vShortEn>
<vShortWch>0</vShortWch>
<v6Lto>0</v6Lto>
<v6WtE>0</v6WtE>
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>Q_SPY, Q_UTEST=0, QXK_ON_CONTEXT_SW</Define>
<Undefine></Undefine>
<IncludePath>.;..\..\..\include;..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\3rd_party\efm32pg1b</IncludePath>
</VariousControls>
</Cads>
<Aads>
<interw>1</interw>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<thumb>0</thumb>
<SplitLS>0</SplitLS>
<SwStkChk>0</SwStkChk>
<NoWarn>0</NoWarn>
<uSurpInc>1</uSurpInc>
<useXO>0</useXO>
<ClangAsOpt>4</ClangAsOpt>
<VariousControls>
<MiscControls></MiscControls>
<Define>Stack_Size=2048 Heap_Size=16</Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Aads>
<LDads>
<umfTarg>1</umfTarg>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<noStLib>0</noStLib>
<RepFail>1</RepFail>
<useFile>0</useFile>
<TextAddressRange>0x00000000</TextAddressRange>
<DataAddressRange>0x20000000</DataAddressRange>
<pXoBase></pXoBase>
<ScatterFile></ScatterFile>
<IncludeLibs></IncludeLibs>
<IncludeLibsPath></IncludeLibsPath>
<Misc>--entry Reset_Handler</Misc>
<LinkerInputFile></LinkerInputFile>
<DisabledWarnings></DisabledWarnings>
</LDads>
</TargetArmAds>
</TargetOption>
<Groups>
<Group>
<GroupName>Applicatioin</GroupName>
<Files>
<File>
<FileName>bsp.h</FileName>
<FileType>5</FileType>
<FilePath>.\bsp.h</FilePath>
</File>
<File>
<FileName>bsp_efm32.c</FileName>
<FileType>1</FileType>
<FilePath>.\bsp_efm32.c</FilePath>
</File>
<File>
<FileName>test_sched.c</FileName>
<FileType>1</FileType>
<FilePath>.\test_sched.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>efm32pg1b</GroupName>
<Files>
<File>
<FileName>startup_efm32pg1b.s</FileName>
<FileType>2</FileType>
<FilePath>..\..\..\..\3rd_party\efm32pg1b\arm\startup_efm32pg1b.s</FilePath>
</File>
<File>
<FileName>em_cmu.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\3rd_party\efm32pg1b\em_cmu.c</FilePath>
</File>
<File>
<FileName>em_emu.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\3rd_party\efm32pg1b\em_emu.c</FilePath>
</File>
<File>
<FileName>em_gpio.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\3rd_party\efm32pg1b\em_gpio.c</FilePath>
</File>
<File>
<FileName>system_efm32pg1b.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c</FilePath>
</File>
<File>
<FileName>em_system.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\3rd_party\efm32pg1b\em_system.c</FilePath>
</File>
<File>
<FileName>em_usart.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\3rd_party\efm32pg1b\em_usart.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>QP</GroupName>
<Files>
<File>
<FileName>qep_hsm.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qep_hsm.c</FilePath>
</File>
<File>
<FileName>qep_msm.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qep_msm.c</FilePath>
</File>
<File>
<FileName>qf_act.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_act.c</FilePath>
</File>
<File>
<FileName>qf_actq.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_actq.c</FilePath>
</File>
<File>
<FileName>qf_defer.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_defer.c</FilePath>
</File>
<File>
<FileName>qf_dyn.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_dyn.c</FilePath>
</File>
<File>
<FileName>qf_mem.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_mem.c</FilePath>
</File>
<File>
<FileName>qf_ps.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_ps.c</FilePath>
</File>
<File>
<FileName>qf_qact.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_qact.c</FilePath>
</File>
<File>
<FileName>qf_qeq.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_qeq.c</FilePath>
</File>
<File>
<FileName>qf_qmact.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_qmact.c</FilePath>
</File>
<File>
<FileName>qf_time.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qf\qf_time.c</FilePath>
</File>
<File>
<FileName>qxk.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qxk\qxk.c</FilePath>
</File>
<File>
<FileName>qxk_mutex.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qxk\qxk_mutex.c</FilePath>
</File>
<File>
<FileName>qxk_sema.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qxk\qxk_sema.c</FilePath>
</File>
<File>
<FileName>qxk_xthr.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qxk\qxk_xthr.c</FilePath>
</File>
<File>
<FileName>qstamp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\include\qstamp.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>QP_port</GroupName>
<Files>
<File>
<FileName>qep_port.h</FileName>
<FileType>5</FileType>
<FilePath>..\..\..\ports\arm-cm\qxk\armclang\qep_port.h</FilePath>
</File>
<File>
<FileName>qf_port.h</FileName>
<FileType>5</FileType>
<FilePath>..\..\..\ports\arm-cm\qxk\armclang\qf_port.h</FilePath>
</File>
<File>
<FileName>qs_port.h</FileName>
<FileType>5</FileType>
<FilePath>..\..\..\ports\arm-cm\qxk\armclang\qs_port.h</FilePath>
</File>
<File>
<FileName>qxk_port.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\ports\arm-cm\qxk\armclang\qxk_port.c</FilePath>
</File>
<File>
<FileName>qxk_port.h</FileName>
<FileType>5</FileType>
<FilePath>..\..\..\ports\arm-cm\qxk\armclang\qxk_port.h</FilePath>
</File>
<File>
<FileName>qutest_port.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\3rd_party\efm32pg1b\qutest\qutest_port.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>QS</GroupName>
<Files>
<File>
<FileName>qs.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qs\qs.c</FilePath>
</File>
<File>
<FileName>qs_64bit.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qs\qs_64bit.c</FilePath>
</File>
<File>
<FileName>qs_fp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qs\qs_fp.c</FilePath>
</File>
<File>
<FileName>qs_rx.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qs\qs_rx.c</FilePath>
</File>
<File>
<FileName>qutest.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\src\qs\qutest.c</FilePath>
</File>
</Files>
</Group>
</Groups>
</Target>
</Targets>
<RTE>
<apis/>
<components/>
<files/>
</RTE>
<LayerInfo>
<Layers>
<Layer>
<LayName>test</LayName>
<LayPrjMark>1</LayPrjMark>
</Layer>
</Layers>
</LayerInfo>
</Project>

View File

@ -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 <www.gnu.org/licenses>.
//
// Contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
#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
}

View File

@ -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")