1、QP/C框架源代码下载

GitHub - QuantumLeaps/qpc

下载命令(镜像网址+kk):

git clone https://kkgithub.com/QuantumLeaps/qpc --recurse-submodules
git clone https://kkgithub.com/QuantumLeaps/qpc --recurse-submodules --depth 1

 

2、QPC集成开发环境安装:https://www.state-machine.com/

安装目录详情:

3、创建工程

(1)源码路径:D:\Code\QP_source\qpc

(2)在QP_source下新增blinky文件夹

PS D:\Code\QP_source> ls
目录: D:\Code\QP_source
Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----          2025/7/8     23:10                blinky
d-----          2025/7/7     22:45                qpc

(3)查看 D:\Code\QP_source\qpc 路径下的 cmakeSupport.md 文件

(4)拷贝 D:\Code\QP_source\qpc\3rd_party\cmake 中的 qpc_sdk_import.cmake 至blinky文件夹

        拷贝 D:\Code\QP_source\qpc\examples\posix-win32\blinky 中的 blinky.c 至blinky文件夹

(5)创建CMake脚本文件:

# use a recent CMake version
cmake_minimum_required(VERSION 3.23 FATAL_ERROR)
cmake_policy(VERSION 3.23...3.28)
cmake_policy(SET CMP0083 NEW)
cmake_policy(SET CMP0105 NEW)
cmake_policy(SET CMP0116 NEW)
cmake_policy(SET CMP0128 NEW)

# include general project config & import qpc
set(QPC_SDK_PATH ${CMAKE_SOURCE_DIR}/../qpc)  # qpc框架源代码路径
# set(QPC_FETCH_FROM_GIT ON)
# set(QPC_FETCH_FROM_GIT_PATH ${CMAKE_SOURCE_DIR}/Source/qpc-sdk)
include(qpc_sdk_import.cmake)

# default image/project name is trafficlight
# Give a special name via -DIMAGE=<image>
# the main project
project(blinky # the name of the project
        VERSION "1.0.0"
        DESCRIPTION "my 1st qpc project"
        LANGUAGES C
)

# the project target(s)
add_executable( $(PROJECT_NAME) blinky.c)

include(${QPC_SDK_PATH}/qpc_sdk_init.cmake)
set(QPC_PROJECT $(PROJECT_NAME))
set(QPC_CFG_KERNEL QV)
set(QPC_CFG_GUI FALSE)
set(QPC_CFG_PORT win32)

qpc_sdk_init()

target_link_libraries($(PROJECT_NAME) PRIVATE qpc)

 

至此在blinky目录下有这四个文件

image

 

(6) 生成构建文件,生成构建文件目录在build文件夹中

PS D:\Code\QP_source\blinky> cmake -B build -G "MinGW Makefiles"
-- qpc_import.cmake starting...
QPC_SDK_PATH is D:/Code/QP_source/qpc
Set QPC_CFG_GUI to ('FALSE') since not specified
Set QPC_CFG_UNIT_TEST to ('OFF') since not specified
Set QPC_CFG_VERBOSE to ('OFF') since not specified
-- Set QPC_CFG_PORT to ('win32')
-- Found port dir - './win32-qv' for port win32, KERNEL qv
-- ========================================================
  Configured project qpc for win32
    PROJECT_NAME                = blinky
    TARGET                      =
    IMAGE                       =
    SW_VERSION                  =
    PORT                        = win32

    QPC_CFG_GUI                 = FALSE
    QPC_CFG_UNIT_TEST           = OFF
    QPC_CFG_KERNEL              = QV
    QPC_CFG_DEBUG               = ON
    CMAKE_C_CPPCHECK            =
-- ========================================================

-- Configuring done (0.3s)
-- Generating done (0.1s)
-- Build files have been written to: D:/Code/QP_source/blinky/build

 

(7) 通过 cmake --build build/ 编译生成可执行文件,其中build/表示构建文件所在路径

PS D:\Code\QP_source\blinky> cmake --build build/
[  6%] Building C object qpc-sdk/CMakeFiles/qpc.dir/src/qf/qep_hsm.c.obj
[ 12%] Building C object qpc-sdk/CMakeFiles/qpc.dir/src/qf/qep_msm.c.obj
[ 18%] Building C object qpc-sdk/CMakeFiles/qpc.dir/src/qf/qf_act.c.obj
[ 25%] Building C object qpc-sdk/CMakeFiles/qpc.dir/src/qf/qf_defer.c.obj
[ 31%] Building C object qpc-sdk/CMakeFiles/qpc.dir/src/qf/qf_dyn.c.obj
[ 37%] Building C object qpc-sdk/CMakeFiles/qpc.dir/src/qf/qf_ps.c.obj
[ 43%] Building C object qpc-sdk/CMakeFiles/qpc.dir/src/qf/qf_qact.c.obj
[ 50%] Building C object qpc-sdk/CMakeFiles/qpc.dir/src/qf/qf_qeq.c.obj
[ 56%] Building C object qpc-sdk/CMakeFiles/qpc.dir/src/qf/qf_qmact.c.obj
[ 62%] Building C object qpc-sdk/CMakeFiles/qpc.dir/src/qf/qf_time.c.obj
[ 68%] Building C object qpc-sdk/CMakeFiles/qpc.dir/src/qf/qf_actq.c.obj
[ 75%] Building C object qpc-sdk/CMakeFiles/qpc.dir/src/qf/qf_mem.c.obj
[ 81%] Building C object qpc-sdk/CMakeFiles/qpc.dir/ports/win32-qv/qf_port.c.obj
[ 87%] Linking C static library libqpc.a
[ 87%] Built target qpc
[ 93%] Building C object CMakeFiles/blinky.dir/blinky.c.obj
[100%] Linking C executable blinky.exe
[100%] Built target blinky

(8)执行程序

 

(9)在Linux环境下编译运行:

① 设置平台为posix

image

② 文件夹拷贝至ubuntu

image

③ 在blinky目录下构建,生成build目录,在build目录下可执行文件 blinky, 执行 sudo ./blinky

cmake -B build -G "Unix Makefiles"
cmake --build build/

 

控制键盘上的LED灯闪烁,而不是仅仅打印 LED ON 和 LED OFF,所以blinky.c文件修改如下:

#include "qpc.h"

#include "safe_std.h" // portable "safe" <stdio.h>/<string.h> facilities
#include <stdlib.h>   // for exit()
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define LED_TRIGGER "/sys/class/leds/input1::capslock/trigger"
#define LED_BRIGHTNESS "/sys/class/leds/input1::capslock/brightness"
#define USAGE() fprintf(stderr, "usage:\n %s <on|off>\n %s <trigger> <type>\n", argv[0], argv[0])
// Q_DEFINE_THIS_FILE

#ifdef Q_SPY
#error Simple Blinky Application does not provide Spy build configuration
#endif

enum
{
    BSP_TICKS_PER_SEC = 100
};

//..........................................................................
void BSP_ledOff(void)
{
    int fd1, fd2;
    fd1 = open(LED_TRIGGER, O_RDWR);
    if (0 > fd1)
    {
        perror("open error");
        exit(-1);
    }

    fd2 = open(LED_BRIGHTNESS, O_RDWR);
    if (0 > fd2)
    {
        perror("open error");
        exit(-1);
    }

    write(fd1, "none", 4);
    write(fd2, "0", 1);
}
//..........................................................................
void BSP_ledOn(void)
{
    int fd1, fd2;
    fd1 = open(LED_TRIGGER, O_RDWR);
    if (0 > fd1)
    {
        perror("open error");
        exit(-1);
    }

    fd2 = open(LED_BRIGHTNESS, O_RDWR);
    if (0 > fd2)
    {
        perror("open error");
        exit(-1);
    }

    write(fd1, "none", 4);
    write(fd2, "1", 1);
}

//..........................................................................
Q_NORETURN Q_onError(char const *const module, int_t const id)
{
    FPRINTF_S(stderr, "ERROR in %s:%d", module, id);
    exit(-1);
}
//..........................................................................
void assert_failed(char const *const module, int_t const id); // prototype
void assert_failed(char const *const module, int_t const id)
{
    Q_onError(module, id);
}
//..........................................................................
void QF_onStartup(void) {}
//..........................................................................
void QF_onCleanup(void) {}
//..........................................................................
void QF_onClockTick(void)
{
    QTIMEEVT_TICK_X(0U, (void *)0); // clock tick processing
}

enum BlinkySignals
{
    TIMEOUT_SIG = Q_USER_SIG,
    MAX_SIG
};

///============== ask QM to declare the Blinky class ================
//$declare${AOs::Blinky} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

//${AOs::Blinky} .............................................................
typedef struct Blinky
{
    // protected:
    QActive super;

    // private:
    QTimeEvt timeEvt;

    // public:
} Blinky;

extern Blinky Blinky_inst;

// public:

// constructor
static void Blinky_ctor(Blinky *const me);

// 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;

int main()
{
    QF_init(); // initialize the framework

    Blinky_ctor(&Blinky_inst); // explicitly call the "constructor"
    static QEvt const *blinky_queueSto[10];
    QActive_start(AO_Blinky,
                  1U, // priority
                  blinky_queueSto, Q_DIM(blinky_queueSto),
                  (void *)0, 0U, // no stack
                  (void *)0);    // no initialization parameter
    return QF_run();             // run the QF application
}

//================ ask QM to define the Blinky class ================
//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Check for the minimum required QP version
#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE ^ 4294967295U) % 0x2710U))
#error qpc version 7.3.0 or higher required
#endif
//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${AOs::Blinky} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

//${AOs::Blinky} .............................................................
Blinky Blinky_inst;

//${AOs::Blinky::ctor} .......................................................
static void Blinky_ctor(Blinky *const me)
{
    QActive_ctor(&me->super, Q_STATE_CAST(&Blinky_initial));
    QTimeEvt_ctorX(&me->timeEvt, &me->super, TIMEOUT_SIG, 0U);
}

//${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} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

 

posted on 2025-07-08 08:22  轩~邈  阅读(344)  评论(0)    收藏  举报