6.9.0
@ -399,7 +399,7 @@ static void SetSysClock(void)
|
||||
RCC->CFGR |= RCC_CFGR_SW_PLL;
|
||||
|
||||
/* Wait till the main PLL is used as system clock source */
|
||||
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
|
||||
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
2199
doxygen/Doxyfile
2199
doxygen/Doxyfile-CHM
@ -2,6 +2,45 @@ namespace QP {
|
||||
|
||||
/** @page history Revision History
|
||||
|
||||
@section qpcpp_6_9_0 Version 6.9.0, 2020-08-21
|
||||
The main purpose of this release is to adjust the QP/C++ RTEF to the changes and improvements introduced in [QTools 6.9.0](https://www.state-machine.com/qtools/history.html). Specifically, QP/C++ now includes examples for the new [QView Visualization & Monitoring](https://www.state-machine.com/qtools/qview.html) as well as adjustments for the new version of [QUTest Unit Testing](https://www.state-machine.com/qtools/qutest.html).
|
||||
|
||||
|
||||
__Source code changes:__
|
||||
|
||||
Added new #QS_QF_RUN trace record to [QS software tracing](https://www.state-machine.com/qtools/qs.html), which is now generated in all QP/C++ ports upon the entry to QF::run(). This trace record marks the end of the application startup, at which time all the [QS dictionaries](https://www.state-machine.com/qtools/qs.html#qs_dict) are typically produced.
|
||||
|
||||
@note
|
||||
The addition of the #QS_QF_RUN trace record affects only the [Spy build configuration](https://www.state-machine.com/qpc/struct.html#comp_qs) and is has **no impact** on the Release or Debug build configurations.
|
||||
|
||||
|
||||
__Updated Ports:__
|
||||
|
||||
+ All QP/C++ ports to 3rd-party RTOSes (embOS, FreeRTOS, ThreadX, uC/OS-II) and OSes (POSIX, POSIX-QV, WIN32, WIN32-QV) have been updated to generate the #QS_QF_RUN trace record.
|
||||
|
||||
+ Additionally the POSIX and POSIX-QV ports have been updated to add the call to `pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)` (see also [bug#276](https://sourceforge.net/p/qpc/bugs/276))
|
||||
|
||||
|
||||
__Updated Examples:__
|
||||
|
||||
+ All [QUTest](https://www.state-machine.com/qtools/qutest.html) examples (`qpcpp\examples\qutest` directory) have been modified to use the new location of the `qutest.py` Python module. Also, all QUTest examples that use the `on_reset()` callback have been modified to call `expect_run()`.
|
||||
|
||||
@note
|
||||
The #QS_QF_RUN record is now generated in [QUTest unit testing](https://www.state-machine.com/qtools/qutest.html), which requires adjustments in the existing [test scripts](https://www.state-machine.com/qtools/qutest_script.html). Specifically, the test scripts that provide their own [on_reset() callback](https://www.state-machine.com/qtools/namespacequtest__dsl.html#aa40735b0e2865f928331d30798090ee2) must now also call [expect_run()](https://www.state-machine.com/qtools/namespacequtest__dsl.html#a6a958064a793bd7edd6ecc39e03c356a).
|
||||
|
||||
|
||||
+ ARM Cortex-M examples for STM32 NUCLEO-L053RE (`qpcpp\examples\arm-cm\dpp_nucleo-l053r8`) and NUCLEO-L152RE (`qpcpp\examples\arm-cm\dpp_nucleo-l152re`) have been modified to support bi-directional QSPY communication. These examples now include the QView demos.
|
||||
+ Added examples of new [Sequence Diagram Generation](https://www.state-machine.com/qtools/html/qspy_seq.html) in QSPY 6.9.0
|
||||
|
||||
|
||||
__Bug Fixes:__
|
||||
|
||||
+ [bug#276 "QP/C/C++ POSIX port doesn't set thread priorities correctly"](https://sourceforge.net/p/qpc/bugs/276)
|
||||
|
||||
+ [bug#277 "QP/C++6.8.2 game-gui and dpp-gui examples fail to compile with Visual Studio"](https://sourceforge.net/p/qpc/bugs/277)
|
||||
|
||||
|
||||
|
||||
@section qpcpp_6_8_2 Version 6.8.2, 2020-07-17
|
||||
|
||||
__Source code changes:__
|
||||
|
@ -3,8 +3,8 @@ namespace QP {
|
||||
/// @file
|
||||
/// command-line macros and macros for porting QP
|
||||
|
||||
/// The preprocessor switch to disable checking assertions
|
||||
///
|
||||
//! The preprocessor switch to disable checking assertions
|
||||
//
|
||||
/// When defined, Q_NASSERT disables the following macros #Q_ASSERT,
|
||||
/// #Q_REQUIRE, #Q_ENSURE, #Q_INVARIANT, #Q_ERROR as well as
|
||||
/// #Q_ASSERT_ID, #Q_REQUIRE_ID, #Q_ENSURE_ID, #Q_INVARIANT_ID, and
|
||||
@ -16,9 +16,9 @@ namespace QP {
|
||||
/// failures when the switch Q_NASSERT is defined.
|
||||
#define Q_NASSERT
|
||||
|
||||
/// The preprocessor switch to activate the event-constructors
|
||||
/// and destructors
|
||||
///
|
||||
//! The preprocessor switch to activate the event-constructors
|
||||
//! and destructors
|
||||
//
|
||||
/// When Q_EVT_CTOR is defined (typically in the qep_port.hpp header file),
|
||||
/// QP::QEvt becomes a class with constructor and virtual destructor.
|
||||
/// More importantly, the subclasses of QEvt (your custom events) can have
|
||||
@ -27,41 +27,42 @@ namespace QP {
|
||||
/// is invoked before recycling the event with QP::QF::gc().
|
||||
#define Q_EVT_CTOR
|
||||
|
||||
/// The preprocessor switch to activate the QS software tracing
|
||||
/// instrumentation in the code
|
||||
///
|
||||
//! The preprocessor switch to activate the QS software tracing
|
||||
//! instrumentation in the code
|
||||
//
|
||||
/// When defined, Q_SPY activates the QS software tracing instrumentation.
|
||||
/// When Q_SPY is not defined, the QS instrumentation in the code does
|
||||
/// not generate any code.
|
||||
#define Q_SPY
|
||||
|
||||
/// The preprocessor switch to activate the QUTest unit testing
|
||||
/// instrumentation in the code */
|
||||
//! The preprocessor switch to activate the QUTest unit testing
|
||||
//! instrumentation in the code
|
||||
///
|
||||
/// @note
|
||||
/// This macro requires that #Q_SPY be defined as well.
|
||||
#define Q_UTEST
|
||||
|
||||
/// This macro defines the type of the OS-Object used for blocking
|
||||
/// the native QF event queue when the queue is empty
|
||||
///
|
||||
/// In QK, the OS object is used to hold the per-thread flags, which might
|
||||
/// be used, for example, to remember the thread attributes (e.g.,
|
||||
/// if the thread uses a floating point co-processor). The OS object value
|
||||
/// is set on per-thread basis in QActive::start(). Later, the extended
|
||||
/// context switch macros (QK_EXT_SAVE() and QK_EXT_RESTORE()) might use
|
||||
/// the per-thread flags to determine what kind of extended context switch
|
||||
/// this particular thread needs (e.g., the thread might not be using the
|
||||
/// coprocessor or might be using a different one).
|
||||
#define QF_OS_OBJECT_TYPE uint8_t
|
||||
//! This macro defines the type of the thread handle used for AOs
|
||||
#define QF_THREAD_TYPE void*
|
||||
|
||||
/// This macro defines the type of the thread handle used for the
|
||||
/// active objects. This macro depends on the QP port.
|
||||
#define QF_THREAD_TYPE void *
|
||||
//! This macro defines the type of the event-queue used for AOs
|
||||
#define QF_EQUEUE_TYPE QEQueue
|
||||
|
||||
/// Platform-dependent macro defining how QF should block the calling
|
||||
/// task when the QF native queue is empty
|
||||
//! This macro defines the type of the OS-Object used for blocking
|
||||
// the native ::QEQueue when the queue is empty
|
||||
//
|
||||
/// @description
|
||||
/// This macro is used when ::QEQueue is used as the event-queue for AOs
|
||||
/// but also the AO queue must *block* when the queue is empty.
|
||||
/// In that case, #QF_OS_OBJECT_TYPE specifies the blocking mechanism.
|
||||
/// For examle, in the POSIX port, the blocking mechanism is a condition
|
||||
/// variable.
|
||||
///
|
||||
#define QF_OS_OBJECT_TYPE pthread_cond_t
|
||||
|
||||
//! Platform-dependent macro defining how QF should block the calling
|
||||
//! task when the QF native queue is empty
|
||||
//
|
||||
/// @note This is just an example of #QACTIVE_EQUEUE_WAIT_ for the QK-port
|
||||
/// of QF. QK never activates a task that has no events to process, so in this
|
||||
/// case the macro asserts that the queue is not empty. In other QF ports you
|
||||
@ -70,9 +71,9 @@ namespace QP {
|
||||
#define QACTIVE_EQUEUE_WAIT_(me_) \
|
||||
Q_ASSERT((me_)->m_eQueue.m_frontEvt != nullptr)
|
||||
|
||||
/// Platform-dependent macro defining how QF should signal the
|
||||
/// active object task that an event has just arrived.
|
||||
///
|
||||
//! Platform-dependent macro defining how QF should signal the
|
||||
//! active object task that an event has just arrived.
|
||||
//
|
||||
/// The macro is necessary only when the native QF event queue is used.
|
||||
/// The signaling of task involves unblocking the task if it is blocked.
|
||||
///
|
||||
@ -89,13 +90,13 @@ namespace QP {
|
||||
uint8_t p = QK_schedPrio_(); \
|
||||
if (p != 0U) { \
|
||||
QK_sched_(p); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
/// This macro defines the type of the event pool used in this QF port.
|
||||
///
|
||||
/// \note This is a specific implementation for the QK-port of QF.
|
||||
//! This macro defines the type of the event pool used in this QF port.
|
||||
//
|
||||
/// @note This is a specific implementation for the QK-port of QF.
|
||||
/// In other QF ports you need to define the macro appropriately for
|
||||
/// the underlying kernel/OS you're using.
|
||||
#define QF_EPOOL_TYPE_ QMPool
|
||||
@ -110,7 +111,7 @@ namespace QP {
|
||||
|
||||
/// Platform-dependent macro defining the event pool initialization
|
||||
///
|
||||
/// \note This is a specific implementation for the QK-port of QF.
|
||||
/// @note This is a specific implementation for the QK-port of QF.
|
||||
/// In other QF ports you need to define the macro appropriately for
|
||||
/// the underlying kernel/OS you're using.
|
||||
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \
|
||||
@ -119,24 +120,24 @@ namespace QP {
|
||||
/// Platform-dependent macro defining how QF should obtain the
|
||||
/// event pool block-size
|
||||
///
|
||||
/// \note This is a specific implementation for the QK-port of QF.
|
||||
/// @note This is a specific implementation for the QK-port of QF.
|
||||
/// In other QF ports you need to define the macro appropriately for
|
||||
/// the underlying kernel/OS you're using.
|
||||
#define QF_EPOOL_EVENT_SIZE_(p_) static_cast<uint32_t>((p_).getBlockSize())
|
||||
|
||||
/// Platform-dependent macro defining how QF should obtain an event
|
||||
/// \a e_ from the event pool \a p_
|
||||
/// @a e_ from the event pool @a p_
|
||||
///
|
||||
/// \note This is a specific implementation for the QK-port of QF.
|
||||
/// @note This is a specific implementation for the QK-port of QF.
|
||||
/// In other QF ports you need to define the macro appropriately for
|
||||
/// the underlying kernel/OS you're using.
|
||||
#define QF_EPOOL_GET_(p_, e_, m_) \
|
||||
((e_) = static_cast<QEvt *>((p_).get((m_))))
|
||||
|
||||
/// Platform-dependent macro defining how QF should return an event
|
||||
/// \a e_ to the event pool \a p_
|
||||
/// @a e_ to the event pool @a p_
|
||||
///
|
||||
/// \note This is a specific implementation for the QK-port of QF.
|
||||
/// @note This is a specific implementation for the QK-port of QF.
|
||||
/// In other QF ports you need to define the macro appropriately for
|
||||
/// the underlying kernel/OS you're using.
|
||||
#define QF_EPOOL_PUT_(p_, e_) ((p_).put(e_))
|
||||
|
@ -8,7 +8,7 @@ To check what's new in QP/C++, please see @ref history "QP/C++ Revision History"
|
||||
|
||||
|
||||
@section ab_about What is it?
|
||||
<a class="extern" target="_blank" href="https://www.state-machine.com/products/"><strong>QP/C++™ (Quantum Platform in C++)</strong></a> is a lightweight <a class="extern" target="_blank" href="https://www.state-machine.com/doc/concepts#RTEF"><strong>Real-Time Embedded Framework (RTEF)</strong></a> for building modern, responsive and modular real-time embedded applications as systems of asynchronous event-driven <a class="extern" target="_blank" href="https://www.state-machine.com/doc/concepts#Active"><strong>active objects</strong></a> (<a href="http://en.wikipedia.org/wiki/Actor_model">actors</a>). QP/C++™ is a member of a larger family of real-time embedded frameworks (RTEFs) consisting of QP/C++, <a href="https://www.state-machine.com/qpc" target="_blank" class="extern">QP/C</a>, and <a href="https://www.state-machine.com/qpn" target="_blank" class="extern">QP-nano</a> frameworks, which are all strictly quality controlled, thoroughly documented, and available under @ref licensing "dual licensing model".
|
||||
<a class="extern" target="_blank" href="https://www.state-machine.com/products/"><strong>QP/C++™ (Quantum Platform in C++)</strong></a> is a lightweight <a class="extern" target="_blank" href="https://www.state-machine.com/doc/concepts#RTEF"><strong>Real-Time Embedded Framework (RTEF)</strong></a> for building modern, responsive and modular real-time embedded applications as systems of asynchronous event-driven <a class="extern" target="_blank" href="https://www.state-machine.com/doc/concepts#Active"><strong>active objects</strong></a> (<a href="https://en.wikipedia.org/wiki/Actor_model">actors</a>). QP/C++™ is a member of a larger family of real-time embedded frameworks (RTEFs) consisting of QP/C++ and <a href="https://www.state-machine.com/qpc" target="_blank" class="extern">QP/C</a> frameworks, which are all strictly quality controlled, thoroughly documented, and available under @ref licensing "dual licensing model".
|
||||
|
||||
The behavior of active objects is specified in QP/C++ by means of <a href="https://www.state-machine.com/doc/concepts#HSM" target="_blank" class="extern"><strong>hierarchical state machines</strong></a> (UML statecharts). The framework supports @ref sm "manual coding of UML state machines in C++" as well as automatic code generation by means of the free <a href="https://www.state-machine.com/qm"><strong>QM™ model-based design tool</strong></a>.
|
||||
|
||||
@ -31,51 +31,40 @@ The main goals of the QP/C++™ framework are:
|
||||
- to provide event-driven timing services (time events).
|
||||
- to provide a selection of built-in real-time kernels to run the QP applications, such as the cooperative @ref qv "QV kernel", the preemptive non-blocking @ref qk "QK kernel", and the preemptive blocking @ref qxk "QXK kernel".
|
||||
- to provide testing support for applications based on software tracing (@ref qs "Q-Spy").
|
||||
- to provide portability layer and ready-to-use ports to @ref ports_rtos "3rd-party RTOSes" and desktop operating systems such as @ref win32 "Windows", @ref posix "Linux and MacOS".
|
||||
- to provide portability layer and ready-to-use ports to @ref ports_rtos "3rd-party RTOSes" and desktop operating systems such as @ref win32 "Windows", @ref posix "Linux and MacOS".
|
||||
- to provide a target for modeling and automatic code generation from the <a href="https://www.state-machine.com/qm" target="_blank" class="extern">QM™ model-based design (MBD) tool</a>.
|
||||
|
||||
|
||||
|
||||
@section ab_special What's special about it?
|
||||
|
||||
The QP/C++™ Real-Time Embedded Framework (RTEF) is a unique offering on the embedded software market. It provides a modern, reusable **architecture** of embedded applications, which combines object-orientation and @ref sm "hierarchical state machines" with the particular model of concurrency, known as <a class="extern" target="_blank" href="https://www.state-machine.com/doc/concepts#Active"><strong>active objects</strong></a> (actors). This architecture is generally **safer**, more responsive and easier to understand than "free threading" with a traditional Real-Time Operating System (RTOS). It also provides sufficiently high level of abstraction and the right abstractions to effectively apply modeling and code generation to deeply embedded systems.
|
||||
|
||||
|
||||
|
||||
@subsection oop Object Orientation
|
||||
QP/C++™ is fundamentally an **object-oriented** framework, which means that the framework itself and your applications derived from the framework are fundamentally composed of <a href="https://en.wikipedia.org/wiki/Class_(computer_programming)" target="_blank" class="extern">classes</a> and only classes can have @ref sm "state machines" associated with them.
|
||||
|
||||
|
||||
|
||||
@subsection lightweight Lightweight
|
||||
The most unique characteristic of the QP/C++™ framework is its very small footprint, especially in RAM. In this respect, QP/C++™ requires less resources than even the smallest conventional Real-Time Operating System (RTOS) kernel. At the same time, QP/C++ gives you a much higher level of abstraction than a conventional RTOS. With QP, you work at the level of active objects, state machines and events, as opposed to "naked" threads of an RTOS.
|
||||
|
||||
|
||||
|
||||
@subsection hsms Hierarchical State Machines
|
||||
The behavior of active objects is specified in QP/C++ by means of
|
||||
<a class="extern" target="_blank" href="https://www.state-machine.com/doc/concepts#HSM">hierarchical state machines (UML statecharts)</a>. The framework supports @ref sm "manual coding of UML state machines in C++" as well as fully automatic code generation by means of the free graphical <a class="extern" target="_blank" href="https://www.state-machine.com/qm">QM™ model-based design (MBD) tool</a>.
|
||||
<a class="extern" target="_blank" href="https://www.state-machine.com/doc/concepts#HSM">hierarchical state machines (UML statecharts)</a>. The framework supports @ref sm "manual coding of UML state machines in C++" (or C in case of QP/C) as well as fully **automatic code generation** by means of the free graphical <a class="extern" target="_blank" href="https://www.state-machine.com/qm">QM™ model-based design (MBD) tool</a>.
|
||||
|
||||
@remarks
|
||||
State machines can be an incredibly powerful technique, but they require an event-driven **infrastructure** (framework) that provides, at a minimum: a run-to-completion (RTC) execution context for each state machine, queuing of events, and event-based timing services. This is really the pivotal point. Without an event-driven framework (like QP/C++), state machines are like <a class="extern" target="_blank" href="https://www.state-machine.com/doc/concepts#Infrastructure">cars without an infrastructure of roads</a>.
|
||||
|
||||
|
||||
|
||||
@subsection kernels Built-in Kernels
|
||||
The QP™/C++ framework can run on @ref exa_native "bare-metal single-chip microcontrollers", completely replacing a traditional RTOS. The framework contains a selection of built-in real-time kernels, such as the cooperative @ref qv "QV kernel", the preemptive non-blocking @ref qk "QK kernel", and the preemptive, dual-mode, blocking @ref qxk "QXK kernel". The QXK kernel <span class="highlight">provides all the features you might expect from a traditional <strong>RTOS kernel</strong></span> and has been specifically designed for mixing event-driven active objects with traditional blocking code, such as commercial middleware (TCP/IP stacks, UDP stacks, embedded file systems, etc.) or legacy software. @ref ports_native "Native QP ports" and ready-to-use @ref exa_native "examples" are provided for major @ref exa_ref_mcu "CPU families".
|
||||
|
||||
|
||||
|
||||
@subsection inter Interoperability
|
||||
QP/C++ can also work with many traditional @ref exa_rtos "RTOSes" and @ref exa_rtos "desktop OSes" (such as Windows and Linux).
|
||||
|
||||
|
||||
|
||||
@subsection popular Popularity & Maturity
|
||||
With over 15 years of continuous development and <a class="extern" target="_blank" href="https://sourceforge.net/projects/qpc/files/stats/timeline?dates=2016-01-01+to+2016-12-31">60,000 downloads a year</a>, the QP™ RTEF family is the most mature and popular such solution on the embedded software market.
|
||||
|
||||
The QP™ frameworks are used in <a href="https://www.state-machine.com/about/customers" target="_blank" class="extern">millions of products worldwide</a> in aerospace, medical devices, consumer electronics, wired and wireless telecommunications, industrial automation, transportation, robotics, and many more.
|
||||
|
||||
With over 15 years of continuous development and <a class="extern" target="_blank" href="https://sourceforge.net/projects/qpc/files/stats/timeline?dates=2016-01-01+to+2016-12-31">60,000 downloads a year</a>, the QP™ RTEF family is the most mature and popular such solution on the embedded software market. The QP™ frameworks are used in <a href="https://www.state-machine.com/about/customers" target="_blank" class="extern">millions of products worldwide</a> in medical devices, consumer electronics, wired and wireless telecommunications, industrial automation, transportation, aerospace, robotics, and many more.
|
||||
|
||||
|
||||
@subsection psicc2 Book
|
||||
@ -84,25 +73,20 @@ The book, <a class="extern" target="_blank" href="https://www.state-machine.com/
|
||||
@image html PSiCC2-3D.jpg "Practical UML Statecharts in C/C++, 2nd Edition"
|
||||
|
||||
|
||||
|
||||
@section licensing How is it licensed?
|
||||
|
||||
QP/C++ is licensed under the increasingly popular <a class="extern" target="_blank" href="https://www.state-machine.com/licensing">dual licensing model</a>, in which both the open source software distribution mechanism and traditional closed source software distribution models are combined.
|
||||
|
||||
@note If your company has a policy forbidding open source in your product, all QP frameworks can be licensed commercially, in which case you don't use any open source license and you do not violate your policy.
|
||||
|
||||
|
||||
|
||||
@subsection open-source Open Source Projects
|
||||
If you are developing and distributing open source applications under the GNU General Public License (GPL), as published by the Free Software Foundation, then you are free to use the Quantum Leaps software under the <a class="extern" target="_blank" href="http://www.gnu.org/copyleft/gpl.html">GPL version 3</a> of the License, or (at your option) any later version. Please note that GPL requires that all modifications to the original code as well as your application code (Derivative Works as defined in the Copyright Law) must also be released under the terms of the GPL open source license.
|
||||
|
||||
|
||||
|
||||
@subsection closed-source Closed Source Projects
|
||||
If you are developing and distributing traditional closed source applications, you can purchase one of <a class="extern" target="_blank" href="https://www.state-machine.com/licensing/#Commercial">Quantum Leaps commercial licenses</a>, which are specifically designed for users interested in retaining the proprietary status of their code. All Quantum Leaps commercial licenses expressly supersede the GPL open source license. This means that when you license Quantum Leaps software under a commercial license, you specifically do not use the software under the open source license and therefore you are not subject to any of its terms.
|
||||
|
||||
|
||||
|
||||
@section support How to get help?
|
||||
Please post any **technical questions** to the <a class="extern" target="_blank" href="http://sourceforge.net/p/qpc/discussion/668726"><strong>Free Support Forum</strong></a> hosted on SourceForge.net. Posts to this forum benefit the whole community and are typically answered the same day.
|
||||
|
||||
@ -111,7 +95,6 @@ Direct **Commercial Support** is available to the commercial licensees. Every co
|
||||
Training and consulting services are also available from Quantum Leaps. Please refer to the <a class="extern" target="_blank" href="https://www.state-machine.com/contact">Contact web-page</a> for more information.
|
||||
|
||||
|
||||
|
||||
@section contact Contact Information
|
||||
|
||||
- Quantum Leaps Web site: <a class="extern" target="_blank" href="https://www.state-machine.com">state-machine.com</a>
|
||||
|
@ -1,8 +1,8 @@
|
||||
@echo off
|
||||
:: ==========================================================================
|
||||
:: Product: QP/C++ script for generating Doxygen documentation
|
||||
:: Last Updated for Version: 6.8.2
|
||||
:: Date of the Last Update: 2020-06-22
|
||||
:: Last Updated for Version: 6.9.0
|
||||
:: Date of the Last Update: 2020-08-24
|
||||
::
|
||||
:: Q u a n t u m L e a P s
|
||||
:: ------------------------
|
||||
|
@ -40,7 +40,7 @@
|
||||
3 1 17 1 3 QP::QTimeEvt::toTimeEvt@462-464@..\include\qf.hpp
|
||||
3 1 10 1 3 QP::QF::getVersion@493-495@..\include\qf.hpp
|
||||
1 1 14 1 1 QP::QTicker::init@637-637@..\include\qf.hpp
|
||||
3 1 10 1 3 QP::QK::getVersion@160-162@..\include\qk.hpp
|
||||
3 1 10 1 3 QP::QK::getVersion@155-157@..\include\qk.hpp
|
||||
3 1 11 1 3 QP::QMPool::getBlockSize@149-151@..\include\qmpool.hpp
|
||||
3 1 11 1 3 QP::QPSet::setEmpty@81-83@..\include\qpset.hpp
|
||||
3 1 15 1 3 QP::QPSet::isEmpty@86-88@..\include\qpset.hpp
|
||||
@ -56,10 +56,10 @@
|
||||
8 2 70 1 8 QP::QPSet::insert@162-169@..\include\qpset.hpp
|
||||
8 2 74 1 8 QP::QPSet::rmove@175-182@..\include\qpset.hpp
|
||||
5 2 40 1 5 QP::QPSet::findMax@185-189@..\include\qpset.hpp
|
||||
7 1 28 1 7 QP::QS::force_cast@499-505@..\include\qs.hpp
|
||||
14 4 87 1 14 QP::QS::rxPut@563-576@..\include\qs.hpp
|
||||
6 1 51 5 6 QP::QActiveDummy::start@597-602@..\include\qs.hpp
|
||||
1 1 14 1 1 QP::QActiveDummy::init@605-605@..\include\qs.hpp
|
||||
7 1 28 1 7 QP::QS::force_cast@500-506@..\include\qs.hpp
|
||||
14 4 87 1 14 QP::QS::rxPut@564-577@..\include\qs.hpp
|
||||
6 1 51 5 6 QP::QActiveDummy::start@598-603@..\include\qs.hpp
|
||||
1 1 14 1 1 QP::QActiveDummy::init@606-606@..\include\qs.hpp
|
||||
1 1 14 1 1 QP::QXThread::init@86-86@..\include\qxthread.hpp
|
||||
6 1 51 5 6 QP::QXThread::start@99-104@..\include\qxthread.hpp
|
||||
2 1 15 2 3 QP::QEvt@101-103@..\src\qf\qep_hsm.cpp
|
||||
@ -132,49 +132,49 @@
|
||||
11 2 79 1 16 QP::QF::init@78-93@..\src\qk\qk.cpp
|
||||
3 1 14 1 4 QP::QF::stop@111-114@..\src\qk\qk.cpp
|
||||
6 2 26 1 8 QP::initial_events@119-126@..\src\qk\qk.cpp
|
||||
10 3 40 1 14 QP::QF::run@137-150@..\src\qk\qk.cpp
|
||||
21 5 142 6 30 QP::QActive::start@168-197@..\src\qk\qk.cpp
|
||||
21 2 138 1 32 QP::QK::schedLock@222-253@..\src\qk\qk.cpp
|
||||
22 4 149 1 33 QP::QK::schedUnlock@272-304@..\src\qk\qk.cpp
|
||||
14 3 94 1 17 QK_sched_@324-340@..\src\qk\qk.cpp
|
||||
61 15 421 1 105 QK_activate_@351-455@..\src\qk\qk.cpp
|
||||
12 3 51 1 19 QP::QF::run@137-155@..\src\qk\qk.cpp
|
||||
21 5 142 6 30 QP::QActive::start@173-202@..\src\qk\qk.cpp
|
||||
21 2 138 1 32 QP::QK::schedLock@227-258@..\src\qk\qk.cpp
|
||||
22 4 149 1 33 QP::QK::schedUnlock@277-309@..\src\qk\qk.cpp
|
||||
14 3 94 1 17 QK_sched_@329-345@..\src\qk\qk.cpp
|
||||
61 15 421 1 105 QK_activate_@356-460@..\src\qk\qk.cpp
|
||||
9 2 67 1 13 QP::QF::init@79-91@..\src\qv\qv.cpp
|
||||
3 1 12 1 4 QP::QF::stop@109-112@..\src\qv\qv.cpp
|
||||
37 9 198 1 71 QP::QF::run@130-200@..\src\qv\qv.cpp
|
||||
15 3 112 6 22 QP::QActive::start@218-239@..\src\qv\qv.cpp
|
||||
39 9 209 1 76 QP::QF::run@130-205@..\src\qv\qv.cpp
|
||||
15 3 112 6 22 QP::QActive::start@223-244@..\src\qv\qv.cpp
|
||||
2 1 10 0 2 QP::QXKIdleThread::QXKIdleThread@68-69@..\src\qxk\qxk.cpp
|
||||
14 2 105 1 22 QP::QF::init@85-106@..\src\qxk\qxk.cpp
|
||||
3 1 12 1 4 QP::QF::stop@124-127@..\src\qxk\qxk.cpp
|
||||
6 2 26 1 8 QP::initial_events@132-139@..\src\qxk\qxk.cpp
|
||||
10 3 40 1 15 QP::QF::run@148-162@..\src\qxk\qxk.cpp
|
||||
23 6 156 6 32 QP::QActive::start@179-210@..\src\qxk\qxk.cpp
|
||||
23 3 150 1 33 QP::QXK::schedLock@233-265@..\src\qxk\qxk.cpp
|
||||
22 4 149 1 34 QP::QXK::schedUnlock@288-321@..\src\qxk\qxk.cpp
|
||||
51 7 296 1 69 QXK_sched_@341-409@..\src\qxk\qxk.cpp
|
||||
77 16 547 1 133 QXK_activate_@420-552@..\src\qxk\qxk.cpp
|
||||
13 2 72 1 20 QXK_current@555-574@..\src\qxk\qxk.cpp
|
||||
12 3 51 1 20 QP::QF::run@148-167@..\src\qxk\qxk.cpp
|
||||
23 6 156 6 32 QP::QActive::start@184-215@..\src\qxk\qxk.cpp
|
||||
23 3 150 1 33 QP::QXK::schedLock@238-270@..\src\qxk\qxk.cpp
|
||||
22 4 149 1 34 QP::QXK::schedUnlock@293-326@..\src\qxk\qxk.cpp
|
||||
51 7 296 1 69 QXK_sched_@346-414@..\src\qxk\qxk.cpp
|
||||
77 16 547 1 133 QXK_activate_@425-557@..\src\qxk\qxk.cpp
|
||||
13 2 72 1 20 QXK_current@560-579@..\src\qxk\qxk.cpp
|
||||
16 4 105 1 24 QP::QXMutex::init@84-107@..\src\qxk\qxk_mutex.cpp
|
||||
66 12 456 1 108 QP::QXMutex::lock@129-236@..\src\qxk\qxk_mutex.cpp
|
||||
66 12 459 1 108 QP::QXMutex::lock@129-236@..\src\qxk\qxk_mutex.cpp
|
||||
47 10 301 1 71 QP::QXMutex::tryLock@256-326@..\src\qxk\qxk_mutex.cpp
|
||||
68 16 460 1 115 QP::QXMutex::unlock@345-459@..\src\qxk\qxk_mutex.cpp
|
||||
68 16 463 1 115 QP::QXMutex::unlock@345-459@..\src\qxk\qxk_mutex.cpp
|
||||
8 1 55 2 10 QP::QXSemaphore::init@77-86@..\src\qxk\qxk_sema.cpp
|
||||
43 7 274 1 68 QP::QXSemaphore::wait@109-176@..\src\qxk\qxk_sema.cpp
|
||||
43 7 277 1 68 QP::QXSemaphore::wait@109-176@..\src\qxk\qxk_sema.cpp
|
||||
15 2 55 1 20 QP::QXSemaphore::tryWait@191-210@..\src\qxk\qxk_sema.cpp
|
||||
27 6 169 1 46 QP::QXSemaphore::signal@230-275@..\src\qxk\qxk_sema.cpp
|
||||
27 6 175 1 46 QP::QXSemaphore::signal@230-275@..\src\qxk\qxk_sema.cpp
|
||||
8 1 54 2 8 QP::QXThread::QXThread@81-88@..\src\qxk\qxk_xthr.cpp
|
||||
4 1 23 1 4 QP::QXThread::init@92-95@..\src\qxk\qxk_xthr.cpp
|
||||
4 1 23 1 4 QP::QXThread::dispatch@98-101@..\src\qxk\qxk_xthr.cpp
|
||||
25 6 185 6 44 QP::QXThread::start@124-167@..\src\qxk\qxk_xthr.cpp
|
||||
96 13 480 2 129 QP::QXThread::post_@206-334@..\src\qxk\qxk_xthr.cpp
|
||||
4 1 23 1 4 QP::QXThread::postLIFO@345-348@..\src\qxk\qxk_xthr.cpp
|
||||
60 7 436 1 86 QP::QXThread::queueGet@370-455@..\src\qxk\qxk_xthr.cpp
|
||||
5 1 47 1 6 QP::QXThread::block_@464-469@..\src\qxk\qxk_xthr.cpp
|
||||
8 3 56 1 9 QP::QXThread::unblock_@478-486@..\src\qxk\qxk_xthr.cpp
|
||||
4 1 26 1 4 QP::QXThread::init@92-95@..\src\qxk\qxk_xthr.cpp
|
||||
4 1 26 1 4 QP::QXThread::dispatch@98-101@..\src\qxk\qxk_xthr.cpp
|
||||
25 6 191 6 44 QP::QXThread::start@124-167@..\src\qxk\qxk_xthr.cpp
|
||||
96 13 486 2 129 QP::QXThread::post_@206-334@..\src\qxk\qxk_xthr.cpp
|
||||
4 1 26 1 4 QP::QXThread::postLIFO@345-348@..\src\qxk\qxk_xthr.cpp
|
||||
60 7 439 1 86 QP::QXThread::queueGet@370-455@..\src\qxk\qxk_xthr.cpp
|
||||
5 1 50 1 6 QP::QXThread::block_@464-469@..\src\qxk\qxk_xthr.cpp
|
||||
8 3 59 1 9 QP::QXThread::unblock_@478-486@..\src\qxk\qxk_xthr.cpp
|
||||
18 3 135 2 33 QP::QXThread::teArm_@496-528@..\src\qxk\qxk_xthr.cpp
|
||||
11 2 42 1 14 QP::QXThread::teDisarm_@537-550@..\src\qxk\qxk_xthr.cpp
|
||||
20 3 169 1 34 QP::QXThread::delay@554-587@..\src\qxk\qxk_xthr.cpp
|
||||
14 2 58 1 16 QP::QXThread::delayCancel@591-606@..\src\qxk\qxk_xthr.cpp
|
||||
14 2 106 1 23 QXK_threadRet_@623-645@..\src\qxk\qxk_xthr.cpp
|
||||
14 2 109 1 23 QXK_threadRet_@623-645@..\src\qxk\qxk_xthr.cpp
|
||||
3 1 16 1 3 QP::QF_EVT_POOL_ID_@140-142@..\src\qf_pkg.hpp
|
||||
3 1 16 1 3 QP::QF_EVT_REF_CTR_@145-147@..\src\qf_pkg.hpp
|
||||
3 1 21 1 3 QP::QF_EVT_REF_CTR_INC_@150-152@..\src\qf_pkg.hpp
|
||||
@ -210,12 +210,12 @@ NLOC Avg.NLOC AvgCCN Avg.token function_cnt file
|
||||
159 30.0 4.0 154.4 5 ..\src\qf\qf_qeq.cpp
|
||||
27 3.8 1.0 25.3 6 ..\src\qf\qf_qmact.cpp
|
||||
232 24.4 3.4 133.9 9 ..\src\qf\qf_time.cpp
|
||||
184 18.8 4.1 122.6 9 ..\src\qk\qk.cpp
|
||||
76 16.0 3.8 97.2 4 ..\src\qv\qv.cpp
|
||||
263 22.2 4.3 142.1 11 ..\src\qxk\qxk.cpp
|
||||
206 49.2 10.5 330.5 4 ..\src\qxk\qxk_mutex.cpp
|
||||
102 23.2 4.0 138.2 4 ..\src\qxk\qxk_sema.cpp
|
||||
305 20.8 3.3 131.2 14 ..\src\qxk\qxk_xthr.cpp
|
||||
186 19.0 4.1 123.8 9 ..\src\qk\qk.cpp
|
||||
78 16.5 3.8 100.0 4 ..\src\qv\qv.cpp
|
||||
265 22.4 4.3 143.1 11 ..\src\qxk\qxk.cpp
|
||||
206 49.2 10.5 332.0 4 ..\src\qxk\qxk_mutex.cpp
|
||||
102 23.2 4.0 140.5 4 ..\src\qxk\qxk_sema.cpp
|
||||
305 20.8 3.3 133.6 14 ..\src\qxk\qxk_xthr.cpp
|
||||
24 3.0 1.0 18.5 4 ..\src\qf_pkg.hpp
|
||||
9 0.0 0.0 0.0 0 ..\src\qs_pkg.hpp
|
||||
13 0.0 0.0 0.0 0 ..\src\qxk_pkg.hpp
|
||||
@ -229,6 +229,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
|
||||
------------------------------------------------------------------------------------------
|
||||
3969 16.8 3.1 103.3 174 1 0.01 0.04
|
||||
3975 16.9 3.1 103.8 174 1 0.01 0.04
|
||||
@endcode
|
||||
*/
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Model: dpp.qm
|
||||
// File: ${.::dpp.hpp}
|
||||
//
|
||||
// This code has been generated by QM 4.6.0 <www.state-machine.com/qm/>.
|
||||
// This code has been generated by QM 5.0.3 <www.state-machine.com/qm/>.
|
||||
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
|
||||
//
|
||||
// This program is open source software: you can redistribute it and/or
|
||||
@ -22,7 +22,8 @@
|
||||
namespace DPP {
|
||||
|
||||
enum DPPSignals {
|
||||
EAT_SIG = QP::Q_USER_SIG, // published by Table to let a philosopher eat
|
||||
TIMEOUT_SIG = QP::Q_USER_SIG, // time event timeout
|
||||
EAT_SIG, // published by Table to let a philosopher eat
|
||||
DONE_SIG, // published by Philosopher when done eating
|
||||
PAUSE_SIG, // published by BSP to pause the application
|
||||
SERVE_SIG, // published by BSP to serve re-start serving forks
|
||||
@ -48,7 +49,7 @@ public:
|
||||
//.$enddecl${Events::TableEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
// number of philosophers
|
||||
#define N_PHILO 5U
|
||||
#define N_PHILO ((uint8_t)5)
|
||||
|
||||
//.$declare${AOs::AO_Philo[N_PHILO]} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
@ -57,7 +58,6 @@ extern QP::QActive * const AO_Philo[N_PHILO];
|
||||
|
||||
} // namespace DPP
|
||||
//.$enddecl${AOs::AO_Philo[N_PHILO]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
//.$declare${AOs::AO_Table} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
@ -83,4 +83,4 @@ extern QP::QXThread * const XT_Test2;
|
||||
//.$enddecl${AOs::XT_Test2} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
#endif // QXK_HPP
|
||||
|
||||
#endif // DPP_HPP
|
||||
#endif // DPP_HPP
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<model version="4.6.0" links="1">
|
||||
<model version="5.0.3" links="1">
|
||||
<documentation>Dining Philosopher Problem example with MSM state machines</documentation>
|
||||
<!--${qpcpp}-->
|
||||
<framework name="qpcpp"/>
|
||||
@ -15,11 +15,15 @@
|
||||
<package name="AOs" stereotype="0x02" namespace="DPP::">
|
||||
<!--${AOs::Philo}-->
|
||||
<class name="Philo" superclass="qpcpp::QActive">
|
||||
<!--${AOs::Philo::inst[N_PHILO]}-->
|
||||
<attribute name="inst[N_PHILO]" type="Philo" visibility="0x00" properties="0x01">
|
||||
<documentation>The array of static insts of the Philo class (Singleton pattern)</documentation>
|
||||
</attribute>
|
||||
<!--${AOs::Philo::m_timeEvt}-->
|
||||
<attribute name="m_timeEvt" type="QP::QTimeEvt" visibility="0x02" properties="0x00"/>
|
||||
<!--${AOs::Philo::Philo}-->
|
||||
<operation name="Philo" type="" visibility="0x00" properties="0x00">
|
||||
<code> : QActive(Q_STATE_CAST(&Philo::initial)),
|
||||
<code> : QActive(&initial),
|
||||
m_timeEvt(this, TIMEOUT_SIG, 0U)</code>
|
||||
</operation>
|
||||
<!--${AOs::Philo::SM}-->
|
||||
@ -28,27 +32,30 @@
|
||||
<initial target="../1">
|
||||
<action>static bool registered = false; // starts off with 0, per C-standard
|
||||
(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);
|
||||
|
||||
if (!registered) {
|
||||
registered = true;
|
||||
|
||||
QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[4].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4].m_timeEvt);
|
||||
|
||||
QS_FUN_DICTIONARY(&initial);
|
||||
QS_FUN_DICTIONARY(&thinking);
|
||||
QS_FUN_DICTIONARY(&hungry);
|
||||
QS_FUN_DICTIONARY(&eating);
|
||||
QS_FUN_DICTIONARY(&Philo::initial);
|
||||
QS_FUN_DICTIONARY(&Philo::thinking);
|
||||
QS_FUN_DICTIONARY(&Philo::hungry);
|
||||
QS_FUN_DICTIONARY(&Philo::eating);
|
||||
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, nullptr);
|
||||
}
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal for each Philos
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, this); // signal for each Philos</action>
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);</action>
|
||||
<initial_glyph conn="2,3,5,1,20,5,-3">
|
||||
<action box="0,-2,6,2"/>
|
||||
</initial_glyph>
|
||||
@ -65,7 +72,7 @@ QS_SIG_DICTIONARY(TIMEOUT_SIG, this); // signal for each Philos</action>
|
||||
</tran>
|
||||
<!--${AOs::Philo::SM::thinking::EAT, DONE}-->
|
||||
<tran trig="EAT, DONE">
|
||||
<action>// EAT or DONE must be for other Philos than this one
|
||||
<action>/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));</action>
|
||||
<tran_glyph conn="2,16,3,-1,13">
|
||||
<action box="0,-2,14,2"/>
|
||||
@ -127,7 +134,7 @@ QP::QF::PUBLISH(pe, this);
|
||||
</tran>
|
||||
<!--${AOs::Philo::SM::eating::EAT, DONE}-->
|
||||
<tran trig="EAT, DONE">
|
||||
<action>// EAT or DONE must be for other Philos than this one
|
||||
<action>/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));</action>
|
||||
<tran_glyph conn="2,55,3,-1,13">
|
||||
<action box="0,-2,14,2"/>
|
||||
@ -143,13 +150,17 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));</action>
|
||||
</class>
|
||||
<!--${AOs::Table}-->
|
||||
<class name="Table" superclass="qpcpp::QActive">
|
||||
<!--${AOs::Table::inst}-->
|
||||
<attribute name="inst" type="Table" visibility="0x00" properties="0x01">
|
||||
<documentation>The only static inst of the Table class (Singleton pattern)</documentation>
|
||||
</attribute>
|
||||
<!--${AOs::Table::m_fork[N_PHILO]}-->
|
||||
<attribute name="m_fork[N_PHILO]" type="uint8_t" visibility="0x02" properties="0x00"/>
|
||||
<!--${AOs::Table::m_isHungry[N_PHILO]}-->
|
||||
<attribute name="m_isHungry[N_PHILO]" type="bool" visibility="0x02" properties="0x00"/>
|
||||
<!--${AOs::Table::Table}-->
|
||||
<operation name="Table" type="" visibility="0x00" properties="0x00">
|
||||
<code> : QActive(Q_STATE_CAST(&Table::initial))
|
||||
<code> : QActive(&initial)
|
||||
|
||||
for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
m_fork[n] = FREE;
|
||||
@ -162,6 +173,16 @@ for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
<initial target="../1/2">
|
||||
<action>(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
QS_OBJ_DICTIONARY(&Table::inst);
|
||||
|
||||
QS_SIG_DICTIONARY(DONE_SIG, nullptr); // global signals
|
||||
QS_SIG_DICTIONARY(EAT_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(PAUSE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(SERVE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(TEST_SIG, nullptr);
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal just for Table
|
||||
|
||||
subscribe(DONE_SIG);
|
||||
subscribe(PAUSE_SIG);
|
||||
subscribe(SERVE_SIG);
|
||||
@ -171,17 +192,7 @@ for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
m_fork[n] = FREE;
|
||||
m_isHungry[n] = false;
|
||||
BSP::displayPhilStat(n, THINKING);
|
||||
}
|
||||
|
||||
// global signals...
|
||||
QS_SIG_DICTIONARY(DONE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(EAT_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(PAUSE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(SERVE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(TEST_SIG, nullptr);
|
||||
|
||||
// signals just for this AO...
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this);</action>
|
||||
}</action>
|
||||
<initial_glyph conn="3,3,5,1,45,18,-10">
|
||||
<action box="0,-2,6,2"/>
|
||||
</initial_glyph>
|
||||
@ -355,9 +366,19 @@ m_fork[n] = FREE;</action>
|
||||
</statechart>
|
||||
</class>
|
||||
<!--${AOs::AO_Philo[N_PHILO]}-->
|
||||
<attribute name="AO_Philo[N_PHILO]" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
|
||||
<attribute name="AO_Philo[N_PHILO]" type="QP::QActive * const" visibility="0x00" properties="0x00">
|
||||
<code>= { // "opaque" pointers to Philo AO
|
||||
&Philo::inst[0],
|
||||
&Philo::inst[1],
|
||||
&Philo::inst[2],
|
||||
&Philo::inst[3],
|
||||
&Philo::inst[4]
|
||||
};</code>
|
||||
</attribute>
|
||||
<!--${AOs::AO_Table}-->
|
||||
<attribute name="AO_Table" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
|
||||
<attribute name="AO_Table" type="QP::QActive * const" visibility="0x00" properties="0x00">
|
||||
<code>= &Table::inst; // "opaque" pointer to Table AO</code>
|
||||
</attribute>
|
||||
<!--${AOs::XT_Test1}-->
|
||||
<attribute name="XT_Test1" type="QP::QXThread * const" visibility="0x00" properties="0x00"/>
|
||||
<!--${AOs::XT_Test2}-->
|
||||
@ -373,7 +394,8 @@ m_fork[n] = FREE;</action>
|
||||
namespace DPP {
|
||||
|
||||
enum DPPSignals {
|
||||
EAT_SIG = QP::Q_USER_SIG, // published by Table to let a philosopher eat
|
||||
TIMEOUT_SIG = QP::Q_USER_SIG, // time event timeout
|
||||
EAT_SIG, // published by Table to let a philosopher eat
|
||||
DONE_SIG, // published by Philosopher when done eating
|
||||
PAUSE_SIG, // published by BSP to pause the application
|
||||
SERVE_SIG, // published by BSP to serve re-start serving forks
|
||||
@ -386,22 +408,20 @@ enum DPPSignals {
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
$declare(Events::TableEvt)
|
||||
$declare${Events::TableEvt}
|
||||
|
||||
// number of philosophers
|
||||
#define N_PHILO (static_cast<uint8_t>(5))
|
||||
#define N_PHILO ((uint8_t)5)
|
||||
|
||||
$declare(AOs::AO_Philo[N_PHILO])
|
||||
|
||||
$declare(AOs::AO_Table)
|
||||
$declare${AOs::AO_Philo[N_PHILO]}
|
||||
$declare${AOs::AO_Table}
|
||||
|
||||
#ifdef QXK_HPP
|
||||
$declare(AOs::XT_Test1)
|
||||
$declare(AOs::XT_Test2)
|
||||
$declare${AOs::XT_Test1}
|
||||
$declare${AOs::XT_Test2}
|
||||
#endif // QXK_HPP
|
||||
|
||||
#endif // DPP_HPP
|
||||
</text>
|
||||
#endif // DPP_HPP</text>
|
||||
</file>
|
||||
<!--${.::philo.cpp}-->
|
||||
<file name="philo.cpp">
|
||||
@ -409,16 +429,14 @@ $declare(AOs::XT_Test2)
|
||||
#include "dpp.hpp"
|
||||
#include "bsp.hpp"
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// Active object class -------------------------------------------------------
|
||||
$declare(AOs::Philo)
|
||||
$declare${AOs::Philo}
|
||||
|
||||
namespace DPP {
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Philo l_philo[N_PHILO]; // storage for all Philos
|
||||
|
||||
// helper function to provide a randomized think time for Philos
|
||||
inline QP::QTimeEvtCtr think_time() {
|
||||
return static_cast<QP::QTimeEvtCtr>((BSP::random() % BSP::TICKS_PER_SEC)
|
||||
@ -431,28 +449,15 @@ inline QP::QTimeEvtCtr eat_time() {
|
||||
+ BSP::TICKS_PER_SEC);
|
||||
}
|
||||
|
||||
// helper function to provide the ID of Philo
|
||||
inline uint8_t PHILO_ID(Philo const * const philo) {
|
||||
return static_cast<uint8_t>(philo - l_philo);
|
||||
// helper function to provide the ID of Philo "me"
|
||||
inline uint8_t PHILO_ID(Philo const * const me) {
|
||||
return static_cast<uint8_t>(me - &Philo::inst[0]);
|
||||
}
|
||||
|
||||
enum InternalSignals { // internal signals
|
||||
TIMEOUT_SIG = MAX_SIG
|
||||
};
|
||||
|
||||
// Global objects ------------------------------------------------------------
|
||||
QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
|
||||
&l_philo[0],
|
||||
&l_philo[1],
|
||||
&l_philo[2],
|
||||
&l_philo[3],
|
||||
&l_philo[4]
|
||||
};
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
// Philo definition ----------------------------------------------------------
|
||||
$define(AOs::Philo)</text>
|
||||
$define${AOs::AO_Philo[N_PHILO]}
|
||||
$define${AOs::Philo}</text>
|
||||
</file>
|
||||
<!--${.::table.cpp}-->
|
||||
<file name="table.cpp">
|
||||
@ -460,13 +465,13 @@ $define(AOs::Philo)</text>
|
||||
#include "dpp.hpp"
|
||||
#include "bsp.hpp"
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// Active object class -------------------------------------------------------
|
||||
$declare(AOs::Table)
|
||||
|
||||
namespace DPP {
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// helper function to provide the RIGHT neighbour of a Philo[n]
|
||||
inline uint8_t RIGHT(uint8_t const n) {
|
||||
return static_cast<uint8_t>((n + (N_PHILO - 1U)) % N_PHILO);
|
||||
@ -477,24 +482,17 @@ inline uint8_t LEFT(uint8_t const n) {
|
||||
return static_cast<uint8_t>((n + 1U) % N_PHILO);
|
||||
}
|
||||
|
||||
static uint8_t const FREE = static_cast<uint8_t>(0);
|
||||
static uint8_t const USED = static_cast<uint8_t>(1);
|
||||
constexpr uint8_t FREE = static_cast<uint8_t>(0);
|
||||
constexpr uint8_t USED = static_cast<uint8_t>(1);
|
||||
|
||||
static char_t const * const THINKING = &"thinking"[0];
|
||||
static char_t const * const HUNGRY = &"hungry "[0];
|
||||
static char_t const * const EATING = &"eating "[0];
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Table l_table; // the single instance of the Table active object
|
||||
|
||||
// Global-scope objects ------------------------------------------------------
|
||||
QP::QActive * const AO_Table = &l_table; // "opaque" AO pointer
|
||||
constexpr char_t const * const THINKING = &"thinking"[0];
|
||||
constexpr char_t const * const HUNGRY = &"hungry "[0];
|
||||
constexpr char_t const * const EATING = &"eating "[0];
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
//............................................................................
|
||||
$define(AOs::Table)
|
||||
</text>
|
||||
$define${AOs::AO_Table}
|
||||
$define(AOs::Table)</text>
|
||||
</file>
|
||||
</directory>
|
||||
</model>
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Model: dpp.qm
|
||||
// File: ${.::philo.cpp}
|
||||
//
|
||||
// This code has been generated by QM 4.6.0 <www.state-machine.com/qm/>.
|
||||
// This code has been generated by QM 5.0.3 <www.state-machine.com/qm/>.
|
||||
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
|
||||
//
|
||||
// This program is open source software: you can redistribute it and/or
|
||||
@ -20,12 +20,17 @@
|
||||
#include "dpp.hpp"
|
||||
#include "bsp.hpp"
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// Active object class -------------------------------------------------------
|
||||
//.$declare${AOs::Philo} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::Philo} .............................................................
|
||||
class Philo : public QP::QActive {
|
||||
public:
|
||||
static Philo inst[N_PHILO];
|
||||
|
||||
private:
|
||||
QP::QTimeEvt m_timeEvt;
|
||||
|
||||
@ -44,11 +49,7 @@ protected:
|
||||
|
||||
namespace DPP {
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Philo l_philo[N_PHILO]; // storage for all Philos
|
||||
|
||||
// helper function to provide a randomized think time for Philos
|
||||
inline QP::QTimeEvtCtr think_time() {
|
||||
return static_cast<QP::QTimeEvtCtr>((BSP::random() % BSP::TICKS_PER_SEC)
|
||||
@ -61,40 +62,41 @@ inline QP::QTimeEvtCtr eat_time() {
|
||||
+ BSP::TICKS_PER_SEC);
|
||||
}
|
||||
|
||||
// helper function to provide the ID of Philo
|
||||
inline uint8_t PHILO_ID(Philo const * const philo) {
|
||||
return static_cast<uint8_t>(philo - l_philo);
|
||||
// helper function to provide the ID of Philo "me"
|
||||
inline uint8_t PHILO_ID(Philo const * const me) {
|
||||
return static_cast<uint8_t>(me - &Philo::inst[0]);
|
||||
}
|
||||
|
||||
enum InternalSignals { // internal signals
|
||||
TIMEOUT_SIG = MAX_SIG
|
||||
};
|
||||
|
||||
// Global objects ------------------------------------------------------------
|
||||
QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
|
||||
&l_philo[0],
|
||||
&l_philo[1],
|
||||
&l_philo[2],
|
||||
&l_philo[3],
|
||||
&l_philo[4]
|
||||
};
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
// Philo definition ----------------------------------------------------------
|
||||
//.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
//. Check for the minimum required QP version
|
||||
#if (QP_VERSION < 650U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
|
||||
#error qpcpp version 6.5.0 or higher required
|
||||
#if (QP_VERSION < 680U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
|
||||
#error qpcpp version 6.8.0 or higher required
|
||||
#endif
|
||||
//.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//.$define${AOs::AO_Philo[N_PHILO]} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::AO_Philo[N_PHILO]} .................................................
|
||||
QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
|
||||
&Philo::inst[0],
|
||||
&Philo::inst[1],
|
||||
&Philo::inst[2],
|
||||
&Philo::inst[3],
|
||||
&Philo::inst[4]
|
||||
};
|
||||
|
||||
} // namespace DPP
|
||||
//.$enddef${AOs::AO_Philo[N_PHILO]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//.$define${AOs::Philo} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::Philo} .............................................................
|
||||
Philo Philo::inst[N_PHILO];
|
||||
//.${AOs::Philo::Philo} ......................................................
|
||||
Philo::Philo()
|
||||
: QActive(Q_STATE_CAST(&Philo::initial)),
|
||||
: QActive(&initial),
|
||||
m_timeEvt(this, TIMEOUT_SIG, 0U)
|
||||
{}
|
||||
|
||||
@ -103,27 +105,30 @@ Q_STATE_DEF(Philo, initial) {
|
||||
//.${AOs::Philo::SM::initial}
|
||||
static bool registered = false; // starts off with 0, per C-standard
|
||||
(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);
|
||||
|
||||
if (!registered) {
|
||||
registered = true;
|
||||
|
||||
QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[4].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4].m_timeEvt);
|
||||
|
||||
QS_FUN_DICTIONARY(&initial);
|
||||
QS_FUN_DICTIONARY(&thinking);
|
||||
QS_FUN_DICTIONARY(&hungry);
|
||||
QS_FUN_DICTIONARY(&eating);
|
||||
QS_FUN_DICTIONARY(&Philo::initial);
|
||||
QS_FUN_DICTIONARY(&Philo::thinking);
|
||||
QS_FUN_DICTIONARY(&Philo::hungry);
|
||||
QS_FUN_DICTIONARY(&Philo::eating);
|
||||
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, nullptr);
|
||||
}
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal for each Philos
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, this); // signal for each Philos
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);
|
||||
return tran(&thinking);
|
||||
}
|
||||
//.${AOs::Philo::SM::thinking} ...............................................
|
||||
@ -150,7 +155,7 @@ Q_STATE_DEF(Philo, thinking) {
|
||||
//.${AOs::Philo::SM::thinking::EAT, DONE}
|
||||
case EAT_SIG: // intentionally fall through
|
||||
case DONE_SIG: {
|
||||
// EAT or DONE must be for other Philos than this one
|
||||
/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));
|
||||
status_ = Q_RET_HANDLED;
|
||||
break;
|
||||
@ -231,7 +236,7 @@ Q_STATE_DEF(Philo, eating) {
|
||||
//.${AOs::Philo::SM::eating::EAT, DONE}
|
||||
case EAT_SIG: // intentionally fall through
|
||||
case DONE_SIG: {
|
||||
// EAT or DONE must be for other Philos than this one
|
||||
/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));
|
||||
status_ = Q_RET_HANDLED;
|
||||
break;
|
||||
|
@ -49,14 +49,6 @@ int main() {
|
||||
|
||||
DPP::BSP::init(); // initialize the BSP
|
||||
|
||||
// object dictionaries...
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Table);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[0]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[1]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[2]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[3]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[4]);
|
||||
|
||||
QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe
|
||||
|
||||
// initialize event pools...
|
||||
|
@ -1,324 +0,0 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Product: QSpyView -- Customization example for DPP application
|
||||
# Last updated for version 6.6.0
|
||||
# Last updated on 2019-11-30
|
||||
#
|
||||
# Q u a n t u m L e a P s
|
||||
# ---------------------------
|
||||
# innovating embedded systems
|
||||
#
|
||||
# Copyright (C) Quantum Leaps, LLC, All rights reserved.
|
||||
#
|
||||
# This program is open source software: you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as published
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Contact information:
|
||||
# https://www.state-machine.com
|
||||
# mailto:info@state-machine.com
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# command handlers ===========================================================
|
||||
proc onMyCommand {} {
|
||||
# do something here, for example:
|
||||
# - inject an event to the Target
|
||||
# - send a command to the Target
|
||||
# - peek memory
|
||||
# - poke memory
|
||||
# - exectute system tick in the Target
|
||||
# - open a dialog box...
|
||||
# - etc.
|
||||
|
||||
# as an example, the following code sends a command to the Target
|
||||
variable ::qspy::QS_RX
|
||||
::qspy::sendPkt [binary format cciii $qspy::QS_RX(COMMAND) 1 12345 0 0]
|
||||
}
|
||||
|
||||
proc onPause {} {
|
||||
global theButtonId theBtnState
|
||||
if {[string equal $theBtnState BTN_UP]} { ;# is DWN?
|
||||
set theBtnState BTN_DWN
|
||||
::qspy::sendCurrObj SM_AO AO_Table
|
||||
::qspy::sendEvent 255 PAUSE_SIG
|
||||
#::qspy::sendEvent 6 6 0
|
||||
} else {
|
||||
set theBtnState BTN_UP
|
||||
::qspy::sendCurrObj SM_AO l_table
|
||||
::qspy::sendEvent 255 SERVE_SIG
|
||||
#::qspy::sendEvent 6 7 0
|
||||
}
|
||||
.canv.c itemconfigure $theButtonId -image ::img::$theBtnState
|
||||
}
|
||||
|
||||
# additinal menu options =====================================================
|
||||
.mbar.cust add command -label "MyCommand" -command onMyCommand
|
||||
|
||||
|
||||
# specific canvas for DPP ====================================================
|
||||
set scriptFolder [file dirname [file normalize [info script]]]
|
||||
|
||||
image create photo ::img::e -file $scriptFolder/img/eating.gif
|
||||
image create photo ::img::h -file $scriptFolder/img/hungry.gif
|
||||
image create photo ::img::t -file $scriptFolder/img/thinking.gif
|
||||
image create photo ::img::BTN_UP -file $scriptFolder/img/BTN_UP.gif
|
||||
image create photo ::img::BTN_DWN -file $scriptFolder/img/BTN_DWN.gif
|
||||
|
||||
wm geometry .canv =400x260
|
||||
.canv.c configure -width 400
|
||||
.canv.c configure -height 260
|
||||
|
||||
set thePhiloId [.canv.c create image 190 57 -image ::img::t]
|
||||
.canv.c create image 273 100 -image ::img::t
|
||||
.canv.c create image 237 185 -image ::img::t
|
||||
.canv.c create image 146 184 -image ::img::t
|
||||
.canv.c create image 107 100 -image ::img::t
|
||||
|
||||
|
||||
set theButtonId [.canv.c create image 200 120 -image ::img::BTN_UP]
|
||||
set theBtnState BTN_UP
|
||||
.canv.c bind $theButtonId <ButtonPress-1> onPause
|
||||
|
||||
# QS record handlers =========================================================
|
||||
|
||||
# user record handlers [100..124] --------------------------------------------
|
||||
proc ::qspy::rec100 {} { ;# QS_USER
|
||||
variable thePkt
|
||||
variable theFmt
|
||||
binary scan $thePkt xx$theFmt(tstamp)xcxa* \
|
||||
ts philoNum stat
|
||||
|
||||
dispTxt [format "%010u Philo %1d is %s" $ts $philoNum $stat]
|
||||
|
||||
global thePhiloId
|
||||
set img [string index $stat 0]
|
||||
.canv.c itemconfigure [expr $thePhiloId + $philoNum] -image ::img::$img
|
||||
}
|
||||
#.............................................................................
|
||||
proc ::qspy::rec101 {} { ;# QS_USER + 1
|
||||
variable thePkt
|
||||
variable theFmt
|
||||
binary scan $thePkt xc$theFmt(tstamp)xc \
|
||||
cmdId ts par
|
||||
dispTxt [format "%010u cmd=%d param=%d" $ts $cmdId $par]
|
||||
}
|
||||
|
||||
proc ::qspy::rec102 {} { ;# QS_USER + 2
|
||||
}
|
||||
proc ::qspy::rec103 {} { ;# QS_USER + 3
|
||||
}
|
||||
proc ::qspy::rec104 {} { ;# QS_USER + 4
|
||||
}
|
||||
proc ::qspy::rec105 {} { ;# QS_USER + 5
|
||||
}
|
||||
proc ::qspy::rec106 {} { ;# QS_USER + 6
|
||||
}
|
||||
proc ::qspy::rec107 {} { ;# QS_USER + 7
|
||||
}
|
||||
proc ::qspy::rec108 {} { ;# QS_USER + 8
|
||||
}
|
||||
proc ::qspy::rec109 {} { ;# QS_USER + 9
|
||||
}
|
||||
proc ::qspy::rec110 {} { ;# QS_USER + 10
|
||||
}
|
||||
proc ::qspy::rec111 {} { ;# QS_USER + 11
|
||||
}
|
||||
proc ::qspy::rec112 {} { ;# QS_USER + 12
|
||||
}
|
||||
proc ::qspy::rec113 {} { ;# QS_USER + 13
|
||||
}
|
||||
proc ::qspy::rec114 {} { ;# QS_USER + 14
|
||||
}
|
||||
proc ::qspy::rec115 {} { ;# QS_USER + 15
|
||||
}
|
||||
proc ::qspy::rec116 {} { ;# QS_USER + 16
|
||||
}
|
||||
proc ::qspy::rec117 {} { ;# QS_USER + 17
|
||||
}
|
||||
proc ::qspy::rec118 {} { ;# QS_USER + 18
|
||||
}
|
||||
proc ::qspy::rec119 {} { ;# QS_USER + 19
|
||||
}
|
||||
proc ::qspy::rec120 {} { ;# QS_USER + 20
|
||||
}
|
||||
proc ::qspy::rec121 {} { ;# QS_USER + 21
|
||||
}
|
||||
proc ::qspy::rec122 {} { ;# QS_USER + 22
|
||||
}
|
||||
proc ::qspy::rec123 {} { ;# QS_USER + 23
|
||||
}
|
||||
proc ::qspy::rec124 {} { ;# QS_USER + 24
|
||||
}
|
||||
|
||||
|
||||
# special record handlers ----------------------------------------------------
|
||||
proc ::qspy::recRESET {} { ;# target reset callback
|
||||
}
|
||||
proc ::qspy::recINFO {} { ;# target info callback
|
||||
}
|
||||
|
||||
# standard record handlers [1..54] -------------------------------------------
|
||||
proc ::qspy::rec0 {} { ;# QS_EMPTY
|
||||
}
|
||||
|
||||
# [1] QEP records...
|
||||
proc ::qspy::rec1 {} { ;# QS_QEP_STATE_ENTRY
|
||||
}
|
||||
proc ::qspy::rec2 {} { ;# QS_QEP_STATE_EXIT
|
||||
}
|
||||
proc ::qspy::rec3 {} { ;# QS_QEP_STATE_INIT
|
||||
}
|
||||
proc ::qspy::rec4 {} { ;# QS_QEP_INIT_TRAN
|
||||
}
|
||||
proc ::qspy::rec5 {} { ;# QS_QEP_INTERN_TRAN
|
||||
}
|
||||
proc ::qspy::rec6 {} { ;# QS_QEP_TRAN
|
||||
}
|
||||
proc ::qspy::rec7 {} { ;# QS_QEP_IGNORED
|
||||
}
|
||||
proc ::qspy::rec8 {} { ;# QS_QEP_DISPATCH
|
||||
}
|
||||
proc ::qspy::rec9 {} { ;# QS_QEP_UNHANDLED
|
||||
}
|
||||
|
||||
# [10] QF records...
|
||||
proc ::qspy::rec10 {} { ;# QS_QF_ACTIVE_ADD
|
||||
}
|
||||
proc ::qspy::rec11 {} { ;# QS_QF_ACTIVE_REMOVE
|
||||
}
|
||||
proc ::qspy::rec12 {} { ;# QS_QF_ACTIVE_SUBSCRIBE
|
||||
}
|
||||
proc ::qspy::rec13 {} { ;# QS_QF_ACTIVE_UNSUBSCRIBE
|
||||
}
|
||||
proc ::qspy::rec14 {} { ;# QS_QF_ACTIVE_POST_FIFO
|
||||
}
|
||||
proc ::qspy::rec15 {} { ;# QS_QF_ACTIVE_POST_LIFO
|
||||
}
|
||||
proc ::qspy::rec16 {} { ;# QS_QF_ACTIVE_GET
|
||||
}
|
||||
proc ::qspy::rec17 {} { ;# QS_QF_ACTIVE_GET_LAST
|
||||
}
|
||||
proc ::qspy::rec18 {} { ;# QS_QF_EQUEUE_INIT
|
||||
}
|
||||
proc ::qspy::rec19 {} { ;# QS_QF_EQUEUE_POST_FIFO
|
||||
}
|
||||
proc ::qspy::rec20 {} { ;# QS_QF_EQUEUE_POST_LIFO
|
||||
}
|
||||
proc ::qspy::rec21 {} { ;# QS_QF_EQUEUE_GET
|
||||
}
|
||||
proc ::qspy::rec22 {} { ;# QS_QF_EQUEUE_GET_LAST
|
||||
}
|
||||
proc ::qspy::rec23 {} { ;# QS_QF_MPOOL_INIT
|
||||
}
|
||||
proc ::qspy::rec24 {} { ;# QS_QF_MPOOL_GET
|
||||
}
|
||||
proc ::qspy::rec25 {} { ;# QS_QF_MPOOL_PUT
|
||||
}
|
||||
proc ::qspy::rec26 {} { ;# QS_QF_PUBLISH
|
||||
}
|
||||
proc ::qspy::rec27 {} { ;# QS_QF_RESERVED8
|
||||
}
|
||||
proc ::qspy::rec28 {} { ;# QS_QF_NEW
|
||||
}
|
||||
proc ::qspy::rec29 {} { ;# QS_QF_GC_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec30 {} { ;# QS_QF_GC
|
||||
}
|
||||
proc ::qspy::rec31 {} { ;# QS_QF_TICK
|
||||
}
|
||||
proc ::qspy::rec32 {} { ;# QS_QF_TIMEEVT_ARM
|
||||
}
|
||||
proc ::qspy::rec33 {} { ;# QS_QF_TIMEEVT_AUTO_DISARM
|
||||
}
|
||||
proc ::qspy::rec34 {} { ;# QS_QF_TIMEEVT_DISARM_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec35 {} { ;# QS_QF_TIMEEVT_DISARM
|
||||
}
|
||||
proc ::qspy::rec36 {} { ;# QS_QF_TIMEEVT_REARM
|
||||
}
|
||||
proc ::qspy::rec37 {} { ;# QS_QF_TIMEEVT_POST
|
||||
}
|
||||
proc ::qspy::rec38 {} { ;# QS_QF_TIMEEVT_CTR
|
||||
}
|
||||
proc ::qspy::rec39 {} { ;# QS_QF_CRIT_ENTRY
|
||||
}
|
||||
proc ::qspy::rec40 {} { ;# QS_QF_CRIT_EXIT
|
||||
}
|
||||
proc ::qspy::rec41 {} { ;# QS_QF_ISR_ENTRY
|
||||
}
|
||||
proc ::qspy::rec42 {} { ;# QS_QF_ISR_EXIT
|
||||
}
|
||||
proc ::qspy::rec43 {} { ;# QS_QF_INT_DISABLE
|
||||
}
|
||||
proc ::qspy::rec44 {} { ;# QS_QF_INT_ENABLE
|
||||
}
|
||||
proc ::qspy::rec45 {} { ;# QS_QF_ACTIVE_POST_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec46 {} { ;# QS_QF_EQUEUE_POST_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec47 {} { ;# QS_QF_MPOOL_GET_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec48 {} { ;# QS_QF_RESERVED1
|
||||
}
|
||||
proc ::qspy::rec49 {} { ;# QS_QF_RESERVED0
|
||||
}
|
||||
|
||||
# [50] QK/QV records
|
||||
proc ::qspy::rec50 {} { ;# QS_QK_MUTEX_LOCK
|
||||
}
|
||||
proc ::qspy::rec51 {} { ;# QS_QK_MUTEX_UNLOCK
|
||||
}
|
||||
proc ::qspy::rec52 {} { ;# QS_QVK_SCHEDULE
|
||||
}
|
||||
proc ::qspy::rec53 {} { ;# QS_QVK_IDLE
|
||||
}
|
||||
proc ::qspy::rec54 {} { ;# QS_QK_RESUME
|
||||
}
|
||||
|
||||
# [55] Additional QEP records
|
||||
proc ::qspy::rec55 {} { ;# QS_QEP_TRAN_HIST
|
||||
}
|
||||
proc ::qspy::rec56 {} { ;# QS_QEP_TRAN_EP
|
||||
}
|
||||
proc ::qspy::rec57 {} { ;# QS_QEP_TRAN_XP
|
||||
}
|
||||
proc ::qspy::rec58 {} { ;# QS_QEP_RESERVED1
|
||||
}
|
||||
proc ::qspy::rec59 {} { ;# QS_QEP_RESERVED0
|
||||
}
|
||||
|
||||
# Miscellaneous QS records
|
||||
proc ::qspy::rec60 {} { ;# QS_SIG_DICT
|
||||
}
|
||||
proc ::qspy::rec61 {} { ;# QS_OBJ_DICT
|
||||
}
|
||||
proc ::qspy::rec62 {} { ;# QS_FUN_DICT
|
||||
}
|
||||
proc ::qspy::rec63 {} { ;# QS_USR_DICT
|
||||
}
|
||||
|
||||
# proc ::qspy::64 ;# QS_TARGET_INFO not used, see proc recINFO
|
||||
|
||||
proc ::qspy::rec65 {} { ;# QS_RESERVED0
|
||||
}
|
||||
proc ::qspy::rec66 {} { ;# QS_RX_STATUS
|
||||
}
|
||||
proc ::qspy::rec67 {} { ;# QS_TEST_STATUS
|
||||
}
|
||||
proc ::qspy::rec68 {} { ;# QS_PEEK_DATA
|
||||
}
|
||||
proc ::qspy::rec69 {} { ;# QS_ASSERT_FAIL
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
if "%QTOOLS%"=="" (
|
||||
set QTOOLS=C:\qp\qtools
|
||||
)
|
||||
wish %QTOOLS%\qspy\tcl\qspyview.tcl dpp.tcl
|
@ -49,14 +49,6 @@ int main() {
|
||||
|
||||
DPP::BSP::init(); // initialize the BSP
|
||||
|
||||
// object dictionaries...
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Table);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[0]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[1]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[2]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[3]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[4]);
|
||||
|
||||
QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe
|
||||
|
||||
// initialize event pools...
|
||||
|
104
examples/arm-cm/dpp_efm32-slstk3401a/qview/dpp.py
Normal file
@ -0,0 +1,104 @@
|
||||
# This is an example of QView customization for a specific application
|
||||
# (DPP in this case). This example animates the Phil images on the
|
||||
# QView canvas. Additionally, there is a button in the middle of the screen,
|
||||
# which, when clicked once pauses the DPP ("forks" are not being served).
|
||||
# A second click on the button, "un-pauses" the DPP ("forks" are served
|
||||
# to all hungry Philosophers).
|
||||
#
|
||||
# This version of the DPP customization uses the application-specific
|
||||
# packet QS_USER_00 (PHILO_STAT) produced when the status of a Philo changes.
|
||||
#
|
||||
|
||||
class DPP:
|
||||
def __init__(self):
|
||||
|
||||
# add commands to the Custom menu...
|
||||
QView.custom_menu.add_command(label="Custom command",
|
||||
command=self.cust_command)
|
||||
|
||||
# configure the custom QView.canvas...
|
||||
QView.show_canvas() # make the canvas visible
|
||||
QView.canvas.configure(width=400, height=260)
|
||||
|
||||
# tuple of activity images (correspond to self._philo_state)
|
||||
self._act_img = (
|
||||
PhotoImage(file=HOME_DIR + "/img/thinking.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/hungry.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/eating.gif"),
|
||||
)
|
||||
# tuple of philo canvas images (correspond to self._philo_obj)
|
||||
self._philo_img = (\
|
||||
QView.canvas.create_image(190, 57, image=self._act_img[0]),
|
||||
QView.canvas.create_image(273, 100, image=self._act_img[0]),
|
||||
QView.canvas.create_image(237, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(146, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(107, 100, image=self._act_img[0])
|
||||
)
|
||||
|
||||
# button images for UP and DOWN
|
||||
self.img_UP = PhotoImage(file=HOME_DIR + "/img/BTN_UP.gif")
|
||||
self.img_DWN = PhotoImage(file=HOME_DIR + "/img/BTN_DWN.gif")
|
||||
|
||||
# images of a button for pause/serve
|
||||
self.btn = QView.canvas.create_image(200, 120, image=self.img_UP)
|
||||
QView.canvas.tag_bind(self.btn, "<ButtonPress-1>", self.cust_pause)
|
||||
|
||||
# request target reset on startup...
|
||||
# NOTE: Normally, for an embedded application you would like
|
||||
# to start with resetting the Target, to start clean with
|
||||
# Qs dictionaries, etc.
|
||||
reset_target()
|
||||
|
||||
# on_reset() callback
|
||||
def on_reset(self):
|
||||
# clear the lists
|
||||
self._philo_obj = [0, 0, 0, 0, 0]
|
||||
self._philo_state = [0, 0, 0]
|
||||
|
||||
# on_run() callback
|
||||
def on_run(self):
|
||||
glb_filter("QS_USER_00")
|
||||
|
||||
# NOTE: the names of objects for loc_filter() and current_obj()
|
||||
# must match the QS Object Dictionaries produced by the application.
|
||||
current_obj(OBJ_AO, "Table::inst")
|
||||
loc_filter(OBJ_TE, "Philo::inst[0].timeEvt")
|
||||
|
||||
# turn lists into tuples for better performance
|
||||
self._philo_obj = tuple(self._philo_obj)
|
||||
self._philo_state = tuple(self._philo_state)
|
||||
|
||||
|
||||
# example of a custom command
|
||||
def cust_command(self):
|
||||
command(1, 12345)
|
||||
|
||||
# example of a custom interaction with a canvas object (pause/serve)
|
||||
def cust_pause(self, event):
|
||||
if QView.canvas.itemcget(self.btn, "image") != str(self.img_UP):
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_UP)
|
||||
post("SERVE_SIG")
|
||||
QView.print_text("Table SERVING")
|
||||
else:
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_DWN)
|
||||
post("PAUSE_SIG")
|
||||
QView.print_text("Table PAUSED")
|
||||
|
||||
# intercept the QS_USER_00 application-specific packet
|
||||
# this packet has the following structure (see bsp.c:displayPhilStat()):
|
||||
# record-ID, seq-num, Timestamp, format-byte, Philo-num,
|
||||
# format-bye, Zero-terminated string (status)
|
||||
def QS_USER_00(self, packet):
|
||||
# unpack: Timestamp->data[0], Philo-num->data[1], status->data[3]
|
||||
data = qunpack("xxTxBxZ", packet)
|
||||
i = data[1]
|
||||
j = ("t", "h", "e").index(data[2][0]) # the first letter
|
||||
|
||||
# animate the given philo image according to its activity
|
||||
QView.canvas.itemconfig(self._philo_img[i], image=self._act_img[j])
|
||||
|
||||
# print a message to the text view
|
||||
QView.print_text("%010d Philo %1d is %s"%(data[0], i, data[2]))
|
||||
|
||||
#=============================================================================
|
||||
QView.customize(DPP()) # set the QView customization
|
148
examples/arm-cm/dpp_efm32-slstk3401a/qview/dpp1.py
Normal file
@ -0,0 +1,148 @@
|
||||
# This is an example of QView customization for a specific application
|
||||
# (DPP in this case). This example animates the Phil images on the
|
||||
# QView canvas. Additionally, there is a button in the middle of the screen,
|
||||
# which, when clicked once pauses the DPP ("forks" are not being served).
|
||||
# A second click on the button, "un-pauses" the DPP ("forks" are served
|
||||
# to all hungry Philosophers).
|
||||
#
|
||||
# This version of the DPP customization uses the standard QS_QEP_STATE_ENTRY
|
||||
# packet, which provides information about the current states of the dining
|
||||
# Philosophers. The example also demonstrates how to intercept the QS
|
||||
# "dictionary" records QS_OBJ_DICT and QS_FUN_DICT to extract the information
|
||||
# about the addresses of the Philosopher objects and the states of their
|
||||
# state machines.
|
||||
#
|
||||
|
||||
class DPP:
|
||||
def __init__(self):
|
||||
|
||||
# add commands to the Custom menu...
|
||||
QView.custom_menu.add_command(label="Custom command",
|
||||
command=self.cust_command)
|
||||
|
||||
# configure the custom QView.canvas...
|
||||
QView.show_canvas() # make the canvas visible
|
||||
QView.canvas.configure(width=400, height=260)
|
||||
|
||||
# tuple of activity images (correspond to self._philo_state)
|
||||
self._act_img = (
|
||||
PhotoImage(file=HOME_DIR + "/img/thinking.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/hungry.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/eating.gif"),
|
||||
)
|
||||
# tuple of philo canvas images (correspond to self._philo_obj)
|
||||
self._philo_img = (\
|
||||
QView.canvas.create_image(190, 57, image=self._act_img[0]),
|
||||
QView.canvas.create_image(273, 100, image=self._act_img[0]),
|
||||
QView.canvas.create_image(237, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(146, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(107, 100, image=self._act_img[0])
|
||||
)
|
||||
|
||||
# button images for UP and DOWN
|
||||
self.img_UP = PhotoImage(file=HOME_DIR + "/img/BTN_UP.gif")
|
||||
self.img_DWN = PhotoImage(file=HOME_DIR + "/img/BTN_DWN.gif")
|
||||
|
||||
# images of a button for pause/serve
|
||||
self.btn = QView.canvas.create_image(200, 120, image=self.img_UP)
|
||||
QView.canvas.tag_bind(self.btn, "<ButtonPress-1>", self.cust_pause)
|
||||
|
||||
# request target reset on startup...
|
||||
# NOTE: Normally, for an embedded application you would like
|
||||
# to start with resetting the Target, to start clean with
|
||||
# Qs dictionaries, etc.
|
||||
reset_target()
|
||||
|
||||
# on_reset() callback invoked when Target-reset packet is received
|
||||
# NOTE: the QS dictionaries are not known at this time yet, so
|
||||
# this callback shouild generally not set filters or current objects
|
||||
def on_reset(self):
|
||||
# (re)set the lists
|
||||
self._philo_obj = [0, 0, 0, 0, 0]
|
||||
self._philo_state = [0, 0, 0]
|
||||
|
||||
# on_run() callback invoked when the QF_RUN packet is received
|
||||
# NOTE: the QS dictionaries are typically known at this time yet, so
|
||||
# this callback can set filters or current objects
|
||||
def on_run(self):
|
||||
glb_filter("QS_QEP_TRAN")
|
||||
|
||||
# NOTE: the names of objects for loc_filter() and current_obj()
|
||||
# must match the QS Object Dictionaries produced by the application.
|
||||
current_obj(OBJ_AO, "Table::inst")
|
||||
loc_filter(OBJ_TE, "Philo::inst[0].m_timeEvt")
|
||||
|
||||
# turn lists into tuples for better performance
|
||||
self._philo_obj = tuple(self._philo_obj)
|
||||
self._philo_state = tuple(self._philo_state)
|
||||
|
||||
|
||||
# example of a custom command
|
||||
def cust_command(self):
|
||||
command(1, 12345)
|
||||
|
||||
# example of a custom interaction with a canvas object (pause/serve)
|
||||
def cust_pause(self, event):
|
||||
if QView.canvas.itemcget(self.btn, "image") != str(self.img_UP):
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_UP)
|
||||
post("SERVE_SIG")
|
||||
QView.print_text("Table SERVING")
|
||||
else:
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_DWN)
|
||||
post("PAUSE_SIG")
|
||||
QView.print_text("Table PAUSED")
|
||||
|
||||
# intercept the QS_OBJ_DICT stadard packet
|
||||
# this packet has the following structure:
|
||||
# record-ID, seq-num, Object-ptr, Zero-terminated string
|
||||
def QS_OBJ_DICT(self, packet):
|
||||
data = qunpack("xxOZ", packet)
|
||||
try:
|
||||
# NOTE: the names of objects must match the QS Object Dictionaries
|
||||
# produced by the application.
|
||||
i = ("Philo::inst[0]",
|
||||
"Philo::inst[1]",
|
||||
"Philo::inst[2]",
|
||||
"Philo::inst[3]",
|
||||
"Philo::inst[4]").index(data[1])
|
||||
self._philo_obj[i] = data[0]
|
||||
except:
|
||||
pass # dictionary for a different object
|
||||
|
||||
# intercept the QS_FUN_DICT stadard packet
|
||||
# this packet has the following structure:
|
||||
# record-ID, seq-num, Function-ptr, Zero-terminated string
|
||||
def QS_FUN_DICT(self, packet):
|
||||
data = qunpack("xxFZ", packet)
|
||||
try:
|
||||
# NOTE: the names of states must match the QS Object Dictionaries
|
||||
# produced by the application.
|
||||
j = ("Philo::thinking",
|
||||
"Philo::hungry",
|
||||
"Philo::eating").index(data[1])
|
||||
self._philo_state[j] = data[0]
|
||||
except:
|
||||
pass # dictionary for a different state
|
||||
|
||||
# intercept the QS_QEP_TRAN stadard packet
|
||||
# this packet has the following structure:
|
||||
# record-ID, seq-num, Timestamp, Signal, Object-ptr,
|
||||
# Function-ptr (source state), Function-ptr (new active state)
|
||||
def QS_QEP_TRAN(self, packet):
|
||||
data = qunpack("xxTSOFF", packet)
|
||||
try:
|
||||
i = self._philo_obj.index(data[2])
|
||||
j = self._philo_state.index(data[4])
|
||||
|
||||
# animate the given philo image according to its activity
|
||||
QView.canvas.itemconfig(self._philo_img[i],
|
||||
image=self._act_img[j])
|
||||
# print a message to the text view
|
||||
QView.print_text("%010d Philo %d is %s"\
|
||||
%(data[0], i, ("thinking", "hungry", "eating")[j]))
|
||||
except:
|
||||
pass # state-entry in a different object
|
||||
|
||||
#=============================================================================
|
||||
# instantiate the DPP class and set it as the QView customization
|
||||
QView.customize(DPP())
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
8
examples/arm-cm/dpp_efm32-slstk3401a/qview/qview-dpp.bat
Normal file
@ -0,0 +1,8 @@
|
||||
@setlocal
|
||||
|
||||
if "%QTOOLS%"=="" (
|
||||
set QTOOLS=C:\qp\qtools
|
||||
)
|
||||
python %QTOOLS%\qview\qview.py dpp.py
|
||||
|
||||
@endlocal
|
BIN
examples/arm-cm/dpp_efm32-slstk3401a/qview/qview-dpp.lnk
Normal file
@ -0,0 +1,8 @@
|
||||
@setlocal
|
||||
|
||||
if "%QTOOLS%"=="" (
|
||||
set QTOOLS=C:\qp\qtools
|
||||
)
|
||||
python %QTOOLS%\qview\qview.py dpp1.py
|
||||
|
||||
@endlocal
|
BIN
examples/arm-cm/dpp_efm32-slstk3401a/qview/qview-dpp1.lnk
Normal file
@ -56,12 +56,7 @@ int main() {
|
||||
DPP::BSP::init(); // initialize the BSP
|
||||
|
||||
// object dictionaries...
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Table);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[0]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[1]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[2]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[3]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[4]);
|
||||
QS_OBJ_DICTIONARY(&l_ticker0);
|
||||
|
||||
// init publish-subscribe
|
||||
QP::QF::psInit(subscrSto, Q_DIM(subscrSto));
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Model: dpp.qm
|
||||
// File: ${.::table.cpp}
|
||||
//
|
||||
// This code has been generated by QM 4.6.0 <www.state-machine.com/qm/>.
|
||||
// This code has been generated by QM 5.0.3 <www.state-machine.com/qm/>.
|
||||
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
|
||||
//
|
||||
// This program is open source software: you can redistribute it and/or
|
||||
@ -20,12 +20,17 @@
|
||||
#include "dpp.hpp"
|
||||
#include "bsp.hpp"
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// Active object class -------------------------------------------------------
|
||||
//.$declare${AOs::Table} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::Table} .............................................................
|
||||
class Table : public QP::QActive {
|
||||
public:
|
||||
static Table inst;
|
||||
|
||||
private:
|
||||
uint8_t m_fork[N_PHILO];
|
||||
bool m_isHungry[N_PHILO];
|
||||
@ -45,8 +50,6 @@ protected:
|
||||
|
||||
namespace DPP {
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// helper function to provide the RIGHT neighbour of a Philo[n]
|
||||
inline uint8_t RIGHT(uint8_t const n) {
|
||||
return static_cast<uint8_t>((n + (N_PHILO - 1U)) % N_PHILO);
|
||||
@ -57,35 +60,37 @@ inline uint8_t LEFT(uint8_t const n) {
|
||||
return static_cast<uint8_t>((n + 1U) % N_PHILO);
|
||||
}
|
||||
|
||||
static uint8_t const FREE = 0U;
|
||||
static uint8_t const USED = 1U;
|
||||
constexpr uint8_t FREE = static_cast<uint8_t>(0);
|
||||
constexpr uint8_t USED = static_cast<uint8_t>(1);
|
||||
|
||||
static char const * const THINKING = &"thinking"[0];
|
||||
static char const * const HUNGRY = &"hungry "[0];
|
||||
static char const * const EATING = &"eating "[0];
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Table l_table; // the single instance of the Table active object
|
||||
|
||||
// Global-scope objects ------------------------------------------------------
|
||||
QP::QActive * const AO_Table = &l_table; // "opaque" AO pointer
|
||||
constexpr char_t const * const THINKING = &"thinking"[0];
|
||||
constexpr char_t const * const HUNGRY = &"hungry "[0];
|
||||
constexpr char_t const * const EATING = &"eating "[0];
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
//............................................................................
|
||||
//.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
//. Check for the minimum required QP version
|
||||
#if (QP_VERSION < 650U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
|
||||
#error qpcpp version 6.5.0 or higher required
|
||||
#if (QP_VERSION < 680U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
|
||||
#error qpcpp version 6.8.0 or higher required
|
||||
#endif
|
||||
//.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//.$define${AOs::AO_Table} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::AO_Table} ..........................................................
|
||||
QP::QActive * const AO_Table = &Table::inst; // "opaque" pointer to Table AO
|
||||
|
||||
} // namespace DPP
|
||||
//.$enddef${AOs::AO_Table} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//.$define${AOs::Table} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::Table} .............................................................
|
||||
Table Table::inst;
|
||||
//.${AOs::Table::Table} ......................................................
|
||||
Table::Table()
|
||||
: QActive(Q_STATE_CAST(&Table::initial))
|
||||
: QActive(&initial)
|
||||
{
|
||||
for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
m_fork[n] = FREE;
|
||||
@ -98,6 +103,16 @@ Q_STATE_DEF(Table, initial) {
|
||||
//.${AOs::Table::SM::initial}
|
||||
(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
QS_OBJ_DICTIONARY(&Table::inst);
|
||||
|
||||
QS_SIG_DICTIONARY(DONE_SIG, nullptr); // global signals
|
||||
QS_SIG_DICTIONARY(EAT_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(PAUSE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(SERVE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(TEST_SIG, nullptr);
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal just for Table
|
||||
|
||||
subscribe(DONE_SIG);
|
||||
subscribe(PAUSE_SIG);
|
||||
subscribe(SERVE_SIG);
|
||||
@ -109,19 +124,9 @@ Q_STATE_DEF(Table, initial) {
|
||||
BSP::displayPhilStat(n, THINKING);
|
||||
}
|
||||
|
||||
// global signals...
|
||||
QS_SIG_DICTIONARY(DONE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(EAT_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(PAUSE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(SERVE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(TEST_SIG, nullptr);
|
||||
|
||||
// signals just for this AO...
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this);
|
||||
|
||||
QS_FUN_DICTIONARY(&active);
|
||||
QS_FUN_DICTIONARY(&serving);
|
||||
QS_FUN_DICTIONARY(&paused);
|
||||
QS_FUN_DICTIONARY(&Table::active);
|
||||
QS_FUN_DICTIONARY(&Table::serving);
|
||||
QS_FUN_DICTIONARY(&Table::paused);
|
||||
|
||||
return tran(&serving);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//****************************************************************************
|
||||
// Product: DPP example, Win32-GUI
|
||||
// Last Updated for Version: 6.8.4
|
||||
// Last Updated for Version: 6.9.0
|
||||
// Date of the Last Update: 2020-08-06
|
||||
//
|
||||
// Q u a n t u m L e a P s
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Model: dpp.qm
|
||||
// File: ${.::dpp.hpp}
|
||||
//
|
||||
// This code has been generated by QM 4.6.0 <www.state-machine.com/qm/>.
|
||||
// This code has been generated by QM 5.0.3 <www.state-machine.com/qm/>.
|
||||
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
|
||||
//
|
||||
// This program is open source software: you can redistribute it and/or
|
||||
@ -22,7 +22,8 @@
|
||||
namespace DPP {
|
||||
|
||||
enum DPPSignals {
|
||||
EAT_SIG = QP::Q_USER_SIG, // published by Table to let a philosopher eat
|
||||
TIMEOUT_SIG = QP::Q_USER_SIG, // time event timeout
|
||||
EAT_SIG, // published by Table to let a philosopher eat
|
||||
DONE_SIG, // published by Philosopher when done eating
|
||||
PAUSE_SIG, // published by BSP to pause the application
|
||||
SERVE_SIG, // published by BSP to serve re-start serving forks
|
||||
@ -48,7 +49,7 @@ public:
|
||||
//.$enddecl${Events::TableEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
// number of philosophers
|
||||
#define N_PHILO (static_cast<uint8_t>(5))
|
||||
#define N_PHILO ((uint8_t)5)
|
||||
|
||||
//.$declare${AOs::AO_Philo[N_PHILO]} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
@ -57,7 +58,6 @@ extern QP::QActive * const AO_Philo[N_PHILO];
|
||||
|
||||
} // namespace DPP
|
||||
//.$enddecl${AOs::AO_Philo[N_PHILO]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
//.$declare${AOs::AO_Table} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
@ -83,4 +83,4 @@ extern QP::QXThread * const XT_Test2;
|
||||
//.$enddecl${AOs::XT_Test2} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
#endif // QXK_HPP
|
||||
|
||||
#endif // DPP_HPP
|
||||
#endif // DPP_HPP
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<model version="4.6.0" links="1">
|
||||
<model version="5.0.3" links="1">
|
||||
<documentation>Dining Philosopher Problem example with MSM state machines</documentation>
|
||||
<!--${qpcpp}-->
|
||||
<framework name="qpcpp"/>
|
||||
@ -15,11 +15,15 @@
|
||||
<package name="AOs" stereotype="0x02" namespace="DPP::">
|
||||
<!--${AOs::Philo}-->
|
||||
<class name="Philo" superclass="qpcpp::QActive">
|
||||
<!--${AOs::Philo::inst[N_PHILO]}-->
|
||||
<attribute name="inst[N_PHILO]" type="Philo" visibility="0x00" properties="0x01">
|
||||
<documentation>The array of static insts of the Philo class (Singleton pattern)</documentation>
|
||||
</attribute>
|
||||
<!--${AOs::Philo::m_timeEvt}-->
|
||||
<attribute name="m_timeEvt" type="QP::QTimeEvt" visibility="0x02" properties="0x00"/>
|
||||
<!--${AOs::Philo::Philo}-->
|
||||
<operation name="Philo" type="" visibility="0x00" properties="0x00">
|
||||
<code> : QActive(Q_STATE_CAST(&Philo::initial)),
|
||||
<code> : QActive(&initial),
|
||||
m_timeEvt(this, TIMEOUT_SIG, 0U)</code>
|
||||
</operation>
|
||||
<!--${AOs::Philo::SM}-->
|
||||
@ -28,27 +32,30 @@
|
||||
<initial target="../1">
|
||||
<action>static bool registered = false; // starts off with 0, per C-standard
|
||||
(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);
|
||||
|
||||
if (!registered) {
|
||||
registered = true;
|
||||
|
||||
QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[4].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4].m_timeEvt);
|
||||
|
||||
QS_FUN_DICTIONARY(&initial);
|
||||
QS_FUN_DICTIONARY(&thinking);
|
||||
QS_FUN_DICTIONARY(&hungry);
|
||||
QS_FUN_DICTIONARY(&eating);
|
||||
QS_FUN_DICTIONARY(&Philo::initial);
|
||||
QS_FUN_DICTIONARY(&Philo::thinking);
|
||||
QS_FUN_DICTIONARY(&Philo::hungry);
|
||||
QS_FUN_DICTIONARY(&Philo::eating);
|
||||
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, nullptr);
|
||||
}
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal for each Philos
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, this); // signal for each Philos</action>
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);</action>
|
||||
<initial_glyph conn="2,3,5,1,20,5,-3">
|
||||
<action box="0,-2,6,2"/>
|
||||
</initial_glyph>
|
||||
@ -65,7 +72,7 @@ QS_SIG_DICTIONARY(TIMEOUT_SIG, this); // signal for each Philos</action>
|
||||
</tran>
|
||||
<!--${AOs::Philo::SM::thinking::EAT, DONE}-->
|
||||
<tran trig="EAT, DONE">
|
||||
<action>// EAT or DONE must be for other Philos than this one
|
||||
<action>/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));</action>
|
||||
<tran_glyph conn="2,16,3,-1,13">
|
||||
<action box="0,-2,14,2"/>
|
||||
@ -127,7 +134,7 @@ QP::QF::PUBLISH(pe, this);
|
||||
</tran>
|
||||
<!--${AOs::Philo::SM::eating::EAT, DONE}-->
|
||||
<tran trig="EAT, DONE">
|
||||
<action>// EAT or DONE must be for other Philos than this one
|
||||
<action>/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));</action>
|
||||
<tran_glyph conn="2,55,3,-1,13">
|
||||
<action box="0,-2,14,2"/>
|
||||
@ -143,13 +150,17 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));</action>
|
||||
</class>
|
||||
<!--${AOs::Table}-->
|
||||
<class name="Table" superclass="qpcpp::QActive">
|
||||
<!--${AOs::Table::inst}-->
|
||||
<attribute name="inst" type="Table" visibility="0x00" properties="0x01">
|
||||
<documentation>The only static inst of the Table class (Singleton pattern)</documentation>
|
||||
</attribute>
|
||||
<!--${AOs::Table::m_fork[N_PHILO]}-->
|
||||
<attribute name="m_fork[N_PHILO]" type="uint8_t" visibility="0x02" properties="0x00"/>
|
||||
<!--${AOs::Table::m_isHungry[N_PHILO]}-->
|
||||
<attribute name="m_isHungry[N_PHILO]" type="bool" visibility="0x02" properties="0x00"/>
|
||||
<!--${AOs::Table::Table}-->
|
||||
<operation name="Table" type="" visibility="0x00" properties="0x00">
|
||||
<code> : QActive(Q_STATE_CAST(&Table::initial))
|
||||
<code> : QActive(&initial)
|
||||
|
||||
for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
m_fork[n] = FREE;
|
||||
@ -162,6 +173,16 @@ for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
<initial target="../1/2">
|
||||
<action>(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
QS_OBJ_DICTIONARY(&Table::inst);
|
||||
|
||||
QS_SIG_DICTIONARY(DONE_SIG, nullptr); // global signals
|
||||
QS_SIG_DICTIONARY(EAT_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(PAUSE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(SERVE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(TEST_SIG, nullptr);
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal just for Table
|
||||
|
||||
subscribe(DONE_SIG);
|
||||
subscribe(PAUSE_SIG);
|
||||
subscribe(SERVE_SIG);
|
||||
@ -171,17 +192,7 @@ for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
m_fork[n] = FREE;
|
||||
m_isHungry[n] = false;
|
||||
BSP::displayPhilStat(n, THINKING);
|
||||
}
|
||||
|
||||
// global signals...
|
||||
QS_SIG_DICTIONARY(DONE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(EAT_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(PAUSE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(SERVE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(TEST_SIG, nullptr);
|
||||
|
||||
// signals just for this AO...
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this);</action>
|
||||
}</action>
|
||||
<initial_glyph conn="3,3,5,1,45,18,-10">
|
||||
<action box="0,-2,6,2"/>
|
||||
</initial_glyph>
|
||||
@ -355,9 +366,19 @@ m_fork[n] = FREE;</action>
|
||||
</statechart>
|
||||
</class>
|
||||
<!--${AOs::AO_Philo[N_PHILO]}-->
|
||||
<attribute name="AO_Philo[N_PHILO]" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
|
||||
<attribute name="AO_Philo[N_PHILO]" type="QP::QActive * const" visibility="0x00" properties="0x00">
|
||||
<code>= { // "opaque" pointers to Philo AO
|
||||
&Philo::inst[0],
|
||||
&Philo::inst[1],
|
||||
&Philo::inst[2],
|
||||
&Philo::inst[3],
|
||||
&Philo::inst[4]
|
||||
};</code>
|
||||
</attribute>
|
||||
<!--${AOs::AO_Table}-->
|
||||
<attribute name="AO_Table" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
|
||||
<attribute name="AO_Table" type="QP::QActive * const" visibility="0x00" properties="0x00">
|
||||
<code>= &Table::inst; // "opaque" pointer to Table AO</code>
|
||||
</attribute>
|
||||
<!--${AOs::XT_Test1}-->
|
||||
<attribute name="XT_Test1" type="QP::QXThread * const" visibility="0x00" properties="0x00"/>
|
||||
<!--${AOs::XT_Test2}-->
|
||||
@ -373,7 +394,8 @@ m_fork[n] = FREE;</action>
|
||||
namespace DPP {
|
||||
|
||||
enum DPPSignals {
|
||||
EAT_SIG = QP::Q_USER_SIG, // published by Table to let a philosopher eat
|
||||
TIMEOUT_SIG = QP::Q_USER_SIG, // time event timeout
|
||||
EAT_SIG, // published by Table to let a philosopher eat
|
||||
DONE_SIG, // published by Philosopher when done eating
|
||||
PAUSE_SIG, // published by BSP to pause the application
|
||||
SERVE_SIG, // published by BSP to serve re-start serving forks
|
||||
@ -386,22 +408,20 @@ enum DPPSignals {
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
$declare(Events::TableEvt)
|
||||
$declare${Events::TableEvt}
|
||||
|
||||
// number of philosophers
|
||||
#define N_PHILO (static_cast<uint8_t>(5))
|
||||
#define N_PHILO ((uint8_t)5)
|
||||
|
||||
$declare(AOs::AO_Philo[N_PHILO])
|
||||
|
||||
$declare(AOs::AO_Table)
|
||||
$declare${AOs::AO_Philo[N_PHILO]}
|
||||
$declare${AOs::AO_Table}
|
||||
|
||||
#ifdef QXK_HPP
|
||||
$declare(AOs::XT_Test1)
|
||||
$declare(AOs::XT_Test2)
|
||||
$declare${AOs::XT_Test1}
|
||||
$declare${AOs::XT_Test2}
|
||||
#endif // QXK_HPP
|
||||
|
||||
#endif // DPP_HPP
|
||||
</text>
|
||||
#endif // DPP_HPP</text>
|
||||
</file>
|
||||
<!--${.::philo.cpp}-->
|
||||
<file name="philo.cpp">
|
||||
@ -409,16 +429,14 @@ $declare(AOs::XT_Test2)
|
||||
#include "dpp.hpp"
|
||||
#include "bsp.hpp"
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// Active object class -------------------------------------------------------
|
||||
$declare(AOs::Philo)
|
||||
$declare${AOs::Philo}
|
||||
|
||||
namespace DPP {
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Philo l_philo[N_PHILO]; // storage for all Philos
|
||||
|
||||
// helper function to provide a randomized think time for Philos
|
||||
inline QP::QTimeEvtCtr think_time() {
|
||||
return static_cast<QP::QTimeEvtCtr>((BSP::random() % BSP::TICKS_PER_SEC)
|
||||
@ -431,28 +449,15 @@ inline QP::QTimeEvtCtr eat_time() {
|
||||
+ BSP::TICKS_PER_SEC);
|
||||
}
|
||||
|
||||
// helper function to provide the ID of Philo
|
||||
inline uint8_t PHILO_ID(Philo const * const philo) {
|
||||
return static_cast<uint8_t>(philo - l_philo);
|
||||
// helper function to provide the ID of Philo "me"
|
||||
inline uint8_t PHILO_ID(Philo const * const me) {
|
||||
return static_cast<uint8_t>(me - &Philo::inst[0]);
|
||||
}
|
||||
|
||||
enum InternalSignals { // internal signals
|
||||
TIMEOUT_SIG = MAX_SIG
|
||||
};
|
||||
|
||||
// Global objects ------------------------------------------------------------
|
||||
QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
|
||||
&l_philo[0],
|
||||
&l_philo[1],
|
||||
&l_philo[2],
|
||||
&l_philo[3],
|
||||
&l_philo[4]
|
||||
};
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
// Philo definition ----------------------------------------------------------
|
||||
$define(AOs::Philo)</text>
|
||||
$define${AOs::AO_Philo[N_PHILO]}
|
||||
$define${AOs::Philo}</text>
|
||||
</file>
|
||||
<!--${.::table.cpp}-->
|
||||
<file name="table.cpp">
|
||||
@ -460,13 +465,13 @@ $define(AOs::Philo)</text>
|
||||
#include "dpp.hpp"
|
||||
#include "bsp.hpp"
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// Active object class -------------------------------------------------------
|
||||
$declare(AOs::Table)
|
||||
|
||||
namespace DPP {
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// helper function to provide the RIGHT neighbour of a Philo[n]
|
||||
inline uint8_t RIGHT(uint8_t const n) {
|
||||
return static_cast<uint8_t>((n + (N_PHILO - 1U)) % N_PHILO);
|
||||
@ -477,24 +482,17 @@ inline uint8_t LEFT(uint8_t const n) {
|
||||
return static_cast<uint8_t>((n + 1U) % N_PHILO);
|
||||
}
|
||||
|
||||
static uint8_t const FREE = static_cast<uint8_t>(0);
|
||||
static uint8_t const USED = static_cast<uint8_t>(1);
|
||||
constexpr uint8_t FREE = static_cast<uint8_t>(0);
|
||||
constexpr uint8_t USED = static_cast<uint8_t>(1);
|
||||
|
||||
static char_t const * const THINKING = &"thinking"[0];
|
||||
static char_t const * const HUNGRY = &"hungry "[0];
|
||||
static char_t const * const EATING = &"eating "[0];
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Table l_table; // the single instance of the Table active object
|
||||
|
||||
// Global-scope objects ------------------------------------------------------
|
||||
QP::QActive * const AO_Table = &l_table; // "opaque" AO pointer
|
||||
constexpr char_t const * const THINKING = &"thinking"[0];
|
||||
constexpr char_t const * const HUNGRY = &"hungry "[0];
|
||||
constexpr char_t const * const EATING = &"eating "[0];
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
//............................................................................
|
||||
$define(AOs::Table)
|
||||
</text>
|
||||
$define${AOs::AO_Table}
|
||||
$define(AOs::Table)</text>
|
||||
</file>
|
||||
</directory>
|
||||
</model>
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Model: dpp.qm
|
||||
// File: ${.::philo.cpp}
|
||||
//
|
||||
// This code has been generated by QM 4.6.0 <www.state-machine.com/qm/>.
|
||||
// This code has been generated by QM 5.0.3 <www.state-machine.com/qm/>.
|
||||
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
|
||||
//
|
||||
// This program is open source software: you can redistribute it and/or
|
||||
@ -20,12 +20,17 @@
|
||||
#include "dpp.hpp"
|
||||
#include "bsp.hpp"
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// Active object class -------------------------------------------------------
|
||||
//.$declare${AOs::Philo} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::Philo} .............................................................
|
||||
class Philo : public QP::QActive {
|
||||
public:
|
||||
static Philo inst[N_PHILO];
|
||||
|
||||
private:
|
||||
QP::QTimeEvt m_timeEvt;
|
||||
|
||||
@ -44,11 +49,7 @@ protected:
|
||||
|
||||
namespace DPP {
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Philo l_philo[N_PHILO]; // storage for all Philos
|
||||
|
||||
// helper function to provide a randomized think time for Philos
|
||||
inline QP::QTimeEvtCtr think_time() {
|
||||
return static_cast<QP::QTimeEvtCtr>((BSP::random() % BSP::TICKS_PER_SEC)
|
||||
@ -61,40 +62,41 @@ inline QP::QTimeEvtCtr eat_time() {
|
||||
+ BSP::TICKS_PER_SEC);
|
||||
}
|
||||
|
||||
// helper function to provide the ID of Philo
|
||||
inline uint8_t PHILO_ID(Philo const * const philo) {
|
||||
return static_cast<uint8_t>(philo - l_philo);
|
||||
// helper function to provide the ID of Philo "me"
|
||||
inline uint8_t PHILO_ID(Philo const * const me) {
|
||||
return static_cast<uint8_t>(me - &Philo::inst[0]);
|
||||
}
|
||||
|
||||
enum InternalSignals { // internal signals
|
||||
TIMEOUT_SIG = MAX_SIG
|
||||
};
|
||||
|
||||
// Global objects ------------------------------------------------------------
|
||||
QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
|
||||
&l_philo[0],
|
||||
&l_philo[1],
|
||||
&l_philo[2],
|
||||
&l_philo[3],
|
||||
&l_philo[4]
|
||||
};
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
// Philo definition ----------------------------------------------------------
|
||||
//.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
//. Check for the minimum required QP version
|
||||
#if (QP_VERSION < 650U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
|
||||
#error qpcpp version 6.5.0 or higher required
|
||||
#if (QP_VERSION < 680U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
|
||||
#error qpcpp version 6.8.0 or higher required
|
||||
#endif
|
||||
//.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//.$define${AOs::AO_Philo[N_PHILO]} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::AO_Philo[N_PHILO]} .................................................
|
||||
QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
|
||||
&Philo::inst[0],
|
||||
&Philo::inst[1],
|
||||
&Philo::inst[2],
|
||||
&Philo::inst[3],
|
||||
&Philo::inst[4]
|
||||
};
|
||||
|
||||
} // namespace DPP
|
||||
//.$enddef${AOs::AO_Philo[N_PHILO]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//.$define${AOs::Philo} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::Philo} .............................................................
|
||||
Philo Philo::inst[N_PHILO];
|
||||
//.${AOs::Philo::Philo} ......................................................
|
||||
Philo::Philo()
|
||||
: QActive(Q_STATE_CAST(&Philo::initial)),
|
||||
: QActive(&initial),
|
||||
m_timeEvt(this, TIMEOUT_SIG, 0U)
|
||||
{}
|
||||
|
||||
@ -103,27 +105,30 @@ Q_STATE_DEF(Philo, initial) {
|
||||
//.${AOs::Philo::SM::initial}
|
||||
static bool registered = false; // starts off with 0, per C-standard
|
||||
(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);
|
||||
|
||||
if (!registered) {
|
||||
registered = true;
|
||||
|
||||
QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[4].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4].m_timeEvt);
|
||||
|
||||
QS_FUN_DICTIONARY(&initial);
|
||||
QS_FUN_DICTIONARY(&thinking);
|
||||
QS_FUN_DICTIONARY(&hungry);
|
||||
QS_FUN_DICTIONARY(&eating);
|
||||
QS_FUN_DICTIONARY(&Philo::initial);
|
||||
QS_FUN_DICTIONARY(&Philo::thinking);
|
||||
QS_FUN_DICTIONARY(&Philo::hungry);
|
||||
QS_FUN_DICTIONARY(&Philo::eating);
|
||||
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, nullptr);
|
||||
}
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal for each Philos
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, this); // signal for each Philos
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);
|
||||
return tran(&thinking);
|
||||
}
|
||||
//.${AOs::Philo::SM::thinking} ...............................................
|
||||
@ -150,7 +155,7 @@ Q_STATE_DEF(Philo, thinking) {
|
||||
//.${AOs::Philo::SM::thinking::EAT, DONE}
|
||||
case EAT_SIG: // intentionally fall through
|
||||
case DONE_SIG: {
|
||||
// EAT or DONE must be for other Philos than this one
|
||||
/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));
|
||||
status_ = Q_RET_HANDLED;
|
||||
break;
|
||||
@ -231,7 +236,7 @@ Q_STATE_DEF(Philo, eating) {
|
||||
//.${AOs::Philo::SM::eating::EAT, DONE}
|
||||
case EAT_SIG: // intentionally fall through
|
||||
case DONE_SIG: {
|
||||
// EAT or DONE must be for other Philos than this one
|
||||
/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));
|
||||
status_ = Q_RET_HANDLED;
|
||||
break;
|
||||
|
@ -49,14 +49,6 @@ int main() {
|
||||
|
||||
DPP::BSP::init(); // initialize the BSP
|
||||
|
||||
// object dictionaries...
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Table);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[0]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[1]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[2]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[3]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[4]);
|
||||
|
||||
QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe
|
||||
|
||||
// initialize event pools...
|
||||
|
@ -1,324 +0,0 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Product: QSpyView -- Customization example for DPP application
|
||||
# Last updated for version 6.6.0
|
||||
# Last updated on 2019-11-30
|
||||
#
|
||||
# Q u a n t u m L e a P s
|
||||
# ---------------------------
|
||||
# innovating embedded systems
|
||||
#
|
||||
# Copyright (C) Quantum Leaps, LLC, All rights reserved.
|
||||
#
|
||||
# This program is open source software: you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as published
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Contact information:
|
||||
# https://www.state-machine.com
|
||||
# mailto:info@state-machine.com
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# command handlers ===========================================================
|
||||
proc onMyCommand {} {
|
||||
# do something here, for example:
|
||||
# - inject an event to the Target
|
||||
# - send a command to the Target
|
||||
# - peek memory
|
||||
# - poke memory
|
||||
# - exectute system tick in the Target
|
||||
# - open a dialog box...
|
||||
# - etc.
|
||||
|
||||
# as an example, the following code sends a command to the Target
|
||||
variable ::qspy::QS_RX
|
||||
::qspy::sendPkt [binary format cciii $qspy::QS_RX(COMMAND) 1 12345 0 0]
|
||||
}
|
||||
|
||||
proc onPause {} {
|
||||
global theButtonId theBtnState
|
||||
if {[string equal $theBtnState BTN_UP]} { ;# is DWN?
|
||||
set theBtnState BTN_DWN
|
||||
::qspy::sendCurrObj SM_AO AO_Table
|
||||
::qspy::sendEvent 255 PAUSE_SIG
|
||||
#::qspy::sendEvent 6 6 0
|
||||
} else {
|
||||
set theBtnState BTN_UP
|
||||
::qspy::sendCurrObj SM_AO l_table
|
||||
::qspy::sendEvent 255 SERVE_SIG
|
||||
#::qspy::sendEvent 6 7 0
|
||||
}
|
||||
.canv.c itemconfigure $theButtonId -image ::img::$theBtnState
|
||||
}
|
||||
|
||||
# additinal menu options =====================================================
|
||||
.mbar.cust add command -label "MyCommand" -command onMyCommand
|
||||
|
||||
|
||||
# specific canvas for DPP ====================================================
|
||||
set scriptFolder [file dirname [file normalize [info script]]]
|
||||
|
||||
image create photo ::img::e -file $scriptFolder/img/eating.gif
|
||||
image create photo ::img::h -file $scriptFolder/img/hungry.gif
|
||||
image create photo ::img::t -file $scriptFolder/img/thinking.gif
|
||||
image create photo ::img::BTN_UP -file $scriptFolder/img/BTN_UP.gif
|
||||
image create photo ::img::BTN_DWN -file $scriptFolder/img/BTN_DWN.gif
|
||||
|
||||
wm geometry .canv =400x260
|
||||
.canv.c configure -width 400
|
||||
.canv.c configure -height 260
|
||||
|
||||
set thePhiloId [.canv.c create image 190 57 -image ::img::t]
|
||||
.canv.c create image 273 100 -image ::img::t
|
||||
.canv.c create image 237 185 -image ::img::t
|
||||
.canv.c create image 146 184 -image ::img::t
|
||||
.canv.c create image 107 100 -image ::img::t
|
||||
|
||||
|
||||
set theButtonId [.canv.c create image 200 120 -image ::img::BTN_UP]
|
||||
set theBtnState BTN_UP
|
||||
.canv.c bind $theButtonId <ButtonPress-1> onPause
|
||||
|
||||
# QS record handlers =========================================================
|
||||
|
||||
# user record handlers [100..124] --------------------------------------------
|
||||
proc ::qspy::rec100 {} { ;# QS_USER
|
||||
variable thePkt
|
||||
variable theFmt
|
||||
binary scan $thePkt xx$theFmt(tstamp)xcxa* \
|
||||
ts philoNum stat
|
||||
|
||||
dispTxt [format "%010u Philo %1d is %s" $ts $philoNum $stat]
|
||||
|
||||
global thePhiloId
|
||||
set img [string index $stat 0]
|
||||
.canv.c itemconfigure [expr $thePhiloId + $philoNum] -image ::img::$img
|
||||
}
|
||||
#.............................................................................
|
||||
proc ::qspy::rec101 {} { ;# QS_USER + 1
|
||||
variable thePkt
|
||||
variable theFmt
|
||||
binary scan $thePkt xc$theFmt(tstamp)xc \
|
||||
cmdId ts par
|
||||
dispTxt [format "%010u cmd=%d param=%d" $ts $cmdId $par]
|
||||
}
|
||||
|
||||
proc ::qspy::rec102 {} { ;# QS_USER + 2
|
||||
}
|
||||
proc ::qspy::rec103 {} { ;# QS_USER + 3
|
||||
}
|
||||
proc ::qspy::rec104 {} { ;# QS_USER + 4
|
||||
}
|
||||
proc ::qspy::rec105 {} { ;# QS_USER + 5
|
||||
}
|
||||
proc ::qspy::rec106 {} { ;# QS_USER + 6
|
||||
}
|
||||
proc ::qspy::rec107 {} { ;# QS_USER + 7
|
||||
}
|
||||
proc ::qspy::rec108 {} { ;# QS_USER + 8
|
||||
}
|
||||
proc ::qspy::rec109 {} { ;# QS_USER + 9
|
||||
}
|
||||
proc ::qspy::rec110 {} { ;# QS_USER + 10
|
||||
}
|
||||
proc ::qspy::rec111 {} { ;# QS_USER + 11
|
||||
}
|
||||
proc ::qspy::rec112 {} { ;# QS_USER + 12
|
||||
}
|
||||
proc ::qspy::rec113 {} { ;# QS_USER + 13
|
||||
}
|
||||
proc ::qspy::rec114 {} { ;# QS_USER + 14
|
||||
}
|
||||
proc ::qspy::rec115 {} { ;# QS_USER + 15
|
||||
}
|
||||
proc ::qspy::rec116 {} { ;# QS_USER + 16
|
||||
}
|
||||
proc ::qspy::rec117 {} { ;# QS_USER + 17
|
||||
}
|
||||
proc ::qspy::rec118 {} { ;# QS_USER + 18
|
||||
}
|
||||
proc ::qspy::rec119 {} { ;# QS_USER + 19
|
||||
}
|
||||
proc ::qspy::rec120 {} { ;# QS_USER + 20
|
||||
}
|
||||
proc ::qspy::rec121 {} { ;# QS_USER + 21
|
||||
}
|
||||
proc ::qspy::rec122 {} { ;# QS_USER + 22
|
||||
}
|
||||
proc ::qspy::rec123 {} { ;# QS_USER + 23
|
||||
}
|
||||
proc ::qspy::rec124 {} { ;# QS_USER + 24
|
||||
}
|
||||
|
||||
|
||||
# special record handlers ----------------------------------------------------
|
||||
proc ::qspy::recRESET {} { ;# target reset callback
|
||||
}
|
||||
proc ::qspy::recINFO {} { ;# target info callback
|
||||
}
|
||||
|
||||
# standard record handlers [1..54] -------------------------------------------
|
||||
proc ::qspy::rec0 {} { ;# QS_EMPTY
|
||||
}
|
||||
|
||||
# [1] QEP records...
|
||||
proc ::qspy::rec1 {} { ;# QS_QEP_STATE_ENTRY
|
||||
}
|
||||
proc ::qspy::rec2 {} { ;# QS_QEP_STATE_EXIT
|
||||
}
|
||||
proc ::qspy::rec3 {} { ;# QS_QEP_STATE_INIT
|
||||
}
|
||||
proc ::qspy::rec4 {} { ;# QS_QEP_INIT_TRAN
|
||||
}
|
||||
proc ::qspy::rec5 {} { ;# QS_QEP_INTERN_TRAN
|
||||
}
|
||||
proc ::qspy::rec6 {} { ;# QS_QEP_TRAN
|
||||
}
|
||||
proc ::qspy::rec7 {} { ;# QS_QEP_IGNORED
|
||||
}
|
||||
proc ::qspy::rec8 {} { ;# QS_QEP_DISPATCH
|
||||
}
|
||||
proc ::qspy::rec9 {} { ;# QS_QEP_UNHANDLED
|
||||
}
|
||||
|
||||
# [10] QF records...
|
||||
proc ::qspy::rec10 {} { ;# QS_QF_ACTIVE_ADD
|
||||
}
|
||||
proc ::qspy::rec11 {} { ;# QS_QF_ACTIVE_REMOVE
|
||||
}
|
||||
proc ::qspy::rec12 {} { ;# QS_QF_ACTIVE_SUBSCRIBE
|
||||
}
|
||||
proc ::qspy::rec13 {} { ;# QS_QF_ACTIVE_UNSUBSCRIBE
|
||||
}
|
||||
proc ::qspy::rec14 {} { ;# QS_QF_ACTIVE_POST_FIFO
|
||||
}
|
||||
proc ::qspy::rec15 {} { ;# QS_QF_ACTIVE_POST_LIFO
|
||||
}
|
||||
proc ::qspy::rec16 {} { ;# QS_QF_ACTIVE_GET
|
||||
}
|
||||
proc ::qspy::rec17 {} { ;# QS_QF_ACTIVE_GET_LAST
|
||||
}
|
||||
proc ::qspy::rec18 {} { ;# QS_QF_EQUEUE_INIT
|
||||
}
|
||||
proc ::qspy::rec19 {} { ;# QS_QF_EQUEUE_POST_FIFO
|
||||
}
|
||||
proc ::qspy::rec20 {} { ;# QS_QF_EQUEUE_POST_LIFO
|
||||
}
|
||||
proc ::qspy::rec21 {} { ;# QS_QF_EQUEUE_GET
|
||||
}
|
||||
proc ::qspy::rec22 {} { ;# QS_QF_EQUEUE_GET_LAST
|
||||
}
|
||||
proc ::qspy::rec23 {} { ;# QS_QF_MPOOL_INIT
|
||||
}
|
||||
proc ::qspy::rec24 {} { ;# QS_QF_MPOOL_GET
|
||||
}
|
||||
proc ::qspy::rec25 {} { ;# QS_QF_MPOOL_PUT
|
||||
}
|
||||
proc ::qspy::rec26 {} { ;# QS_QF_PUBLISH
|
||||
}
|
||||
proc ::qspy::rec27 {} { ;# QS_QF_RESERVED8
|
||||
}
|
||||
proc ::qspy::rec28 {} { ;# QS_QF_NEW
|
||||
}
|
||||
proc ::qspy::rec29 {} { ;# QS_QF_GC_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec30 {} { ;# QS_QF_GC
|
||||
}
|
||||
proc ::qspy::rec31 {} { ;# QS_QF_TICK
|
||||
}
|
||||
proc ::qspy::rec32 {} { ;# QS_QF_TIMEEVT_ARM
|
||||
}
|
||||
proc ::qspy::rec33 {} { ;# QS_QF_TIMEEVT_AUTO_DISARM
|
||||
}
|
||||
proc ::qspy::rec34 {} { ;# QS_QF_TIMEEVT_DISARM_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec35 {} { ;# QS_QF_TIMEEVT_DISARM
|
||||
}
|
||||
proc ::qspy::rec36 {} { ;# QS_QF_TIMEEVT_REARM
|
||||
}
|
||||
proc ::qspy::rec37 {} { ;# QS_QF_TIMEEVT_POST
|
||||
}
|
||||
proc ::qspy::rec38 {} { ;# QS_QF_TIMEEVT_CTR
|
||||
}
|
||||
proc ::qspy::rec39 {} { ;# QS_QF_CRIT_ENTRY
|
||||
}
|
||||
proc ::qspy::rec40 {} { ;# QS_QF_CRIT_EXIT
|
||||
}
|
||||
proc ::qspy::rec41 {} { ;# QS_QF_ISR_ENTRY
|
||||
}
|
||||
proc ::qspy::rec42 {} { ;# QS_QF_ISR_EXIT
|
||||
}
|
||||
proc ::qspy::rec43 {} { ;# QS_QF_INT_DISABLE
|
||||
}
|
||||
proc ::qspy::rec44 {} { ;# QS_QF_INT_ENABLE
|
||||
}
|
||||
proc ::qspy::rec45 {} { ;# QS_QF_ACTIVE_POST_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec46 {} { ;# QS_QF_EQUEUE_POST_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec47 {} { ;# QS_QF_MPOOL_GET_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec48 {} { ;# QS_QF_RESERVED1
|
||||
}
|
||||
proc ::qspy::rec49 {} { ;# QS_QF_RESERVED0
|
||||
}
|
||||
|
||||
# [50] QK/QV records
|
||||
proc ::qspy::rec50 {} { ;# QS_QK_MUTEX_LOCK
|
||||
}
|
||||
proc ::qspy::rec51 {} { ;# QS_QK_MUTEX_UNLOCK
|
||||
}
|
||||
proc ::qspy::rec52 {} { ;# QS_QVK_SCHEDULE
|
||||
}
|
||||
proc ::qspy::rec53 {} { ;# QS_QVK_IDLE
|
||||
}
|
||||
proc ::qspy::rec54 {} { ;# QS_QK_RESUME
|
||||
}
|
||||
|
||||
# [55] Additional QEP records
|
||||
proc ::qspy::rec55 {} { ;# QS_QEP_TRAN_HIST
|
||||
}
|
||||
proc ::qspy::rec56 {} { ;# QS_QEP_TRAN_EP
|
||||
}
|
||||
proc ::qspy::rec57 {} { ;# QS_QEP_TRAN_XP
|
||||
}
|
||||
proc ::qspy::rec58 {} { ;# QS_QEP_RESERVED1
|
||||
}
|
||||
proc ::qspy::rec59 {} { ;# QS_QEP_RESERVED0
|
||||
}
|
||||
|
||||
# Miscellaneous QS records
|
||||
proc ::qspy::rec60 {} { ;# QS_SIG_DICT
|
||||
}
|
||||
proc ::qspy::rec61 {} { ;# QS_OBJ_DICT
|
||||
}
|
||||
proc ::qspy::rec62 {} { ;# QS_FUN_DICT
|
||||
}
|
||||
proc ::qspy::rec63 {} { ;# QS_USR_DICT
|
||||
}
|
||||
|
||||
# proc ::qspy::64 ;# QS_TARGET_INFO not used, see proc recINFO
|
||||
|
||||
proc ::qspy::rec65 {} { ;# QS_RESERVED0
|
||||
}
|
||||
proc ::qspy::rec66 {} { ;# QS_RX_STATUS
|
||||
}
|
||||
proc ::qspy::rec67 {} { ;# QS_TEST_STATUS
|
||||
}
|
||||
proc ::qspy::rec68 {} { ;# QS_PEEK_DATA
|
||||
}
|
||||
proc ::qspy::rec69 {} { ;# QS_ASSERT_FAIL
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
if "%QTOOLS%"=="" (
|
||||
set QTOOLS=C:\qp\qtools
|
||||
)
|
||||
wish %QTOOLS%\qspy\tcl\qspyview.tcl dpp.tcl
|
@ -49,14 +49,6 @@ int main() {
|
||||
|
||||
DPP::BSP::init(); // initialize the BSP
|
||||
|
||||
// object dictionaries...
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Table);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[0]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[1]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[2]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[3]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[4]);
|
||||
|
||||
QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe
|
||||
|
||||
// initialize event pools...
|
||||
|
104
examples/arm-cm/dpp_ek-tm4c123gxl/qview/dpp.py
Normal file
@ -0,0 +1,104 @@
|
||||
# This is an example of QView customization for a specific application
|
||||
# (DPP in this case). This example animates the Phil images on the
|
||||
# QView canvas. Additionally, there is a button in the middle of the screen,
|
||||
# which, when clicked once pauses the DPP ("forks" are not being served).
|
||||
# A second click on the button, "un-pauses" the DPP ("forks" are served
|
||||
# to all hungry Philosophers).
|
||||
#
|
||||
# This version of the DPP customization uses the application-specific
|
||||
# packet QS_USER_00 (PHILO_STAT) produced when the status of a Philo changes.
|
||||
#
|
||||
|
||||
class DPP:
|
||||
def __init__(self):
|
||||
|
||||
# add commands to the Custom menu...
|
||||
QView.custom_menu.add_command(label="Custom command",
|
||||
command=self.cust_command)
|
||||
|
||||
# configure the custom QView.canvas...
|
||||
QView.show_canvas() # make the canvas visible
|
||||
QView.canvas.configure(width=400, height=260)
|
||||
|
||||
# tuple of activity images (correspond to self._philo_state)
|
||||
self._act_img = (
|
||||
PhotoImage(file=HOME_DIR + "/img/thinking.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/hungry.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/eating.gif"),
|
||||
)
|
||||
# tuple of philo canvas images (correspond to self._philo_obj)
|
||||
self._philo_img = (\
|
||||
QView.canvas.create_image(190, 57, image=self._act_img[0]),
|
||||
QView.canvas.create_image(273, 100, image=self._act_img[0]),
|
||||
QView.canvas.create_image(237, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(146, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(107, 100, image=self._act_img[0])
|
||||
)
|
||||
|
||||
# button images for UP and DOWN
|
||||
self.img_UP = PhotoImage(file=HOME_DIR + "/img/BTN_UP.gif")
|
||||
self.img_DWN = PhotoImage(file=HOME_DIR + "/img/BTN_DWN.gif")
|
||||
|
||||
# images of a button for pause/serve
|
||||
self.btn = QView.canvas.create_image(200, 120, image=self.img_UP)
|
||||
QView.canvas.tag_bind(self.btn, "<ButtonPress-1>", self.cust_pause)
|
||||
|
||||
# request target reset on startup...
|
||||
# NOTE: Normally, for an embedded application you would like
|
||||
# to start with resetting the Target, to start clean with
|
||||
# Qs dictionaries, etc.
|
||||
reset_target()
|
||||
|
||||
# on_reset() callback
|
||||
def on_reset(self):
|
||||
# clear the lists
|
||||
self._philo_obj = [0, 0, 0, 0, 0]
|
||||
self._philo_state = [0, 0, 0]
|
||||
|
||||
# on_run() callback
|
||||
def on_run(self):
|
||||
glb_filter("QS_USER_00")
|
||||
|
||||
# NOTE: the names of objects for loc_filter() and current_obj()
|
||||
# must match the QS Object Dictionaries produced by the application.
|
||||
current_obj(OBJ_AO, "Table::inst")
|
||||
loc_filter(OBJ_TE, "Philo::inst[0].timeEvt")
|
||||
|
||||
# turn lists into tuples for better performance
|
||||
self._philo_obj = tuple(self._philo_obj)
|
||||
self._philo_state = tuple(self._philo_state)
|
||||
|
||||
|
||||
# example of a custom command
|
||||
def cust_command(self):
|
||||
command(1, 12345)
|
||||
|
||||
# example of a custom interaction with a canvas object (pause/serve)
|
||||
def cust_pause(self, event):
|
||||
if QView.canvas.itemcget(self.btn, "image") != str(self.img_UP):
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_UP)
|
||||
post("SERVE_SIG")
|
||||
QView.print_text("Table SERVING")
|
||||
else:
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_DWN)
|
||||
post("PAUSE_SIG")
|
||||
QView.print_text("Table PAUSED")
|
||||
|
||||
# intercept the QS_USER_00 application-specific packet
|
||||
# this packet has the following structure (see bsp.c:displayPhilStat()):
|
||||
# record-ID, seq-num, Timestamp, format-byte, Philo-num,
|
||||
# format-bye, Zero-terminated string (status)
|
||||
def QS_USER_00(self, packet):
|
||||
# unpack: Timestamp->data[0], Philo-num->data[1], status->data[3]
|
||||
data = qunpack("xxTxBxZ", packet)
|
||||
i = data[1]
|
||||
j = ("t", "h", "e").index(data[2][0]) # the first letter
|
||||
|
||||
# animate the given philo image according to its activity
|
||||
QView.canvas.itemconfig(self._philo_img[i], image=self._act_img[j])
|
||||
|
||||
# print a message to the text view
|
||||
QView.print_text("%010d Philo %1d is %s"%(data[0], i, data[2]))
|
||||
|
||||
#=============================================================================
|
||||
QView.customize(DPP()) # set the QView customization
|
148
examples/arm-cm/dpp_ek-tm4c123gxl/qview/dpp1.py
Normal file
@ -0,0 +1,148 @@
|
||||
# This is an example of QView customization for a specific application
|
||||
# (DPP in this case). This example animates the Phil images on the
|
||||
# QView canvas. Additionally, there is a button in the middle of the screen,
|
||||
# which, when clicked once pauses the DPP ("forks" are not being served).
|
||||
# A second click on the button, "un-pauses" the DPP ("forks" are served
|
||||
# to all hungry Philosophers).
|
||||
#
|
||||
# This version of the DPP customization uses the standard QS_QEP_STATE_ENTRY
|
||||
# packet, which provides information about the current states of the dining
|
||||
# Philosophers. The example also demonstrates how to intercept the QS
|
||||
# "dictionary" records QS_OBJ_DICT and QS_FUN_DICT to extract the information
|
||||
# about the addresses of the Philosopher objects and the states of their
|
||||
# state machines.
|
||||
#
|
||||
|
||||
class DPP:
|
||||
def __init__(self):
|
||||
|
||||
# add commands to the Custom menu...
|
||||
QView.custom_menu.add_command(label="Custom command",
|
||||
command=self.cust_command)
|
||||
|
||||
# configure the custom QView.canvas...
|
||||
QView.show_canvas() # make the canvas visible
|
||||
QView.canvas.configure(width=400, height=260)
|
||||
|
||||
# tuple of activity images (correspond to self._philo_state)
|
||||
self._act_img = (
|
||||
PhotoImage(file=HOME_DIR + "/img/thinking.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/hungry.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/eating.gif"),
|
||||
)
|
||||
# tuple of philo canvas images (correspond to self._philo_obj)
|
||||
self._philo_img = (\
|
||||
QView.canvas.create_image(190, 57, image=self._act_img[0]),
|
||||
QView.canvas.create_image(273, 100, image=self._act_img[0]),
|
||||
QView.canvas.create_image(237, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(146, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(107, 100, image=self._act_img[0])
|
||||
)
|
||||
|
||||
# button images for UP and DOWN
|
||||
self.img_UP = PhotoImage(file=HOME_DIR + "/img/BTN_UP.gif")
|
||||
self.img_DWN = PhotoImage(file=HOME_DIR + "/img/BTN_DWN.gif")
|
||||
|
||||
# images of a button for pause/serve
|
||||
self.btn = QView.canvas.create_image(200, 120, image=self.img_UP)
|
||||
QView.canvas.tag_bind(self.btn, "<ButtonPress-1>", self.cust_pause)
|
||||
|
||||
# request target reset on startup...
|
||||
# NOTE: Normally, for an embedded application you would like
|
||||
# to start with resetting the Target, to start clean with
|
||||
# Qs dictionaries, etc.
|
||||
reset_target()
|
||||
|
||||
# on_reset() callback invoked when Target-reset packet is received
|
||||
# NOTE: the QS dictionaries are not known at this time yet, so
|
||||
# this callback shouild generally not set filters or current objects
|
||||
def on_reset(self):
|
||||
# (re)set the lists
|
||||
self._philo_obj = [0, 0, 0, 0, 0]
|
||||
self._philo_state = [0, 0, 0]
|
||||
|
||||
# on_run() callback invoked when the QF_RUN packet is received
|
||||
# NOTE: the QS dictionaries are typically known at this time yet, so
|
||||
# this callback can set filters or current objects
|
||||
def on_run(self):
|
||||
glb_filter("QS_QEP_TRAN")
|
||||
|
||||
# NOTE: the names of objects for loc_filter() and current_obj()
|
||||
# must match the QS Object Dictionaries produced by the application.
|
||||
current_obj(OBJ_AO, "Table::inst")
|
||||
loc_filter(OBJ_TE, "Philo::inst[0].m_timeEvt")
|
||||
|
||||
# turn lists into tuples for better performance
|
||||
self._philo_obj = tuple(self._philo_obj)
|
||||
self._philo_state = tuple(self._philo_state)
|
||||
|
||||
|
||||
# example of a custom command
|
||||
def cust_command(self):
|
||||
command(1, 12345)
|
||||
|
||||
# example of a custom interaction with a canvas object (pause/serve)
|
||||
def cust_pause(self, event):
|
||||
if QView.canvas.itemcget(self.btn, "image") != str(self.img_UP):
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_UP)
|
||||
post("SERVE_SIG")
|
||||
QView.print_text("Table SERVING")
|
||||
else:
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_DWN)
|
||||
post("PAUSE_SIG")
|
||||
QView.print_text("Table PAUSED")
|
||||
|
||||
# intercept the QS_OBJ_DICT stadard packet
|
||||
# this packet has the following structure:
|
||||
# record-ID, seq-num, Object-ptr, Zero-terminated string
|
||||
def QS_OBJ_DICT(self, packet):
|
||||
data = qunpack("xxOZ", packet)
|
||||
try:
|
||||
# NOTE: the names of objects must match the QS Object Dictionaries
|
||||
# produced by the application.
|
||||
i = ("Philo::inst[0]",
|
||||
"Philo::inst[1]",
|
||||
"Philo::inst[2]",
|
||||
"Philo::inst[3]",
|
||||
"Philo::inst[4]").index(data[1])
|
||||
self._philo_obj[i] = data[0]
|
||||
except:
|
||||
pass # dictionary for a different object
|
||||
|
||||
# intercept the QS_FUN_DICT stadard packet
|
||||
# this packet has the following structure:
|
||||
# record-ID, seq-num, Function-ptr, Zero-terminated string
|
||||
def QS_FUN_DICT(self, packet):
|
||||
data = qunpack("xxFZ", packet)
|
||||
try:
|
||||
# NOTE: the names of states must match the QS Object Dictionaries
|
||||
# produced by the application.
|
||||
j = ("Philo::thinking",
|
||||
"Philo::hungry",
|
||||
"Philo::eating").index(data[1])
|
||||
self._philo_state[j] = data[0]
|
||||
except:
|
||||
pass # dictionary for a different state
|
||||
|
||||
# intercept the QS_QEP_TRAN stadard packet
|
||||
# this packet has the following structure:
|
||||
# record-ID, seq-num, Timestamp, Signal, Object-ptr,
|
||||
# Function-ptr (source state), Function-ptr (new active state)
|
||||
def QS_QEP_TRAN(self, packet):
|
||||
data = qunpack("xxTSOFF", packet)
|
||||
try:
|
||||
i = self._philo_obj.index(data[2])
|
||||
j = self._philo_state.index(data[4])
|
||||
|
||||
# animate the given philo image according to its activity
|
||||
QView.canvas.itemconfig(self._philo_img[i],
|
||||
image=self._act_img[j])
|
||||
# print a message to the text view
|
||||
QView.print_text("%010d Philo %d is %s"\
|
||||
%(data[0], i, ("thinking", "hungry", "eating")[j]))
|
||||
except:
|
||||
pass # state-entry in a different object
|
||||
|
||||
#=============================================================================
|
||||
# instantiate the DPP class and set it as the QView customization
|
||||
QView.customize(DPP())
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
8
examples/arm-cm/dpp_ek-tm4c123gxl/qview/qview-dpp.bat
Normal file
@ -0,0 +1,8 @@
|
||||
@setlocal
|
||||
|
||||
if "%QTOOLS%"=="" (
|
||||
set QTOOLS=C:\qp\qtools
|
||||
)
|
||||
python %QTOOLS%\qview\qview.py dpp.py
|
||||
|
||||
@endlocal
|
BIN
examples/arm-cm/dpp_ek-tm4c123gxl/qview/qview-dpp.lnk
Normal file
8
examples/arm-cm/dpp_ek-tm4c123gxl/qview/qview-dpp1.bat
Normal file
@ -0,0 +1,8 @@
|
||||
@setlocal
|
||||
|
||||
if "%QTOOLS%"=="" (
|
||||
set QTOOLS=C:\qp\qtools
|
||||
)
|
||||
python %QTOOLS%\qview\qview.py dpp1.py
|
||||
|
||||
@endlocal
|
BIN
examples/arm-cm/dpp_ek-tm4c123gxl/qview/qview-dpp1.lnk
Normal file
@ -55,14 +55,6 @@ int main() {
|
||||
QP::QF::init(); // initialize the framework and the underlying RT kernel
|
||||
DPP::BSP::init(); // initialize the BSP
|
||||
|
||||
// object dictionaries...
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Table);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[0]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[1]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[2]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[3]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[4]);
|
||||
|
||||
// init publish-subscribe
|
||||
QP::QF::psInit(subscrSto, Q_DIM(subscrSto));
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Model: dpp.qm
|
||||
// File: ${.::table.cpp}
|
||||
//
|
||||
// This code has been generated by QM 4.6.0 <www.state-machine.com/qm/>.
|
||||
// This code has been generated by QM 5.0.3 <www.state-machine.com/qm/>.
|
||||
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
|
||||
//
|
||||
// This program is open source software: you can redistribute it and/or
|
||||
@ -20,12 +20,17 @@
|
||||
#include "dpp.hpp"
|
||||
#include "bsp.hpp"
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// Active object class -------------------------------------------------------
|
||||
//.$declare${AOs::Table} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::Table} .............................................................
|
||||
class Table : public QP::QActive {
|
||||
public:
|
||||
static Table inst;
|
||||
|
||||
private:
|
||||
uint8_t m_fork[N_PHILO];
|
||||
bool m_isHungry[N_PHILO];
|
||||
@ -45,8 +50,6 @@ protected:
|
||||
|
||||
namespace DPP {
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// helper function to provide the RIGHT neighbour of a Philo[n]
|
||||
inline uint8_t RIGHT(uint8_t const n) {
|
||||
return static_cast<uint8_t>((n + (N_PHILO - 1U)) % N_PHILO);
|
||||
@ -57,35 +60,37 @@ inline uint8_t LEFT(uint8_t const n) {
|
||||
return static_cast<uint8_t>((n + 1U) % N_PHILO);
|
||||
}
|
||||
|
||||
static uint8_t const FREE = static_cast<uint8_t>(0);
|
||||
static uint8_t const USED = static_cast<uint8_t>(1);
|
||||
constexpr uint8_t FREE = static_cast<uint8_t>(0);
|
||||
constexpr uint8_t USED = static_cast<uint8_t>(1);
|
||||
|
||||
static char const * const THINKING = &"thinking"[0];
|
||||
static char const * const HUNGRY = &"hungry "[0];
|
||||
static char const * const EATING = &"eating "[0];
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Table l_table; // the single instance of the Table active object
|
||||
|
||||
// Global-scope objects ------------------------------------------------------
|
||||
QP::QActive * const AO_Table = &l_table; // "opaque" AO pointer
|
||||
constexpr char_t const * const THINKING = &"thinking"[0];
|
||||
constexpr char_t const * const HUNGRY = &"hungry "[0];
|
||||
constexpr char_t const * const EATING = &"eating "[0];
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
//............................................................................
|
||||
//.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
//. Check for the minimum required QP version
|
||||
#if (QP_VERSION < 650U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
|
||||
#error qpcpp version 6.5.0 or higher required
|
||||
#if (QP_VERSION < 680U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
|
||||
#error qpcpp version 6.8.0 or higher required
|
||||
#endif
|
||||
//.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//.$define${AOs::AO_Table} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::AO_Table} ..........................................................
|
||||
QP::QActive * const AO_Table = &Table::inst; // "opaque" pointer to Table AO
|
||||
|
||||
} // namespace DPP
|
||||
//.$enddef${AOs::AO_Table} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//.$define${AOs::Table} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::Table} .............................................................
|
||||
Table Table::inst;
|
||||
//.${AOs::Table::Table} ......................................................
|
||||
Table::Table()
|
||||
: QActive(Q_STATE_CAST(&Table::initial))
|
||||
: QActive(&initial)
|
||||
{
|
||||
for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
m_fork[n] = FREE;
|
||||
@ -98,6 +103,16 @@ Q_STATE_DEF(Table, initial) {
|
||||
//.${AOs::Table::SM::initial}
|
||||
(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
QS_OBJ_DICTIONARY(&Table::inst);
|
||||
|
||||
QS_SIG_DICTIONARY(DONE_SIG, nullptr); // global signals
|
||||
QS_SIG_DICTIONARY(EAT_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(PAUSE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(SERVE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(TEST_SIG, nullptr);
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal just for Table
|
||||
|
||||
subscribe(DONE_SIG);
|
||||
subscribe(PAUSE_SIG);
|
||||
subscribe(SERVE_SIG);
|
||||
@ -109,19 +124,9 @@ Q_STATE_DEF(Table, initial) {
|
||||
BSP::displayPhilStat(n, THINKING);
|
||||
}
|
||||
|
||||
// global signals...
|
||||
QS_SIG_DICTIONARY(DONE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(EAT_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(PAUSE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(SERVE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(TEST_SIG, nullptr);
|
||||
|
||||
// signals just for this AO...
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this);
|
||||
|
||||
QS_FUN_DICTIONARY(&active);
|
||||
QS_FUN_DICTIONARY(&serving);
|
||||
QS_FUN_DICTIONARY(&paused);
|
||||
QS_FUN_DICTIONARY(&Table::active);
|
||||
QS_FUN_DICTIONARY(&Table::serving);
|
||||
QS_FUN_DICTIONARY(&Table::paused);
|
||||
|
||||
return tran(&serving);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Model: dpp.qm
|
||||
// File: ${.::dpp.hpp}
|
||||
//
|
||||
// This code has been generated by QM 4.6.0 <www.state-machine.com/qm/>.
|
||||
// This code has been generated by QM 5.0.3 <www.state-machine.com/qm/>.
|
||||
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
|
||||
//
|
||||
// This program is open source software: you can redistribute it and/or
|
||||
@ -22,7 +22,8 @@
|
||||
namespace DPP {
|
||||
|
||||
enum DPPSignals {
|
||||
EAT_SIG = QP::Q_USER_SIG, // published by Table to let a philosopher eat
|
||||
TIMEOUT_SIG = QP::Q_USER_SIG, // time event timeout
|
||||
EAT_SIG, // published by Table to let a philosopher eat
|
||||
DONE_SIG, // published by Philosopher when done eating
|
||||
PAUSE_SIG, // published by BSP to pause the application
|
||||
SERVE_SIG, // published by BSP to serve re-start serving forks
|
||||
@ -57,7 +58,6 @@ extern QP::QActive * const AO_Philo[N_PHILO];
|
||||
|
||||
} // namespace DPP
|
||||
//.$enddecl${AOs::AO_Philo[N_PHILO]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
//.$declare${AOs::AO_Table} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
@ -83,4 +83,4 @@ extern QP::QXThread * const XT_Test2;
|
||||
//.$enddecl${AOs::XT_Test2} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
#endif // QXK_HPP
|
||||
|
||||
#endif // DPP_HPP
|
||||
#endif // DPP_HPP
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<model version="4.6.0" links="1">
|
||||
<model version="5.0.3" links="1">
|
||||
<documentation>Dining Philosopher Problem example with MSM state machines</documentation>
|
||||
<!--${qpcpp}-->
|
||||
<framework name="qpcpp"/>
|
||||
@ -15,11 +15,15 @@
|
||||
<package name="AOs" stereotype="0x02" namespace="DPP::">
|
||||
<!--${AOs::Philo}-->
|
||||
<class name="Philo" superclass="qpcpp::QActive">
|
||||
<!--${AOs::Philo::inst[N_PHILO]}-->
|
||||
<attribute name="inst[N_PHILO]" type="Philo" visibility="0x00" properties="0x01">
|
||||
<documentation>The array of static insts of the Philo class (Singleton pattern)</documentation>
|
||||
</attribute>
|
||||
<!--${AOs::Philo::m_timeEvt}-->
|
||||
<attribute name="m_timeEvt" type="QP::QTimeEvt" visibility="0x02" properties="0x00"/>
|
||||
<!--${AOs::Philo::Philo}-->
|
||||
<operation name="Philo" type="" visibility="0x00" properties="0x00">
|
||||
<code> : QActive(Q_STATE_CAST(&Philo::initial)),
|
||||
<code> : QActive(&initial),
|
||||
m_timeEvt(this, TIMEOUT_SIG, 0U)</code>
|
||||
</operation>
|
||||
<!--${AOs::Philo::SM}-->
|
||||
@ -28,27 +32,30 @@
|
||||
<initial target="../1">
|
||||
<action>static bool registered = false; // starts off with 0, per C-standard
|
||||
(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);
|
||||
|
||||
if (!registered) {
|
||||
registered = true;
|
||||
|
||||
QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[4].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4].m_timeEvt);
|
||||
|
||||
QS_FUN_DICTIONARY(&initial);
|
||||
QS_FUN_DICTIONARY(&thinking);
|
||||
QS_FUN_DICTIONARY(&hungry);
|
||||
QS_FUN_DICTIONARY(&eating);
|
||||
QS_FUN_DICTIONARY(&Philo::initial);
|
||||
QS_FUN_DICTIONARY(&Philo::thinking);
|
||||
QS_FUN_DICTIONARY(&Philo::hungry);
|
||||
QS_FUN_DICTIONARY(&Philo::eating);
|
||||
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, nullptr);
|
||||
}
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal for each Philos
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, this); // signal for each Philos</action>
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);</action>
|
||||
<initial_glyph conn="2,3,5,1,20,5,-3">
|
||||
<action box="0,-2,6,2"/>
|
||||
</initial_glyph>
|
||||
@ -65,7 +72,7 @@ QS_SIG_DICTIONARY(TIMEOUT_SIG, this); // signal for each Philos</action>
|
||||
</tran>
|
||||
<!--${AOs::Philo::SM::thinking::EAT, DONE}-->
|
||||
<tran trig="EAT, DONE">
|
||||
<action>// EAT or DONE must be for other Philos than this one
|
||||
<action>/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));</action>
|
||||
<tran_glyph conn="2,16,3,-1,13">
|
||||
<action box="0,-2,14,2"/>
|
||||
@ -127,7 +134,7 @@ QP::QF::PUBLISH(pe, this);
|
||||
</tran>
|
||||
<!--${AOs::Philo::SM::eating::EAT, DONE}-->
|
||||
<tran trig="EAT, DONE">
|
||||
<action>// EAT or DONE must be for other Philos than this one
|
||||
<action>/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));</action>
|
||||
<tran_glyph conn="2,55,3,-1,13">
|
||||
<action box="0,-2,14,2"/>
|
||||
@ -143,13 +150,17 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));</action>
|
||||
</class>
|
||||
<!--${AOs::Table}-->
|
||||
<class name="Table" superclass="qpcpp::QActive">
|
||||
<!--${AOs::Table::inst}-->
|
||||
<attribute name="inst" type="Table" visibility="0x00" properties="0x01">
|
||||
<documentation>The only static inst of the Table class (Singleton pattern)</documentation>
|
||||
</attribute>
|
||||
<!--${AOs::Table::m_fork[N_PHILO]}-->
|
||||
<attribute name="m_fork[N_PHILO]" type="uint8_t" visibility="0x02" properties="0x00"/>
|
||||
<!--${AOs::Table::m_isHungry[N_PHILO]}-->
|
||||
<attribute name="m_isHungry[N_PHILO]" type="bool" visibility="0x02" properties="0x00"/>
|
||||
<!--${AOs::Table::Table}-->
|
||||
<operation name="Table" type="" visibility="0x00" properties="0x00">
|
||||
<code> : QActive(Q_STATE_CAST(&Table::initial))
|
||||
<code> : QActive(&initial)
|
||||
|
||||
for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
m_fork[n] = FREE;
|
||||
@ -162,6 +173,16 @@ for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
<initial target="../1/2">
|
||||
<action>(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
QS_OBJ_DICTIONARY(&Table::inst);
|
||||
|
||||
QS_SIG_DICTIONARY(DONE_SIG, nullptr); // global signals
|
||||
QS_SIG_DICTIONARY(EAT_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(PAUSE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(SERVE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(TEST_SIG, nullptr);
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal just for Table
|
||||
|
||||
subscribe(DONE_SIG);
|
||||
subscribe(PAUSE_SIG);
|
||||
subscribe(SERVE_SIG);
|
||||
@ -171,17 +192,7 @@ for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
m_fork[n] = FREE;
|
||||
m_isHungry[n] = false;
|
||||
BSP::displayPhilStat(n, THINKING);
|
||||
}
|
||||
|
||||
// global signals...
|
||||
QS_SIG_DICTIONARY(DONE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(EAT_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(PAUSE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(SERVE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(TEST_SIG, nullptr);
|
||||
|
||||
// signals just for this AO...
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this);</action>
|
||||
}</action>
|
||||
<initial_glyph conn="3,3,5,1,45,18,-10">
|
||||
<action box="0,-2,6,2"/>
|
||||
</initial_glyph>
|
||||
@ -355,9 +366,19 @@ m_fork[n] = FREE;</action>
|
||||
</statechart>
|
||||
</class>
|
||||
<!--${AOs::AO_Philo[N_PHILO]}-->
|
||||
<attribute name="AO_Philo[N_PHILO]" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
|
||||
<attribute name="AO_Philo[N_PHILO]" type="QP::QActive * const" visibility="0x00" properties="0x00">
|
||||
<code>= { // "opaque" pointers to Philo AO
|
||||
&Philo::inst[0],
|
||||
&Philo::inst[1],
|
||||
&Philo::inst[2],
|
||||
&Philo::inst[3],
|
||||
&Philo::inst[4]
|
||||
};</code>
|
||||
</attribute>
|
||||
<!--${AOs::AO_Table}-->
|
||||
<attribute name="AO_Table" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
|
||||
<attribute name="AO_Table" type="QP::QActive * const" visibility="0x00" properties="0x00">
|
||||
<code>= &Table::inst; // "opaque" pointer to Table AO</code>
|
||||
</attribute>
|
||||
<!--${AOs::XT_Test1}-->
|
||||
<attribute name="XT_Test1" type="QP::QXThread * const" visibility="0x00" properties="0x00"/>
|
||||
<!--${AOs::XT_Test2}-->
|
||||
@ -373,7 +394,8 @@ m_fork[n] = FREE;</action>
|
||||
namespace DPP {
|
||||
|
||||
enum DPPSignals {
|
||||
EAT_SIG = QP::Q_USER_SIG, // published by Table to let a philosopher eat
|
||||
TIMEOUT_SIG = QP::Q_USER_SIG, // time event timeout
|
||||
EAT_SIG, // published by Table to let a philosopher eat
|
||||
DONE_SIG, // published by Philosopher when done eating
|
||||
PAUSE_SIG, // published by BSP to pause the application
|
||||
SERVE_SIG, // published by BSP to serve re-start serving forks
|
||||
@ -386,22 +408,20 @@ enum DPPSignals {
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
$declare(Events::TableEvt)
|
||||
$declare${Events::TableEvt}
|
||||
|
||||
// number of philosophers
|
||||
#define N_PHILO ((uint8_t)5)
|
||||
|
||||
$declare(AOs::AO_Philo[N_PHILO])
|
||||
|
||||
$declare(AOs::AO_Table)
|
||||
$declare${AOs::AO_Philo[N_PHILO]}
|
||||
$declare${AOs::AO_Table}
|
||||
|
||||
#ifdef QXK_HPP
|
||||
$declare(AOs::XT_Test1)
|
||||
$declare(AOs::XT_Test2)
|
||||
$declare${AOs::XT_Test1}
|
||||
$declare${AOs::XT_Test2}
|
||||
#endif // QXK_HPP
|
||||
|
||||
#endif // DPP_HPP
|
||||
</text>
|
||||
#endif // DPP_HPP</text>
|
||||
</file>
|
||||
<!--${.::philo.cpp}-->
|
||||
<file name="philo.cpp">
|
||||
@ -412,13 +432,11 @@ $declare(AOs::XT_Test2)
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// Active object class -------------------------------------------------------
|
||||
$declare(AOs::Philo)
|
||||
$declare${AOs::Philo}
|
||||
|
||||
namespace DPP {
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Philo l_philo[N_PHILO]; // storage for all Philos
|
||||
|
||||
// helper function to provide a randomized think time for Philos
|
||||
inline QP::QTimeEvtCtr think_time() {
|
||||
return static_cast<QP::QTimeEvtCtr>((BSP::random() % BSP::TICKS_PER_SEC)
|
||||
@ -431,28 +449,15 @@ inline QP::QTimeEvtCtr eat_time() {
|
||||
+ BSP::TICKS_PER_SEC);
|
||||
}
|
||||
|
||||
// helper function to provide the ID of Philo
|
||||
inline uint8_t PHILO_ID(Philo const * const philo) {
|
||||
return static_cast<uint8_t>(philo - l_philo);
|
||||
// helper function to provide the ID of Philo "me"
|
||||
inline uint8_t PHILO_ID(Philo const * const me) {
|
||||
return static_cast<uint8_t>(me - &Philo::inst[0]);
|
||||
}
|
||||
|
||||
enum InternalSignals { // internal signals
|
||||
TIMEOUT_SIG = MAX_SIG
|
||||
};
|
||||
|
||||
// Global objects ------------------------------------------------------------
|
||||
QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
|
||||
&l_philo[0],
|
||||
&l_philo[1],
|
||||
&l_philo[2],
|
||||
&l_philo[3],
|
||||
&l_philo[4]
|
||||
};
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
// Philo definition ----------------------------------------------------------
|
||||
$define(AOs::Philo)</text>
|
||||
$define${AOs::AO_Philo[N_PHILO]}
|
||||
$define${AOs::Philo}</text>
|
||||
</file>
|
||||
<!--${.::table.cpp}-->
|
||||
<file name="table.cpp">
|
||||
@ -477,24 +482,17 @@ inline uint8_t LEFT(uint8_t const n) {
|
||||
return static_cast<uint8_t>((n + 1U) % N_PHILO);
|
||||
}
|
||||
|
||||
static uint8_t const FREE = static_cast<uint8_t>(0);
|
||||
static uint8_t const USED = static_cast<uint8_t>(1);
|
||||
constexpr uint8_t FREE = static_cast<uint8_t>(0);
|
||||
constexpr uint8_t USED = static_cast<uint8_t>(1);
|
||||
|
||||
static char_t const * const THINKING = &"thinking"[0];
|
||||
static char_t const * const HUNGRY = &"hungry "[0];
|
||||
static char_t const * const EATING = &"eating "[0];
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Table l_table; // the single instance of the Table active object
|
||||
|
||||
// Global-scope objects ------------------------------------------------------
|
||||
QP::QActive * const AO_Table = &l_table; // "opaque" AO pointer
|
||||
constexpr char_t const * const THINKING = &"thinking"[0];
|
||||
constexpr char_t const * const HUNGRY = &"hungry "[0];
|
||||
constexpr char_t const * const EATING = &"eating "[0];
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
//............................................................................
|
||||
$define(AOs::Table)
|
||||
</text>
|
||||
$define${AOs::AO_Table}
|
||||
$define(AOs::Table)</text>
|
||||
</file>
|
||||
</directory>
|
||||
</model>
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Model: dpp.qm
|
||||
// File: ${.::philo.cpp}
|
||||
//
|
||||
// This code has been generated by QM 4.6.0 <www.state-machine.com/qm/>.
|
||||
// This code has been generated by QM 5.0.3 <www.state-machine.com/qm/>.
|
||||
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
|
||||
//
|
||||
// This program is open source software: you can redistribute it and/or
|
||||
@ -28,6 +28,9 @@ namespace DPP {
|
||||
|
||||
//.${AOs::Philo} .............................................................
|
||||
class Philo : public QP::QActive {
|
||||
public:
|
||||
static Philo inst[N_PHILO];
|
||||
|
||||
private:
|
||||
QP::QTimeEvt m_timeEvt;
|
||||
|
||||
@ -47,8 +50,6 @@ protected:
|
||||
namespace DPP {
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Philo l_philo[N_PHILO]; // storage for all Philos
|
||||
|
||||
// helper function to provide a randomized think time for Philos
|
||||
inline QP::QTimeEvtCtr think_time() {
|
||||
return static_cast<QP::QTimeEvtCtr>((BSP::random() % BSP::TICKS_PER_SEC)
|
||||
@ -61,40 +62,41 @@ inline QP::QTimeEvtCtr eat_time() {
|
||||
+ BSP::TICKS_PER_SEC);
|
||||
}
|
||||
|
||||
// helper function to provide the ID of Philo
|
||||
inline uint8_t PHILO_ID(Philo const * const philo) {
|
||||
return static_cast<uint8_t>(philo - l_philo);
|
||||
// helper function to provide the ID of Philo "me"
|
||||
inline uint8_t PHILO_ID(Philo const * const me) {
|
||||
return static_cast<uint8_t>(me - &Philo::inst[0]);
|
||||
}
|
||||
|
||||
enum InternalSignals { // internal signals
|
||||
TIMEOUT_SIG = MAX_SIG
|
||||
};
|
||||
|
||||
// Global objects ------------------------------------------------------------
|
||||
QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
|
||||
&l_philo[0],
|
||||
&l_philo[1],
|
||||
&l_philo[2],
|
||||
&l_philo[3],
|
||||
&l_philo[4]
|
||||
};
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
// Philo definition ----------------------------------------------------------
|
||||
//.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
//. Check for the minimum required QP version
|
||||
#if (QP_VERSION < 650U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
|
||||
#error qpcpp version 6.5.0 or higher required
|
||||
#if (QP_VERSION < 680U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
|
||||
#error qpcpp version 6.8.0 or higher required
|
||||
#endif
|
||||
//.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//.$define${AOs::AO_Philo[N_PHILO]} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::AO_Philo[N_PHILO]} .................................................
|
||||
QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
|
||||
&Philo::inst[0],
|
||||
&Philo::inst[1],
|
||||
&Philo::inst[2],
|
||||
&Philo::inst[3],
|
||||
&Philo::inst[4]
|
||||
};
|
||||
|
||||
} // namespace DPP
|
||||
//.$enddef${AOs::AO_Philo[N_PHILO]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//.$define${AOs::Philo} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::Philo} .............................................................
|
||||
Philo Philo::inst[N_PHILO];
|
||||
//.${AOs::Philo::Philo} ......................................................
|
||||
Philo::Philo()
|
||||
: QActive(Q_STATE_CAST(&Philo::initial)),
|
||||
: QActive(&initial),
|
||||
m_timeEvt(this, TIMEOUT_SIG, 0U)
|
||||
{}
|
||||
|
||||
@ -103,27 +105,30 @@ Q_STATE_DEF(Philo, initial) {
|
||||
//.${AOs::Philo::SM::initial}
|
||||
static bool registered = false; // starts off with 0, per C-standard
|
||||
(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);
|
||||
|
||||
if (!registered) {
|
||||
registered = true;
|
||||
|
||||
QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[4].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4].m_timeEvt);
|
||||
|
||||
QS_FUN_DICTIONARY(&initial);
|
||||
QS_FUN_DICTIONARY(&thinking);
|
||||
QS_FUN_DICTIONARY(&hungry);
|
||||
QS_FUN_DICTIONARY(&eating);
|
||||
QS_FUN_DICTIONARY(&Philo::initial);
|
||||
QS_FUN_DICTIONARY(&Philo::thinking);
|
||||
QS_FUN_DICTIONARY(&Philo::hungry);
|
||||
QS_FUN_DICTIONARY(&Philo::eating);
|
||||
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, nullptr);
|
||||
}
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal for each Philos
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, this); // signal for each Philos
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);
|
||||
return tran(&thinking);
|
||||
}
|
||||
//.${AOs::Philo::SM::thinking} ...............................................
|
||||
@ -150,7 +155,7 @@ Q_STATE_DEF(Philo, thinking) {
|
||||
//.${AOs::Philo::SM::thinking::EAT, DONE}
|
||||
case EAT_SIG: // intentionally fall through
|
||||
case DONE_SIG: {
|
||||
// EAT or DONE must be for other Philos than this one
|
||||
/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));
|
||||
status_ = Q_RET_HANDLED;
|
||||
break;
|
||||
@ -231,7 +236,7 @@ Q_STATE_DEF(Philo, eating) {
|
||||
//.${AOs::Philo::SM::eating::EAT, DONE}
|
||||
case EAT_SIG: // intentionally fall through
|
||||
case DONE_SIG: {
|
||||
// EAT or DONE must be for other Philos than this one
|
||||
/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));
|
||||
status_ = Q_RET_HANDLED;
|
||||
break;
|
||||
|
@ -62,14 +62,6 @@ int main() {
|
||||
//
|
||||
DPP::BSP::init();
|
||||
|
||||
// object dictionaries...
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Table);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[0]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[1]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[2]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[3]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[4]);
|
||||
|
||||
// start the active objects...
|
||||
for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
DPP::AO_Philo[n]->start((uint_fast8_t)(n + 1U), // priority
|
||||
|
@ -1,324 +0,0 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Product: QSpyView -- Customization example for DPP application
|
||||
# Last updated for version 6.6.0
|
||||
# Last updated on 2019-11-30
|
||||
#
|
||||
# Q u a n t u m L e a P s
|
||||
# ---------------------------
|
||||
# innovating embedded systems
|
||||
#
|
||||
# Copyright (C) Quantum Leaps, LLC, All rights reserved.
|
||||
#
|
||||
# This program is open source software: you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as published
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Contact information:
|
||||
# https://www.state-machine.com
|
||||
# mailto:info@state-machine.com
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# command handlers ===========================================================
|
||||
proc onMyCommand {} {
|
||||
# do something here, for example:
|
||||
# - inject an event to the Target
|
||||
# - send a command to the Target
|
||||
# - peek memory
|
||||
# - poke memory
|
||||
# - exectute system tick in the Target
|
||||
# - open a dialog box...
|
||||
# - etc.
|
||||
|
||||
# as an example, the following code sends a command to the Target
|
||||
variable ::qspy::QS_RX
|
||||
::qspy::sendPkt [binary format cciii $qspy::QS_RX(COMMAND) 1 12345 0 0]
|
||||
}
|
||||
|
||||
proc onPause {} {
|
||||
global theButtonId theBtnState
|
||||
if {[string equal $theBtnState BTN_UP]} { ;# is DWN?
|
||||
set theBtnState BTN_DWN
|
||||
::qspy::sendCurrObj SM_AO AO_Table
|
||||
::qspy::sendEvent 255 PAUSE_SIG
|
||||
#::qspy::sendEvent 6 6 0
|
||||
} else {
|
||||
set theBtnState BTN_UP
|
||||
::qspy::sendCurrObj SM_AO l_table
|
||||
::qspy::sendEvent 255 SERVE_SIG
|
||||
#::qspy::sendEvent 6 7 0
|
||||
}
|
||||
.canv.c itemconfigure $theButtonId -image ::img::$theBtnState
|
||||
}
|
||||
|
||||
# additinal menu options =====================================================
|
||||
.mbar.cust add command -label "MyCommand" -command onMyCommand
|
||||
|
||||
|
||||
# specific canvas for DPP ====================================================
|
||||
set scriptFolder [file dirname [file normalize [info script]]]
|
||||
|
||||
image create photo ::img::e -file $scriptFolder/img/eating.gif
|
||||
image create photo ::img::h -file $scriptFolder/img/hungry.gif
|
||||
image create photo ::img::t -file $scriptFolder/img/thinking.gif
|
||||
image create photo ::img::BTN_UP -file $scriptFolder/img/BTN_UP.gif
|
||||
image create photo ::img::BTN_DWN -file $scriptFolder/img/BTN_DWN.gif
|
||||
|
||||
wm geometry .canv =400x260
|
||||
.canv.c configure -width 400
|
||||
.canv.c configure -height 260
|
||||
|
||||
set thePhiloId [.canv.c create image 190 57 -image ::img::t]
|
||||
.canv.c create image 273 100 -image ::img::t
|
||||
.canv.c create image 237 185 -image ::img::t
|
||||
.canv.c create image 146 184 -image ::img::t
|
||||
.canv.c create image 107 100 -image ::img::t
|
||||
|
||||
|
||||
set theButtonId [.canv.c create image 200 120 -image ::img::BTN_UP]
|
||||
set theBtnState BTN_UP
|
||||
.canv.c bind $theButtonId <ButtonPress-1> onPause
|
||||
|
||||
# QS record handlers =========================================================
|
||||
|
||||
# user record handlers [100..124] --------------------------------------------
|
||||
proc ::qspy::rec100 {} { ;# QS_USER
|
||||
variable thePkt
|
||||
variable theFmt
|
||||
binary scan $thePkt xx$theFmt(tstamp)xcxa* \
|
||||
ts philoNum stat
|
||||
|
||||
dispTxt [format "%010u Philo %1d is %s" $ts $philoNum $stat]
|
||||
|
||||
global thePhiloId
|
||||
set img [string index $stat 0]
|
||||
.canv.c itemconfigure [expr $thePhiloId + $philoNum] -image ::img::$img
|
||||
}
|
||||
#.............................................................................
|
||||
proc ::qspy::rec101 {} { ;# QS_USER + 1
|
||||
variable thePkt
|
||||
variable theFmt
|
||||
binary scan $thePkt xc$theFmt(tstamp)xc \
|
||||
cmdId ts par
|
||||
dispTxt [format "%010u cmd=%d param=%d" $ts $cmdId $par]
|
||||
}
|
||||
|
||||
proc ::qspy::rec102 {} { ;# QS_USER + 2
|
||||
}
|
||||
proc ::qspy::rec103 {} { ;# QS_USER + 3
|
||||
}
|
||||
proc ::qspy::rec104 {} { ;# QS_USER + 4
|
||||
}
|
||||
proc ::qspy::rec105 {} { ;# QS_USER + 5
|
||||
}
|
||||
proc ::qspy::rec106 {} { ;# QS_USER + 6
|
||||
}
|
||||
proc ::qspy::rec107 {} { ;# QS_USER + 7
|
||||
}
|
||||
proc ::qspy::rec108 {} { ;# QS_USER + 8
|
||||
}
|
||||
proc ::qspy::rec109 {} { ;# QS_USER + 9
|
||||
}
|
||||
proc ::qspy::rec110 {} { ;# QS_USER + 10
|
||||
}
|
||||
proc ::qspy::rec111 {} { ;# QS_USER + 11
|
||||
}
|
||||
proc ::qspy::rec112 {} { ;# QS_USER + 12
|
||||
}
|
||||
proc ::qspy::rec113 {} { ;# QS_USER + 13
|
||||
}
|
||||
proc ::qspy::rec114 {} { ;# QS_USER + 14
|
||||
}
|
||||
proc ::qspy::rec115 {} { ;# QS_USER + 15
|
||||
}
|
||||
proc ::qspy::rec116 {} { ;# QS_USER + 16
|
||||
}
|
||||
proc ::qspy::rec117 {} { ;# QS_USER + 17
|
||||
}
|
||||
proc ::qspy::rec118 {} { ;# QS_USER + 18
|
||||
}
|
||||
proc ::qspy::rec119 {} { ;# QS_USER + 19
|
||||
}
|
||||
proc ::qspy::rec120 {} { ;# QS_USER + 20
|
||||
}
|
||||
proc ::qspy::rec121 {} { ;# QS_USER + 21
|
||||
}
|
||||
proc ::qspy::rec122 {} { ;# QS_USER + 22
|
||||
}
|
||||
proc ::qspy::rec123 {} { ;# QS_USER + 23
|
||||
}
|
||||
proc ::qspy::rec124 {} { ;# QS_USER + 24
|
||||
}
|
||||
|
||||
|
||||
# special record handlers ----------------------------------------------------
|
||||
proc ::qspy::recRESET {} { ;# target reset callback
|
||||
}
|
||||
proc ::qspy::recINFO {} { ;# target info callback
|
||||
}
|
||||
|
||||
# standard record handlers [1..54] -------------------------------------------
|
||||
proc ::qspy::rec0 {} { ;# QS_EMPTY
|
||||
}
|
||||
|
||||
# [1] QEP records...
|
||||
proc ::qspy::rec1 {} { ;# QS_QEP_STATE_ENTRY
|
||||
}
|
||||
proc ::qspy::rec2 {} { ;# QS_QEP_STATE_EXIT
|
||||
}
|
||||
proc ::qspy::rec3 {} { ;# QS_QEP_STATE_INIT
|
||||
}
|
||||
proc ::qspy::rec4 {} { ;# QS_QEP_INIT_TRAN
|
||||
}
|
||||
proc ::qspy::rec5 {} { ;# QS_QEP_INTERN_TRAN
|
||||
}
|
||||
proc ::qspy::rec6 {} { ;# QS_QEP_TRAN
|
||||
}
|
||||
proc ::qspy::rec7 {} { ;# QS_QEP_IGNORED
|
||||
}
|
||||
proc ::qspy::rec8 {} { ;# QS_QEP_DISPATCH
|
||||
}
|
||||
proc ::qspy::rec9 {} { ;# QS_QEP_UNHANDLED
|
||||
}
|
||||
|
||||
# [10] QF records...
|
||||
proc ::qspy::rec10 {} { ;# QS_QF_ACTIVE_ADD
|
||||
}
|
||||
proc ::qspy::rec11 {} { ;# QS_QF_ACTIVE_REMOVE
|
||||
}
|
||||
proc ::qspy::rec12 {} { ;# QS_QF_ACTIVE_SUBSCRIBE
|
||||
}
|
||||
proc ::qspy::rec13 {} { ;# QS_QF_ACTIVE_UNSUBSCRIBE
|
||||
}
|
||||
proc ::qspy::rec14 {} { ;# QS_QF_ACTIVE_POST_FIFO
|
||||
}
|
||||
proc ::qspy::rec15 {} { ;# QS_QF_ACTIVE_POST_LIFO
|
||||
}
|
||||
proc ::qspy::rec16 {} { ;# QS_QF_ACTIVE_GET
|
||||
}
|
||||
proc ::qspy::rec17 {} { ;# QS_QF_ACTIVE_GET_LAST
|
||||
}
|
||||
proc ::qspy::rec18 {} { ;# QS_QF_EQUEUE_INIT
|
||||
}
|
||||
proc ::qspy::rec19 {} { ;# QS_QF_EQUEUE_POST_FIFO
|
||||
}
|
||||
proc ::qspy::rec20 {} { ;# QS_QF_EQUEUE_POST_LIFO
|
||||
}
|
||||
proc ::qspy::rec21 {} { ;# QS_QF_EQUEUE_GET
|
||||
}
|
||||
proc ::qspy::rec22 {} { ;# QS_QF_EQUEUE_GET_LAST
|
||||
}
|
||||
proc ::qspy::rec23 {} { ;# QS_QF_MPOOL_INIT
|
||||
}
|
||||
proc ::qspy::rec24 {} { ;# QS_QF_MPOOL_GET
|
||||
}
|
||||
proc ::qspy::rec25 {} { ;# QS_QF_MPOOL_PUT
|
||||
}
|
||||
proc ::qspy::rec26 {} { ;# QS_QF_PUBLISH
|
||||
}
|
||||
proc ::qspy::rec27 {} { ;# QS_QF_RESERVED8
|
||||
}
|
||||
proc ::qspy::rec28 {} { ;# QS_QF_NEW
|
||||
}
|
||||
proc ::qspy::rec29 {} { ;# QS_QF_GC_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec30 {} { ;# QS_QF_GC
|
||||
}
|
||||
proc ::qspy::rec31 {} { ;# QS_QF_TICK
|
||||
}
|
||||
proc ::qspy::rec32 {} { ;# QS_QF_TIMEEVT_ARM
|
||||
}
|
||||
proc ::qspy::rec33 {} { ;# QS_QF_TIMEEVT_AUTO_DISARM
|
||||
}
|
||||
proc ::qspy::rec34 {} { ;# QS_QF_TIMEEVT_DISARM_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec35 {} { ;# QS_QF_TIMEEVT_DISARM
|
||||
}
|
||||
proc ::qspy::rec36 {} { ;# QS_QF_TIMEEVT_REARM
|
||||
}
|
||||
proc ::qspy::rec37 {} { ;# QS_QF_TIMEEVT_POST
|
||||
}
|
||||
proc ::qspy::rec38 {} { ;# QS_QF_TIMEEVT_CTR
|
||||
}
|
||||
proc ::qspy::rec39 {} { ;# QS_QF_CRIT_ENTRY
|
||||
}
|
||||
proc ::qspy::rec40 {} { ;# QS_QF_CRIT_EXIT
|
||||
}
|
||||
proc ::qspy::rec41 {} { ;# QS_QF_ISR_ENTRY
|
||||
}
|
||||
proc ::qspy::rec42 {} { ;# QS_QF_ISR_EXIT
|
||||
}
|
||||
proc ::qspy::rec43 {} { ;# QS_QF_INT_DISABLE
|
||||
}
|
||||
proc ::qspy::rec44 {} { ;# QS_QF_INT_ENABLE
|
||||
}
|
||||
proc ::qspy::rec45 {} { ;# QS_QF_ACTIVE_POST_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec46 {} { ;# QS_QF_EQUEUE_POST_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec47 {} { ;# QS_QF_MPOOL_GET_ATTEMPT
|
||||
}
|
||||
proc ::qspy::rec48 {} { ;# QS_QF_RESERVED1
|
||||
}
|
||||
proc ::qspy::rec49 {} { ;# QS_QF_RESERVED0
|
||||
}
|
||||
|
||||
# [50] QK/QV records
|
||||
proc ::qspy::rec50 {} { ;# QS_QK_MUTEX_LOCK
|
||||
}
|
||||
proc ::qspy::rec51 {} { ;# QS_QK_MUTEX_UNLOCK
|
||||
}
|
||||
proc ::qspy::rec52 {} { ;# QS_QVK_SCHEDULE
|
||||
}
|
||||
proc ::qspy::rec53 {} { ;# QS_QVK_IDLE
|
||||
}
|
||||
proc ::qspy::rec54 {} { ;# QS_QK_RESUME
|
||||
}
|
||||
|
||||
# [55] Additional QEP records
|
||||
proc ::qspy::rec55 {} { ;# QS_QEP_TRAN_HIST
|
||||
}
|
||||
proc ::qspy::rec56 {} { ;# QS_QEP_TRAN_EP
|
||||
}
|
||||
proc ::qspy::rec57 {} { ;# QS_QEP_TRAN_XP
|
||||
}
|
||||
proc ::qspy::rec58 {} { ;# QS_QEP_RESERVED1
|
||||
}
|
||||
proc ::qspy::rec59 {} { ;# QS_QEP_RESERVED0
|
||||
}
|
||||
|
||||
# Miscellaneous QS records
|
||||
proc ::qspy::rec60 {} { ;# QS_SIG_DICT
|
||||
}
|
||||
proc ::qspy::rec61 {} { ;# QS_OBJ_DICT
|
||||
}
|
||||
proc ::qspy::rec62 {} { ;# QS_FUN_DICT
|
||||
}
|
||||
proc ::qspy::rec63 {} { ;# QS_USR_DICT
|
||||
}
|
||||
|
||||
# proc ::qspy::64 ;# QS_TARGET_INFO not used, see proc recINFO
|
||||
|
||||
proc ::qspy::rec65 {} { ;# QS_RESERVED0
|
||||
}
|
||||
proc ::qspy::rec66 {} { ;# QS_RX_STATUS
|
||||
}
|
||||
proc ::qspy::rec67 {} { ;# QS_TEST_STATUS
|
||||
}
|
||||
proc ::qspy::rec68 {} { ;# QS_PEEK_DATA
|
||||
}
|
||||
proc ::qspy::rec69 {} { ;# QS_ASSERT_FAIL
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
if "%QTOOLS%"=="" (
|
||||
set QTOOLS=C:\qp\qtools
|
||||
)
|
||||
wish %QTOOLS%\qspy\tcl\qspyview.tcl dpp.tcl
|
@ -62,14 +62,6 @@ int main() {
|
||||
//
|
||||
DPP::BSP::init();
|
||||
|
||||
// object dictionaries...
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Table);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[0]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[1]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[2]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[3]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[4]);
|
||||
|
||||
// start the active objects...
|
||||
for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
DPP::AO_Philo[n]->start((uint_fast8_t)(n + 1U), // priority
|
||||
|
104
examples/arm-cm/dpp_nucleo-h743zi/qview/dpp.py
Normal file
@ -0,0 +1,104 @@
|
||||
# This is an example of QView customization for a specific application
|
||||
# (DPP in this case). This example animates the Phil images on the
|
||||
# QView canvas. Additionally, there is a button in the middle of the screen,
|
||||
# which, when clicked once pauses the DPP ("forks" are not being served).
|
||||
# A second click on the button, "un-pauses" the DPP ("forks" are served
|
||||
# to all hungry Philosophers).
|
||||
#
|
||||
# This version of the DPP customization uses the application-specific
|
||||
# packet QS_USER_00 (PHILO_STAT) produced when the status of a Philo changes.
|
||||
#
|
||||
|
||||
class DPP:
|
||||
def __init__(self):
|
||||
|
||||
# add commands to the Custom menu...
|
||||
QView.custom_menu.add_command(label="Custom command",
|
||||
command=self.cust_command)
|
||||
|
||||
# configure the custom QView.canvas...
|
||||
QView.show_canvas() # make the canvas visible
|
||||
QView.canvas.configure(width=400, height=260)
|
||||
|
||||
# tuple of activity images (correspond to self._philo_state)
|
||||
self._act_img = (
|
||||
PhotoImage(file=HOME_DIR + "/img/thinking.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/hungry.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/eating.gif"),
|
||||
)
|
||||
# tuple of philo canvas images (correspond to self._philo_obj)
|
||||
self._philo_img = (\
|
||||
QView.canvas.create_image(190, 57, image=self._act_img[0]),
|
||||
QView.canvas.create_image(273, 100, image=self._act_img[0]),
|
||||
QView.canvas.create_image(237, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(146, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(107, 100, image=self._act_img[0])
|
||||
)
|
||||
|
||||
# button images for UP and DOWN
|
||||
self.img_UP = PhotoImage(file=HOME_DIR + "/img/BTN_UP.gif")
|
||||
self.img_DWN = PhotoImage(file=HOME_DIR + "/img/BTN_DWN.gif")
|
||||
|
||||
# images of a button for pause/serve
|
||||
self.btn = QView.canvas.create_image(200, 120, image=self.img_UP)
|
||||
QView.canvas.tag_bind(self.btn, "<ButtonPress-1>", self.cust_pause)
|
||||
|
||||
# request target reset on startup...
|
||||
# NOTE: Normally, for an embedded application you would like
|
||||
# to start with resetting the Target, to start clean with
|
||||
# Qs dictionaries, etc.
|
||||
reset_target()
|
||||
|
||||
# on_reset() callback
|
||||
def on_reset(self):
|
||||
# clear the lists
|
||||
self._philo_obj = [0, 0, 0, 0, 0]
|
||||
self._philo_state = [0, 0, 0]
|
||||
|
||||
# on_run() callback
|
||||
def on_run(self):
|
||||
glb_filter("QS_USER_00")
|
||||
|
||||
# NOTE: the names of objects for loc_filter() and current_obj()
|
||||
# must match the QS Object Dictionaries produced by the application.
|
||||
current_obj(OBJ_AO, "Table::inst")
|
||||
loc_filter(OBJ_TE, "Philo::inst[0].timeEvt")
|
||||
|
||||
# turn lists into tuples for better performance
|
||||
self._philo_obj = tuple(self._philo_obj)
|
||||
self._philo_state = tuple(self._philo_state)
|
||||
|
||||
|
||||
# example of a custom command
|
||||
def cust_command(self):
|
||||
command(1, 12345)
|
||||
|
||||
# example of a custom interaction with a canvas object (pause/serve)
|
||||
def cust_pause(self, event):
|
||||
if QView.canvas.itemcget(self.btn, "image") != str(self.img_UP):
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_UP)
|
||||
post("SERVE_SIG")
|
||||
QView.print_text("Table SERVING")
|
||||
else:
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_DWN)
|
||||
post("PAUSE_SIG")
|
||||
QView.print_text("Table PAUSED")
|
||||
|
||||
# intercept the QS_USER_00 application-specific packet
|
||||
# this packet has the following structure (see bsp.c:displayPhilStat()):
|
||||
# record-ID, seq-num, Timestamp, format-byte, Philo-num,
|
||||
# format-bye, Zero-terminated string (status)
|
||||
def QS_USER_00(self, packet):
|
||||
# unpack: Timestamp->data[0], Philo-num->data[1], status->data[3]
|
||||
data = qunpack("xxTxBxZ", packet)
|
||||
i = data[1]
|
||||
j = ("t", "h", "e").index(data[2][0]) # the first letter
|
||||
|
||||
# animate the given philo image according to its activity
|
||||
QView.canvas.itemconfig(self._philo_img[i], image=self._act_img[j])
|
||||
|
||||
# print a message to the text view
|
||||
QView.print_text("%010d Philo %1d is %s"%(data[0], i, data[2]))
|
||||
|
||||
#=============================================================================
|
||||
QView.customize(DPP()) # set the QView customization
|
148
examples/arm-cm/dpp_nucleo-h743zi/qview/dpp1.py
Normal file
@ -0,0 +1,148 @@
|
||||
# This is an example of QView customization for a specific application
|
||||
# (DPP in this case). This example animates the Phil images on the
|
||||
# QView canvas. Additionally, there is a button in the middle of the screen,
|
||||
# which, when clicked once pauses the DPP ("forks" are not being served).
|
||||
# A second click on the button, "un-pauses" the DPP ("forks" are served
|
||||
# to all hungry Philosophers).
|
||||
#
|
||||
# This version of the DPP customization uses the standard QS_QEP_STATE_ENTRY
|
||||
# packet, which provides information about the current states of the dining
|
||||
# Philosophers. The example also demonstrates how to intercept the QS
|
||||
# "dictionary" records QS_OBJ_DICT and QS_FUN_DICT to extract the information
|
||||
# about the addresses of the Philosopher objects and the states of their
|
||||
# state machines.
|
||||
#
|
||||
|
||||
class DPP:
|
||||
def __init__(self):
|
||||
|
||||
# add commands to the Custom menu...
|
||||
QView.custom_menu.add_command(label="Custom command",
|
||||
command=self.cust_command)
|
||||
|
||||
# configure the custom QView.canvas...
|
||||
QView.show_canvas() # make the canvas visible
|
||||
QView.canvas.configure(width=400, height=260)
|
||||
|
||||
# tuple of activity images (correspond to self._philo_state)
|
||||
self._act_img = (
|
||||
PhotoImage(file=HOME_DIR + "/img/thinking.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/hungry.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/eating.gif"),
|
||||
)
|
||||
# tuple of philo canvas images (correspond to self._philo_obj)
|
||||
self._philo_img = (\
|
||||
QView.canvas.create_image(190, 57, image=self._act_img[0]),
|
||||
QView.canvas.create_image(273, 100, image=self._act_img[0]),
|
||||
QView.canvas.create_image(237, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(146, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(107, 100, image=self._act_img[0])
|
||||
)
|
||||
|
||||
# button images for UP and DOWN
|
||||
self.img_UP = PhotoImage(file=HOME_DIR + "/img/BTN_UP.gif")
|
||||
self.img_DWN = PhotoImage(file=HOME_DIR + "/img/BTN_DWN.gif")
|
||||
|
||||
# images of a button for pause/serve
|
||||
self.btn = QView.canvas.create_image(200, 120, image=self.img_UP)
|
||||
QView.canvas.tag_bind(self.btn, "<ButtonPress-1>", self.cust_pause)
|
||||
|
||||
# request target reset on startup...
|
||||
# NOTE: Normally, for an embedded application you would like
|
||||
# to start with resetting the Target, to start clean with
|
||||
# Qs dictionaries, etc.
|
||||
reset_target()
|
||||
|
||||
# on_reset() callback invoked when Target-reset packet is received
|
||||
# NOTE: the QS dictionaries are not known at this time yet, so
|
||||
# this callback shouild generally not set filters or current objects
|
||||
def on_reset(self):
|
||||
# (re)set the lists
|
||||
self._philo_obj = [0, 0, 0, 0, 0]
|
||||
self._philo_state = [0, 0, 0]
|
||||
|
||||
# on_run() callback invoked when the QF_RUN packet is received
|
||||
# NOTE: the QS dictionaries are typically known at this time yet, so
|
||||
# this callback can set filters or current objects
|
||||
def on_run(self):
|
||||
glb_filter("QS_QEP_TRAN")
|
||||
|
||||
# NOTE: the names of objects for loc_filter() and current_obj()
|
||||
# must match the QS Object Dictionaries produced by the application.
|
||||
current_obj(OBJ_AO, "Table::inst")
|
||||
loc_filter(OBJ_TE, "Philo::inst[0].m_timeEvt")
|
||||
|
||||
# turn lists into tuples for better performance
|
||||
self._philo_obj = tuple(self._philo_obj)
|
||||
self._philo_state = tuple(self._philo_state)
|
||||
|
||||
|
||||
# example of a custom command
|
||||
def cust_command(self):
|
||||
command(1, 12345)
|
||||
|
||||
# example of a custom interaction with a canvas object (pause/serve)
|
||||
def cust_pause(self, event):
|
||||
if QView.canvas.itemcget(self.btn, "image") != str(self.img_UP):
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_UP)
|
||||
post("SERVE_SIG")
|
||||
QView.print_text("Table SERVING")
|
||||
else:
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_DWN)
|
||||
post("PAUSE_SIG")
|
||||
QView.print_text("Table PAUSED")
|
||||
|
||||
# intercept the QS_OBJ_DICT stadard packet
|
||||
# this packet has the following structure:
|
||||
# record-ID, seq-num, Object-ptr, Zero-terminated string
|
||||
def QS_OBJ_DICT(self, packet):
|
||||
data = qunpack("xxOZ", packet)
|
||||
try:
|
||||
# NOTE: the names of objects must match the QS Object Dictionaries
|
||||
# produced by the application.
|
||||
i = ("Philo::inst[0]",
|
||||
"Philo::inst[1]",
|
||||
"Philo::inst[2]",
|
||||
"Philo::inst[3]",
|
||||
"Philo::inst[4]").index(data[1])
|
||||
self._philo_obj[i] = data[0]
|
||||
except:
|
||||
pass # dictionary for a different object
|
||||
|
||||
# intercept the QS_FUN_DICT stadard packet
|
||||
# this packet has the following structure:
|
||||
# record-ID, seq-num, Function-ptr, Zero-terminated string
|
||||
def QS_FUN_DICT(self, packet):
|
||||
data = qunpack("xxFZ", packet)
|
||||
try:
|
||||
# NOTE: the names of states must match the QS Object Dictionaries
|
||||
# produced by the application.
|
||||
j = ("Philo::thinking",
|
||||
"Philo::hungry",
|
||||
"Philo::eating").index(data[1])
|
||||
self._philo_state[j] = data[0]
|
||||
except:
|
||||
pass # dictionary for a different state
|
||||
|
||||
# intercept the QS_QEP_TRAN stadard packet
|
||||
# this packet has the following structure:
|
||||
# record-ID, seq-num, Timestamp, Signal, Object-ptr,
|
||||
# Function-ptr (source state), Function-ptr (new active state)
|
||||
def QS_QEP_TRAN(self, packet):
|
||||
data = qunpack("xxTSOFF", packet)
|
||||
try:
|
||||
i = self._philo_obj.index(data[2])
|
||||
j = self._philo_state.index(data[4])
|
||||
|
||||
# animate the given philo image according to its activity
|
||||
QView.canvas.itemconfig(self._philo_img[i],
|
||||
image=self._act_img[j])
|
||||
# print a message to the text view
|
||||
QView.print_text("%010d Philo %d is %s"\
|
||||
%(data[0], i, ("thinking", "hungry", "eating")[j]))
|
||||
except:
|
||||
pass # state-entry in a different object
|
||||
|
||||
#=============================================================================
|
||||
# instantiate the DPP class and set it as the QView customization
|
||||
QView.customize(DPP())
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
8
examples/arm-cm/dpp_nucleo-h743zi/qview/qview-dpp.bat
Normal file
@ -0,0 +1,8 @@
|
||||
@setlocal
|
||||
|
||||
if "%QTOOLS%"=="" (
|
||||
set QTOOLS=C:\qp\qtools
|
||||
)
|
||||
python %QTOOLS%\qview\qview.py dpp.py
|
||||
|
||||
@endlocal
|
BIN
examples/arm-cm/dpp_nucleo-h743zi/qview/qview-dpp.lnk
Normal file
8
examples/arm-cm/dpp_nucleo-h743zi/qview/qview-dpp1.bat
Normal file
@ -0,0 +1,8 @@
|
||||
@setlocal
|
||||
|
||||
if "%QTOOLS%"=="" (
|
||||
set QTOOLS=C:\qp\qtools
|
||||
)
|
||||
python %QTOOLS%\qview\qview.py dpp1.py
|
||||
|
||||
@endlocal
|
BIN
examples/arm-cm/dpp_nucleo-h743zi/qview/qview-dpp1.lnk
Normal file
@ -68,14 +68,6 @@ int main() {
|
||||
//
|
||||
DPP::BSP::init();
|
||||
|
||||
// object dictionaries...
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Table);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[0]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[1]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[2]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[3]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[4]);
|
||||
|
||||
// start the extended Test1 thread
|
||||
DPP::XT_Test1->start(
|
||||
1U, // QP prio of the thread
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Model: dpp.qm
|
||||
// File: ${.::table.cpp}
|
||||
//
|
||||
// This code has been generated by QM 4.6.0 <www.state-machine.com/qm/>.
|
||||
// This code has been generated by QM 5.0.3 <www.state-machine.com/qm/>.
|
||||
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
|
||||
//
|
||||
// This program is open source software: you can redistribute it and/or
|
||||
@ -28,6 +28,9 @@ namespace DPP {
|
||||
|
||||
//.${AOs::Table} .............................................................
|
||||
class Table : public QP::QActive {
|
||||
public:
|
||||
static Table inst;
|
||||
|
||||
private:
|
||||
uint8_t m_fork[N_PHILO];
|
||||
bool m_isHungry[N_PHILO];
|
||||
@ -57,35 +60,37 @@ inline uint8_t LEFT(uint8_t const n) {
|
||||
return static_cast<uint8_t>((n + 1U) % N_PHILO);
|
||||
}
|
||||
|
||||
static uint8_t const FREE = static_cast<uint8_t>(0);
|
||||
static uint8_t const USED = static_cast<uint8_t>(1);
|
||||
constexpr uint8_t FREE = static_cast<uint8_t>(0);
|
||||
constexpr uint8_t USED = static_cast<uint8_t>(1);
|
||||
|
||||
static char const * const THINKING = &"thinking"[0];
|
||||
static char const * const HUNGRY = &"hungry "[0];
|
||||
static char const * const EATING = &"eating "[0];
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Table l_table; // the single instance of the Table active object
|
||||
|
||||
// Global-scope objects ------------------------------------------------------
|
||||
QP::QActive * const AO_Table = &l_table; // "opaque" AO pointer
|
||||
constexpr char_t const * const THINKING = &"thinking"[0];
|
||||
constexpr char_t const * const HUNGRY = &"hungry "[0];
|
||||
constexpr char_t const * const EATING = &"eating "[0];
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
//............................................................................
|
||||
//.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
//. Check for the minimum required QP version
|
||||
#if (QP_VERSION < 650U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
|
||||
#error qpcpp version 6.5.0 or higher required
|
||||
#if (QP_VERSION < 680U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
|
||||
#error qpcpp version 6.8.0 or higher required
|
||||
#endif
|
||||
//.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//.$define${AOs::AO_Table} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::AO_Table} ..........................................................
|
||||
QP::QActive * const AO_Table = &Table::inst; // "opaque" pointer to Table AO
|
||||
|
||||
} // namespace DPP
|
||||
//.$enddef${AOs::AO_Table} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//.$define${AOs::Table} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::Table} .............................................................
|
||||
Table Table::inst;
|
||||
//.${AOs::Table::Table} ......................................................
|
||||
Table::Table()
|
||||
: QActive(Q_STATE_CAST(&Table::initial))
|
||||
: QActive(&initial)
|
||||
{
|
||||
for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
m_fork[n] = FREE;
|
||||
@ -98,6 +103,16 @@ Q_STATE_DEF(Table, initial) {
|
||||
//.${AOs::Table::SM::initial}
|
||||
(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
QS_OBJ_DICTIONARY(&Table::inst);
|
||||
|
||||
QS_SIG_DICTIONARY(DONE_SIG, nullptr); // global signals
|
||||
QS_SIG_DICTIONARY(EAT_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(PAUSE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(SERVE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(TEST_SIG, nullptr);
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal just for Table
|
||||
|
||||
subscribe(DONE_SIG);
|
||||
subscribe(PAUSE_SIG);
|
||||
subscribe(SERVE_SIG);
|
||||
@ -109,19 +124,9 @@ Q_STATE_DEF(Table, initial) {
|
||||
BSP::displayPhilStat(n, THINKING);
|
||||
}
|
||||
|
||||
// global signals...
|
||||
QS_SIG_DICTIONARY(DONE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(EAT_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(PAUSE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(SERVE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(TEST_SIG, nullptr);
|
||||
|
||||
// signals just for this AO...
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this);
|
||||
|
||||
QS_FUN_DICTIONARY(&active);
|
||||
QS_FUN_DICTIONARY(&serving);
|
||||
QS_FUN_DICTIONARY(&paused);
|
||||
QS_FUN_DICTIONARY(&Table::active);
|
||||
QS_FUN_DICTIONARY(&Table::serving);
|
||||
QS_FUN_DICTIONARY(&Table::paused);
|
||||
|
||||
return tran(&serving);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Model: dpp.qm
|
||||
// File: ${.::dpp.hpp}
|
||||
//
|
||||
// This code has been generated by QM 4.6.0 <www.state-machine.com/qm/>.
|
||||
// This code has been generated by QM 5.0.3 <www.state-machine.com/qm/>.
|
||||
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
|
||||
//
|
||||
// This program is open source software: you can redistribute it and/or
|
||||
@ -22,7 +22,8 @@
|
||||
namespace DPP {
|
||||
|
||||
enum DPPSignals {
|
||||
EAT_SIG = QP::Q_USER_SIG, // published by Table to let a philosopher eat
|
||||
TIMEOUT_SIG = QP::Q_USER_SIG, // time event timeout
|
||||
EAT_SIG, // published by Table to let a philosopher eat
|
||||
DONE_SIG, // published by Philosopher when done eating
|
||||
PAUSE_SIG, // published by BSP to pause the application
|
||||
SERVE_SIG, // published by BSP to serve re-start serving forks
|
||||
@ -57,7 +58,6 @@ extern QP::QActive * const AO_Philo[N_PHILO];
|
||||
|
||||
} // namespace DPP
|
||||
//.$enddecl${AOs::AO_Philo[N_PHILO]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
//.$declare${AOs::AO_Table} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
@ -83,4 +83,4 @@ extern QP::QXThread * const XT_Test2;
|
||||
//.$enddecl${AOs::XT_Test2} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
#endif // QXK_HPP
|
||||
|
||||
#endif // DPP_HPP
|
||||
#endif // DPP_HPP
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<model version="4.6.0" links="1">
|
||||
<model version="5.0.3" links="1">
|
||||
<documentation>Dining Philosopher Problem example with MSM state machines</documentation>
|
||||
<!--${qpcpp}-->
|
||||
<framework name="qpcpp"/>
|
||||
@ -15,11 +15,15 @@
|
||||
<package name="AOs" stereotype="0x02" namespace="DPP::">
|
||||
<!--${AOs::Philo}-->
|
||||
<class name="Philo" superclass="qpcpp::QActive">
|
||||
<!--${AOs::Philo::inst[N_PHILO]}-->
|
||||
<attribute name="inst[N_PHILO]" type="Philo" visibility="0x00" properties="0x01">
|
||||
<documentation>The array of static insts of the Philo class (Singleton pattern)</documentation>
|
||||
</attribute>
|
||||
<!--${AOs::Philo::m_timeEvt}-->
|
||||
<attribute name="m_timeEvt" type="QP::QTimeEvt" visibility="0x02" properties="0x00"/>
|
||||
<!--${AOs::Philo::Philo}-->
|
||||
<operation name="Philo" type="" visibility="0x00" properties="0x00">
|
||||
<code> : QActive(Q_STATE_CAST(&Philo::initial)),
|
||||
<code> : QActive(&initial),
|
||||
m_timeEvt(this, TIMEOUT_SIG, 0U)</code>
|
||||
</operation>
|
||||
<!--${AOs::Philo::SM}-->
|
||||
@ -28,27 +32,30 @@
|
||||
<initial target="../1">
|
||||
<action>static bool registered = false; // starts off with 0, per C-standard
|
||||
(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);
|
||||
|
||||
if (!registered) {
|
||||
registered = true;
|
||||
|
||||
QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[4].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4].m_timeEvt);
|
||||
|
||||
QS_FUN_DICTIONARY(&initial);
|
||||
QS_FUN_DICTIONARY(&thinking);
|
||||
QS_FUN_DICTIONARY(&hungry);
|
||||
QS_FUN_DICTIONARY(&eating);
|
||||
QS_FUN_DICTIONARY(&Philo::initial);
|
||||
QS_FUN_DICTIONARY(&Philo::thinking);
|
||||
QS_FUN_DICTIONARY(&Philo::hungry);
|
||||
QS_FUN_DICTIONARY(&Philo::eating);
|
||||
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, nullptr);
|
||||
}
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal for each Philos
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, this); // signal for each Philos</action>
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);</action>
|
||||
<initial_glyph conn="2,3,5,1,20,5,-3">
|
||||
<action box="0,-2,6,2"/>
|
||||
</initial_glyph>
|
||||
@ -65,7 +72,7 @@ QS_SIG_DICTIONARY(TIMEOUT_SIG, this); // signal for each Philos</action>
|
||||
</tran>
|
||||
<!--${AOs::Philo::SM::thinking::EAT, DONE}-->
|
||||
<tran trig="EAT, DONE">
|
||||
<action>// EAT or DONE must be for other Philos than this one
|
||||
<action>/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));</action>
|
||||
<tran_glyph conn="2,16,3,-1,13">
|
||||
<action box="0,-2,14,2"/>
|
||||
@ -127,7 +134,7 @@ QP::QF::PUBLISH(pe, this);
|
||||
</tran>
|
||||
<!--${AOs::Philo::SM::eating::EAT, DONE}-->
|
||||
<tran trig="EAT, DONE">
|
||||
<action>// EAT or DONE must be for other Philos than this one
|
||||
<action>/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));</action>
|
||||
<tran_glyph conn="2,55,3,-1,13">
|
||||
<action box="0,-2,14,2"/>
|
||||
@ -143,13 +150,17 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));</action>
|
||||
</class>
|
||||
<!--${AOs::Table}-->
|
||||
<class name="Table" superclass="qpcpp::QActive">
|
||||
<!--${AOs::Table::inst}-->
|
||||
<attribute name="inst" type="Table" visibility="0x00" properties="0x01">
|
||||
<documentation>The only static inst of the Table class (Singleton pattern)</documentation>
|
||||
</attribute>
|
||||
<!--${AOs::Table::m_fork[N_PHILO]}-->
|
||||
<attribute name="m_fork[N_PHILO]" type="uint8_t" visibility="0x02" properties="0x00"/>
|
||||
<!--${AOs::Table::m_isHungry[N_PHILO]}-->
|
||||
<attribute name="m_isHungry[N_PHILO]" type="bool" visibility="0x02" properties="0x00"/>
|
||||
<!--${AOs::Table::Table}-->
|
||||
<operation name="Table" type="" visibility="0x00" properties="0x00">
|
||||
<code> : QActive(Q_STATE_CAST(&Table::initial))
|
||||
<code> : QActive(&initial)
|
||||
|
||||
for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
m_fork[n] = FREE;
|
||||
@ -162,6 +173,16 @@ for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
<initial target="../1/2">
|
||||
<action>(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
QS_OBJ_DICTIONARY(&Table::inst);
|
||||
|
||||
QS_SIG_DICTIONARY(DONE_SIG, nullptr); // global signals
|
||||
QS_SIG_DICTIONARY(EAT_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(PAUSE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(SERVE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(TEST_SIG, nullptr);
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal just for Table
|
||||
|
||||
subscribe(DONE_SIG);
|
||||
subscribe(PAUSE_SIG);
|
||||
subscribe(SERVE_SIG);
|
||||
@ -171,17 +192,7 @@ for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
m_fork[n] = FREE;
|
||||
m_isHungry[n] = false;
|
||||
BSP::displayPhilStat(n, THINKING);
|
||||
}
|
||||
|
||||
// global signals...
|
||||
QS_SIG_DICTIONARY(DONE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(EAT_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(PAUSE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(SERVE_SIG, nullptr);
|
||||
QS_SIG_DICTIONARY(TEST_SIG, nullptr);
|
||||
|
||||
// signals just for this AO...
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this);</action>
|
||||
}</action>
|
||||
<initial_glyph conn="3,3,5,1,45,18,-10">
|
||||
<action box="0,-2,6,2"/>
|
||||
</initial_glyph>
|
||||
@ -355,9 +366,19 @@ m_fork[n] = FREE;</action>
|
||||
</statechart>
|
||||
</class>
|
||||
<!--${AOs::AO_Philo[N_PHILO]}-->
|
||||
<attribute name="AO_Philo[N_PHILO]" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
|
||||
<attribute name="AO_Philo[N_PHILO]" type="QP::QActive * const" visibility="0x00" properties="0x00">
|
||||
<code>= { // "opaque" pointers to Philo AO
|
||||
&Philo::inst[0],
|
||||
&Philo::inst[1],
|
||||
&Philo::inst[2],
|
||||
&Philo::inst[3],
|
||||
&Philo::inst[4]
|
||||
};</code>
|
||||
</attribute>
|
||||
<!--${AOs::AO_Table}-->
|
||||
<attribute name="AO_Table" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
|
||||
<attribute name="AO_Table" type="QP::QActive * const" visibility="0x00" properties="0x00">
|
||||
<code>= &Table::inst; // "opaque" pointer to Table AO</code>
|
||||
</attribute>
|
||||
<!--${AOs::XT_Test1}-->
|
||||
<attribute name="XT_Test1" type="QP::QXThread * const" visibility="0x00" properties="0x00"/>
|
||||
<!--${AOs::XT_Test2}-->
|
||||
@ -373,7 +394,8 @@ m_fork[n] = FREE;</action>
|
||||
namespace DPP {
|
||||
|
||||
enum DPPSignals {
|
||||
EAT_SIG = QP::Q_USER_SIG, // published by Table to let a philosopher eat
|
||||
TIMEOUT_SIG = QP::Q_USER_SIG, // time event timeout
|
||||
EAT_SIG, // published by Table to let a philosopher eat
|
||||
DONE_SIG, // published by Philosopher when done eating
|
||||
PAUSE_SIG, // published by BSP to pause the application
|
||||
SERVE_SIG, // published by BSP to serve re-start serving forks
|
||||
@ -386,22 +408,20 @@ enum DPPSignals {
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
$declare(Events::TableEvt)
|
||||
$declare${Events::TableEvt}
|
||||
|
||||
// number of philosophers
|
||||
#define N_PHILO ((uint8_t)5)
|
||||
|
||||
$declare(AOs::AO_Philo[N_PHILO])
|
||||
|
||||
$declare(AOs::AO_Table)
|
||||
$declare${AOs::AO_Philo[N_PHILO]}
|
||||
$declare${AOs::AO_Table}
|
||||
|
||||
#ifdef QXK_HPP
|
||||
$declare(AOs::XT_Test1)
|
||||
$declare(AOs::XT_Test2)
|
||||
$declare${AOs::XT_Test1}
|
||||
$declare${AOs::XT_Test2}
|
||||
#endif // QXK_HPP
|
||||
|
||||
#endif // DPP_HPP
|
||||
</text>
|
||||
#endif // DPP_HPP</text>
|
||||
</file>
|
||||
<!--${.::philo.cpp}-->
|
||||
<file name="philo.cpp">
|
||||
@ -412,13 +432,11 @@ $declare(AOs::XT_Test2)
|
||||
Q_DEFINE_THIS_FILE
|
||||
|
||||
// Active object class -------------------------------------------------------
|
||||
$declare(AOs::Philo)
|
||||
$declare${AOs::Philo}
|
||||
|
||||
namespace DPP {
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Philo l_philo[N_PHILO]; // storage for all Philos
|
||||
|
||||
// helper function to provide a randomized think time for Philos
|
||||
inline QP::QTimeEvtCtr think_time() {
|
||||
return static_cast<QP::QTimeEvtCtr>((BSP::random() % BSP::TICKS_PER_SEC)
|
||||
@ -431,28 +449,15 @@ inline QP::QTimeEvtCtr eat_time() {
|
||||
+ BSP::TICKS_PER_SEC);
|
||||
}
|
||||
|
||||
// helper function to provide the ID of Philo
|
||||
inline uint8_t PHILO_ID(Philo const * const philo) {
|
||||
return static_cast<uint8_t>(philo - l_philo);
|
||||
// helper function to provide the ID of Philo "me"
|
||||
inline uint8_t PHILO_ID(Philo const * const me) {
|
||||
return static_cast<uint8_t>(me - &Philo::inst[0]);
|
||||
}
|
||||
|
||||
enum InternalSignals { // internal signals
|
||||
TIMEOUT_SIG = MAX_SIG
|
||||
};
|
||||
|
||||
// Global objects ------------------------------------------------------------
|
||||
QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
|
||||
&l_philo[0],
|
||||
&l_philo[1],
|
||||
&l_philo[2],
|
||||
&l_philo[3],
|
||||
&l_philo[4]
|
||||
};
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
// Philo definition ----------------------------------------------------------
|
||||
$define(AOs::Philo)</text>
|
||||
$define${AOs::AO_Philo[N_PHILO]}
|
||||
$define${AOs::Philo}</text>
|
||||
</file>
|
||||
<!--${.::table.cpp}-->
|
||||
<file name="table.cpp">
|
||||
@ -477,24 +482,17 @@ inline uint8_t LEFT(uint8_t const n) {
|
||||
return static_cast<uint8_t>((n + 1U) % N_PHILO);
|
||||
}
|
||||
|
||||
static uint8_t const FREE = static_cast<uint8_t>(0);
|
||||
static uint8_t const USED = static_cast<uint8_t>(1);
|
||||
constexpr uint8_t FREE = static_cast<uint8_t>(0);
|
||||
constexpr uint8_t USED = static_cast<uint8_t>(1);
|
||||
|
||||
static char_t const * const THINKING = &"thinking"[0];
|
||||
static char_t const * const HUNGRY = &"hungry "[0];
|
||||
static char_t const * const EATING = &"eating "[0];
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Table l_table; // the single instance of the Table active object
|
||||
|
||||
// Global-scope objects ------------------------------------------------------
|
||||
QP::QActive * const AO_Table = &l_table; // "opaque" AO pointer
|
||||
constexpr char_t const * const THINKING = &"thinking"[0];
|
||||
constexpr char_t const * const HUNGRY = &"hungry "[0];
|
||||
constexpr char_t const * const EATING = &"eating "[0];
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
//............................................................................
|
||||
$define(AOs::Table)
|
||||
</text>
|
||||
$define${AOs::AO_Table}
|
||||
$define(AOs::Table)</text>
|
||||
</file>
|
||||
</directory>
|
||||
</model>
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Model: dpp.qm
|
||||
// File: ${.::philo.cpp}
|
||||
//
|
||||
// This code has been generated by QM 4.6.0 <www.state-machine.com/qm/>.
|
||||
// This code has been generated by QM 5.0.3 <www.state-machine.com/qm/>.
|
||||
// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
|
||||
//
|
||||
// This program is open source software: you can redistribute it and/or
|
||||
@ -28,6 +28,9 @@ namespace DPP {
|
||||
|
||||
//.${AOs::Philo} .............................................................
|
||||
class Philo : public QP::QActive {
|
||||
public:
|
||||
static Philo inst[N_PHILO];
|
||||
|
||||
private:
|
||||
QP::QTimeEvt m_timeEvt;
|
||||
|
||||
@ -47,8 +50,6 @@ protected:
|
||||
namespace DPP {
|
||||
|
||||
// Local objects -------------------------------------------------------------
|
||||
static Philo l_philo[N_PHILO]; // storage for all Philos
|
||||
|
||||
// helper function to provide a randomized think time for Philos
|
||||
inline QP::QTimeEvtCtr think_time() {
|
||||
return static_cast<QP::QTimeEvtCtr>((BSP::random() % BSP::TICKS_PER_SEC)
|
||||
@ -61,40 +62,41 @@ inline QP::QTimeEvtCtr eat_time() {
|
||||
+ BSP::TICKS_PER_SEC);
|
||||
}
|
||||
|
||||
// helper function to provide the ID of Philo
|
||||
inline uint8_t PHILO_ID(Philo const * const philo) {
|
||||
return static_cast<uint8_t>(philo - l_philo);
|
||||
// helper function to provide the ID of Philo "me"
|
||||
inline uint8_t PHILO_ID(Philo const * const me) {
|
||||
return static_cast<uint8_t>(me - &Philo::inst[0]);
|
||||
}
|
||||
|
||||
enum InternalSignals { // internal signals
|
||||
TIMEOUT_SIG = MAX_SIG
|
||||
};
|
||||
|
||||
// Global objects ------------------------------------------------------------
|
||||
QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
|
||||
&l_philo[0],
|
||||
&l_philo[1],
|
||||
&l_philo[2],
|
||||
&l_philo[3],
|
||||
&l_philo[4]
|
||||
};
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
// Philo definition ----------------------------------------------------------
|
||||
//.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
//. Check for the minimum required QP version
|
||||
#if (QP_VERSION < 650U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
|
||||
#error qpcpp version 6.5.0 or higher required
|
||||
#if (QP_VERSION < 680U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
|
||||
#error qpcpp version 6.8.0 or higher required
|
||||
#endif
|
||||
//.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//.$define${AOs::AO_Philo[N_PHILO]} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::AO_Philo[N_PHILO]} .................................................
|
||||
QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
|
||||
&Philo::inst[0],
|
||||
&Philo::inst[1],
|
||||
&Philo::inst[2],
|
||||
&Philo::inst[3],
|
||||
&Philo::inst[4]
|
||||
};
|
||||
|
||||
} // namespace DPP
|
||||
//.$enddef${AOs::AO_Philo[N_PHILO]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//.$define${AOs::Philo} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
namespace DPP {
|
||||
|
||||
//.${AOs::Philo} .............................................................
|
||||
Philo Philo::inst[N_PHILO];
|
||||
//.${AOs::Philo::Philo} ......................................................
|
||||
Philo::Philo()
|
||||
: QActive(Q_STATE_CAST(&Philo::initial)),
|
||||
: QActive(&initial),
|
||||
m_timeEvt(this, TIMEOUT_SIG, 0U)
|
||||
{}
|
||||
|
||||
@ -103,27 +105,30 @@ Q_STATE_DEF(Philo, initial) {
|
||||
//.${AOs::Philo::SM::initial}
|
||||
static bool registered = false; // starts off with 0, per C-standard
|
||||
(void)e; // suppress the compiler warning about unused parameter
|
||||
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);
|
||||
|
||||
if (!registered) {
|
||||
registered = true;
|
||||
|
||||
QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&l_philo[4].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[0].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[1].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[2].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[3].m_timeEvt);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4]);
|
||||
QS_OBJ_DICTIONARY(&Philo::inst[4].m_timeEvt);
|
||||
|
||||
QS_FUN_DICTIONARY(&initial);
|
||||
QS_FUN_DICTIONARY(&thinking);
|
||||
QS_FUN_DICTIONARY(&hungry);
|
||||
QS_FUN_DICTIONARY(&eating);
|
||||
QS_FUN_DICTIONARY(&Philo::initial);
|
||||
QS_FUN_DICTIONARY(&Philo::thinking);
|
||||
QS_FUN_DICTIONARY(&Philo::hungry);
|
||||
QS_FUN_DICTIONARY(&Philo::eating);
|
||||
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, nullptr);
|
||||
}
|
||||
|
||||
QS_SIG_DICTIONARY(HUNGRY_SIG, this); // signal for each Philos
|
||||
QS_SIG_DICTIONARY(TIMEOUT_SIG, this); // signal for each Philos
|
||||
subscribe(EAT_SIG);
|
||||
subscribe(TEST_SIG);
|
||||
return tran(&thinking);
|
||||
}
|
||||
//.${AOs::Philo::SM::thinking} ...............................................
|
||||
@ -150,7 +155,7 @@ Q_STATE_DEF(Philo, thinking) {
|
||||
//.${AOs::Philo::SM::thinking::EAT, DONE}
|
||||
case EAT_SIG: // intentionally fall through
|
||||
case DONE_SIG: {
|
||||
// EAT or DONE must be for other Philos than this one
|
||||
/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));
|
||||
status_ = Q_RET_HANDLED;
|
||||
break;
|
||||
@ -231,7 +236,7 @@ Q_STATE_DEF(Philo, eating) {
|
||||
//.${AOs::Philo::SM::eating::EAT, DONE}
|
||||
case EAT_SIG: // intentionally fall through
|
||||
case DONE_SIG: {
|
||||
// EAT or DONE must be for other Philos than this one
|
||||
/* EAT or DONE must be for other Philos than this one */
|
||||
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(this));
|
||||
status_ = Q_RET_HANDLED;
|
||||
break;
|
||||
|
@ -517,7 +517,7 @@
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>ST-LINKIII-KEIL_SWO</Key>
|
||||
<Name>-U066CFF484951775087074312 -O8431 -SF4000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P2 -N00("ARM CoreSight SW-DP") -D00(0BC11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8004 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32L0xx_64.FLM -FS08000000 -FL010000 -FP0($$Device:STM32L053R8Tx$CMSIS\Flash\STM32L0xx_64.FLM)</Name>
|
||||
<Name>-U066CFF484951775087074312 -O8431 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P2 -N00("ARM CoreSight SW-DP (ARM Core") -D00(0BC11477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8004 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32L0xx_64.FLM -FS08000000 -FL010000 -FP0($$Device:STM32L053R8Tx$CMSIS\Flash\STM32L0xx_64.FLM)</Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
@ -532,7 +532,7 @@
|
||||
<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)</Name>
|
||||
<Name>(1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)</Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
@ -930,30 +930,6 @@
|
||||
<File>
|
||||
<GroupNumber>4</GroupNumber>
|
||||
<FileNumber>25</FileNumber>
|
||||
<FileType>5</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\..\..\..\..\ports\arm-cm\qk\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\qk\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>8</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@ -973,7 +949,7 @@
|
||||
<RteFlg>0</RteFlg>
|
||||
<File>
|
||||
<GroupNumber>5</GroupNumber>
|
||||
<FileNumber>28</FileNumber>
|
||||
<FileNumber>26</FileNumber>
|
||||
<FileType>8</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@ -985,7 +961,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>5</GroupNumber>
|
||||
<FileNumber>29</FileNumber>
|
||||
<FileNumber>27</FileNumber>
|
||||
<FileType>8</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@ -997,7 +973,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>5</GroupNumber>
|
||||
<FileNumber>30</FileNumber>
|
||||
<FileNumber>28</FileNumber>
|
||||
<FileType>8</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
|
@ -517,16 +517,6 @@
|
||||
<Group>
|
||||
<GroupName>QP_port</GroupName>
|
||||
<Files>
|
||||
<File>
|
||||
<FileName>qep_port.h</FileName>
|
||||
<FileType>5</FileType>
|
||||
<FilePath>..\..\..\..\..\ports\arm-cm\qk\armclang\qep_port.h</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>qf_port.h</FileName>
|
||||
<FileType>5</FileType>
|
||||
<FilePath>..\..\..\..\..\ports\arm-cm\qk\armclang\qf_port.h</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>qk_port.cpp</FileName>
|
||||
<FileType>8</FileType>
|
||||
@ -1136,16 +1126,6 @@
|
||||
<Group>
|
||||
<GroupName>QP_port</GroupName>
|
||||
<Files>
|
||||
<File>
|
||||
<FileName>qep_port.h</FileName>
|
||||
<FileType>5</FileType>
|
||||
<FilePath>..\..\..\..\..\ports\arm-cm\qk\armclang\qep_port.h</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>qf_port.h</FileName>
|
||||
<FileType>5</FileType>
|
||||
<FilePath>..\..\..\..\..\ports\arm-cm\qk\armclang\qf_port.h</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>qk_port.cpp</FileName>
|
||||
<FileType>8</FileType>
|
||||
@ -1755,16 +1735,6 @@
|
||||
<Group>
|
||||
<GroupName>QP_port</GroupName>
|
||||
<Files>
|
||||
<File>
|
||||
<FileName>qep_port.h</FileName>
|
||||
<FileType>5</FileType>
|
||||
<FilePath>..\..\..\..\..\ports\arm-cm\qk\armclang\qep_port.h</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>qf_port.h</FileName>
|
||||
<FileType>5</FileType>
|
||||
<FilePath>..\..\..\..\..\ports\arm-cm\qk\armclang\qf_port.h</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>qk_port.cpp</FileName>
|
||||
<FileType>8</FileType>
|
||||
|
@ -1,7 +1,7 @@
|
||||
///***************************************************************************
|
||||
// Product: DPP example, STM32 NUCLEO-L053R8 board, preemptive QK kernel
|
||||
// Last updated for version 5.9.7
|
||||
// Last updated on 2016-08-20
|
||||
// Last Updated for Version: 6.9.0
|
||||
// Date of the Last Update: 2020-08-14
|
||||
//
|
||||
// Q u a n t u m L e a P s
|
||||
// ---------------------------
|
||||
@ -28,7 +28,7 @@
|
||||
// along with this program. If not, see <www.gnu.org/licenses/>.
|
||||
//
|
||||
// Contact information:
|
||||
// https://state-machine.com
|
||||
// <www.state-machine.com/licensing>
|
||||
// <info@state-machine.com>
|
||||
//****************************************************************************
|
||||
#include "qpcpp.hpp"
|
||||
@ -38,31 +38,11 @@
|
||||
#include "stm32l0xx.h" // CMSIS-compliant header file for the MCU used
|
||||
// add other drivers if necessary...
|
||||
|
||||
Q_DEFINE_THIS_FILE
|
||||
Q_DEFINE_THIS_FILE // define the name of this file for assertions
|
||||
|
||||
// namespace DPP *************************************************************
|
||||
namespace DPP {
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority().
|
||||
// DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE!
|
||||
//
|
||||
enum KernelUnawareISRs { // see NOTE00
|
||||
// ...
|
||||
MAX_KERNEL_UNAWARE_CMSIS_PRI // keep always last
|
||||
};
|
||||
// "kernel-unaware" interrupts can't overlap "kernel-aware" interrupts
|
||||
Q_ASSERT_COMPILE(MAX_KERNEL_UNAWARE_CMSIS_PRI <= QF_AWARE_ISR_CMSIS_PRI);
|
||||
|
||||
enum KernelAwareISRs {
|
||||
EXTI0_1_PRIO = QF_AWARE_ISR_CMSIS_PRI, // see NOTE00
|
||||
SYSTICK_PRIO,
|
||||
// ...
|
||||
MAX_KERNEL_AWARE_CMSIS_PRI // keep always last
|
||||
};
|
||||
// "kernel-aware" interrupts should not overlap the PendSV priority
|
||||
Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
|
||||
|
||||
// Local-scope objects -------------------------------------------------------
|
||||
// LED pins available on the board (just one user LED LD2--Green on PA.5)
|
||||
#define LED_LD2 (1U << 5)
|
||||
@ -128,7 +108,7 @@ void SysTick_Handler(void) {
|
||||
static QP::QEvt const pauseEvt = { DPP::PAUSE_SIG, 0U, 0U};
|
||||
QP::QF::PUBLISH(&pauseEvt, &l_SysTick_Handler);
|
||||
}
|
||||
else { // the button is released
|
||||
else { // the button is released
|
||||
static QP::QEvt const serveEvt = { DPP::SERVE_SIG, 0U, 0U};
|
||||
QP::QF::PUBLISH(&serveEvt, &l_SysTick_Handler);
|
||||
}
|
||||
@ -147,6 +127,17 @@ void EXTI0_1_IRQHandler(void) {
|
||||
|
||||
QK_ISR_EXIT(); // inform QK about exiting an ISR
|
||||
}
|
||||
//............................................................................
|
||||
#ifdef Q_SPY
|
||||
void USART2_IRQHandler(void); // prototype
|
||||
void USART2_IRQHandler(void) { // used in QS-RX (kernel UNAWARE interrutp)
|
||||
// is RX register NOT empty?
|
||||
if ((USART2->ISR & (1U << 5)) != 0) {
|
||||
uint32_t b = USART2->RDR;
|
||||
QP::QS::rxPut(b);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@ -249,12 +240,16 @@ void QF::onStartup(void) {
|
||||
// Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority().
|
||||
// DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE!
|
||||
//
|
||||
NVIC_SetPriority(SysTick_IRQn, DPP::SYSTICK_PRIO);
|
||||
NVIC_SetPriority(EXTI0_1_IRQn, DPP::EXTI0_1_PRIO);
|
||||
NVIC_SetPriority(SysTick_IRQn, QF_AWARE_ISR_CMSIS_PRI + 1);
|
||||
NVIC_SetPriority(EXTI0_1_IRQn, QF_AWARE_ISR_CMSIS_PRI + 2);
|
||||
NVIC_SetPriority(USART2_IRQn, 0); // kernel UNAWARE interrupt
|
||||
// ...
|
||||
|
||||
// enable IRQs...
|
||||
NVIC_EnableIRQ(EXTI0_1_IRQn);
|
||||
#ifdef Q_SPY
|
||||
NVIC_EnableIRQ(USART2_IRQn); // UART2 interrupt used for QS-RX
|
||||
#endif
|
||||
}
|
||||
//............................................................................
|
||||
void QF::onCleanup(void) {
|
||||
@ -268,7 +263,9 @@ void QK::onIdle(void) {
|
||||
QF_INT_ENABLE();
|
||||
|
||||
#ifdef Q_SPY
|
||||
if ((USART2->ISR & 0x0080U) != 0) { // is TXE empty?
|
||||
QS::rxParse(); // parse all the received bytes
|
||||
|
||||
if ((USART2->ISR & (1U << 7)) != 0) { // is TXE empty?
|
||||
QF_INT_DISABLE();
|
||||
uint16_t b = QS::getByte();
|
||||
QF_INT_ENABLE();
|
||||
@ -322,26 +319,31 @@ extern "C" Q_NORETURN Q_onAssert(char const * const module, int_t const loc) {
|
||||
//............................................................................
|
||||
bool QS::onStartup(void const *arg) {
|
||||
static uint8_t qsBuf[2*1024]; // buffer for Quantum Spy
|
||||
static uint8_t qsRxBuf[128]; /* buffer for QS-RX channel */
|
||||
|
||||
initBuf(qsBuf, sizeof(qsBuf));
|
||||
rxInitBuf(qsRxBuf, sizeof(qsRxBuf));
|
||||
|
||||
// enable peripheral clock for USART2
|
||||
RCC->IOPENR |= ( 1ul << 0); // Enable GPIOA clock
|
||||
RCC->APB1ENR |= ( 1ul << 17); // Enable USART#2 clock
|
||||
RCC->IOPENR |= ( 1U << 0); // Enable GPIOA clock
|
||||
RCC->APB1ENR |= ( 1U << 17); // Enable USART#2 clock
|
||||
|
||||
// Configure PA3 to USART2_RX, PA2 to USART2_TX */
|
||||
GPIOA->AFR[0] &= ~((15ul << 4* 3) | (15ul << 4* 2) );
|
||||
GPIOA->AFR[0] |= (( 4ul << 4* 3) | ( 4ul << 4* 2) );
|
||||
GPIOA->MODER &= ~(( 3ul << 2* 3) | ( 3ul << 2* 2) );
|
||||
GPIOA->MODER |= (( 2ul << 2* 3) | ( 2ul << 2* 2) );
|
||||
GPIOA->AFR[0] &= ~((15U << 4* 3) | (15U << 4* 2) );
|
||||
GPIOA->AFR[0] |= (( 4U << 4* 3) | ( 4U << 4* 2) );
|
||||
GPIOA->MODER &= ~(( 3U << 2* 3) | ( 3U << 2* 2) );
|
||||
GPIOA->MODER |= (( 2U << 2* 3) | ( 2U << 2* 2) );
|
||||
|
||||
USART2->BRR = __USART_BRR(SystemCoreClock, 115200ul); // baud rate
|
||||
USART2->CR3 = 0x0000; // no flow control
|
||||
USART2->CR2 = 0x0000; // 1 stop bit
|
||||
USART2->CR1 = ((1ul << 2) | // enable RX
|
||||
(1ul << 3) | // enable TX
|
||||
(0ul << 12) | // 8 data bits
|
||||
(0ul << 28) | // 8 data bits
|
||||
(1ul << 0) ); // enable USART
|
||||
USART2->BRR = __USART_BRR(SystemCoreClock, 115200U); // baud rate
|
||||
USART2->CR3 = 0x0000 | // no flow control
|
||||
(1U << 12); // disable overrun detection (OVRDIS)
|
||||
USART2->CR2 = 0x0000; // 1 stop bit
|
||||
USART2->CR1 = ((1U << 2) | // enable RX
|
||||
(1U << 3) | // enable TX
|
||||
(1U << 5) | // enable RX interrupt
|
||||
(0U << 12) | // 8 data bits
|
||||
(0U << 28) | // 8 data bits
|
||||
(1U << 0) ); // enable USART
|
||||
|
||||
DPP::QS_tickPeriod_ = SystemCoreClock / DPP::BSP::TICKS_PER_SEC;
|
||||
DPP::QS_tickTime_ = DPP::QS_tickPeriod_; // to start the timestamp at zero
|
||||
@ -381,9 +383,9 @@ void QS::onFlush(void) {
|
||||
QF_INT_DISABLE();
|
||||
while ((b = getByte()) != QS_EOD) { // while not End-Of-Data...
|
||||
QF_INT_ENABLE();
|
||||
while ((USART2->ISR & 0x0080U) == 0U) { // while TXE not empty
|
||||
while ((USART2->ISR & (1U << 7)) == 0U) { // while TXE not empty
|
||||
}
|
||||
USART2->TDR = (b & 0xFFU); // put into the DR register
|
||||
USART2->TDR = (b & 0xFFU); // put into the DR register
|
||||
QF_INT_DISABLE();
|
||||
}
|
||||
QF_INT_ENABLE();
|
||||
@ -391,7 +393,7 @@ void QS::onFlush(void) {
|
||||
//............................................................................
|
||||
//! callback function to reset the target (to be implemented in the BSP)
|
||||
void QS::onReset(void) {
|
||||
//TBD
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
//............................................................................
|
||||
//! callback function to execute a uesr command (to be implemented in BSP)
|
||||
|
@ -11,7 +11,7 @@
|
||||
<name>General</name>
|
||||
<archiveVersion>3</archiveVersion>
|
||||
<data>
|
||||
<version>30</version>
|
||||
<version>31</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>1</debug>
|
||||
<option>
|
||||
@ -66,7 +66,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>OGLastSavedByProductVersion</name>
|
||||
<state>8.20.2.14834</state>
|
||||
<state>8.40.2.22864</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>GeneralEnableMisra</name>
|
||||
@ -112,11 +112,11 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>RTConfigPath2</name>
|
||||
<state>$TOOLKIT_DIR$\INC\c\DLib_Config_Normal.h</state>
|
||||
<state>$TOOLKIT_DIR$\inc\c\DLib_Config_Normal.h</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>GBECoreSlave</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -133,7 +133,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>CoreVariant</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -156,7 +156,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>GFPUCoreSlave2</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -204,13 +204,18 @@
|
||||
<name>TrustZone</name>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>TrustZoneModes</name>
|
||||
<version>0</version>
|
||||
<state>0</state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
<name>ICCARM</name>
|
||||
<archiveVersion>2</archiveVersion>
|
||||
<data>
|
||||
<version>34</version>
|
||||
<version>35</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>1</debug>
|
||||
<option>
|
||||
@ -463,6 +468,10 @@
|
||||
<name>IccRTTI2</name>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>OICompilerExtraOption</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
@ -683,7 +692,7 @@
|
||||
<name>ILINK</name>
|
||||
<archiveVersion>0</archiveVersion>
|
||||
<data>
|
||||
<version>20</version>
|
||||
<version>23</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>1</debug>
|
||||
<option>
|
||||
@ -995,6 +1004,30 @@
|
||||
<name>IlinkLocaleSelect</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkTrustzoneImportLibraryOut</name>
|
||||
<state>###Unitialized###</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>OILinkExtraOption</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinaryFile2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinarySymbol2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinarySegment2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinaryAlign2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
@ -1039,7 +1072,7 @@
|
||||
<name>General</name>
|
||||
<archiveVersion>3</archiveVersion>
|
||||
<data>
|
||||
<version>30</version>
|
||||
<version>31</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>0</debug>
|
||||
<option>
|
||||
@ -1144,7 +1177,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>GBECoreSlave</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -1161,7 +1194,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>CoreVariant</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -1184,7 +1217,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>GFPUCoreSlave2</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -1232,13 +1265,18 @@
|
||||
<name>TrustZone</name>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>TrustZoneModes</name>
|
||||
<version>0</version>
|
||||
<state>0</state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
<name>ICCARM</name>
|
||||
<archiveVersion>2</archiveVersion>
|
||||
<data>
|
||||
<version>34</version>
|
||||
<version>35</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>0</debug>
|
||||
<option>
|
||||
@ -1491,6 +1529,10 @@
|
||||
<name>IccRTTI2</name>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>OICompilerExtraOption</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
@ -1711,7 +1753,7 @@
|
||||
<name>ILINK</name>
|
||||
<archiveVersion>0</archiveVersion>
|
||||
<data>
|
||||
<version>20</version>
|
||||
<version>23</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>0</debug>
|
||||
<option>
|
||||
@ -2023,6 +2065,30 @@
|
||||
<name>IlinkLocaleSelect</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkTrustzoneImportLibraryOut</name>
|
||||
<state>###Unitialized###</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>OILinkExtraOption</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinaryFile2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinarySymbol2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinarySegment2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinaryAlign2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
@ -2067,7 +2133,7 @@
|
||||
<name>General</name>
|
||||
<archiveVersion>3</archiveVersion>
|
||||
<data>
|
||||
<version>30</version>
|
||||
<version>31</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>1</debug>
|
||||
<option>
|
||||
@ -2122,7 +2188,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>OGLastSavedByProductVersion</name>
|
||||
<state>8.20.2.14834</state>
|
||||
<state>8.40.2.22864</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>GeneralEnableMisra</name>
|
||||
@ -2172,7 +2238,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>GBECoreSlave</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -2189,7 +2255,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>CoreVariant</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -2212,7 +2278,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>GFPUCoreSlave2</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -2260,13 +2326,18 @@
|
||||
<name>TrustZone</name>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>TrustZoneModes</name>
|
||||
<version>0</version>
|
||||
<state>0</state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
<name>ICCARM</name>
|
||||
<archiveVersion>2</archiveVersion>
|
||||
<data>
|
||||
<version>34</version>
|
||||
<version>35</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>1</debug>
|
||||
<option>
|
||||
@ -2519,6 +2590,10 @@
|
||||
<name>IccRTTI2</name>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>OICompilerExtraOption</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
@ -2739,7 +2814,7 @@
|
||||
<name>ILINK</name>
|
||||
<archiveVersion>0</archiveVersion>
|
||||
<data>
|
||||
<version>20</version>
|
||||
<version>23</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>1</debug>
|
||||
<option>
|
||||
@ -3051,6 +3126,30 @@
|
||||
<name>IlinkLocaleSelect</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkTrustzoneImportLibraryOut</name>
|
||||
<state>###Unitialized###</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>OILinkExtraOption</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinaryFile2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinarySymbol2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinarySegment2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinaryAlign2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
@ -3184,10 +3283,10 @@
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qf_port.h</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qk_port.h</name>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qk_port.cpp</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qk_port.cpp</name>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qk_port.h</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qs_port.h</name>
|
||||
@ -3202,15 +3301,9 @@
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs.cpp</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs_64bit.cpp</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs_fp.cpp</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs_pkg.h</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs_rx.cpp</name>
|
||||
</file>
|
||||
|
@ -47,14 +47,6 @@ int main() {
|
||||
|
||||
DPP::BSP::init(); // initialize the BSP
|
||||
|
||||
// object dictionaries...
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Table);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[0]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[1]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[2]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[3]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[4]);
|
||||
|
||||
QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe
|
||||
|
||||
// initialize event pools...
|
||||
|
@ -931,7 +931,7 @@
|
||||
|
||||
<Group>
|
||||
<GroupName>QS</GroupName>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExp>1</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<cbSel>0</cbSel>
|
||||
<RteFlg>0</RteFlg>
|
||||
|
@ -1218,7 +1218,7 @@
|
||||
<TargetName>dpp-spy</TargetName>
|
||||
<ToolsetNumber>0x4</ToolsetNumber>
|
||||
<ToolsetName>ARM-ADS</ToolsetName>
|
||||
<pCCUsed>6070000::V6.7::.\ARMCLANG</pCCUsed>
|
||||
<pCCUsed>6130001::V6.13.1::.\ARMCLANG</pCCUsed>
|
||||
<uAC6>1</uAC6>
|
||||
<TargetOption>
|
||||
<TargetCommonOption>
|
||||
|
@ -1,7 +1,7 @@
|
||||
///***************************************************************************
|
||||
// Product: DPP example, STM32 NUCLEO-L053R8 board, cooperative QV kernel
|
||||
// Last updated for version 5.9.5
|
||||
// Last updated on 2017-07-20
|
||||
// Last Updated for Version: 6.9.0
|
||||
// Date of the Last Update: 2020-08-14
|
||||
//
|
||||
// Q u a n t u m L e a P s
|
||||
// ---------------------------
|
||||
@ -43,26 +43,6 @@ Q_DEFINE_THIS_FILE
|
||||
// namespace DPP *************************************************************
|
||||
namespace DPP {
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority().
|
||||
// DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE!
|
||||
//
|
||||
enum KernelUnawareISRs { // see NOTE00
|
||||
// ...
|
||||
MAX_KERNEL_UNAWARE_CMSIS_PRI // keep always last
|
||||
};
|
||||
// "kernel-unaware" interrupts can't overlap "kernel-aware" interrupts
|
||||
Q_ASSERT_COMPILE(MAX_KERNEL_UNAWARE_CMSIS_PRI <= QF_AWARE_ISR_CMSIS_PRI);
|
||||
|
||||
enum KernelAwareISRs {
|
||||
EXTI0_1_PRIO = QF_AWARE_ISR_CMSIS_PRI, // see NOTE00
|
||||
SYSTICK_PRIO,
|
||||
// ...
|
||||
MAX_KERNEL_AWARE_CMSIS_PRI // keep always last
|
||||
};
|
||||
// "kernel-aware" interrupts should not overlap the PendSV priority
|
||||
Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
|
||||
|
||||
// Local-scope objects -------------------------------------------------------
|
||||
// LED pins available on the board (just one user LED LD2--Green on PA.5)
|
||||
#define LED_LD2 (1U << 5)
|
||||
@ -70,7 +50,7 @@ Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
|
||||
// Button pins available on the board (just one user Button B1 on PC.13)
|
||||
#define BTN_B1 (1U << 13)
|
||||
|
||||
static unsigned l_rnd; // random seed
|
||||
static unsigned l_rnd; // random seed
|
||||
|
||||
#ifdef Q_SPY
|
||||
|
||||
@ -139,6 +119,17 @@ void EXTI0_1_IRQHandler(void) {
|
||||
DPP::AO_Table->POST(Q_NEW(QP::QEvt, DPP::MAX_PUB_SIG),
|
||||
&l_EXTI0_1_IRQHandler);
|
||||
}
|
||||
//............................................................................
|
||||
#ifdef Q_SPY
|
||||
void USART2_IRQHandler(void); // prototype
|
||||
void USART2_IRQHandler(void) { // used in QS-RX (kernel UNAWARE interrutp)
|
||||
// is RX register NOT empty?
|
||||
if ((USART2->ISR & (1U << 5)) != 0) {
|
||||
uint32_t b = USART2->RDR;
|
||||
QP::QS::rxPut(b);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@ -237,12 +228,16 @@ void QF::onStartup(void) {
|
||||
// Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority().
|
||||
// DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE!
|
||||
//
|
||||
NVIC_SetPriority(SysTick_IRQn, DPP::SYSTICK_PRIO);
|
||||
NVIC_SetPriority(EXTI0_1_IRQn, DPP::EXTI0_1_PRIO);
|
||||
NVIC_SetPriority(SysTick_IRQn, QF_AWARE_ISR_CMSIS_PRI + 1);
|
||||
NVIC_SetPriority(EXTI0_1_IRQn, QF_AWARE_ISR_CMSIS_PRI + 2);
|
||||
NVIC_SetPriority(USART2_IRQn, 0); // kernel UNAWARE interrupt
|
||||
// ...
|
||||
|
||||
// enable IRQs...
|
||||
NVIC_EnableIRQ(EXTI0_1_IRQn);
|
||||
#ifdef Q_SPY
|
||||
NVIC_EnableIRQ(USART2_IRQn); // UART2 interrupt used for QS-RX
|
||||
#endif
|
||||
}
|
||||
//............................................................................
|
||||
void QF::onCleanup(void) {
|
||||
@ -256,7 +251,9 @@ void QV::onIdle(void) { // called with interrupts disabled, see NOTE01
|
||||
|
||||
#ifdef Q_SPY
|
||||
QF_INT_ENABLE();
|
||||
if ((USART2->ISR & 0x0080U) != 0) { // is TXE empty?
|
||||
QS::rxParse(); // parse all the received bytes
|
||||
|
||||
if ((USART2->ISR & (1U << 7)) != 0) { // is TXE empty?
|
||||
QF_INT_DISABLE();
|
||||
uint16_t b = QS::getByte();
|
||||
QF_INT_ENABLE();
|
||||
@ -313,26 +310,31 @@ extern "C" Q_NORETURN Q_onAssert(char const * const module, int_t const loc) {
|
||||
//............................................................................
|
||||
bool QS::onStartup(void const *arg) {
|
||||
static uint8_t qsBuf[2*1024]; // buffer for Quantum Spy
|
||||
static uint8_t qsRxBuf[128]; /* buffer for QS-RX channel */
|
||||
|
||||
initBuf(qsBuf, sizeof(qsBuf));
|
||||
rxInitBuf(qsRxBuf, sizeof(qsRxBuf));
|
||||
|
||||
// enable peripheral clock for USART2
|
||||
RCC->IOPENR |= ( 1ul << 0); // Enable GPIOA clock
|
||||
RCC->APB1ENR |= ( 1ul << 17); // Enable USART#2 clock
|
||||
RCC->IOPENR |= ( 1U << 0); // Enable GPIOA clock
|
||||
RCC->APB1ENR |= ( 1U << 17); // Enable USART#2 clock
|
||||
|
||||
// Configure PA3 to USART2_RX, PA2 to USART2_TX */
|
||||
GPIOA->AFR[0] &= ~((15ul << 4* 3) | (15ul << 4* 2) );
|
||||
GPIOA->AFR[0] |= (( 4ul << 4* 3) | ( 4ul << 4* 2) );
|
||||
GPIOA->MODER &= ~(( 3ul << 2* 3) | ( 3ul << 2* 2) );
|
||||
GPIOA->MODER |= (( 2ul << 2* 3) | ( 2ul << 2* 2) );
|
||||
GPIOA->AFR[0] &= ~((15U << 4* 3) | (15U << 4* 2) );
|
||||
GPIOA->AFR[0] |= (( 4U << 4* 3) | ( 4U << 4* 2) );
|
||||
GPIOA->MODER &= ~(( 3U << 2* 3) | ( 3U << 2* 2) );
|
||||
GPIOA->MODER |= (( 2U << 2* 3) | ( 2U << 2* 2) );
|
||||
|
||||
USART2->BRR = __USART_BRR(SystemCoreClock, 115200ul); // baud rate
|
||||
USART2->CR3 = 0x0000; // no flow control
|
||||
USART2->CR2 = 0x0000; // 1 stop bit
|
||||
USART2->CR1 = ((1ul << 2) | // enable RX
|
||||
(1ul << 3) | // enable TX
|
||||
(0ul << 12) | // 8 data bits
|
||||
(0ul << 28) | // 8 data bits
|
||||
(1ul << 0) ); // enable USART
|
||||
USART2->BRR = __USART_BRR(SystemCoreClock, 115200U); // baud rate
|
||||
USART2->CR3 = 0x0000 | // no flow control
|
||||
(1U << 12); // disable overrun detection (OVRDIS)
|
||||
USART2->CR2 = 0x0000; // 1 stop bit
|
||||
USART2->CR1 = ((1U << 2) | // enable RX
|
||||
(1U << 3) | // enable TX
|
||||
(1U << 5) | // enable RX interrupt
|
||||
(0U << 12) | // 8 data bits
|
||||
(0U << 28) | // 8 data bits
|
||||
(1U << 0) ); // enable USART
|
||||
|
||||
DPP::QS_tickPeriod_ = SystemCoreClock / DPP::BSP::TICKS_PER_SEC;
|
||||
DPP::QS_tickTime_ = DPP::QS_tickPeriod_; // to start the timestamp at zero
|
||||
@ -372,9 +374,9 @@ void QS::onFlush(void) {
|
||||
QF_INT_DISABLE();
|
||||
while ((b = getByte()) != QS_EOD) { // while not End-Of-Data...
|
||||
QF_INT_ENABLE();
|
||||
while ((USART2->ISR & 0x0080U) == 0U) { // while TXE not empty
|
||||
while ((USART2->ISR & (1U << 7)) == 0U) { // while TXE not empty
|
||||
}
|
||||
USART2->TDR = (b & 0xFFU); // put into the DR register
|
||||
USART2->TDR = (b & 0xFFU); // put into the DR register
|
||||
QF_INT_DISABLE();
|
||||
}
|
||||
QF_INT_ENABLE();
|
||||
@ -382,7 +384,7 @@ void QS::onFlush(void) {
|
||||
//............................................................................
|
||||
//! callback function to reset the target (to be implemented in the BSP)
|
||||
void QS::onReset(void) {
|
||||
//TBD
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
//............................................................................
|
||||
//! callback function to execute a uesr command (to be implemented in BSP)
|
||||
|
@ -11,7 +11,7 @@
|
||||
<name>General</name>
|
||||
<archiveVersion>3</archiveVersion>
|
||||
<data>
|
||||
<version>30</version>
|
||||
<version>31</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>1</debug>
|
||||
<option>
|
||||
@ -66,7 +66,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>OGLastSavedByProductVersion</name>
|
||||
<state>8.20.2.14834</state>
|
||||
<state>8.40.2.22864</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>GeneralEnableMisra</name>
|
||||
@ -112,11 +112,11 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>RTConfigPath2</name>
|
||||
<state>$TOOLKIT_DIR$\INC\c\DLib_Config_Normal.h</state>
|
||||
<state>$TOOLKIT_DIR$\inc\c\DLib_Config_Normal.h</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>GBECoreSlave</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -133,7 +133,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>CoreVariant</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -156,7 +156,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>GFPUCoreSlave2</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -204,13 +204,18 @@
|
||||
<name>TrustZone</name>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>TrustZoneModes</name>
|
||||
<version>0</version>
|
||||
<state>0</state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
<name>ICCARM</name>
|
||||
<archiveVersion>2</archiveVersion>
|
||||
<data>
|
||||
<version>34</version>
|
||||
<version>35</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>1</debug>
|
||||
<option>
|
||||
@ -463,6 +468,10 @@
|
||||
<name>IccRTTI2</name>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>OICompilerExtraOption</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
@ -683,7 +692,7 @@
|
||||
<name>ILINK</name>
|
||||
<archiveVersion>0</archiveVersion>
|
||||
<data>
|
||||
<version>20</version>
|
||||
<version>23</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>1</debug>
|
||||
<option>
|
||||
@ -995,6 +1004,30 @@
|
||||
<name>IlinkLocaleSelect</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkTrustzoneImportLibraryOut</name>
|
||||
<state>###Unitialized###</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>OILinkExtraOption</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinaryFile2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinarySymbol2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinarySegment2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinaryAlign2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
@ -1039,7 +1072,7 @@
|
||||
<name>General</name>
|
||||
<archiveVersion>3</archiveVersion>
|
||||
<data>
|
||||
<version>30</version>
|
||||
<version>31</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>0</debug>
|
||||
<option>
|
||||
@ -1144,7 +1177,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>GBECoreSlave</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -1161,7 +1194,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>CoreVariant</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -1184,7 +1217,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>GFPUCoreSlave2</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -1232,13 +1265,18 @@
|
||||
<name>TrustZone</name>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>TrustZoneModes</name>
|
||||
<version>0</version>
|
||||
<state>0</state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
<name>ICCARM</name>
|
||||
<archiveVersion>2</archiveVersion>
|
||||
<data>
|
||||
<version>34</version>
|
||||
<version>35</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>0</debug>
|
||||
<option>
|
||||
@ -1491,6 +1529,10 @@
|
||||
<name>IccRTTI2</name>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>OICompilerExtraOption</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
@ -1711,7 +1753,7 @@
|
||||
<name>ILINK</name>
|
||||
<archiveVersion>0</archiveVersion>
|
||||
<data>
|
||||
<version>20</version>
|
||||
<version>23</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>0</debug>
|
||||
<option>
|
||||
@ -2023,6 +2065,30 @@
|
||||
<name>IlinkLocaleSelect</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkTrustzoneImportLibraryOut</name>
|
||||
<state>###Unitialized###</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>OILinkExtraOption</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinaryFile2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinarySymbol2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinarySegment2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinaryAlign2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
@ -2067,7 +2133,7 @@
|
||||
<name>General</name>
|
||||
<archiveVersion>3</archiveVersion>
|
||||
<data>
|
||||
<version>30</version>
|
||||
<version>31</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>1</debug>
|
||||
<option>
|
||||
@ -2122,7 +2188,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>OGLastSavedByProductVersion</name>
|
||||
<state>8.20.2.14834</state>
|
||||
<state>8.40.2.22864</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>GeneralEnableMisra</name>
|
||||
@ -2172,7 +2238,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>GBECoreSlave</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -2189,7 +2255,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>CoreVariant</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -2212,7 +2278,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>GFPUCoreSlave2</name>
|
||||
<version>26</version>
|
||||
<version>27</version>
|
||||
<state>35</state>
|
||||
</option>
|
||||
<option>
|
||||
@ -2260,13 +2326,18 @@
|
||||
<name>TrustZone</name>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>TrustZoneModes</name>
|
||||
<version>0</version>
|
||||
<state>0</state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
<name>ICCARM</name>
|
||||
<archiveVersion>2</archiveVersion>
|
||||
<data>
|
||||
<version>34</version>
|
||||
<version>35</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>1</debug>
|
||||
<option>
|
||||
@ -2519,6 +2590,10 @@
|
||||
<name>IccRTTI2</name>
|
||||
<state>0</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>OICompilerExtraOption</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
@ -2739,7 +2814,7 @@
|
||||
<name>ILINK</name>
|
||||
<archiveVersion>0</archiveVersion>
|
||||
<data>
|
||||
<version>20</version>
|
||||
<version>23</version>
|
||||
<wantNonLocal>1</wantNonLocal>
|
||||
<debug>1</debug>
|
||||
<option>
|
||||
@ -3051,6 +3126,30 @@
|
||||
<name>IlinkLocaleSelect</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkTrustzoneImportLibraryOut</name>
|
||||
<state>###Unitialized###</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>OILinkExtraOption</name>
|
||||
<state>1</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinaryFile2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinarySymbol2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinarySegment2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
<option>
|
||||
<name>IlinkRawBinaryAlign2</name>
|
||||
<state></state>
|
||||
</option>
|
||||
</data>
|
||||
</settings>
|
||||
<settings>
|
||||
@ -3199,15 +3298,9 @@
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs.cpp</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs_64bit.cpp</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs_fp.cpp</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs_pkg.h</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs_rx.cpp</name>
|
||||
</file>
|
||||
|
@ -47,14 +47,6 @@ int main() {
|
||||
|
||||
DPP::BSP::init(); // initialize the BSP
|
||||
|
||||
// object dictionaries...
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Table);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[0]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[1]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[2]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[3]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[4]);
|
||||
|
||||
QP::QF::psInit(subscrSto, Q_DIM(subscrSto)); // init publish-subscribe
|
||||
|
||||
// initialize event pools...
|
||||
|
104
examples/arm-cm/dpp_nucleo-l053r8/qview/dpp.py
Normal file
@ -0,0 +1,104 @@
|
||||
# This is an example of QView customization for a specific application
|
||||
# (DPP in this case). This example animates the Phil images on the
|
||||
# QView canvas. Additionally, there is a button in the middle of the screen,
|
||||
# which, when clicked once pauses the DPP ("forks" are not being served).
|
||||
# A second click on the button, "un-pauses" the DPP ("forks" are served
|
||||
# to all hungry Philosophers).
|
||||
#
|
||||
# This version of the DPP customization uses the application-specific
|
||||
# packet QS_USER_00 (PHILO_STAT) produced when the status of a Philo changes.
|
||||
#
|
||||
|
||||
class DPP:
|
||||
def __init__(self):
|
||||
|
||||
# add commands to the Custom menu...
|
||||
QView.custom_menu.add_command(label="Custom command",
|
||||
command=self.cust_command)
|
||||
|
||||
# configure the custom QView.canvas...
|
||||
QView.show_canvas() # make the canvas visible
|
||||
QView.canvas.configure(width=400, height=260)
|
||||
|
||||
# tuple of activity images (correspond to self._philo_state)
|
||||
self._act_img = (
|
||||
PhotoImage(file=HOME_DIR + "/img/thinking.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/hungry.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/eating.gif"),
|
||||
)
|
||||
# tuple of philo canvas images (correspond to self._philo_obj)
|
||||
self._philo_img = (\
|
||||
QView.canvas.create_image(190, 57, image=self._act_img[0]),
|
||||
QView.canvas.create_image(273, 100, image=self._act_img[0]),
|
||||
QView.canvas.create_image(237, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(146, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(107, 100, image=self._act_img[0])
|
||||
)
|
||||
|
||||
# button images for UP and DOWN
|
||||
self.img_UP = PhotoImage(file=HOME_DIR + "/img/BTN_UP.gif")
|
||||
self.img_DWN = PhotoImage(file=HOME_DIR + "/img/BTN_DWN.gif")
|
||||
|
||||
# images of a button for pause/serve
|
||||
self.btn = QView.canvas.create_image(200, 120, image=self.img_UP)
|
||||
QView.canvas.tag_bind(self.btn, "<ButtonPress-1>", self.cust_pause)
|
||||
|
||||
# request target reset on startup...
|
||||
# NOTE: Normally, for an embedded application you would like
|
||||
# to start with resetting the Target, to start clean with
|
||||
# Qs dictionaries, etc.
|
||||
reset_target()
|
||||
|
||||
# on_reset() callback
|
||||
def on_reset(self):
|
||||
# clear the lists
|
||||
self._philo_obj = [0, 0, 0, 0, 0]
|
||||
self._philo_state = [0, 0, 0]
|
||||
|
||||
# on_run() callback
|
||||
def on_run(self):
|
||||
glb_filter("QS_USER_00")
|
||||
|
||||
# NOTE: the names of objects for loc_filter() and current_obj()
|
||||
# must match the QS Object Dictionaries produced by the application.
|
||||
current_obj(OBJ_AO, "Table::inst")
|
||||
loc_filter(OBJ_TE, "Philo::inst[0].timeEvt")
|
||||
|
||||
# turn lists into tuples for better performance
|
||||
self._philo_obj = tuple(self._philo_obj)
|
||||
self._philo_state = tuple(self._philo_state)
|
||||
|
||||
|
||||
# example of a custom command
|
||||
def cust_command(self):
|
||||
command(1, 12345)
|
||||
|
||||
# example of a custom interaction with a canvas object (pause/serve)
|
||||
def cust_pause(self, event):
|
||||
if QView.canvas.itemcget(self.btn, "image") != str(self.img_UP):
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_UP)
|
||||
post("SERVE_SIG")
|
||||
QView.print_text("Table SERVING")
|
||||
else:
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_DWN)
|
||||
post("PAUSE_SIG")
|
||||
QView.print_text("Table PAUSED")
|
||||
|
||||
# intercept the QS_USER_00 application-specific packet
|
||||
# this packet has the following structure (see bsp.c:displayPhilStat()):
|
||||
# record-ID, seq-num, Timestamp, format-byte, Philo-num,
|
||||
# format-bye, Zero-terminated string (status)
|
||||
def QS_USER_00(self, packet):
|
||||
# unpack: Timestamp->data[0], Philo-num->data[1], status->data[3]
|
||||
data = qunpack("xxTxBxZ", packet)
|
||||
i = data[1]
|
||||
j = ("t", "h", "e").index(data[2][0]) # the first letter
|
||||
|
||||
# animate the given philo image according to its activity
|
||||
QView.canvas.itemconfig(self._philo_img[i], image=self._act_img[j])
|
||||
|
||||
# print a message to the text view
|
||||
QView.print_text("%010d Philo %1d is %s"%(data[0], i, data[2]))
|
||||
|
||||
#=============================================================================
|
||||
QView.customize(DPP()) # set the QView customization
|
148
examples/arm-cm/dpp_nucleo-l053r8/qview/dpp1.py
Normal file
@ -0,0 +1,148 @@
|
||||
# This is an example of QView customization for a specific application
|
||||
# (DPP in this case). This example animates the Phil images on the
|
||||
# QView canvas. Additionally, there is a button in the middle of the screen,
|
||||
# which, when clicked once pauses the DPP ("forks" are not being served).
|
||||
# A second click on the button, "un-pauses" the DPP ("forks" are served
|
||||
# to all hungry Philosophers).
|
||||
#
|
||||
# This version of the DPP customization uses the standard QS_QEP_STATE_ENTRY
|
||||
# packet, which provides information about the current states of the dining
|
||||
# Philosophers. The example also demonstrates how to intercept the QS
|
||||
# "dictionary" records QS_OBJ_DICT and QS_FUN_DICT to extract the information
|
||||
# about the addresses of the Philosopher objects and the states of their
|
||||
# state machines.
|
||||
#
|
||||
|
||||
class DPP:
|
||||
def __init__(self):
|
||||
|
||||
# add commands to the Custom menu...
|
||||
QView.custom_menu.add_command(label="Custom command",
|
||||
command=self.cust_command)
|
||||
|
||||
# configure the custom QView.canvas...
|
||||
QView.show_canvas() # make the canvas visible
|
||||
QView.canvas.configure(width=400, height=260)
|
||||
|
||||
# tuple of activity images (correspond to self._philo_state)
|
||||
self._act_img = (
|
||||
PhotoImage(file=HOME_DIR + "/img/thinking.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/hungry.gif"),
|
||||
PhotoImage(file=HOME_DIR + "/img/eating.gif"),
|
||||
)
|
||||
# tuple of philo canvas images (correspond to self._philo_obj)
|
||||
self._philo_img = (\
|
||||
QView.canvas.create_image(190, 57, image=self._act_img[0]),
|
||||
QView.canvas.create_image(273, 100, image=self._act_img[0]),
|
||||
QView.canvas.create_image(237, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(146, 185, image=self._act_img[0]),
|
||||
QView.canvas.create_image(107, 100, image=self._act_img[0])
|
||||
)
|
||||
|
||||
# button images for UP and DOWN
|
||||
self.img_UP = PhotoImage(file=HOME_DIR + "/img/BTN_UP.gif")
|
||||
self.img_DWN = PhotoImage(file=HOME_DIR + "/img/BTN_DWN.gif")
|
||||
|
||||
# images of a button for pause/serve
|
||||
self.btn = QView.canvas.create_image(200, 120, image=self.img_UP)
|
||||
QView.canvas.tag_bind(self.btn, "<ButtonPress-1>", self.cust_pause)
|
||||
|
||||
# request target reset on startup...
|
||||
# NOTE: Normally, for an embedded application you would like
|
||||
# to start with resetting the Target, to start clean with
|
||||
# Qs dictionaries, etc.
|
||||
reset_target()
|
||||
|
||||
# on_reset() callback invoked when Target-reset packet is received
|
||||
# NOTE: the QS dictionaries are not known at this time yet, so
|
||||
# this callback shouild generally not set filters or current objects
|
||||
def on_reset(self):
|
||||
# (re)set the lists
|
||||
self._philo_obj = [0, 0, 0, 0, 0]
|
||||
self._philo_state = [0, 0, 0]
|
||||
|
||||
# on_run() callback invoked when the QF_RUN packet is received
|
||||
# NOTE: the QS dictionaries are typically known at this time yet, so
|
||||
# this callback can set filters or current objects
|
||||
def on_run(self):
|
||||
glb_filter("QS_QEP_TRAN")
|
||||
|
||||
# NOTE: the names of objects for loc_filter() and current_obj()
|
||||
# must match the QS Object Dictionaries produced by the application.
|
||||
current_obj(OBJ_AO, "Table::inst")
|
||||
loc_filter(OBJ_TE, "Philo::inst[0].m_timeEvt")
|
||||
|
||||
# turn lists into tuples for better performance
|
||||
self._philo_obj = tuple(self._philo_obj)
|
||||
self._philo_state = tuple(self._philo_state)
|
||||
|
||||
|
||||
# example of a custom command
|
||||
def cust_command(self):
|
||||
command(1, 12345)
|
||||
|
||||
# example of a custom interaction with a canvas object (pause/serve)
|
||||
def cust_pause(self, event):
|
||||
if QView.canvas.itemcget(self.btn, "image") != str(self.img_UP):
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_UP)
|
||||
post("SERVE_SIG")
|
||||
QView.print_text("Table SERVING")
|
||||
else:
|
||||
QView.canvas.itemconfig(self.btn, image=self.img_DWN)
|
||||
post("PAUSE_SIG")
|
||||
QView.print_text("Table PAUSED")
|
||||
|
||||
# intercept the QS_OBJ_DICT stadard packet
|
||||
# this packet has the following structure:
|
||||
# record-ID, seq-num, Object-ptr, Zero-terminated string
|
||||
def QS_OBJ_DICT(self, packet):
|
||||
data = qunpack("xxOZ", packet)
|
||||
try:
|
||||
# NOTE: the names of objects must match the QS Object Dictionaries
|
||||
# produced by the application.
|
||||
i = ("Philo::inst[0]",
|
||||
"Philo::inst[1]",
|
||||
"Philo::inst[2]",
|
||||
"Philo::inst[3]",
|
||||
"Philo::inst[4]").index(data[1])
|
||||
self._philo_obj[i] = data[0]
|
||||
except:
|
||||
pass # dictionary for a different object
|
||||
|
||||
# intercept the QS_FUN_DICT stadard packet
|
||||
# this packet has the following structure:
|
||||
# record-ID, seq-num, Function-ptr, Zero-terminated string
|
||||
def QS_FUN_DICT(self, packet):
|
||||
data = qunpack("xxFZ", packet)
|
||||
try:
|
||||
# NOTE: the names of states must match the QS Object Dictionaries
|
||||
# produced by the application.
|
||||
j = ("Philo::thinking",
|
||||
"Philo::hungry",
|
||||
"Philo::eating").index(data[1])
|
||||
self._philo_state[j] = data[0]
|
||||
except:
|
||||
pass # dictionary for a different state
|
||||
|
||||
# intercept the QS_QEP_TRAN stadard packet
|
||||
# this packet has the following structure:
|
||||
# record-ID, seq-num, Timestamp, Signal, Object-ptr,
|
||||
# Function-ptr (source state), Function-ptr (new active state)
|
||||
def QS_QEP_TRAN(self, packet):
|
||||
data = qunpack("xxTSOFF", packet)
|
||||
try:
|
||||
i = self._philo_obj.index(data[2])
|
||||
j = self._philo_state.index(data[4])
|
||||
|
||||
# animate the given philo image according to its activity
|
||||
QView.canvas.itemconfig(self._philo_img[i],
|
||||
image=self._act_img[j])
|
||||
# print a message to the text view
|
||||
QView.print_text("%010d Philo %d is %s"\
|
||||
%(data[0], i, ("thinking", "hungry", "eating")[j]))
|
||||
except:
|
||||
pass # state-entry in a different object
|
||||
|
||||
#=============================================================================
|
||||
# instantiate the DPP class and set it as the QView customization
|
||||
QView.customize(DPP())
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
8
examples/arm-cm/dpp_nucleo-l053r8/qview/qview-dpp.bat
Normal file
@ -0,0 +1,8 @@
|
||||
@setlocal
|
||||
|
||||
if "%QTOOLS%"=="" (
|
||||
set QTOOLS=C:\qp\qtools
|
||||
)
|
||||
python %QTOOLS%\qview\qview.py dpp.py
|
||||
|
||||
@endlocal
|
BIN
examples/arm-cm/dpp_nucleo-l053r8/qview/qview-dpp.lnk
Normal file
8
examples/arm-cm/dpp_nucleo-l053r8/qview/qview-dpp1.bat
Normal file
@ -0,0 +1,8 @@
|
||||
@setlocal
|
||||
|
||||
if "%QTOOLS%"=="" (
|
||||
set QTOOLS=C:\qp\qtools
|
||||
)
|
||||
python %QTOOLS%\qview\qview.py dpp1.py
|
||||
|
||||
@endlocal
|
BIN
examples/arm-cm/dpp_nucleo-l053r8/qview/qview-dpp1.lnk
Normal file
@ -1268,7 +1268,7 @@
|
||||
<TargetName>dpp-spy</TargetName>
|
||||
<ToolsetNumber>0x4</ToolsetNumber>
|
||||
<ToolsetName>ARM-ADS</ToolsetName>
|
||||
<pCCUsed>6070000::V6.7::.\ARMCLANG</pCCUsed>
|
||||
<pCCUsed>6130001::V6.13.1::.\ARMCLANG</pCCUsed>
|
||||
<uAC6>1</uAC6>
|
||||
<TargetOption>
|
||||
<TargetCommonOption>
|
||||
|
@ -1,7 +1,7 @@
|
||||
///***************************************************************************
|
||||
// Product: DPP example, STM32 NUCLEO-L053R8 board, preemptive QXK kernel
|
||||
// Last Updated for Version: 6.1.1
|
||||
// Date of the Last Update: 2018-02-17
|
||||
// Last Updated for Version: 6.9.0
|
||||
// Date of the Last Update: 2020-08-14
|
||||
//
|
||||
// Q u a n t u m L e a P s
|
||||
// ---------------------------
|
||||
@ -43,26 +43,6 @@ Q_DEFINE_THIS_FILE // define the name of this file for assertions
|
||||
// namespace DPP *************************************************************
|
||||
namespace DPP {
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority().
|
||||
// DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE!
|
||||
//
|
||||
enum KernelUnawareISRs { // see NOTE1
|
||||
// ...
|
||||
MAX_KERNEL_UNAWARE_CMSIS_PRI // keep always last
|
||||
};
|
||||
// "kernel-unaware" interrupts can't overlap "kernel-aware" interrupts
|
||||
Q_ASSERT_COMPILE(MAX_KERNEL_UNAWARE_CMSIS_PRI <= QF_AWARE_ISR_CMSIS_PRI);
|
||||
|
||||
enum KernelAwareISRs {
|
||||
EXTI0_1_PRIO = QF_AWARE_ISR_CMSIS_PRI, // see NOTE00
|
||||
SYSTICK_PRIO,
|
||||
// ...
|
||||
MAX_KERNEL_AWARE_CMSIS_PRI // keep always last
|
||||
};
|
||||
// "kernel-aware" interrupts should not overlap the PendSV priority
|
||||
Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
|
||||
|
||||
// Local-scope objects -------------------------------------------------------
|
||||
// LED pins available on the board (just one user LED LD2--Green on PA.5)
|
||||
#define LED_LD2 (1U << 5)
|
||||
@ -151,6 +131,17 @@ void EXTI0_1_IRQHandler(void) {
|
||||
|
||||
QXK_ISR_EXIT(); // inform QXK about exiting an ISR
|
||||
}
|
||||
//............................................................................
|
||||
#ifdef Q_SPY
|
||||
void USART2_IRQHandler(void); // prototype
|
||||
void USART2_IRQHandler(void) { // used in QS-RX (kernel UNAWARE interrupt)
|
||||
// is RX register NOT empty?
|
||||
if ((USART2->ISR & (1U << 5)) != 0) {
|
||||
uint32_t b = USART2->RDR;
|
||||
QP::QS::rxPut(b);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@ -227,7 +218,7 @@ uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
|
||||
l_rnd = rnd; // set for the next time
|
||||
QP::QXK::schedUnlock(lockStat); // sched unlock around l_rnd
|
||||
|
||||
return (rnd >> 8);
|
||||
return rnd >> 8;
|
||||
}
|
||||
//............................................................................
|
||||
void BSP::randomSeed(uint32_t seed) {
|
||||
@ -264,18 +255,22 @@ void QF::onStartup(void) {
|
||||
// set up the SysTick timer to fire at BSP::TICKS_PER_SEC rate
|
||||
SysTick_Config(SystemCoreClock / DPP::BSP::TICKS_PER_SEC);
|
||||
|
||||
// set priorities of ALL ISRs used in the system, see NOTE00
|
||||
// set priorities of ALL ISRs used in the system, see NOTE1
|
||||
//
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority().
|
||||
// DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE!
|
||||
//
|
||||
NVIC_SetPriority(SysTick_IRQn, DPP::SYSTICK_PRIO);
|
||||
NVIC_SetPriority(EXTI0_1_IRQn, DPP::EXTI0_1_PRIO);
|
||||
NVIC_SetPriority(SysTick_IRQn, QF_AWARE_ISR_CMSIS_PRI + 1);
|
||||
NVIC_SetPriority(EXTI0_1_IRQn, QF_AWARE_ISR_CMSIS_PRI + 2);
|
||||
NVIC_SetPriority(USART2_IRQn, 0); // kernel UNAWARE interrupt
|
||||
// ...
|
||||
|
||||
// enable IRQs...
|
||||
NVIC_EnableIRQ(EXTI0_1_IRQn);
|
||||
#ifdef Q_SPY
|
||||
NVIC_EnableIRQ(USART2_IRQn); // UART2 interrupt used for QS-RX
|
||||
#endif
|
||||
}
|
||||
//............................................................................
|
||||
void QF::onCleanup(void) {
|
||||
@ -298,14 +293,16 @@ void QXK_onContextSw(QActive *prev, QActive *next) {
|
||||
#endif // QXK_ON_CONTEXT_SW
|
||||
//............................................................................
|
||||
void QXK::onIdle(void) {
|
||||
// toggle the User LED on and then off (not enough LEDs, see NOTE01)
|
||||
// toggle the User LED on and then off (not enough LEDs, see NOTE2)
|
||||
QF_INT_DISABLE();
|
||||
//GPIOA->BSRR |= (LED_LD2); // turn LED[n] on
|
||||
//GPIOA->BSRR |= (LED_LD2 << 16); // turn LED[n] off
|
||||
QF_INT_ENABLE();
|
||||
|
||||
#ifdef Q_SPY
|
||||
if ((USART2->ISR & 0x0080U) != 0) { // is TXE empty?
|
||||
QS::rxParse(); // parse all the received bytes
|
||||
|
||||
if ((USART2->ISR & (1U << 7)) != 0) { // is TXE empty?
|
||||
QF_INT_DISABLE();
|
||||
uint16_t b = QS::getByte();
|
||||
QF_INT_ENABLE();
|
||||
@ -328,7 +325,8 @@ void QXK::onIdle(void) {
|
||||
// reset the board, then connect with ST-Link Utilities and erase the part.
|
||||
// The trick with BOOT(0) is it gets the part to run the System Loader
|
||||
// instead of your broken code. When done disconnect BOOT0, and start over.
|
||||
//__WFI(); // Wait-For-Interrupt
|
||||
//
|
||||
//__WFI(); Wait-For-Interrupt
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -362,26 +360,31 @@ extern "C" Q_NORETURN Q_onAssert(char const * const module, int_t const loc) {
|
||||
//............................................................................
|
||||
bool QS::onStartup(void const *arg) {
|
||||
static uint8_t qsBuf[2*1024]; // buffer for Quantum Spy
|
||||
static uint8_t qsRxBuf[128]; /* buffer for QS-RX channel */
|
||||
|
||||
initBuf(qsBuf, sizeof(qsBuf));
|
||||
rxInitBuf(qsRxBuf, sizeof(qsRxBuf));
|
||||
|
||||
// enable peripheral clock for USART2
|
||||
RCC->IOPENR |= ( 1ul << 0); // Enable GPIOA clock
|
||||
RCC->APB1ENR |= ( 1ul << 17); // Enable USART#2 clock
|
||||
RCC->IOPENR |= ( 1U << 0); // Enable GPIOA clock
|
||||
RCC->APB1ENR |= ( 1U << 17); // Enable USART#2 clock
|
||||
|
||||
// Configure PA3 to USART2_RX, PA2 to USART2_TX */
|
||||
GPIOA->AFR[0] &= ~((15ul << 4* 3) | (15ul << 4* 2) );
|
||||
GPIOA->AFR[0] |= (( 4ul << 4* 3) | ( 4ul << 4* 2) );
|
||||
GPIOA->MODER &= ~(( 3ul << 2* 3) | ( 3ul << 2* 2) );
|
||||
GPIOA->MODER |= (( 2ul << 2* 3) | ( 2ul << 2* 2) );
|
||||
GPIOA->AFR[0] &= ~((15U << 4* 3) | (15U << 4* 2) );
|
||||
GPIOA->AFR[0] |= (( 4U << 4* 3) | ( 4U << 4* 2) );
|
||||
GPIOA->MODER &= ~(( 3U << 2* 3) | ( 3U << 2* 2) );
|
||||
GPIOA->MODER |= (( 2U << 2* 3) | ( 2U << 2* 2) );
|
||||
|
||||
USART2->BRR = __USART_BRR(SystemCoreClock, 115200ul); // baud rate
|
||||
USART2->CR3 = 0x0000; // no flow control
|
||||
USART2->CR2 = 0x0000; // 1 stop bit
|
||||
USART2->CR1 = ((1ul << 2) | // enable RX
|
||||
(1ul << 3) | // enable TX
|
||||
(0ul << 12) | // 8 data bits
|
||||
(0ul << 28) | // 8 data bits
|
||||
(1ul << 0) ); // enable USART
|
||||
USART2->BRR = __USART_BRR(SystemCoreClock, 115200U); // baud rate
|
||||
USART2->CR3 = 0x0000 | // no flow control
|
||||
(1U << 12); // disable overrun detection (OVRDIS)
|
||||
USART2->CR2 = 0x0000; // 1 stop bit
|
||||
USART2->CR1 = ((1U << 2) | // enable RX
|
||||
(1U << 3) | // enable TX
|
||||
(1U << 5) | // enable RX interrupt
|
||||
(0U << 12) | // 8 data bits
|
||||
(0U << 28) | // 8 data bits
|
||||
(1U << 0) ); // enable USART
|
||||
|
||||
DPP::QS_tickPeriod_ = SystemCoreClock / DPP::BSP::TICKS_PER_SEC;
|
||||
DPP::QS_tickTime_ = DPP::QS_tickPeriod_; // to start the timestamp at zero
|
||||
@ -412,9 +415,9 @@ void QS::onFlush(void) {
|
||||
QF_INT_DISABLE();
|
||||
while ((b = getByte()) != QS_EOD) { // while not End-Of-Data...
|
||||
QF_INT_ENABLE();
|
||||
while ((USART2->ISR & 0x0080U) == 0U) { // while TXE not empty
|
||||
while ((USART2->ISR & (1U << 7)) == 0U) { // while TXE not empty
|
||||
}
|
||||
USART2->TDR = (b & 0xFFU); // put into the DR register
|
||||
USART2->TDR = (b & 0xFFU); // put into the DR register
|
||||
QF_INT_DISABLE();
|
||||
}
|
||||
QF_INT_ENABLE();
|
||||
@ -422,10 +425,10 @@ void QS::onFlush(void) {
|
||||
//............................................................................
|
||||
//! callback function to reset the target (to be implemented in the BSP)
|
||||
void QS::onReset(void) {
|
||||
//TBD
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
//............................................................................
|
||||
//! callback function to execute a user command (to be implemented in BSP)
|
||||
//! callback function to execute a uesr command (to be implemented in BSP)
|
||||
void QS::onCommand(uint8_t cmdId, uint32_t param1,
|
||||
uint32_t param2, uint32_t param3)
|
||||
{
|
||||
@ -435,17 +438,6 @@ void QS::onCommand(uint8_t cmdId, uint32_t param1,
|
||||
(void)param3;
|
||||
//TBD
|
||||
}
|
||||
|
||||
/*???
|
||||
void bug_test(void) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < 10; i++) {
|
||||
QS_BEGIN(123, 0);
|
||||
QS_U32(8, 0);
|
||||
QS_END();
|
||||
}
|
||||
}
|
||||
*/
|
||||
#endif // Q_SPY
|
||||
//--------------------------------------------------------------------------*/
|
||||
|
||||
@ -459,14 +451,14 @@ void bug_test(void) {
|
||||
//
|
||||
// Only ISRs prioritized at or below the QF_AWARE_ISR_CMSIS_PRI level (i.e.,
|
||||
// with the numerical values of priorities equal or higher than
|
||||
// QF_AWARE_ISR_CMSIS_PRI) are allowed to call the QK_ISR_ENTRY/QK_ISR_ENTRY
|
||||
// macros or any other QF/QK services. These ISRs are "QF-aware".
|
||||
// QF_AWARE_ISR_CMSIS_PRI) are allowed to call the QXK_ISR_ENTRY/QXK_ISR_ENTRY
|
||||
// macros or any other QF/QXK services. These ISRs are "QF-aware".
|
||||
//
|
||||
// Conversely, any ISRs prioritized above the QF_AWARE_ISR_CMSIS_PRI priority
|
||||
// level (i.e., with the numerical values of priorities less than
|
||||
// QF_AWARE_ISR_CMSIS_PRI) are never disabled and are not aware of the kernel.
|
||||
// Such "QF-unaware" ISRs cannot call any QF/QK services. In particular they
|
||||
// can NOT call the macros QK_ISR_ENTRY/QK_ISR_ENTRY. The only mechanism
|
||||
// Such "QF-unaware" ISRs cannot call any QF/QXK services. In particular they
|
||||
// can NOT call the macros QXK_ISR_ENTRY/QXK_ISR_ENTRY. The only mechanism
|
||||
// by which a "QF-unaware" ISR can communicate with the QF framework is by
|
||||
// triggering a "QF-aware" ISR, which can post/publish events.
|
||||
//
|
||||
|
@ -2188,7 +2188,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>OGLastSavedByProductVersion</name>
|
||||
<state>8.20.2.14834</state>
|
||||
<state>8.40.2.22864</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>GeneralEnableMisra</name>
|
||||
@ -3308,15 +3308,9 @@
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs.cpp</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs_64bit.cpp</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs_fp.cpp</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs_pkg.h</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\..\..\..\..\..\src\qs\qs_rx.cpp</name>
|
||||
</file>
|
||||
|
@ -56,12 +56,6 @@ int main() {
|
||||
DPP::BSP::init(); // initialize the BSP
|
||||
|
||||
// object dictionaries...
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Table);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[0]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[1]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[2]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[3]);
|
||||
QS_OBJ_DICTIONARY(DPP::AO_Philo[4]);
|
||||
QS_OBJ_DICTIONARY(&l_ticker0);
|
||||
|
||||
// init publish-subscribe
|
||||
|