新闻  |   论坛  |   博客  |   在线研讨会
多线程框架FOR ARM
bjluhaijun | 2008-10-12 18:11:08    阅读:67304   发布文章

 

框架实现多线程切换;

                      构件封装了完整的事务函数;

           状态模式是基于状态图的编程方式。

 

一、   文件目录说明:

1、            FrameWork :存放所有的多线程框架文件。

2、            Includes   头文件

3、            Src:         用户源文件,main.c

4、            OBJ:        工程文件

5、            COMMON:   ARM芯片初始化文件

6、            其它目录是软件构件:

TMR_FW:计时器构件

CLK_FW:实时时钟构件

COMM_FW:串口驱动构件

DISP_FW:显示驱动构件

KEY_FW:按健驱动构件

二、   多线程框架文件说明:

1、          FrameWork.c : 调度函数和线程初始化

2、          FrameWork.h:头文件

3、          EventQueue.c:事件队列

4、          EventQueue.h:头文件

5、          FSM.c:事件分发(有限状态机)

6、          FSM.h 头文件

7、          EventDefer.c:事件延迟(可选是否编译)

8、          EventDefer.h:头文件

9、          FW_CFG.h:框架配置文件

三、   调度原理:

   1 用一个字节变量的每一位代表一个任务是否就绪,1为就绪,0为休眠。

2 这个字节从高位到低位代表的任务,优先级也从高到低。

3 通过查表从就绪的任务中找出最高优先级的任务并执行,同时清就绪标志。

          

        就绪表ActObjReadySet

1

0

1

0

0

0

0

0

      位:7      6       5       4       3       2       1       0 

  任务号:8      7       6       5       4       3       2       1        

      

        上表表示有两任务:任务8和任务6 就绪。

        因为8位优先级高,我们来查表:

PRIORITY_TABLE[]= {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4};       

ready = ActObjReadySet;// 10100000

    if (ready != 0) {

        if ((ready & 0xF0) != 0U) {       

            prionum = PRIORITY_TABLE[ready >> 4] + 4;

        }else{

            prionum = PRIORITY_TABLE[ready];

        }

        }

     查表结果为4 4+4= 8

计算结果为8,所以优先级为8的任务先执行,并清就绪位,完成后再次计算结果为6,优先级为6的任务再执行。 

 

 

四、   线程间通信:

1、事件队列

线程间通信通过事件队列来完成,

    void EvtPostQue(INT8U prio,Event sig,Param par)

    void EvtPostQueISR(INT8U prio,Event sig,Param par)

    上面两个函数用于事件发送,一个是在线程中,一个是在中断中发送。有三个参数:优先级、事件信号、传递参数(可选)。

事件发送后,放在队列中,同时让对应的线程就绪。

从队列中取出事件信号由调度函数(ActObjScheduler())来完成,用户不用干预,只需发送事件信号就可以了。

2、事件延迟(可选编译项):

BOOLEAN EvtDefer(INT8U prio,Event sig,Param par):向延迟队列发送一个事件信号。(延迟一个事件)

void EvtRecall(INT8U prio):如果延迟队列中有事件,则取出放到事件队列中去处理。(唤醒一个事)

五、在应用中使用框架:

1、在工程文件中加入框架源文件,并修改FW_CFG.h,做配置。

2main.c中相关函数的调用:

int main (void)

{

    InitialMCU();

    ActObjInit();

    … …

    InitialObj();

    while(1){

        ActObjScheduler();//调度

    }

}

void InitialObj(void)  { //初始化所用线程

    Fsm *a;

    ActObjInitTran(1,(State)&COMM1RxTx);//初始化线程1

    ActObjInitTran(2,(State)&COMM2RxTx); //初始化线程2

    ActObjInitTran(3,(State)&COMM3RxTx); //初始化线程3

    ActObjInitTran(4,(State)&COMM4RxTx); //初始化线程4

    … …

}

void COMM1RxTx(Fsm *me)

{

  switch (SIG(me)) {

        case COMRX_SIG:

… …

}

… …

KEIL UVISION3 工程参考

 

 

附录:函数说明

 

FrameWork.c

 

1void ActObjInit(void)

初始化线程和事件队列。

2void ActObjScheduler(void),调度

找出就绪线程中的最高优先级的线程。

 

EventQueue.c

 

3void EvtPostQue(INT8U prio,Event sig)

向队列发送事件信号,如果当前q->EvtQNRead == 0,

(((Fsm *)(me_))->Sig_) = sig,否则放在队列中

 

4void EvtPostQueISR(INT8U prio,Event sig)

同上个函数,在中断中调用。

 

FSM.C

 

5void Fsm_dispatch(Fsm *me) 事件分发函数

   ActObjScheduler()中调用,参数是一个指向当前线程的指针。

             

 FSM.H

1、              TRAN(target_) 宏替换

      状态转换, target_ 是指向当前状态处理器函数的指针。

      例如:TRAN(&Obj1State1);

      状态转换就是把 *me->State__ 的值换一个函数指针。

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
嵌入式应用经验介绍
最近文章
多线程框架FOR ARM
2008-10-12 18:11:08
最小的多线程框架
2008-09-16 16:55:26
使用任务调度的优势
2008-09-16 16:43:58
推荐文章
最近访客