一、填空题(每空2分,共30分)
- 微处理器有两种总线架构,数据和指令同一接口的是冯洛伊曼结构,分开的指令和数据接口、取值和数据访问可以并行进行的是哈佛结构。
- ARM微处理器有七种工作模式,它们分为两类:特权模式、非特权模式。其中用户模式属于非特权模式。
- ARM核有两个指令集,分别是:ARM指令集、Thumb指令集。
- ARM微处理器复位后,PC(R15)的地址通常0x0000,初始的工作模式是管理模式,R13通常用来做堆栈指针,R14通常用来做链接寄存器。
- 在ARM体系架构中对复杂的内存管理是通过系统控制协处理器存储管理单元(MMU)和存储器保护单元(MPU)来进行的。当系统发生数据中止异常和预取中止异常时,异常处理程序透过嵌入式操作系统的内存管理机制,通过MMU交换物理内存和虚拟内存的页面,以保证程序正常执行。
二、问答题(每题3分,共30分)
- 用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)。
答:关键是括号和UL上面,答案如下:
#define (365*24*60*60UL)
- 写一个标准宏MIN,这个宏输入两个参数并返回较小的一个。
答:关键是看是否有括号,防止红展开错误:
#define MIN(A,B) ( (A) <= (B) ? (A) : (B))
- ARM常见的寻址方式有哪些?
答:共9种寻址方式:寄存器寻址、立即寻址、寄存器移位寻址、寄存器间接寻址、基址寻址、多寄存器寻址、堆栈寻址、块拷贝寻址、相对寻址;除了堆栈寻址、块拷贝寻址,其他的寻址方式都很常见。
- S3C244BOX I2C总线接口操作有哪四种操作方式?
答:主机发送器模式、主机接收器模式、从机发送器模式、从机接收器模式。(其实就是IIC的几种通信模式)
- Bootloader在嵌入式系统中主要起什么作用?完成哪些主要工作?
答:bootloader的作用:Boot Loader是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境,最后从别处(Flash、以太网、UART)载入内核映像并跳到入口地址。
bootloader完成的工作:
- 实现基本初始化:如系统时钟、初始化内存、Nand Flash控制器等硬件设备
- 初始化其他扩展功能:比如串口、USB、网络端口等方便开发与调试
- 最终目的是:加载内核到RAM中,并为内核启动配置条件,最后启动内核。
- 字符设备和块设备的主要区别是什么?
答:看对内核驱动基础的理解:
- 字符设备只能以字节为单位访问,而块设备以块为单位访问,例如512字节,1024字节等;
- b.块设备可以随机访问,但是字符设备不可以;
- c.字符和块没有访问量大小的限制,块也可以以字节为单位来访问。
其中,第一点为主要区别。
- 简要说明嵌入式操作系统多任务通信的常用方式?
答:常用的通信方式有:无名管道、有名管道、信号量、消息队列、共享内存、网络socket通信。
- 简述BLX、SWI、STM、LDM、MOV、MVN的含义?
答:它们的含义分别如下(考是否熟悉汇编,在U-BOOT和内核移植时会用到):
- BLX:带链接的切换跳转;
- SWI:软中断;
- STM:把多个32位的存储器值存放到内存;
- LDM:从内存送多个32位字到ARM寄存器;
- MOV:传送一个32位数到寄存器;
- MVN:把一个32位数的逻辑“非”送到寄存器。
- 简述下面代码输出是什么,为什么?
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) ? puts("> 6") : puts("<= 6");
}
答:输出“>6”,原因是:当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。
- 简述下面代码定义的temp变量是什么类型?
typedef int (*test) ( float * , float*)
test tmp;
答:函数的指针,该函数有两个指向浮点数(float)的指针(pointer)作为参数(arguments),并且函数的返回值类型是整型;Pointer to function having two argument that is pointer to float and return int。
三、设计题(每题1.5分,共15分)
- 给定一个整型变量a,写两段代码,第一个设置a的bit3,第二个清除a的bit3。在以上两个操作中,要保持其他位不变。
答:设置a的bit 3:
a |= (0x1<<3);
清除a的bit 3:
a &= ~(0x1<<3)。
- 在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器,写代码去完成这一任务。
答:代码如下:
int *ptr = (int *)0x67a9;
*ptr = 0xaa66;
或者:
int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa66;
变量名ptr可随便取。
- 用变量a给出下面的定义:
- a)一个整型数:int a;
- b)一个指向整型数的指针:*int a;
- c)一个指向指针的指针,它指向的指针是指向一个整型数:**int a;
- d)一个有10个整数的数组:int a[10];
- e)一个有10个指针的数组,该指针是指向一个整型数:*int a[10];
- f)一个指向10个整型数数组的指针:int (a)[10]*;
- g)一个指向函数的指针,该函数有一个整型参数并返回一个整型数:int (a)(int)*;
- h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数:int (a[10])(int)*;
- 以下程序执行到最后,j的值是:
int counter (int i)
{
static int count =0;
count = count +i;
return (count );
}
main()
{
int i , j;
for (i=0; i <=5; i++)
j = counter(i);
}
(a) 10 (b) 15
(c) 6 (d) 7
答案是:B
- 以下程序运行后,输出的结果是:
void f(char**);
main()
{
char * argv[] = { "ab" ,"cd" , "ef" ,"gh", "ij" ,"kl" };
f( argv );
}
void f( char **p )
{
char* t;
t= (p+= sizeof(int))[-1];
printf( "%s" , t);
}
(a) ab (b) cd
(c) ef (d) gh
答案是:B
- 以下程序运行后,输出的结果是:
void e(int );
main()
{
int a;
a=3;
e(a);
}
void e(int n)
{
if(n>0)
{
e(--n);
printf("%d" , n);
e(--n);
}
}
(a) 0 1 2 0 (b) 0 1 2 1
(c) 1 2 0 1 (d) 0 2 1 1
答案为:A.
- 以下程序运行后,输出的结果是:
void f1(int *, int);
void f2(int *, int);
void(*p[2]) ( int *, int);
main()
{
int a;
int b;
p[0] = f1;
p[1] = f2;
a=3;
b=5;
p[0](&a , b);
printf("%d\t %d\t" , a ,b);
p[1](&a , b);
printf("%d\t %d\t" , a ,b);
}
void f1( int* p , int q)
{
int tmp;
tmp =*p;
*p = q;
q= tmp;
}
void f2( int* p , int q)
{
int tmp;
tmp =*p;
*p = q;
q= tmp;
}
(a) 5 5 5 5 (b) 3 5 3 5
(c) 5 3 5 3 (d) 3 3 3 3
答案是:A。
- 以下这段程序运行后,输出的结果是:
void foo(int [][3] );
main()
{
int a [3][3]= { { 1,2,3} , { 4,5,6},{7,8,9}};
foo(a);
printf("%d" , a[2][1]);
}
void foo( int b[][3])
{
++ b;
b[1][1] =9;
}
(a) 8 (b) 9
(c) 7 (d)以上均不对
答案是:B。
- 以下这段程序运行后,输出的结果是:
main()
{
int a[5] = {1,2,3,4,5};
int *ptr = (int*)(&a+1);
printf("%d %d" , *(a+1), *(ptr-1) );
}
(a) 2 2 (b) 2 1
(c) 2 5 (d) 以上均不是
正确答案:C;
- 以下这3个函数哪一个最可能引起指针方面的问题:
int *f1(void)
{
int x =10;
return(&x);
}
int *f2(void)
{
int*ptr;
*ptr =10;
return ptr;
}
int *f3(void)
{
int *ptr;
ptr=(int*) malloc(sizeof(int));
return ptr;
}
(a) 只有 f3
(b) 只有f1 and f3
(c) 只有f1 and f2
(d) f1 f2 ,f3
答案:C
四、评论题(每题5分,共15分)
- C语言同意一些令人震惊的结构,请问下面的结构合法吗?如果合法,它是做什么?
int a = 5, b = 7, c;
c = a+++b;
答:是完全合乎语法的,根据“大嘴法”原则,上面代码被处理成:
c = a++ +b;
执行之后的结果为a = 6, b = 7, c = 12。
-
简述const、volatile、extern三个关键字的含义和用法。
-
中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展——让标准C支持中断。具代表事实是,产生了一个新的关键字__interrupt。下面代码就使用了__interrupt关键字去定义了一个中断服务程序(ISR),请评论一下这段代码存在的问题。
__interrupt double compute_area(double radius)
{
double area = PI*radius*radius;
printf(“Area = %f”,area);
return area;
}
答:上面的程序存在如下四点问题:
- 错误点1:中断服务程序是不能传递参数的,而此段代码带有参数radius;
- 错误点2:中断服务程序不能返回一个值,而此段代码返回了一个运算结果area;
- 错误点3:在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额外的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是很不明智的。
- 错误点4:与第3点类似,printf()经常有重入和性能上的问题。
其中1、2两点是基本的,3、4点比较难。
网友评论