QPnano代码解析

void QF_init(uint_fast8_t maxActive) {
    QActive *a;
    uint_fast8_t p;
    uint_fast8_t n;

    /** @pre the number of active objects must be in range */
    Q_REQUIRE_ID(100, ((uint_fast8_t)1 < maxActive)
                      && (maxActive <= (uint_fast8_t)33));
    QF_maxActive_ = (uint_fast8_t)maxActive - (uint_fast8_t)1;

#ifdef QF_TIMEEVT_USAGE
    for (n = (uint_fast8_t)0; n < (uint_fast8_t)QF_MAX_TICK_RATE; ++n) {
        QF_timerSetX_[n] = (uint_fast8_t)0;
    }
#endif /* QF_TIMEEVT_USAGE */

    QF_readySet_ = (uint_fast32_t)0;

#ifdef qkn_h
    QK_attr_.actPrio = (uint_fast8_t)8; /* QK-nano scheduler locked */

#ifdef QF_ISR_NEST
    QK_attr_.intNest = (uint_fast8_t)0;
#endif

#ifdef QK_SCHED_LOCK
    QK_attr_.lockPrio   = (uint_fast8_t)0;
    QK_attr_.lockHolder = (uint_fast8_t)0;
#endif

#endif /* #ifdef qkn_h */

    /* clear all registered active objects... */
    for (p = (uint_fast8_t)1; p <= QF_maxActive_; ++p) {
        a = QF_ROM_ACTIVE_GET_(p);

        /* QF_active[p] must be initialized */
        Q_ASSERT_ID(110, a != (QActive *)0);

        a->head    = (uint8_t)0;
        a->tail    = (uint8_t)0;
        a->nUsed   = (uint8_t)0;
#if (QF_TIMEEVT_CTR_SIZE != 0)
        for (n = (uint_fast8_t)0; n < (uint_fast8_t)QF_MAX_TICK_RATE; ++n) {
            a->tickCtr[n].nTicks   = (QTimeEvtCtr)0;
#ifdef QF_TIMEEVT_PERIODIC
            a->tickCtr[n].interval = (QTimeEvtCtr)0;
#endif /* def QF_TIMEEVT_PERIODIC */
        }
#endif /* (QF_TIMEEVT_CTR_SIZE != 0) */
    }

#ifdef QV_INIT /* initialization of the QV-nano kernel defined? */
    QV_INIT(); /* port-specific initialization of the QV-nano kernel */
#elif defined QK_INIT /* initialization of the QK-nano kernel defined? */
    QK_INIT(); /* port-specific initialization of the QK-nano kernel */
#endif
}

 

typedef struct QActive {
    QHsm super; /**< derives from the ::QHsm base class */

#if (QF_TIMEEVT_CTR_SIZE != 0)
    /*! Timer for the active object */
    QTimer tickCtr[QF_MAX_TICK_RATE];
#endif /* (QF_TIMEEVT_CTR_SIZE != 0) */

    /*! priority of the active object (1..8) */
    uint8_t prio;

    /*! offset to where next event will be inserted into the buffer */
    uint8_t volatile head;

    /*! offset of where next event will be extracted from the buffer */
    uint8_t volatile tail;

    /*! number of events currently present in the queue
    * (events in the ring buffer + 1 event in the state machine)
    */
    uint8_t volatile nUsed;

} QActive;

 

初始化状态机,清空ringbuffer 清空定时器信息。

看QActive 基本上是消息队列的信息,意思是每个状态机都有一个环形buffer,相当于一个人,自己具备一个电话一样。

这样两个状态机互相发送消息,都是发送到指定的状态机的消息队列中。

int_t QF_run(void) {
   static uint_fast8_t p;
    QActive *a;

#ifdef QF_MAX_ACTIVE /* deprecated constant provided? */
#if (QF_MAX_ACTIVE < 1) || (8 < QF_MAX_ACTIVE)
    #error "QF_MAX_ACTIVE not defined or out of range. Valid range is 1..8"
#endif
    QF_maxActive_ = (uint_fast8_t)QF_MAX_ACTIVE;
#else
    /** @pre the number of active objects must be initialized by calling:
    * QF_init(Q_DIM(QF_active));
    */
    Q_REQUIRE_ID(100, ((uint_fast8_t)1 <= QF_maxActive_)
                      && (QF_maxActive_ <= (uint_fast8_t)32));
#endif

    /* set priorities all registered active objects... */
    for (p = (uint_fast8_t)1; p <= QF_maxActive_; ++p) {
        a = QF_ROM_ACTIVE_GET_(p);

        /* QF_active[p] must be initialized */
        Q_ASSERT_ID(810, a != (QActive *)0);
				// 使用第一个地址来访问,这样在定义 AO的时候就要注意第一个是 状态机类
        a->prio = (uint8_t)p; /* set the priority of the active object */
    }
		
    /* trigger initial transitions in all registered active objects... */
    for (p = (uint_fast8_t)1; p <= QF_maxActive_; ++p) {
        a = QF_ROM_ACTIVE_GET_(p);
        QHSM_INIT(&a->super); /* take the initial transition in the SM */
    }

    QF_onStartup(); /* invoke startup callback */

    /* the event loop of the cooperative QV-nano kernel... */
    QF_INT_DISABLE();
    for (;;) {
				// 修改为32位
        if (QF_readySet_ != (uint_fast32_t)0) {
            QActiveCB const Q_ROM *acb;

#ifdef QF_LOG2
            p = QF_LOG2(QF_readySet_);
#else
						p = QF_qlog2_M0(QF_readySet_);
//					  // 找出最高优先级
//					  // 优先级为1
//					  // 优先级为2
//            /* hi nibble non-zero? */
//            if ((QF_readySet_ & (uint_fast8_t)0xF0) != (uint_fast8_t)0) {
//                p = (uint_fast8_t)(
//                      (uint_fast8_t)Q_ROM_BYTE(QF_log2Lkup[QF_readySet_ >> 4])
//                      + (uint_fast8_t)4);
//            }
//            else { /* hi nibble of QF_readySet_ is zero */
//                p = (uint_fast8_t)Q_ROM_BYTE(QF_log2Lkup[QF_readySet_]);
//            }
#endif /* QF_LOG2 */

            acb = &QF_active[p];
            a = QF_ROM_ACTIVE_GET_(p);

            /* some unsuded events must be available */
            Q_ASSERT_ID(820, a->nUsed > (uint8_t)0);

            --a->nUsed;
            Q_SIG(a) = QF_ROM_QUEUE_AT_(acb, a->tail).sig;
#if (Q_PARAM_SIZE != 0)
            Q_PAR(a) = QF_ROM_QUEUE_AT_(acb, a->tail).par;
#endif
            if (a->tail == (uint8_t)0) { /* wrap around? */
                a->tail = Q_ROM_BYTE(acb->qlen);
            }
            --a->tail;
            QF_INT_ENABLE();

            QHSM_DISPATCH(&a->super); /* dispatch to the HSM (RTC step) */

            QF_INT_DISABLE();
            /* empty queue? */
            if (a->nUsed == (uint8_t)0) {
                /* clear the bit corresponding to 'p' */
                QF_readySet_ &=
                    (uint_fast32_t)~((uint_fast32_t)1 << (p - (uint_fast32_t)1));
            }
        }
        else {
            /* QV_onIdle() must be called with interrupts DISABLED because
            * the determination of the idle condition (no events in the
            * queues) can change at any time by an interrupt posting events
            * to a queue. QV_onIdle() MUST enable interrupts internally,
            * perhaps at the same time as putting the CPU into a power-saving
            * mode.
            */
            QV_onIdle();

            QF_INT_DISABLE();
        }
    }
#ifdef __GNUC__  /* GNU compiler? */
    return (int_t)0;
#endif
}

1.按照序号设置任务优先级,注意这里是合作式,不是实时。

2.启动10ms定时,主要是为了软件定时器使用。其实就是定时发送消息,而不是那些定时执行任务,定时执行任务也对资源释放比较麻烦。这个定时器只是发送消息。即使不释放,也不会搞死机。也可以快速的调试找到问题。

3.进入状态机禁止全局中断。查询置位的任务,如果多个任务置位。需要判断1出现的最早的位置,这个实际就和一般的RTOS查找优先级任务类似,如果有两个不同优先级的任务出现,在M3中有前导0,在M0中没有这个指令,所以可以用C实现,也可以用汇编实现。这个优先级是越大优先级越高。

4.

#if (Q_PARAM_SIZE != 0)
bool QActive_postXISR_(QActive * const me, uint_fast8_t margin,
                       enum_t const sig, QParam const par)
#else
bool QActive_postXISR_(QActive * const me, uint_fast8_t margin,
                       enum_t const sig)
#endif
{
#ifdef QF_ISR_NEST
#ifdef QF_ISR_STAT_TYPE
    QF_ISR_STAT_TYPE stat;
#endif
#endif
    QActiveCB const Q_ROM *acb = &QF_active[me->prio];
    uint_fast8_t qlen = (uint_fast8_t)Q_ROM_BYTE(acb->qlen);

#ifdef QF_ISR_NEST
#ifdef QF_ISR_STAT_TYPE
    QF_ISR_DISABLE(stat);
#else
    QF_INT_DISABLE();
#endif
#endif

    if (margin == QF_NO_MARGIN) {
        if (qlen > (uint_fast8_t)me->nUsed) {
            margin = (uint_fast8_t)true; /* can post */
        }
        else {
            margin = (uint_fast8_t)false; /* cannot post */
#ifndef Q_NASSERT
            QF_INT_ENABLE();
            /* must be able to post event : Q_ERROR_ID(410) */
            Q_onAssert(Q_this_module_, 410);
#endif
        }
    }
    else if ((qlen - (uint_fast8_t)me->nUsed) > margin) {
        margin = (uint_fast8_t)true; /* can post */
    }
    else {
        margin = (uint_fast8_t)false; /* cannot post */
    }

    if (margin) { /* can post the event? */
        /* insert event into the ring buffer (FIFO) */
        QF_ROM_QUEUE_AT_(acb, me->head).sig = (QSignal)sig;
#if (Q_PARAM_SIZE != 0)
        QF_ROM_QUEUE_AT_(acb, me->head).par = par;
#endif
        if (me->head == (uint8_t)0) {
            me->head = (uint8_t)qlen; /* wrap the head */
        }
        --me->head;
        ++me->nUsed;
        /* is this the first event? */
        if (me->nUsed == (uint8_t)1) {
            /* set the bit */

					QF_readySet_ |= (uint_fast32_t)
                ((uint_fast32_t)1 << (me->prio - (uint_fast32_t)1));
        }
    }

#ifdef QF_ISR_NEST
#ifdef QF_ISR_STAT_TYPE
    QF_ISR_RESTORE(stat);
#else
    QF_INT_ENABLE();
#endif
#endif

    return (bool)margin;
}

发送消息:发送的到的任务,从优先级定位任务位置,然后往 队列中放入消息,然后置位 全局变量QF_readySet_。

 

 

qp官网下载qpc,移植到stm32f103单片机,在正点原子战舰V3开发板上实验成功 qp搭建步骤重要提示: #define RED_QUEUE_LEN 3 #define BLUE_QUEUE_LEN 3 #define TACKER_EVENT_POOL_LEN (RED_QUEUE_LEN + BLUE_QUEUE_LEN) static QEvt const * l_redQueueSto[RED_QUEUE_LEN]; //事件队列 static QEvt const * l_blueQueueSto[BLUE_QUEUE_LEN]; //事件队列 static LedEvt LedEvtPoolSto[TACKER_EVENT_POOL_LEN]; //事件池 static QSubscrList SubSrcSto[MAX_PUB_SIG]; //订阅列表 typedef struct LedEvtTag LedEvt; //定义事件结构 struct LedEvtTag{ QEvt super_; uint16_t uiParaH; uint16_t uiParaL; }; //定义信号枚举 enum LedSignals{ START_SIG = Q_USER_SIG, KEY0_SIG, KEY1_SIG, KEY2_SIG, KEYUP_SIG, ALL_OFF_SIG, ONLY_BULE_SIG, ONLY_RED_SIG, ALL_ON_SIG, MAX_PUB_SIG }; void PublishLedEvt(uint16_t uiSig, uint16_t uiParaH, uint16_t uiParaL) //发布事件函数 { LedEvt* peTacker; peTacker = Q_NEW(LedEvt, uiSig); peTacker->uiParaH = uiParaH; peTacker->uiParaL = uiParaL; QF_publish_((QEvt*)peTacker); } QF_init(); //时间事件列表、活动对象查找表、优先级集合 QF_psInit(SubSrcSto, Q_DIM(SubSrcSto)); //初始化事件池 QF_poolInit(LedEvtPoolSto,sizeof(LedEvtPoolSto),sizeof(LedEvtPoolSto[0])); RedLed_Start(uiPrio++, l_redQueueSto, Q_DIM(l_redQueueSto), 0, 0); //建立活动对象 BlueLed_Start(uiPrio++, l_blueQueueSto, Q_DIM(l_blueQueueSto), 0, 0); /////////////////////////////////////////////////// typedef struct RedActiveTag RedActive; //构建一个活动对象活动类型 struct RedActiveTag{ QActive super_; volatile uint16_t RedLedStateNow; uint16_t a; uint16_t b; }; extern RedActive RedLed; RedActive RedLed; void RedLed_Start(uint_fast8_t prio, QEvt const *qSto[], uint_fast16_t qLen, void *stkSto, uint_fast16_t stkSize) { RedLed_Ctor(&RedLed;); QActive_start_((QActive*)&RedLed;, prio, qSto, qLen, stkSto, stkSize, (QEvt const *)0); //创立活动对象的线程并提醒 QF 开始管理活动对象 } void RedLed_Ctor(RedActive* me) { QActive_ctor(&me;->super_, (QStateHandler)RedLed_Initial); //初始化状态机基础类(成员 super) me->RedLedStateNow = 0; }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值