新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 建立一個AVR的RTOS(3)—GCC中對寄存器的分配與使用

        建立一個AVR的RTOS(3)—GCC中對寄存器的分配與使用

        作者: 時間:2016-12-03 來源:網絡 收藏
        第三篇:GCC中對寄存器的分配與使用

        在很多用于AVRRTOS中,都會有任務調度時,插入以下的語句:

        本文引用地址:http://www.104case.com/article/201612/325274.htm

        入棧:

        __asm__ __volatile__("PUSH R0 nt");

        __asm__ __volatile__("PUSH R1 nt");

        ......

        __asm__ __volatile__("PUSH R31 nt");

        出棧

        __asm__ __volatile__("POP R31 nt");

        ......

        __asm__ __volatile__("POP R1 nt");

        __asm__ __volatile__("POP R0 nt");

        通常大家都會認為,在任務調度開始時,當然要將所有的通用寄存器都保存,并且還應該保存程序狀態寄存器SREG。然后再根據相反的次序,將新任務的寄存器的內容恢復。

        但是,事實真的是這樣嗎?如果大家看過陳明計先生寫的small rots51,就會發現,它所保存的通用寄存器不過是4組通用寄存器中的1組。

        在Win AVR中的幫助文件avr-libc Manual中的Related Pages中的Frequently Asked Questions,其實有一個問題是"What registers are used by the C compiler?"回答了編譯器所需要占用的寄存器。一般情況下,編譯器會先用到以下寄存器

        1 Call-used registers (r18-r27, r30-r31):調用函數時作為參數傳遞,也就是用得最多的寄存器。

        2 Call-saved registers (r2-r17, r28-r29):調用函數時作為結果傳遞,當中的r28和r29可能會被作為指向堆棧上的變量的指針。

        3 Fixed registers (r0, r1):固定作用。r0用于存放臨時數據,r1用于存放0。

        還有另一個問題是"How to permanently bind a variable to a register?",是將變量綁定到通用寄存器的方法。而且我發現,如果將某個寄存器定義為變量,編譯器就會不將該寄存器分配作其它用途。這對RTOS是很重要的。

        在"Inline Asm"中的"C Names Used in Assembler Code"明確表示,如果將太多的通用寄存器定義為變量,剛在編譯的過程中,被定義的變量依然可能被編譯器占用。

        大家可以比較以下兩個例子,看看編譯器產生的代碼:(在*.lst文件中)

        第一個例子:沒有定義通用寄存器為變量

        #include

        unsigned char add(unsigned char b,unsigned char c,unsigned char d)

        {

        return b+c*d;

        }

        int main(void)

        {

        unsigned char a=0;

        while(1)

        {

        a++;

        PORTB=add(a,a,a);

        }

        }

        在本例中,"add(a,a,a);"被編譯如下:

        mov r20,r28

        mov r22,r28

        mov r24,r28

        rcall add

        第二個例子:定義通用寄存器為變量

        #include

        unsigned char add(unsigned char b,unsigned char c,unsigned char d)

        {

        return b+c*d;

        }

        register unsigned char a asm("r20"); //將r20定義為變量a

        int main(void)

        {

        while(1)

        {

        a++;

        PORTB=add(a,a,a);

        }

        }

        在本例中,"add(a,a,a);"被編譯如下:

        mov r22,r20

        mov r24,r20

        rcall add

        當然,在上面兩個例子中,有部份代碼被編譯器優化了。

        通過反復測試,發現編譯器一般使用如下寄存器:

        第1類寄存器,第2類寄存器的r28,r29,第3類寄存器

        如在中斷函數中有調用基它函數,剛會在進入中斷后,固定地將第1類寄存器和第3類寄存器入棧,在退出中斷又將它們出棧。



        關鍵詞: AVRRTOSGCC寄存

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 克什克腾旗| 高安市| 马鞍山市| 泰顺县| 司法| 沂南县| 丁青县| 江城| 高陵县| 乌恰县| 陆川县| 田林县| 永平县| 绿春县| 怀柔区| 安西县| 伊吾县| 瑞丽市| 天峻县| 松原市| 左云县| 满洲里市| 贡山| 秭归县| 晋城| 安仁县| 河北省| 五指山市| 延寿县| 九龙县| 通道| 乐陵市| 青川县| 容城县| 开平市| 思茅市| 刚察县| 合水县| 囊谦县| 聂拉木县| 陆良县|