嵌入式编程方面的问题:
1、找出下面程序的错误 (一个中断服务子程序ISR)
interrupt double compute_area(double radius)
{
double area = PI *radius * radius;
printf("\nArea=%f",area);
return area;
}
解答:
a、ISR不能返回一个值。
b、ISR不能传递参数。
c、在许多处理器编译器中,浮点一般都是不可冲入的。有些处理器编译器需要让额外的寄存器入栈,有些处理器编译器就不允许在ISR中做浮点运算。此外ISR应该是短而有效率的。在ISR中做浮点运算是不明智的。
d、printf经常是有冲入性和性能上的问题,所以一般不使用printf函数。
2、volatile关键字的意义和用途
volatile的语法和const的语法是一样的,但是volatile的意思是“在编译器认识的范围外,这个数据可以被改变”。环境在不知原因的条件下改变数据,所以,volatile在告诉编译器不要擅自做出有关数据的任何假定,在优化期间这是特别重要的。
通俗的说,volatile的一个定义为:定义为volatile的变量是说这个变量可能会被异想不到的改变,这样编译器就不会去假设这个变量的值了。精确的说,优化器在用到这个变量的时候必须每次都小心的重新读取这个变量的值,而不是使用寄存器中备份的值。
下面是使用volatile变量的几个例子:
a、并行设备的硬件寄存器,如状态寄存器,处理器的状态不停的在变化,所以寄存器的值也在不断的随处理器状态的变化而变化。
b、一个中断服务子程序中会访问到得非自动变量
c、多线程应用中被几个任务共享的变量。每个线程都有可能会修改变量的值。
下面一个关于volatile的问题:
一个参数既可以是const也是volatile吗?一个指针可以使volatile吗?
第一个问题:是的,最好的例子就是只读的状态寄存器。他是volatile,因为它可能会被意想不到的改变;他又是const,因为程序不应该试图去修改它。
第二个问题:是的。尽管这并不常见,一个例子就是当中断服务子程序修改一个指向一个buffer的指针时。
再看一个实例:
下面的函数有什么错误?
int square(volatile int *ptr)
{
return *ptr * (*ptr);
}
解析:程序的目的是想用来返回指针*ptr指向值的平方,但是由于*ptr是指向一个volatile型参数,编译器将产生下面类似的代码:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a*b;
}
由于*ptr的值可能被意想不到地改变,因此a和b可能是不相同的。结果是可想而知的。
正确的代码如下:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a*a;
}
3、访问特定位置的内存特点
要求设置一绝对地址为0x67a9的整型变量的值为0xaa66.编译器是一个纯粹的ANSI编译器。
典型的答案为:
int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa66;
一种不合理的方法:
*(int *const)(0x67a9) = 0xaa66;
4、写两段代码,一个设置a的bit 3,一个清楚a的bit 3
最佳答案:
#define BIT3 (0x1 << 3)
static int a;
void set_bit3(void)
{
a |= BIT3;
}
void clear_bit3(void)
{
a &= BIT3;
}