建立一个属于自己的建立一个属于自己的AVR的的RTOS(第三篇:第三篇:GCC)
本文为建立一个属于自己的AVR的RTOS:第三篇:GCC中对寄存器的分配与使用相关内容。
第三篇:GCC中对寄存器的分配与使用
在很多用于AVR的RTOS中,都会有任务调度时,插入以下的语句:
入栈:
__asm____volatile__("PUSHR0
");
__asm____volatile__("PUSHR1
");
......
__asm____volatile__("PUSHR31
");
出栈
__asm____volatile__("POPR31
");
......
__asm____volatile__("POPR1
");
__asm____volatile__("POPR0
");
通常大家都会认为,在任务调度开始时,当然要将所有的通用寄存器都保存,并且还应该保存程序状态寄存器SREG。然后再
根据相反的次序,将新任务的寄存器的内容恢复。
但是,事实真的是这样吗?如果大家看过陈明计先生写的smallrots51,就会发现,它所保存的通用寄存器不过是4组通用寄存器
中的1组。
在WinAVR中的帮助文件avr-libcManual中的RelatedPages中的FrequentlyAskedQuestions,其实有一个问题
是"WhatregistersareusedbytheCcompiler?"回答了编译器所需要占用的寄存器。一般情况下,编译器会先用到以下寄存器
1Call-usedregisters(r18-r27,r30-r31):调用函数时作为参数传递,也就是用得最多的寄存器。
2Call-savedregisters(r2-r17,r28-r29):调用函数时作为结果传递,当中的r28和r29可能会被作为指向堆栈上的变量的指针。
3Fixedregisters(r0,r1):固定作用。r0用于存放临时数据,r1用于存放0。
还有另一个问题是"Howtopermanentlybindavariabletoaregister?",是将变量绑定到通用寄存器的方法。而且我发现,如果将某
个寄存器定义为变量,编译器就会不将该寄存器分配作其它用途。这对RTOS是很重要的。
在"InlineAsm"中的"CNamesUsedinAssemblerCode"明确表示,如果将太多的通用寄存器定义为变量,刚在编译的过程中,被
定义的变量依然可能被编译器占用。
大家可以比较以下两个例子,看看编译器产生的代码:(在*.lst文件中)
第一个例子:没有定义通用寄存器为变量
#include<avr/io.h>
unsignedcharadd(unsignedcharb,unsignedcharc,unsignedchard)
{
returnb+c*d;