嵌入式面试题(一):2014大疆

一:编程基础

1、有如下CAT_s结构体定义,回答:

struct CAT_s{
int ld;
char Color;
unsigned short Age;
char *Name;
void(*Jump)(void);
}Garfield;

1)在一台64位的机器上,使用32位编译,Garfield 变量占用多少内存空间?64位编译又是如何?(总分5分)
答案:
考点—>字节对齐
32位系统以4字节对齐,该结构体占16个字节;64位系统以8字节对齐,该结构体占24个字节。结构体里面不同类型参数的排序不同会影响结构体的大小。

在这里插入图片描述
在这里插入图片描述
2) 使用32位编译情况下,给出一种判断所使用机器大小端的方法。(总分5分)
在这里插入图片描述

判断方法:利用union结构体的从低地址开始存,且同一时间内只有一个成员占有内存的特性。大端储存符合阅读习惯。

#include <stdio.h>
int Check_sys()
{
   #数据高位是c,低位是i
    union Un
    {
        char c;
        int i;
    }un;
    un.i = 1;
    return un.c;
}
int main()
{
    int ret=Check_sys();   
    if (1 == ret)  printf("当前模式为小端存储\n");
    else           printf("当前模式为大端存储\n");
    return 0;
}

2、描述下面XXX 这个宏的作用。(总分10分)

#define offsetof(TYPE,MEMBER)((size_t)&((TYPE*)0)->MEMBER)
#define XXX(ptr,type,member({\
const typeof(((type*)0)->member)*__mptr=(ptr);\
(type*)(char*)__mptr – offsetof(type,member));})

答案:

#define offsetof(TYPE,MEMBER)((size_t)&((TYPE*)0)->MEMBER)
  • (TYPE*)0:将0强转为TYPE类型的指针,且指向了0地址空间;
  • (TYPE*)0->MEMEBER:指向结构体中的成员;
  • &((TYPE*)0->MEMBER):获取成员在结构体的位置,因为起始为0,所以获取的地址即为实际的偏移地址
#define XXX(ptr,type,member) ({\
    const typeof(((type*)0)->member) *__mptr=(ptr);\
    (type*)((char*)__mptr – offsetof(type,member));})
  • typeof构造的主要应用是用在宏定义中。可以使用typeof关键字来引用宏参
  • 数的类型。也就是说,typeof(((type*)0)->member)是引用与type结构体的member成员的数据类型;
  • 获得了数据类型之后,定义一个与type结构体的member成员相同的类型的指针变量__mptr,且将ptr值赋给它;
  • 用宏offsetof(type,member),获取member成员在type结构中的偏移量;
    最后将__mptr值减去这个偏移量,就得到这个结构变量的地址了(亦指针)。
    总体思路:ptr是指向正被使用的某类型变量指针;type是包含ptr指向的变量类型的结构类型;member是type结构体中的成员,类型与ptr指向的变量类型一样。功能是计算返回包含ptr指向的变量所在的type类型结构变量的指针

3、简述C 函数:1) 参数如何传递(__cdecl调用方式);2) 返回值如何传递;3) 调用后如何 返回到调用前的下一条指令执行。(总分10分)
答案:

1)
__cdecl:C Declaration的缩写,C的默认调用方法。
__stdcall:StandardCall的缩写,C++的默认调用方式。
在这里插入图片描述
2)
设返回值大小为M字节:

  • M <= 4,将返回值存储在eax返回;
  • 4 < M <=8,把eax,edx联合起来。其中,edx存储高位,eax存储低位;
  • M >8,使用一个临时的栈上内存作为中转,结果返回值对象会被拷贝两次。整个过程使用的是指向返回值的指针来进行拷贝的,而指针本身是通过eax返回的

3)C语言通过硬件栈保存函数的返回地址,被调用函数将返回地址出栈到程序计数器PC中,以返回到调用点。

4、在一个多任务嵌入式系统中,有一个CPU 可直接寻址的32位寄存器REGn ,地址为 0x1F000010,编写一个安全的函数,将寄存器REGn 的指定位反转(要求保持其他bit 的值不变)。(总分10分)
答案:
异或运算。

void bit_reverse(uint32_t nbit)
{
    *((volatile unsigned int *)0x1F000010) ^= (0x01 << nbit);
}

5、有10000个正整数,每个数的取值范围均在1到1000之间,变成找出从小到大排在第 3400(从0开始算起)的那个数,将此数的值返回,要求不使用排序实现。(总分10分)
答案:计算不同整数值对应的整数个数

#include <iostream>
using namespace std;
 
#define TOTAL 10000
#define RANGE 1000
#define REQUIRED 3400
 
int main()
{
	int number[TOTAL] = { 0 };
	int count[RANGE] = { 0 };
	int i, sum = 0;
 
	for (i = 0; i < 10000; i++) {
		number[i] = (rand() % 1000) + 1;		/*产生10000个1-1000之间的随机数*/
	}
 
	for (i = 0; i < 10000; i++) {
		count[number[i] - 1]++;				/*计算10000个整数出现次数*/
	}
 
	for (i = 0; i < 1000; i++) {
		sum += count[i];
		if (sum >= REQUIRED + 1) {
			cout << i + 1 << endl;
			break;
		}
	}
 
	return 0;
}
二.嵌入式基本知识

简述处理器中断处理的过程(中断向量、中断保护现场、中断嵌套、中断返回等)。(总 分10分)
答案:
中断向量:
中断服务程序的入口地址
中断嵌套:
中断系统正在执行一个中断服务时,有另一个优先级更高的中断提出中断请求,这时会暂时终止当前正在执行的级别较低的中断源的服务程序,去处理级别更高的中断源,待处理完毕,再返回到被中断了的中断服务程序继续执行
保护现场:主程序和中断服务子程序都要使用CPU内部寄存器等资源,为使中断处理程序不破坏主程序中寄存器的内容,应先将断点处各寄存器的内容压入堆栈保护起来,再进入的中断中断返回过程如下:首先恢复原保留寄存器的内容和标志位的状态,这称为恢复现场
中断返回:
由用户编程完成。然后,再加返回指令RETI,RETI指令的功能是恢复PC值,使CPU返回断点,这称为恢复断点。恢复现场和断点后,CPU将继续执行原主程序,中断响应过程到此为止处理。现场保护是由用户使用PUSH指令来实现的。
恢复现场:
当中断处理完毕后,用户通过POP指令将保存在堆栈中的各个寄存器的内容弹出,即恢复主程序断点处寄存器的原值。
中断服务:
中断服务是执行中断的主体部分,不同的中断请求,有各自不同的中断服务内容,需要根据中断源所要完成的功能,事先编写相应的中断服务子程序存入内存,等待中断请求响应后调用执行

简述处理器在读内存的过程中,CPU 核、cache 、MMU 如何协同工作?画出CPU 核、 cache 、MMU 、内存之间的关系示意图加以说明(可以以你熟悉的处理器为例)。(总分10分)

三.基本通信知识

请说明总线接口USRT 、I2C 、USB 的异同点(串/并、速度、全/半双工、总线拓扑等)。 (总分5分)
列举你所知道的linux 内核态和用户态之间的通信方式并给出你认为效率最高的方式, 说明理由。(总分5分)

四.系统设计

有一个使用UART 进行通信的子系统X ,其中UART0进行数据包接收和回复,UART1进行数据包转发。子系统X 的通信模块职责是从UART0接收数据包,如果为本地数据包(receiver 为子系统X ),则解析数据包中的命令码(2字节)和数据域(0~128字节),根据命令码调用内部的处理程序,并将处理结果通过UART0回复给发送端,如果非本地数据包,则通过UART1转发。
如果由你来设计子系统X 的通信模块:

  1. 请设计通信数据包格式,并说明各字段的定义;(总分5分)
  2. 在一个实时操作系统中,你会如何部署模块中的任务和缓存数据,画出任务间的数据流
    视图加以说明;(总分5分)
  3. 你会如何设置任务的优先级,说说优缺点;(总分5分)
  4. 如果将命令码对应的处理优先级分为高、低两个等级,你又会如何设计;(总分5分)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值