Explorar o código

移植至RT-Thread

zhouyong %!s(int64=3) %!d(string=hai) anos
pai
achega
f0ab569570

+ 28 - 0
SConscript

@@ -0,0 +1,28 @@
+import rtconfig
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Split("""
+./src/qf/qep_hsm.c
+./src/qf/qep_msm.c
+./src/qf/qf_act.c
+./src/qf/qf_defer.c
+./src/qf/qf_dyn.c
+./src/qf/qf_ps.c
+./src/qf/qf_qact.c
+./src/qf/qf_qeq.c
+./src/qf/qf_qmact.c
+./src/qf/qf_time.c
+./include/qstamp.c
+./ports/rt-thread/qf_hooks.c
+./ports/rt-thread/qf_port.c
+""")
+
+if GetDepend(['QPC_USING_BLINKY_EXAMPLE']):
+    src += Glob('examples/rt-thread/blinky/blinky.c')
+
+path = [cwd + "/ports", cwd + "/include", cwd + "/src"]
+
+group = DefineGroup('qpc', src, depend = ['RT_USING_MAILBOX', 'PKG_USING_QPC'], CPPPATH = path)
+
+Return('group')

+ 17 - 0
examples/rt-thread/blinky/README.md

@@ -0,0 +1,17 @@
+@page exa_workstation_blinky Example: Blinky Console
+
+Blinky on RT-Thread
+
+# Example: Blinky Console
+
+This example corresponds to the QM Tutorial at:
+
+https://www.state-machine.com/qm/gs_tut.html
+
+
+Specifically the files are as follows:
+
+```
+blinky.qm - the QM model for the Blinky active object
+blinky.c  - the generated code for the Blinky application
+```

+ 158 - 0
examples/rt-thread/blinky/blinky.c

@@ -0,0 +1,158 @@
+/*.$file${.::blinky.c} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
+/*
+* Model: blinky.qm
+* File:  ${.::blinky.c}
+*
+* This code has been generated by QM 5.1.4 <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
+* modify it under the terms of the GNU General Public License as published
+* by the Free Software Foundation.
+*
+* 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.
+*/
+/*.$endhead${.::blinky.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
+#include <rtthread.h>
+
+#ifdef QPC_USING_BLINKY_EXAMPLE
+#ifdef RT_USING_FINSH
+
+#include <finsh.h>
+#include "qpc.h"
+Q_DEFINE_THIS_FILE
+
+enum { BSP_TICKS_PER_SEC = 100 };
+
+void BSP_ledOff(void) {
+    rt_kprintf("LED OFF\n");
+}
+void BSP_ledOn(void) {
+    rt_kprintf("LED ON\n");
+}
+
+
+enum BlinkySignals {
+    TIMEOUT_SIG = Q_USER_SIG,
+    MAX_SIG
+};
+
+//*============== ask QM to declare the Blinky class ================*/
+/*.$declare${AOs::Blinky} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
+/*.${AOs::Blinky} ..........................................................*/
+typedef struct Blinky {
+/* protected: */
+    QActive super;
+
+/* public: */
+
+/* private: */
+    QTimeEvt timeEvt;
+} Blinky;
+extern Blinky Blinky_inst;
+
+/* protected: */
+static QState Blinky_initial(Blinky * const me, void const * const par);
+static QState Blinky_off(Blinky * const me, QEvt const * const e);
+static QState Blinky_on(Blinky * const me, QEvt const * const e);
+/*.$enddecl${AOs::Blinky} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
+
+QActive * const AO_Blinky = &Blinky_inst.super;
+
+static void Blinky_ctor(void) {
+    Blinky *me = &Blinky_inst;
+    QActive_ctor(&me->super, Q_STATE_CAST(&Blinky_initial));
+    QTimeEvt_ctorX(&me->timeEvt, &me->super, TIMEOUT_SIG, 0U);
+}
+
+int qpc_blinky_start(void) {
+    /* statically allocate event queue buffer for the Blinky AO */
+    static QEvt const *blinky_queueSto[10];
+    static uint8_t blinky_stack[1024];
+
+    QF_init(); /* initialize the framework */
+
+    Blinky_ctor(); /* explicitly call the "constructor" */
+    QACTIVE_START(AO_Blinky,
+                  1U, /* priority */
+                  blinky_queueSto, Q_DIM(blinky_queueSto),
+                  (void *)blinky_stack, sizeof(blinky_stack), /* no stack */
+                  (void *)0);    /* no initialization parameter */
+    return QF_run(); /* run the QF application */
+}
+
+MSH_CMD_EXPORT(qpc_blinky_start, start qpc blinky example);
+
+/*================ ask QM to define the Blinky class ================*/
+/*.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
+/*. Check for the minimum required QP version */
+#if (QP_VERSION < 690U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
+#error qpc version 6.9.0 or higher required
+#endif
+/*.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
+/*.$define${AOs::Blinky} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
+/*.${AOs::Blinky} ..........................................................*/
+Blinky Blinky_inst;
+/*.${AOs::Blinky::SM} ......................................................*/
+static QState Blinky_initial(Blinky * const me, void const * const par) {
+    /*.${AOs::Blinky::SM::initial} */
+    (void)par; /* unused parameter */
+    QTimeEvt_armX(&me->timeEvt,
+    BSP_TICKS_PER_SEC/2, BSP_TICKS_PER_SEC/2);
+
+    QS_FUN_DICTIONARY(&Blinky_off);
+    QS_FUN_DICTIONARY(&Blinky_on);
+
+    return Q_TRAN(&Blinky_off);
+}
+/*.${AOs::Blinky::SM::off} .................................................*/
+static QState Blinky_off(Blinky * const me, QEvt const * const e) {
+    QState status_;
+    switch (e->sig) {
+        /*.${AOs::Blinky::SM::off} */
+        case Q_ENTRY_SIG: {
+            BSP_ledOff();
+            status_ = Q_HANDLED();
+            break;
+        }
+        /*.${AOs::Blinky::SM::off::TIMEOUT} */
+        case TIMEOUT_SIG: {
+            status_ = Q_TRAN(&Blinky_on);
+            break;
+        }
+        default: {
+            status_ = Q_SUPER(&QHsm_top);
+            break;
+        }
+    }
+    return status_;
+}
+/*.${AOs::Blinky::SM::on} ..................................................*/
+static QState Blinky_on(Blinky * const me, QEvt const * const e) {
+    QState status_;
+    switch (e->sig) {
+        /*.${AOs::Blinky::SM::on} */
+        case Q_ENTRY_SIG: {
+            BSP_ledOn();
+            status_ = Q_HANDLED();
+            break;
+        }
+        /*.${AOs::Blinky::SM::on::TIMEOUT} */
+        case TIMEOUT_SIG: {
+            status_ = Q_TRAN(&Blinky_off);
+            break;
+        }
+        default: {
+            status_ = Q_SUPER(&QHsm_top);
+            break;
+        }
+    }
+    return status_;
+}
+/*.$enddef${AOs::Blinky} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
+
+#endif /* RT_USING_FINSH */
+#endif /* QPC_USING_BLINKY_EXAMPLE */

+ 120 - 0
examples/rt-thread/blinky/blinky.qm

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<model version="5.1.4" links="1">
+ <documentation>Simple &quot;Blinky&quot; model</documentation>
+ <!--${qpc}-->
+ <framework name="qpc"/>
+ <!--${AOs}-->
+ <package name="AOs" stereotype="0x02">
+  <!--${AOs::Blinky}-->
+  <class name="Blinky" superclass="qpc::QActive">
+   <!--${AOs::Blinky::inst}-->
+   <attribute name="inst" type="Blinky" visibility="0x00" properties="0x01"/>
+   <!--${AOs::Blinky::timeEvt}-->
+   <attribute name="timeEvt" type="QTimeEvt" visibility="0x02" properties="0x00"/>
+   <!--${AOs::Blinky::SM}-->
+   <statechart properties="0x03">
+    <!--${AOs::Blinky::SM::initial}-->
+    <initial target="../1">
+     <action>(void)par; /* unused parameter */
+QTimeEvt_armX(&amp;me-&gt;timeEvt,
+BSP_TICKS_PER_SEC/2, BSP_TICKS_PER_SEC/2);</action>
+     <initial_glyph conn="2,3,5,1,20,4,-4">
+      <action box="0,-2,6,2"/>
+     </initial_glyph>
+    </initial>
+    <!--${AOs::Blinky::SM::off}-->
+    <state name="off">
+     <entry>BSP_ledOff();</entry>
+     <!--${AOs::Blinky::SM::off::TIMEOUT}-->
+     <tran trig="TIMEOUT" target="../../2">
+      <tran_glyph conn="2,13,3,1,18,6,-2">
+       <action box="0,-2,8,2"/>
+      </tran_glyph>
+     </tran>
+     <state_glyph node="2,5,16,10">
+      <entry box="1,2,12,4"/>
+     </state_glyph>
+    </state>
+    <!--${AOs::Blinky::SM::on}-->
+    <state name="on">
+     <entry>BSP_ledOn();</entry>
+     <!--${AOs::Blinky::SM::on::TIMEOUT}-->
+     <tran trig="TIMEOUT" target="../../1">
+      <tran_glyph conn="2,25,3,1,20,-15,-4">
+       <action box="0,-2,8,2"/>
+      </tran_glyph>
+     </tran>
+     <state_glyph node="2,17,16,10">
+      <entry box="1,2,12,4"/>
+     </state_glyph>
+    </state>
+    <state_diagram size="24,29"/>
+   </statechart>
+  </class>
+ </package>
+ <!--${.}-->
+ <directory name=".">
+  <!--${.::blinky.c}-->
+  <file name="blinky.c">
+   <text>#include &lt;rtthread.h&gt;
+
+#ifdef QPC_USING_BLINKY_EXAMPLE
+#ifdef RT_USING_FINSH
+
+#include &lt;finsh.h&gt;
+#include &quot;qpc.h&quot;
+Q_DEFINE_THIS_FILE
+
+enum { BSP_TICKS_PER_SEC = 100 };
+
+void BSP_ledOff(void) {
+    rt_kprintf(&quot;LED OFF\n&quot;);
+}
+void BSP_ledOn(void) {
+    rt_kprintf(&quot;LED ON\n&quot;);
+}
+
+
+enum BlinkySignals {
+    TIMEOUT_SIG = Q_USER_SIG,
+    MAX_SIG
+};
+
+//*============== ask QM to declare the Blinky class ================*/
+$declare ${AOs::Blinky}
+
+QActive * const AO_Blinky = &amp;Blinky_inst.super;
+
+static void Blinky_ctor(void) {
+    Blinky *me = &amp;Blinky_inst;
+    QActive_ctor(&amp;me-&gt;super, Q_STATE_CAST(&amp;Blinky_initial));
+    QTimeEvt_ctorX(&amp;me-&gt;timeEvt, &amp;me-&gt;super, TIMEOUT_SIG, 0U);
+}
+
+int qpc_blinky_start(void) {
+    /* statically allocate event queue buffer for the Blinky AO */
+    static QEvt const *blinky_queueSto[10];
+    static uint8_t blinky_stack[1024];
+
+    QF_init(); /* initialize the framework */
+
+    Blinky_ctor(); /* explicitly call the &quot;constructor&quot; */
+    QACTIVE_START(AO_Blinky,
+                  1U, /* priority */
+                  blinky_queueSto, Q_DIM(blinky_queueSto),
+                  (void *)blinky_stack, sizeof(blinky_stack), /* no stack */
+                  (void *)0);    /* no initialization parameter */
+    return QF_run(); /* run the QF application */
+}
+
+MSH_CMD_EXPORT(qpc_blinky_start, start qpc blinky example);
+
+/*================ ask QM to define the Blinky class ================*/
+$define ${AOs::Blinky}
+
+#endif /* RT_USING_FINSH */
+#endif /* QPC_USING_BLINKY_EXAMPLE */
+</text>
+  </file>
+ </directory>
+</model>

+ 48 - 0
ports/rt-thread/qep_port.h

@@ -0,0 +1,48 @@
+/**
+* @file
+* @brief QEP/C port, generic C99 compiler
+* @ingroup ports
+* @cond
+******************************************************************************
+* Last Updated for Version: 5.4.0
+* Date of the Last Update:  2015-04-08
+*
+*                    Q u a n t u m     L e a P s
+*                    ---------------------------
+*                    innovating embedded systems
+*
+* Copyright (C) Quantum Leaps, LLC. state-machine.com.
+*
+* This program is open source software: you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Alternatively, this program may be distributed and modified under the
+* terms of Quantum Leaps commercial licenses, which expressly supersede
+* the GNU General Public License and are specifically designed for
+* licensees interested in retaining the proprietary status of their code.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <www.gnu.org/licenses/>.
+*
+* Contact information:
+* Web:   www.state-machine.com/licensing
+* Email: info@state-machine.com
+******************************************************************************
+* @endcond
+*/
+#ifndef QEP_PORT_H
+#define QEP_PORT_H
+
+#include <stdint.h>  /* Exact-width types. WG14/N843 C99 Standard */
+#include <stdbool.h> /* Boolean type.      WG14/N843 C99 Standard */
+
+#include "qep.h"     /* QEP platform-independent public interface */
+
+#endif /* QEP_PORT_H */

+ 23 - 0
ports/rt-thread/qf_hooks.c

@@ -0,0 +1,23 @@
+#include <rtthread.h>
+#include "qpc.h"
+
+static rt_timer_t qpc_tick_timer;
+
+void QF_onClockTick(void *parameter) {
+    QF_TICK_X(0U, (void *)0);  /* perform the QF clock tick processing */
+}
+
+void QF_onStartup(void) {
+    qpc_tick_timer = rt_timer_create("qpc_tick", QF_onClockTick,
+                                            RT_NULL, 10,
+                                            RT_TIMER_FLAG_PERIODIC);
+    rt_timer_start(qpc_tick_timer);
+}
+
+void QF_onCleanup(void) {
+    rt_timer_stop(qpc_tick_timer);
+}
+
+void Q_onAssert(char const * const module, int loc) {
+    rt_assert_handler(module, "", loc);
+}

+ 250 - 0
ports/rt-thread/qf_port.c

@@ -0,0 +1,250 @@
+/**
+* @file
+* @brief QF/C, port to RT-Thread
+* @ingroup ports
+* @cond
+******************************************************************************
+* Last updated for version 6.9.3
+* Last updated on  2021-04-08
+*
+*                    Q u a n t u m  L e a P s
+*                    ------------------------
+*                    Modern Embedded Software
+*
+* Copyright (C) 2005-2021 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 <www.gnu.org/licenses/>.
+*
+* Contact information:
+* <www.state-machine.com/licensing>
+* <info@state-machine.com>
+******************************************************************************
+* @endcond
+*/
+#define QP_IMPL           /* this is QP implementation */
+#include "qf_port.h"      /* QF port */
+#include "qf_pkg.h"
+#include "qassert.h"
+#ifdef Q_SPY              /* QS software tracing enabled? */
+    #include "qs_port.h"  /* QS port */
+    #include "qs_pkg.h"   /* QS package-scope internal interface */
+#else
+    #include "qs_dummy.h" /* disable the QS software tracing */
+#endif /* Q_SPY */
+
+Q_DEFINE_THIS_MODULE("qf_port")
+
+/*..........................................................................*/
+void QF_init(void) {
+}
+/*..........................................................................*/
+int_t QF_run(void) {
+    QS_CRIT_STAT_
+
+    QF_onStartup();  /* QF callback to configure and start interrupts */
+
+    /* produce the QS_QF_RUN trace record */
+    QS_BEGIN_PRE_(QS_QF_RUN, 0U)
+    QS_END_PRE_()
+
+    return 0; /* return success */
+}
+/*..........................................................................*/
+void QF_stop(void) {
+    QF_onCleanup(); /* cleanup callback */
+}
+/*..........................................................................*/
+static void thread_function(void *parameter) { /* RT-Thread signature */
+    QActive *act = (QActive *)parameter;
+
+    /* event-loop */
+    for (;;) { /* for-ever */
+        QEvt const *e = QActive_get_(act);
+        QHSM_DISPATCH(&act->super, e, act->prio);
+        QF_gc(e); /* check if the event is garbage, and collect it if so */
+    }
+}
+
+/*..........................................................................*/
+void QActive_start_(QActive * const me, uint_fast8_t prio,
+                    QEvt const * * const qSto, uint_fast16_t const qLen,
+                    void * const stkSto, uint_fast16_t const stkSize,
+                    void const * const par)
+{
+    rt_uint8_t tx_prio; /* RT-Thread priority corresponding to the QF priority prio */
+
+    /* allege that the RT-Thread queue is created successfully */
+    Q_ALLEGE_ID(210,
+        rt_mb_init(&me->eQueue,
+            me->thread.name,
+            (void *)qSto,
+            (qLen),
+            RT_IPC_FLAG_FIFO)
+        == RT_EOK);
+
+    me->prio = prio;  /* save the QF priority */
+    QF_add_(me);      /* make QF aware of this active object */
+
+    QHSM_INIT(&me->super, par, me->prio); /* initial tran. (virtual) */
+    QS_FLUSH(); /* flush the trace buffer to the host */
+
+    /* convert QF priority to the RT-Thread priority */
+    tx_prio = QF_MAX_ACTIVE - prio;
+
+    Q_ALLEGE_ID(220,
+        rt_thread_init(
+            &me->thread, /* RT-Thread thread control block */
+            me->thread.name, /* unique thread name */
+            &thread_function, /* thread function */
+            me, /* thread parameter */
+            stkSto,    /* stack start */
+            stkSize,   /* stack size in bytes */
+            tx_prio,   /* RT-Thread priority */
+            5)
+        == RT_EOK);
+    rt_thread_startup(&me->thread);
+}
+/*..........................................................................*/
+void QActive_setAttr(QActive *const me, uint32_t attr1, void const *attr2) {
+    /* this function must be called before QACTIVE_START(),
+    */
+    switch (attr1) {
+        case THREAD_NAME_ATTR:
+            rt_memset(me->thread.name, 0x00, RT_NAME_MAX);
+            rt_strncpy(me->thread.name, (char *)attr2, RT_NAME_MAX - 1);
+            break;
+        /* ... */
+    }
+}
+/*..........................................................................*/
+#ifndef Q_SPY
+bool QActive_post_(QActive * const me, QEvt const * const e,
+                   uint_fast16_t const margin)
+#else
+bool QActive_post_(QActive * const me, QEvt const * const e,
+                   uint_fast16_t const margin, void const * const sender)
+#endif /* Q_SPY */
+{
+    uint_fast16_t nFree;
+    bool status;
+    QF_CRIT_STAT_
+
+    QF_CRIT_E_();
+    nFree = (uint_fast16_t)(me->eQueue.size - me->eQueue.entry);
+
+    if (margin == QF_NO_MARGIN) {
+        if (nFree > 0U) {
+            status = true; /* can post */
+        }
+        else {
+            status = false; /* cannot post */
+            Q_ERROR_ID(510); /* must be able to post the event */
+        }
+    }
+    else if (nFree > (QEQueueCtr)margin) {
+        status = true; /* can post */
+    }
+    else {
+        status = false; /* cannot post */
+    }
+
+    if (status) { /* can post the event? */
+
+        QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_POST, me->prio)
+            QS_TIME_PRE_();       /* timestamp */
+            QS_OBJ_PRE_(sender);  /* the sender object */
+            QS_SIG_PRE_(e->sig);  /* the signal of the event */
+            QS_OBJ_PRE_(me);      /* this active object (recipient) */
+            QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
+            QS_EQC_PRE_(nFree);   /* # free entries available */
+            QS_EQC_PRE_(0U);      /* min # free entries (unknown) */
+        QS_END_NOCRIT_PRE_()
+
+        if (e->poolId_ != 0U) { /* is it a pool event? */
+            QF_EVT_REF_CTR_INC_(e); /* increment the reference counter */
+        }
+
+        QF_CRIT_X_();
+
+        /* posting to the RT-Thread message queue must succeed, see NOTE1 */
+        Q_ALLEGE_ID(520,
+            rt_mb_send(&me->eQueue, (rt_ubase_t)e)
+            == RT_EOK);
+    }
+    else {
+
+        QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_POST_ATTEMPT, me->prio)
+            QS_TIME_PRE_();       /* timestamp */
+            QS_OBJ_PRE_(sender);  /* the sender object */
+            QS_SIG_PRE_(e->sig);  /* the signal of the event */
+            QS_OBJ_PRE_(me);      /* this active object (recipient) */
+            QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
+            QS_EQC_PRE_(nFree);   /* # free entries available */
+            QS_EQC_PRE_(0U);      /* min # free entries (unknown) */
+        QS_END_NOCRIT_PRE_()
+
+        QF_CRIT_X_();
+    }
+
+    return status;
+}
+/*..........................................................................*/
+void QActive_postLIFO_(QActive * const me, QEvt const * const e) {
+    QF_CRIT_STAT_
+    QF_CRIT_E_();
+
+    QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_POST_LIFO, me->prio)
+        QS_TIME_PRE_();       /* timestamp */
+        QS_SIG_PRE_(e->sig);  /* the signal of this event */
+        QS_OBJ_PRE_(me);      /* this active object */
+        QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
+        QS_EQC_PRE_(me->eQueue.size - me->eQueue.entry); /* # free */
+        QS_EQC_PRE_(0U);      /* min # free entries (unknown) */
+    QS_END_NOCRIT_PRE_()
+
+    if (e->poolId_ != 0U) { /* is it a pool event? */
+        QF_EVT_REF_CTR_INC_(e); /* increment the reference counter */
+    }
+
+    QF_CRIT_X_();
+
+    /* LIFO posting must succeed, see NOTE1 */
+    Q_ALLEGE_ID(610,
+        rt_mb_urgent(&me->eQueue, (rt_ubase_t)e)
+        == RT_EOK);
+}
+/*..........................................................................*/
+QEvt const *QActive_get_(QActive * const me) {
+    QEvt *e;
+    QS_CRIT_STAT_
+
+    Q_ALLEGE_ID(710,
+        rt_mb_recv(&me->eQueue, (rt_ubase_t *)&e, RT_WAITING_FOREVER)
+        == RT_EOK);
+
+    QS_BEGIN_PRE_(QS_QF_ACTIVE_GET, me->prio)
+        QS_TIME_PRE_();       /* timestamp */
+        QS_SIG_PRE_(e->sig);  /* the signal of this event */
+        QS_OBJ_PRE_(me);      /* this active object */
+        QS_2U8_PRE_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
+        QS_EQC_PRE_(me->eQueue.size - me->eQueue.entry);/* # free */
+    QS_END_PRE_()
+
+    return e;
+}

+ 99 - 0
ports/rt-thread/qf_port.h

@@ -0,0 +1,99 @@
+/**
+* @file
+* @brief QF/C, port to RT-Thread
+* @cond
+******************************************************************************
+* Last updated for version 6.9.3
+* Last updated on  2021-04-08
+*
+*                    Q u a n t u m  L e a P s
+*                    ------------------------
+*                    Modern Embedded Software
+*
+* Copyright (C) 2005-2021 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 <www.gnu.org/licenses>.
+*
+* Contact information:
+* <www.state-machine.com/licensing>
+* <info@state-machine.com>
+******************************************************************************
+* @endcond
+*/
+#ifndef QF_PORT_H
+#define QF_PORT_H
+
+/* RT-Thread event queue and thread types */
+#define QF_EQUEUE_TYPE      struct rt_mailbox
+#define QF_THREAD_TYPE      struct rt_thread
+
+/* The maximum number of active objects in the application, see NOTE2 */
+#define QF_MAX_ACTIVE       (RT_THREAD_PRIORITY_MAX)
+
+/* QF critical section for RT-Thread, see NOTE3 */
+#define QF_CRIT_ENTRY(stat_)  (rt_enter_critical())
+#define QF_CRIT_EXIT(stat_)   (rt_exit_critical())
+
+enum RT_Thread_ThreadAttrs {
+    THREAD_NAME_ATTR
+};
+
+#include <rtthread.h>   /* RT-Thread API */
+
+#include "qep_port.h"  /* QEP port */
+#include "qequeue.h"   /* used for event deferral */
+#include "qf.h"        /* QF platform-independent public interface */
+#ifdef Q_SPY
+#include "qmpool.h"    /* needed only for QS-RX */
+#endif
+
+/*****************************************************************************
+* interface used only inside QF, but not in applications
+*/
+#ifdef QP_IMPL
+
+    #define QF_SCHED_STAT_
+    #define QF_SCHED_LOCK_(prio_)   rt_enter_critical()
+    #define QF_SCHED_UNLOCK_()      rt_exit_critical()
+
+    /* TreadX block pool operations... */
+    #define QF_EPOOL_TYPE_              struct rt_mempool
+    #define QF_EPOOL_INIT_(pool_, poolSto_, poolSize_, evtSize_)            \
+        Q_ALLEGE(rt_mp_init(&(pool_), (char *)"QP",                         \
+                 (poolSto_), (poolSize_), (evtSize_)) == RT_EOK)
+
+    #define QF_EPOOL_EVENT_SIZE_(pool_)                                     \
+        ((uint_fast16_t)(pool_).block_size)
+
+    #define QF_EPOOL_GET_(pool_, e_, margin_, qs_id_) do {                  \
+        if ((pool_).block_free_count > (margin_)) {                         \
+            e_ = rt_mp_alloc(&(pool_), RT_WAITING_NO);                      \
+        }                                                                   \
+        else {                                                              \
+            (e_) = (QEvt *)0;                                               \
+        }                                                                   \
+    } while (false)
+
+    #define QF_EPOOL_PUT_(dummy, e_, qs_id_)                                \
+        rt_mp_free((void *)(e_));
+
+#endif /* ifdef QP_IMPL */
+
+#endif /* QF_PORT_H */
+

+ 62 - 0
ports/rt-thread/qs_port.h

@@ -0,0 +1,62 @@
+/**
+* @file
+* @brief QS/C port to a 32-bit CPU and a generic C compiler.
+* @ingroup qs
+* @cond
+******************************************************************************
+* Last updated for version 5.6.0
+* Last updated on  2015-12-18
+*
+*                    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 <www.gnu.org/licenses/>.
+*
+* Contact information:
+* <www.state-machine.com/licensing>
+* <info@state-machine.com>
+******************************************************************************
+* @endcond
+*/
+#ifndef QS_PORT_H
+#define QS_PORT_H
+
+/* QS time-stamp size in bytes */
+#define QS_TIME_SIZE     4
+
+/* object pointer size in bytes */
+#define QS_OBJ_PTR_SIZE  4
+
+/* function pointer size in bytes */
+#define QS_FUN_PTR_SIZE  4
+
+/*****************************************************************************
+* NOTE: QS might be used with or without other QP components, in which
+* case the separate definitions of the macros QF_CRIT_STAT_TYPE,
+* QF_CRIT_ENTRY, and QF_CRIT_EXIT are needed. In this port QS is configured
+* to be used with the other QP component, by simply including "qf_port.h"
+* *before* "qs.h".
+*/
+#include "qf_port.h" /* use QS with QF */
+#include "qs.h"      /* QS platform-independent public interface */
+
+#endif /* QS_PORT_H */