这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » AVR的RTOS(人工堆栈)

共1条 1/1 1 跳转至

AVR的RTOS(人工堆栈)

助工
2014-10-05 14:45:01     打赏
在单片机的指令集中,一类指令是专门与堆栈和PC指针打道的,它们是 
    rcall   相对调用子程序指令 
    icall   间接调用子程序指令 
    ret     子程序返回指令 
    reti    中断返回指令    


    对于ret和reti,它们都可以将堆栈栈顶的两个字节被弹出来送入程序计数器PC中,一般用来从子程序或中断中退出。其中reti还可以在退出中断时,重开全局中断使能。 
    有了这个基础,就可以建立我们的人工堆栈了。 
#include <avr/io.h> 
void fun1(void) 
{ 
  unsigned char i=0; 
  while(1) 
  { 
    PORTB=i++; 
    PORTC=0x01<<(i%8); 
  } 
} 

unsigned char Stack[100]; //建立一个100字节的人工堆栈 

void RunFunInNewStack(void (*pfun)(),unsigned char *pStack) 
{ 
  *pStack--=(unsigned int)pfun>>8;    //将函数的地址高位压入堆栈, 
  *pStack--=(unsigned int)pfun;        //将函数的地址低位压入堆栈, 
  SP=pStack;                            //将堆栈指针指向人工堆栈的栈顶 
  __asm__ __volatile__("RET  
\t");    //返回并开中断,开始运行fun1() 

} 

int main(void) 
{ 
   RunFunInNewStack(fun1,&Stack[99]); 
} 

 

RunFunInNewStack(),将指向函数的指针的值保存到一个unsigned  char的数组Stack中,作为人工堆栈。并且将栈顶的数值传递组堆栈指针SP,因此当用"ret"返回时,从SP中恢复到PC中的值,就变为了指向fun1()的地址,开始运行fun1(). 


    上面例子中在RunFunInNewStack()的最后一句嵌入了汇编代码 "ret",实际上是可以去除的。因为在RunFunInNewStack()返回时,编译器已经会加上"ret"。我特意写出来,是为了让大家看到用"ret"作为返回后运行fun1()的过程。


共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]