打造自己的rtos(2)

-------------第二篇: 人工堆栈   

     在单片机的指令集中,一类指令是专门与堆栈和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 /n/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()的过程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值