建立一個屬于自己的AVR的RTOS(1)—函數(shù)的運行
在21IC上,大家都可以看到楊屹寫的關(guān)于UCOSII在51上的移植,于是掀起了51上的RTOS的熱潮。
本文引用地址:http://www.ex-cimer.com/article/201612/325272.htm再后來,陳明計先生推出的small rots,展示了一個用在51上的微內(nèi)核,足以在52上進(jìn)行任務(wù)調(diào)度。
前段時間,在ouravr上面開有專門關(guān)于AVR的Rtos的專欄,并且不少的兄弟把自己的作品拿出來,著實開了不少眼界。這時,我重新回顧了使用單片機的經(jīng)歷,覺得很有必要,從根本上對單片機的RTOS的知識進(jìn)行整理,于是,我開始了編寫一個用在AVR單片機的RTOS。
當(dāng)時,我所有的知識和資源有:
Proteus6.7可以用來模擬仿真avr系列的單片機
WinAVR v2.0.5.48基于GCC AVR的編譯環(huán)境,好處在于可以在C語言中插入asm的語句
mega8 1K的ram有8K的rom,是開發(fā)8位的RTOS的一個理想的器件,并且我對它也比較熟悉。
寫UCOS的Jean J.Labrosse在他的書上有這樣一句話,“漸漸地,我自然會想到,寫個實時內(nèi)核直有那么難嗎?不就是不斷地保存,恢復(fù)CPU的那些寄存器嘛。”
好了,當(dāng)這一切準(zhǔn)備好后,我們就可以開始我們的Rtos for mega8的實驗之旅了。
本文列出的例子,全部完整可用。只需要一個文件就可以編譯了。我相信,只要適當(dāng)可用,最簡單的就是最好的,這樣可以排除一些不必要的干擾,讓大家專注到每一個過程的學(xué)習(xí)。
第一篇:函數(shù)的運行
在一般的單片機系統(tǒng)中,是以前后臺的方式(大循環(huán)+中斷)來處理數(shù)據(jù)和作出反應(yīng)的。
例子如下:
makefile的設(shè)定:運行WinAvr中的Mfile,設(shè)定如下
MCU Type: mega8
Optimization level: s
Debug format :AVR-COFF
C/C++ source file:選譯要編譯的C文件
#include
void fun1(void)
{
unsigned char i=0;
while(1)
{
PORTB=i++;
PORTC=0x01<<(i%8);
}
}
int main(void)
{
fun1();
}
首先,提出一個問題:如果要調(diào)用一個函數(shù),真是只能以上面的方式進(jìn)行嗎?
相信學(xué)習(xí)過C語言的各位會回答,No!我們還有一種方式,就是“用函數(shù)指針變量調(diào)用函數(shù)”,如果大家都和我一樣,當(dāng)初的教科書是譚浩強先生的《C程序設(shè)計》的話,請找回書的第9.5節(jié)。
例子:用函數(shù)指針變量調(diào)用函數(shù)
#include
void fun1(void)
{
unsigned char i=0;
while(1)
{
PORTB=i++;
PORTC=0x01<<(i%8);
}
}
void (*pfun)(); //指向函數(shù)的指針
int main(void)
{
pfun=fun1; //
(*pfun)(); //運行指針?biāo)赶虻暮瘮?shù)
}
第二種,是“把指向函數(shù)的指針變量作函數(shù)參數(shù)”
#include
void fun1(void)
{
unsigned char i=0;
while(1)
{
PORTB=i++;
PORTC=0x01<<(i%8);
}
}
void RunFun(void (*pfun)()) //獲得了要傳遞的函數(shù)的地址
{
(*pfun)(); //在RunFun中,運行指針?biāo)赶虻暮瘮?shù)
}
int main(void)
{
RunFun(fun1); //將函數(shù)的指針作為變量傳遞
}
看到上面的兩種方式,很多人可能會說,“這的確不錯”,但是這樣與我們想要的RTOS,有什么關(guān)系呢?各位請細(xì)心向下看。
以下是GCC對上面的代碼的編譯的情況:
對main()中的RunFun(fun1);的編譯如下
ldi r24,lo8(pm(fun1))
ldi r25,hi8(pm(fun1))
rcall RunFun
對void RunFun(void (*pfun)())的編譯如下
/*void RunFun(void (*pfun)())*/
/*(*pfun)();*/
.LM6:
movw r30,r24
icall
ret
在調(diào)用void RunFun(void (*pfun)())的時候,的確可以把fun1的地址通過r24和r25傳遞給RunFun()。但是,RTOS如何才能有效地利用函數(shù)的地址呢?
評論