DSP

关于ADSP-TigerSHARC的IDLE指令

2019-07-13 21:07发布

手头有一本《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及其兼容单片机,在等待中断的时候,依然不停地取指令,执行指令。