手头有一本《ADSP技术与应用》(机械工业出版社),主要讲解SHARC系列。我在书中P58看到待机指令IDLE,对它的说明如下:
DSP进入低功耗等待状态,程序地址不变,直到某个中断出现才执行中断服务程序和后续指令。
降低功耗,这个比较诱人,因为很多场合电量的提供非常有限。
上面所说是SHARC的IDLE指令,在TigerSHARC中又如何呢?我在ADSP-TS201 TigerSHARCProcessor Programming Reference中找到下面这段话:
This instruction causes theTigerSHARC processor to go into IDLE state. In this state theTigerSHARC processor stops executing instructions and waits for anytype of interrupt.
这段文字说得相当明确,虽然没有说可以降低功耗,但是处理器停止执行指令(...Processor stops executinginstructions...),功耗肯定会下降一些吧。
为了试验一下这条指令,我写了如下的C程序:
#include
#include
#include
const char __argv_string[] = "-abc -xyz";
#define IDLE __builtin_idle()
#define RREAD(reg) __builtin_sysreg_read(reg)
#define RWRITE(reg,value) __builtin_sysreg_write(reg,value)
void irq0_isr(void);
int main( int argc,
char*argv[] )
{
int v;
//将FLAG2设为输出模式
RWRITE(__FLAGREGST,FLAGREG_FLAG2_EN);
//设置IRQ0服务程序
RWRITE(__IVIRQ0,(int)irq0_isr);
//设置跳沿触发
RWRITE(__INTCTL,0);
//允许外部IRQ0
v=RREAD(__IMASKH);
v|=(1<
RWRITE(__IMASKH,v);
//开全局中断使能
RWRITE(__SQCTLST,SQCTL_GIE);
v=0;
IDLE;//调用__builtin_idle()
v=0;
return 0;
}
#pragma interrupt
void irq0_isr(void)
{
static intbutton=0;
button=!button;
if(0==button)
{
RWRITE(__FLAGREGCL,~FLAGREG_FLAG2_OUT);
}
else
{
RWRITE(__FLAGREGST,FLAGREG_FLAG2_OUT);
}
}
在main函数中的IDLE(注意main函数中的那个IDLE不是汇编指令IDLE,而是我自己定义的一个宏,用来调用__builtin_idle)和return0中间的那句v=0设置一个断点,然后用EZ-KIT运行程序,我们会发现VisualDSP++的状态栏一直显示Running而不会到达断点。如果我们通过按钮触发一个IRQ0,则与FLAG2管脚相连的LED发光(表明中断服务程序被执行),程序马上就到达断点处,验证了执行IDLE指令时DSP的行为。
函数__builtin_idle就是用来在程序中加入IDLE指令,看一下反汇编就明白了。
这样看来,如果我们的DSP程序主要任务都是由中断来触发的话,在main中的那个死循环写成while(1);就是不经济的了,如果写成:
while(1)
__builtin_idle();
是否能变得省电呢?应该会吧。可惜手头没有什么仪器测试一下功耗。
在51及其兼容单片机中,没有IDLE这样的指令,如果程序的任务都是由中断触发,则主程序在完成初始化的任务之后,就会用一句SJMP$进行原地跳转。如果用C51,就写while(1);或for(;;);这两种写法对应的汇编都是一样的:
while(1);的汇编代码:
58: while(1);
C:0x0040 80FE SJMP C:0040
for(;;);的汇编代码:
59: for(;;);
C:0x0040 80FE SJMP C:0040
上面汇编代码SJMP前面的80FE就是对应的机器代码。SJMP指令由两个字节组成,第一个字节是80H,表示它是SJMP指令,第二个字节是一个有符号的整数,表示相对偏移量。这条指令是这样被执行的:
首先PC加2,因为这条指令有两个字节;
然后把第二个字节表示的相对偏移量加到PC上,作为下一条指令的地址。
SJMP$对应的机器码是80FE,因为FE是补码形式,对FE取反得到01,然后加一,得到2,于是FE表示-2。指令80FE就是先让PC+2,然后将PC-2,这一加一减,所以PC仍然指向SJMP$,原地跳转。
可见,没有类似IDLE指令的51及其兼容单片机,在等待中断的时候,依然不停地取指令,执行指令。