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_。