资料来源 电子下载网 下载时间 2010-6-19 20:02:09
本文地址 http://3ujj.com/sheji/qianrushi/1/463.html
最小的多线程框架调度原理
引言
由于资源和成本的限制,前后台系统是8位MCU上的主流。本文介绍的方法可以在8位MCU上进行任务切换,代码编译后大约100字节。用户把代码从原来的前后台系统移到多线程框架时,可以去掉很多条件语句,从而又节约了代码。也就是说,既提高了性能,又没有增加代码长度,同时也不需要改变原来的编程方式,只是对原有的函数进行调度。可以在1 KB ROM和64字节RAM的MCU上运行。
1 调度原理
① 用1字节变量的每一位代
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
一个任务是否就绪,1为就绪,0为休眠。
② 这个字节从高位到低位代表的任务,优先级也从高到低。
③ 通过查表从就绪的任务中找出优先级最高的任务并执行,同时清就绪标志。
就绪表ThreadReadyList如下:
上述表示有两个任务――任务8和任务6就绪。
因为8位优先级高,我们来查表:
PRIORITY_TABLE[]= {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4};
ready = ThreadReadyList;// 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的任务再执行。
2 任务就绪方法
任务就绪是一个宏,写成宏是因为在某一些MCU的编译器中规定不能在中断中调用函数。
#defineThreadSet(prio)(ThreadReadyList|= (1
比如在定时器中让优先级为5的任务就绪:
ThreadSet(5);
实际操作为:
ThreadReadyList|=0x10; (编译成汇编代码只一条指令)
把就绪表的第4位置1。
3 任务运行方法
任务运行方法有两种:一种是switch;另一种是函数指针。
因为有些8位机的C编译器不支持函数指针,所以本文只介绍switch方式。(注:作者在ARM的多线程框中用的是函数指针)。
在调度原理中计算出优先级号码prionum:
switch(prionum){
case 8://最高优先级任务8的函数放在这里
break;
case 7://任务7的函数放在这里
break;
……
}
4 任务就绪表上电初始化及完整的任务调度函数
(1) 任务就绪表上电初始化
ThreadReadyList = 0;//在调度前把就绪表清0即可
(2) 完整的任务调度函数
void ThreadScheduler (void) {
INT8U prionum,ready;
prionum = 0;
ready = ThreadReadyList;
if (ready != 0) {
if ((ready & 0xF0) != 0U) {//找出就绪表中优先级最高的任务
prionum = PRIORITY_TABLE[ready >> 4] + 4;
}else{
prionum = PRIORITY_TABLE[ready];
}
ready = READY_CLR_AND[prionum];
OS_ENTER_CRITICAL();//关中断
ThreadReadyList &= ready;//清就绪位
OS_EXIT_CRITICAL();//开中断
switch(prionum){
case 8://最高优先级任务8
break;
case 7://任务7
break;
……
case 2://任务2
break;
case 1://任务1
break;
}
}
}
上面代码中用一个switch语句调用不同的任务函数,看似有点笨,但却解决了很多8位机的编译器不支持函数指针的问
题
快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题
,同时不影响执行效率。如果编译器支持函数指针,就可以把上面的代码改成查表,表格为对应的函数指针,代码会短很多。
5 程序编写方法
(1) 主函数
void main(void){
InitialMCU();
ThreadReadyList = 0;
while(1){
ThreadScheduler ();
}
}
主循环只有一条语句,调用一个函数就可以了,改变了整个程序的结构。主循环中不会有很多的条件语句,去判断哪个程序该执行了;而是在条件满足时置就绪标志,由调度器去调度。
(2) 中断函数
void ISR_Timer(void){
TmrCtr ++;
if(TmrCtr > 5){//40ms
TmrCtr = 0;
ThreadSet (8);//让定时执行的任务就绪
}
}
void ISR_AD(void){
_adf = 0;
ADValue = _adrh;
ThreadSet (3);//让计算任务就绪
}
(3) 任务函数
和其他函数没有区别。
void AlarmOut(){
if(AlarmOutctr > 0){
AlarmOutctr --;
PFD_OUT = !PFD_OUT;
TmrStart(4,15);//1s
}else{
ConctrolStat = END_STAT;
PFD_OUT = 0;
}
}
6 使用任务调度的优势
① 多个线程同时就绪时,高优先级先执行。
② 高优先级线程,最长等待时间是上一个正执行线程的完成时间。
③ 因为最长的主循环时间是最长线程的执行时间,所以有些中断中执行的代码可以移到任务中。
④ 可以减少条件语句。
⑤ 使软件结构更合理、清晰。
结语
本文介绍的方法在Holtek系列8位MCU和NXP公司的LPC900中已有数十个项目的应用,并且在此基础上把switch改为函数指针,加上事件队列和事件延迟后,在LPC2000的ARM上成功应用。
卢海军,主要研究方向为嵌入式软件架构、构件和编程方法。
推荐阅读:(按住 Ctrl 鼠标左键点击标题可以打开详细
内容
财务内部控制制度的内容财务内部控制制度的内容人员招聘与配置的内容项目成本控制的内容消防安全演练内容
)
1、IC检测方法
2、什么是遥感技术
3、什么是无线网址
4、制冷设备维修技巧
5、什么是色温
6、手机RF
设计
领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计
问答
7、微波简史
8、微波小知识
9、卫星导航知识
10、卫星与遥感技术