新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 建立一個(gè)AVR的RTOS(2)—人工堆棧

建立一個(gè)AVR的RTOS(2)—人工堆棧

作者: 時(shí)間:2016-12-03 來源:網(wǎng)絡(luò) 收藏
第二篇:人工堆棧

單片機(jī)的指令集中,一類指令是專門與堆棧和PC指針打道的,它們是

本文引用地址:http://butianyuan.cn/article/201612/325273.htm

rcall相對(duì)調(diào)用子程序指令

icall間接調(diào)用子程序指令

ret子程序返回指令

reti中斷返回指令

對(duì)于ret和reti,它們都可以將堆棧棧頂?shù)膬蓚€(gè)字節(jié)被彈出來送入程序計(jì)數(shù)器PC中,一般用來從子程序或中斷中退出。其中reti還可以在退出中斷時(shí),重開全局中斷使能。

有了這個(gè)基礎(chǔ),就可以建立我們的人工堆棧了。

例:

#include <avr/io.h>

void fun1(void)

{

unsigned char i=0;

while(1)

{

PORTB=i++;

PORTC=0x01<<(i%8);

}

}

unsigned char Stack[100]; //建立一個(gè)100字節(jié)的人工堆棧

void RunFunInNewStack(void (*pfun)(),unsigned char *pStack)

{

*pStack--=(unsigned int)pfun>>8; //將函數(shù)的地址高位壓入堆棧,

*pStack--=(unsigned int)pfun; //將函數(shù)的地址低位壓入堆棧,

SP=pStack; //將堆棧指針指向人工堆棧的棧頂

__asm__ __volatile__("RET nt"); //返回并開中斷,開始運(yùn)行fun1()

}

int main(void)

{

RunFunInNewStack(fun1,&Stack[99]);

}

RunFunInNewStack(),將指向函數(shù)的指針的值保存到一個(gè)unsigned char的數(shù)組Stack中,作為人工堆棧。并且將棧頂?shù)臄?shù)值傳遞組堆棧指針SP,因此當(dāng)用"ret"返回時(shí),從SP中恢復(fù)到PC中的值,就變?yōu)榱酥赶騠un1()的地址,開始運(yùn)行fun1().

上面例子中在RunFunInNewStack()的最后一句嵌入了匯編代碼"ret",實(shí)際上是可以去除的。因?yàn)樵赗unFunInNewStack()返回時(shí),編譯器已經(jīng)會(huì)加上"ret"。我特意寫出來,是為了讓大家看到用"ret"作為返回后運(yùn)行fun1()的過程。



關(guān)鍵詞: AVRRTOS人工堆

評(píng)論


技術(shù)專區(qū)

關(guān)閉