DSP/BISO线程调度DSP/BIOS使用户的应用程序可以由一个线程集合构筑起来,每一个线程执行一个模块化的功能。通过允许高优先级的线程抢占低优先级的线程,以及允许阻塞、同步、通信等各种线程间的交互方式,使得多线程的应用程序可以在一个处理器上运行。DSP/BIOS支持多种不同优先级的线程,每种线程类型都有不同的执行和抢占特性。这些线程按照优先级从高到低的顺序排列如下:硬件中断(HWI),包括CLK函数。软件中断(SWI),包括PRD函数。任务(TSK)。后台线程(IDL)。在DSP/BIOS中,硬件中断有最高的优先级,然后是软件中断,软件中断可以被高优先权软件中断或硬件中断抢先。软件中断是不能被阻塞的。任务的优先权低于软件中断,共有15个任务优先权级别(加上TSK_idle应该16个)。任务在等待某个资源有效时可以被阻塞。后台线程idle_loop是优先级最低的线程。线程优先级如下图表示:下面具体介绍各种线程。HWImodule硬件中断是用来处理应用程序响应外部异步事件时必须执行的关键操作。在典型的DSP应用中,硬件中断是由片上的外设或者DSP外部的设备触发的。中断发生后处理器会通过中断向量跳转到相应的ISR地址。一个中断的跳转由一个DSP/BIOSHWI对象负责,跳转的地址可以是一个用户函数或者是通用的系统HWI调度程序(dispatcher)的入口地址。硬件中断ISR可以使用汇编语言、C语言或者混合编写。HWI函数通常使用汇编来提高效率。如果要完全使用C语言编写,应该使用系统的HWI调度程序,它会在调用用户C函数的前后分别惊醒现场环境保护与恢复。所有的硬件中断都会一直运行到结束,如果一个硬件中断在其ISR得到运行机会前被多次触发,该ISR也只运行一次。因此,用户必须尽量和减少HWI执行的代码量。如果GIE位被使能,一个硬件中断可能被任何其他的被使能的中断抢占。硬件中断没有优先级的区分;线程调度结果首先取决于该类就绪线程是被使能还是被禁止的。下图表示了硬件中断的抢占线程以及整个调度过程:当第一个硬件中断(HWI2)产生时,相应的ISR触发了一个比当前运行的软件中断线程(SWIB)优先级更高的软件中断(SWIA)。并且当第一个ISR运行时,第二个硬件中断(HWI1)产生。因为第一个ISR没有屏蔽掉第二个硬件中断,因此产生第二个ISR抢占了第一个ISR。由于优先级较低的SWI可以被硬件中断异步抢占,因此第一个ISR触发的软件中断在两个硬件中断都执行完毕后才被调度执行。一、实验目的熟悉HWI模块在BIOS下的配置,并初步学会自己独立编写程序实现对TIMER的配置和使用。二、实验任务1、设置定时器来产生周期性的中断。在CCS3.1版本的bios下右击CSL-ChipSupportLibrary-TIMER-TimerConfigurationManager选择插入timercfg,根据实验要求配置相应的参数。(对于ccs3.3版本的bios下没有csl的配置选项,我们需要自己在程序中编写配置指令)2、设置HWI在bios下的Scheduling-HWI-HWI_INT15目录,根据实验要求修改HWI_INT15的Properties。3、建立LOG在bios下的Instrumentation-LOG目录,新建一个名为trace的LOG。4、编写main.c根据以下的程序框架,编写实验程序。#includestd.h#includehwi.h#includelog.h#includecsl.h#includecsl_irq.h#includecsl_timer.h#includehwilabcfg.hstaticUint32TimerEventId;main(){/*GetthetimereventID*/TimerEventId=TIMER_getEventId(hTimer1);/*Enabletheevent*/IRQ_enable(TimerEventId);/*Startthetimer*/TIMER_start(hTimer1);}三、实验过程及内容在本实验中使用的是CCS3.3,因此,timer的配置需要自己来编写实现,对于HWI的配置如图1和图2所示,图1、HWI-GENERAL的配置图2、HWI-GENERAL的配置实验的源程序如下:#includestd.h#includehwi.h#includelog.h#includecsl.h#includecsl_irq.h#includecsl_timer.h#includehwilabcfg.hstaticTIMER_HandlehTimer;staticUint32TimerEventId;main(){//---------Configurethetimerdevices---------//TIMER_ConfigMyTimConfig={0x000002C0,//setthevalueofTimercontrolregister(CTL)0x00001000,//Setperiod0x00000000//Startcountvalueatzero};//InitialiseCSLCSL_init();//OpenTIMER1device,andresetittopower-ondefaultstatehTimer=TIMER_open(TIMER_DEV1,0);TIMER_config(hTimer,&MyTimConfig);//Enablethetimerevents(eventsaredisabledwhileresetting)IRQ_enable(TimerEventId);//StartthetimersTIMER_start(hTimer);//ObtaintheeventIDforthetimerdeviceTimerEventId=TIMER_getEventId(hTimer);}//ISRtoserviceTIMERINT1.voidtimerHWI(){LOG_printf(&trace,HWItimer);}SWImodule软件中断是通过程序中的调用SWI函数而触发的,它提供了一个介于HWI和TSK之间的额外的优先级,用于处理那些时间限制比TSK严格但比HWI宽松的工作。SWI线程适用于处理发生频率较低的或者实时限制没有硬件中断严格的应用程序作业。SWI线程都会一直运行直到完成。SWI使得HWI可以将一些不太关键的处理委托给一个优先级比它低的SWI线程,从而减少CPU在中断服务程序中花费的时间,使得其他的HWI可以得到运行。当软件中断被触发时,它会在所有等待中的硬件中断都执行完才开始执行。正在执行的SWI线程在任何时候都可以被硬件中断抢占,并且SWI线程会在硬件中断执行完毕后才恢复执行。另一方面,SWI总能抢占任务的执行,所有等待中的SWI线程执行完之后具有高优先级的任务才可以开始被调度执行。要创建一个SWI的配置文件,右键点击DSP/BIOS的Scheduling-SWI然后选择添加,这样会增加一个新的SWI工程,点击右键properties改变属性,写入函数并改变优先级。KNL_swi是最低级的并且被保留的,用来安排任务。每一个SWI都有一个邮箱,这个邮箱是个32位的值,来决定是否触发SWI或者作为数值观察SWI函数。当一个SWI运行时可通过函数SWI_getmbox来查看邮箱。这个函数在SWI被移除出触发清单之前返回邮箱数值,当SWI运行时邮箱值被锁存,执行后返回初始值。SWI_getmbox返回的值就是SWI被移除出触发清单之前的邮箱数值。能够触发软件中断的DSP/BIOSAPI函数有:1、SWI_andn:该函数提供的参数的“非”与邮箱值做“与”运算,若邮箱为0,则启动该软件中断;如果一个SWI必须在多个事件都发生之后才触发,就使用SWI_andn来调用;当其他的事件都结束后,都应该调用函数SWI_andn来以互补的位掩模参数来清除SWI邮箱里的值,使其为0触发SWI;2、SWI_dec:使邮箱值减1,若邮箱值为0,则启动该软件中断,并恢复邮箱到初始值;如果我们需要同一个事件必须发生多次之后才触发一个SWI,就可以使用该函数;将SWI的邮箱值配置为该时间发生的次数,然后在事件每次发生时调用SWI_dec,直到时间发生了与邮箱值次数相同的时候,即邮箱值为0时,SWI被触发。3、SWI_post:启动软件中断;4、SWI_inc:启动该软件中断,并对邮箱值加1;如果程序希望SWI在运行前被多次触发的情况下让其多次执行,就可以调用函数SWI_inc;5、SWI_or:启动该软件中断,并且邮箱值与该函数提供的参数做“或”运算;通过使用函数SWI_or可以根据触发事件的不同来调用不同的函数;SWI_or使用位掩模值来对触发事件的类型进行编码,可以将该位掩模值作为标志来识别事件并选择不同的函数来执行。前两个是有条件的触发(邮箱值为0),后三者是无条件的触发。任务过程目的及结果:1.熟悉SWI模块及其使用;2.在PART1中,比较两个SWI在同一优先级的情况下的运行时序,并总结规律;3.在PART2中,比较两个SWI在不同优先级的情况下的运行时序,结合PART1的结果比较,得出规律;4.在PART3中,在周期函数的触发作用下,观察时序,比较优先级相同但邮箱值不同的两个SWI的运行情况,并了解函数SWI_dec()的作用和使用方法以及此处邮箱值的变化和作用;5.在PART4中,创建三个SWI,观察时序图,了解函数SWI_andn()的作用和使用方法以及此处邮箱值的变化和作用;6.在PART5中,创建三个SWI,观察时序图,了解函数SWI_or()的作用和使用方法以及此处邮箱值的变化和作用。PART1:1、实验步骤:1)创建工程以及DSP/BIOS文件以及将.cmd文件添加入工程;2)将输入输出改为模拟Simulator;3)在Instrumentation-LOG添加一个LOG叫做trace;4)添加两个SWI,如下设置:SWI0,priority:1,mailbox:0,function:_funSWI0.SWI1,priority:1,mailbox:0,function:_funSWI1.5)创建一个main函数并触发SWI0,加入工程;6)在main函数中写_funSWI0和_funSWI1函数,用LOG_ptintf输出语句;触发SWI用SWI_post;7)编译连接并通过DSP/BIOS-MessageLog观察。2、程序代码#includestd.h#includelog.h#includeswi.h#includeswilabcfg.hvoidmain(){LOG_printf(&trace,mainstarts);SWI_post(&SWI0);}voidfunSWI0(){LOG_printf(&trace,SWI0begins);SWI_post(&SWI1);LOG_printf(&trace,SWI0ends);}voidfunSWI1(){LOG_printf(&trace,SWI1begins);LOG_printf(&trace,SWI1ends);}3、时序图4、小结在优先级一致(同为1)的情况下,在main中触发SWI0,之后SWI0启动中断,直到SWI0结束后才由它触发SWI1,再到SWI1结束,都是依次按顺序进行。PART2:1、实验步骤与PART1基本相同,主要的区别是将SWI1的优先级设置为2。2、实验代码与PART1相同,只是SWI优先级不同。3、时序图4、小结当优先级不一致时(SWI0为1,SWI1为2),在main中触发SWI0,SWI0开始运行,同时在SWI0中触发SWI1时由于SWI1的优先级高,SWI0被挂起(pending),待SWI1结束后再继续运行SWI0直到结束。PA