首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

]DSP_5_DSP/BIOS_例程分析_同优先级用户任务切换

]DSP_5_DSP/BIOS_例程分析_同优先级用户任务切换

这是在网上找的一个DSP/BIOS同优先级任务切换的例程。


CPU是DM642。用CCS3.3软件仿真。


在Configuration里添加了三个用户任务TSK0~2,优先级都设为1,任务处理函数都设为task,任务参数(task function argument1)依次设为0 1 2。







代码:




#include
<std.h>



#include
<log.h>


#include
<sys.h>



#include
"switestcfg.h"



Void
main()


{  
;


}



Void
task(Arg id_arg)



{


   
Int   
id =
ArgToInt
(id_arg);


   
Int   
i;  


   


LOG_printf(&trace,
"start %d", id);



   



  for
(i
=
0; i
<
5 ; i++) {


   


      
LOG_printf(&trace,
"Loop %d: Task %d Working", i, id);


     


      
TSK_yield();


}


  


   
LOG_printf(&trace,
"Task %d DONE", id);


}




本例中main函数为空。


在所有DSP/BIOS模块初始化之后,调用main函数。此时硬件中断和软件中断都是禁止的。然后程序开始执行任务函数。



首先TSK0调用task函数,任务号id=0,在trace窗口中显示start0,然后进入for循环,


又执行语句LOG_printf(&trace,
"Loop %d: Task %d Working", i, id);



i=0,trace窗口显示Loop 0:Task 0 Working



TSK_yield函数将TSK0挂起,任务切换到TSK1。



TSK1也调用task函数,任务号id=1,在trace窗口中显示start1,然后也进入for循环,i=0,trace窗口显示Loop 0:Task 1 Working



TSK_yield函数将TSK1挂起,任务切换到TSK2。



TSK1还调用task函数,任务号id=2,在trace窗口中显示start2,然后也进入for循环,i=0,trace窗口显示Loop 0:Task 2 Working



TSK_yield函数将TSK2挂起,任务循环切换回到TSK0。



TSK0第二次调用task函数,这时下面三条语句


Int   
id =
ArgToInt
(id_arg);


Int   
i;


LOG_printf(&trace,
"start %d", id);


就不再执行了。


且在for循环中i=0的情况也不再执行了。


因为TSK0第一次执行的时候那三条语句和for循环中i=0的情况都已经执行过了,TSK0被切换的时候这个任务并没有执行完毕也不是被停止,而是被暂时挂起,就相当于在TSK0被切换的时候自动记忆了一个断点,当再次执行TSK0的时候,这个任务就从上次的那个断点出开始继续往下执行。



所以TSK0再次开始执行的时候
i++


i=1, trace窗口显示Loop 1:Task 0 Working



TSK_yield函数再次将TSK0挂起,任务切换到TSK1。



同理TSK1再次开始执行的时候i++


i=1, trace窗口显示Loop 1:Task 1 Working



TSK_yield函数再次将TSK1挂起,任务切换到TSK2。



同理TSK2再次开始执行的时候i++


i=1, trace窗口显示Loop 1:Task 2 Working



TSK_yield函数将TSK2挂起,任务再次循环切换回到TSK0。



如此循环······



TSK0在i=5时跳出for循环执行最后一条语句LOG_printf(&trace,
"Task %d DONE", id);


Trace窗口显示Task 0 DONE



TSK1在i=5时跳出for循环


Trace窗口显示Task 1 DONE



TSK2在i=5时跳出for循环


Trace窗口显示Task 2 DONE



所以message log中的整体显示如下








在Execution Graph中看起来会更直观一些



在这个图中发现一个问题,显示TSK0~2每个任务都执行了六次,但是for循环中i只设置了五个值,这是因为在i=5时虽然跳出了for循环,但是继续执行下一条语句LOG_printf(&trace,
"Task %d DONE", id);也就相当于i从0加到5一共六个值,每个i值TSK0~2都有执行,所以从0到5一共六次。



左上角还有个KNL_swi
是一个软中断,查看其属性如下图:



他的作用是中断访问TSK调度程序,程序一开始运行Other Thread,我想大概是一些初始化的线程,然后运行软中断KNL_swi使用户建立的任务都不执行,KNL-swi结束后才能开始执行TSK-Task Manager中用户建立的TSK0~2。当TSK0~2全部都结束后,KNL_swi与Other Thread交替执行。



从Execution Graph Details中的数据能看出TSK_idle
KNL_swi
管理用户任务的机制

返回列表