嵌入式软件开发基础问题
- Linux
- 
- 驱动
 
- RTOS
- 
- μC/OS
 
- 外设
- 
- Uart
- CAN
- I2C
- I2S
- SPI
- USB
- SDIO
- DMA
 
- C / C++
- 
- 关键字
 
- 多线程编程
- 内存管理
- 
- 数据结构
 
- 计算机 络
- 单片机
- 
- 中断
- 硬件
- 开发
- CPU
 
- 工具
- 
- Keil
 
- 控制方法
- 
- PID
 
- 项目开发
- 非技术类常规问题
- 成套面试题
搜集整理了一波嵌入式软件开发岗位在面试过程中可能会问到的基础问题,方便自己在需要时查阅,现发布出来。
 大部分是摘录于已有的高浏览量文章并使用超链接注明参考和引用处,侵删。
问题主要引用自:
https://blog.nowcoder.net/n/418373944177428fb02ed05aae11ab4b
Linux
- 
Linux和Windows的换行符有什么不同/strong> 
 UNIX/Linux 使用的是 0x0A(LF)
 DOS/Windows 使用 的是0x0D0A(CRLF)
- 
Shell脚本及应用情况 
 Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务Shell 脚本(Shell Script),是一种为 Shell 编写的脚本程序 引用:Shell 教程 
- 
在不联 的电脑上,怎么找关于grep的用法/strong> 
 方法1:grep –help
 方法2:man grep(查询man page)
 方法3:info grep(查询info page)
- 
如何编译镜像/strong> 
 在 Linux 内核中增加程序需要完成以下三项工作:
 1)将编写的源代码复制到 Linux 内核源代码的相应目录
 2)在目录的 Kconfig 文件中增加新源代码对应项目的编译配置选项
 3)在目录的 Makefile 文件中增加对新源代码的编译条目引用:编译Linux内核并运行一个最小镜像 
- 
如何编译设备树/strong> 
 设备树包含DTC(device tree compiler),DTS(device tree source)和DTB(device tree blob)
 DTC编译器可以把DTS文件编译成为DTB
 make dtbs可单独编译DTB引用:Linux内核设备树及编译 
- 
怎么把编译的镜像放到板子上/strong> 
 NXP芯片使用MfgTool 烧写系统,烧写内容包括:
 1)移植编译出来的 uboot 可执行文件: u-boot.imx;
 2)移植编译出来的 zImage 镜像文件和开发板对应的.dtb(设备树);
 3)构建的根文件系统 rootfs
- 
Uboot的启动流程 
 第一阶段:主要是SOC内部的初始化,板级的初始化比较少,所以移植的修改量比较小。此阶段由汇编语言编写,代码主体分布在/uboot/cpu/s5pc11x/start.S和/uboot/board/samsung/x210/lowlevel_init.S中。
 第二阶段:主要是板级的初始化,SOC内部的初始化比较少,移植的修改量主要在此。此阶段由c语言编写,代码主体分布在/uboot/lib_arm/board.c中。
 
- 
key_report的底层实现 
 参考案例:Linux之解析鼠标input事件数据
- 
写一个key驱动,其中的中断函数怎么实现/strong> 
 参考代码:Linux驱动之按键驱动编写(中断方式)
RTOS
- 
各实时操作系统对比
 参考:uCOS、FreeRTOS、RTThread、RTX等RTOS的对比之特点
μC/OS
- 
μC/OS移植要点 
 移植与3部分内容有关:CPU、操作系统和板级硬件相关代码(BSP)
 μC/OS-III的移植工作包括四个内核相关文件(os_cpu.h、os_cpu_a.asm、os_cpu_a.inc和os_cpu_c.c)的代码编写或修改。
 移植工作还需要编写或修改三个CPU相关文件:cpu.h、cpu_a.asm和cpu_c.c。
 最后,用户需要针对所用的评估板或目标板编写或修改板级支持包(BSP)。
- 
μC/OS-III和μC/OS-II的区别 
 1)μC/OS-II是一个定位于8/16位以及低端32位CPU的RTOS内核,μC/OS-III则是定位于高端32位(及个别高端16位)CPU的RTOS内核;
 2)μC/OS-III同时支持优先级与时间片调度算法;
 3)μC/OS-III将中断级人物调度交给系统任务处理,缩短中断执行时间;
 4)μC/OS-III采用哈希散列表机制处理时钟街拍,真正做到了硬实时;
 5)μC/OS-III可直接向任务发信 量,简化了程序,提高了实时性;
 6)μC/OS-III支持的任务数理论上不受限制;
 7)μC/OS-III支持同优先级任务
- 
μC/OS如何避免优先级翻转 
 设置天花板优先级
 优先级继承参考:uCOS-II中任务的优先级翻转现象 
- 
优先级调度算法 
 非抢占式优先权调度算法
 抢占式优先权调度算法参考:优先级调度算法 
外设
Uart
- 
Uart怎么确定数据正确性/strong> 
 硬件上:
 改变其对0电位以及1电位的定义,吸收差分信 的优点做改进。对于差模信 改怎么抑制的问题,可以吸收类似NEC码的方式,给0与1信 一个容差时间,存在较大的差模信 存在的情况下,对电平的传输也影响不大。软件上: 
 采取固定帧头帧尾+数据码正反码+CRC校验的方式。事实上一般的通信增加正反码固定帧头帧尾的方式已经很稳定了。只是在其基础上对数据进行了一个二次保险而已。引用:UART怎样保证数据的实时性与可靠性 
- 
RS232、RS485、RS422、串口的区别 
 参考:详解RS232、RS485、RS422、串口和握手
CAN
- 
CAN通讯简介 
 Controller Area Network
 CAN 控制器根据两根线上的电位差来判断总线电平。总线电平分为显性电平(0)和隐性电平(1)。发送方通过使总线电平发生变化,将消息发送给接收方
- 
CAN协议特点 
 1)多主控制.在总线空闲时,所有单元都可以发送消息(多主控制),而两个以上的单元同时开始发送消息时,根据标识符(Identifier 以下称为 ID)决定优先级
 2)系统的若软性。与总线相连的单元没有类似于“地址”的信息
 3)通信速度较快,通信距离远。最高1Mbps(距离小于40M),最远可达10KM(速率低于5Kbps)
 4)具有错误检测、错误通知和错误恢复功能
 5)故障封闭功能。CAN 可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部故障、驱动器故障、断线等)
 6)连接节点多。CAN 总线是可同时连接多个单元的总线,可连接的单元总数理论上是没有限制的引用:CAN通信详解 
I2C
- 
I2C通信协议通信信 
 起始信
 终止信
 写数据
 读数据
 应答信
 非应答信参考:对 IIC 总线的理解、调用函数以及常见面试问题 
- 
I2C设备的地址多少位/strong> 
 I2C 协议规定设备地址可以是 7 位或 10 位,实际中 7 位的地址应用比较广泛。
- 
I2C读写时序 
 写时序:
 开始信 →主机+从设备地址+写命令→从机应答→主机+设备内部寄存器地址→从机应答→主机写入数据→从机应答→是否继续发送,不发送的话,发送停止信 P读时序: 
 开始信 →主机+从设备地址+写命令→从机应答→主机+设备内部寄存器地址→从机应答→主机+写入从机地址+读命令→从机应答→从设备将数据放入到SDA上,主机读取数据引用:I2C读写时序 
- 
I2C的特点、速度/strong> 
 特点:
 1)简单性、有效性
 2)支持多主控速度: 
 最高传送速率100kbps引用:I2C特点 
- 
项目开发用的软件I2C还是硬件的么考虑的件I2C和硬件I2C有什么异同/strong> 
 硬件I2C:
 对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的软件I2C: 
 一般是用GPIO管脚,用软件控制管脚状态以模拟I2C通信波形异同: 
 1)硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活
 2)硬件I2C用法比较复杂,软件I2C的流程更清楚一些
 3)硬件I2C速度比软件I2C快,并且可以用DMA
 4)软件I2C可以在任何管脚上,而硬件I2C只能在固定管脚上
 5)软件I2C模拟协议的时序,一般较硬件I2C稳定引用:硬件I2C和软件I2C的区别 
I2S
- 
I2S简介 
 I2S(Inter—IC Sound)总线, 又称集成电路内置音频总线,是飞利浦公司为数字音频设备之间的音频数据传输而制定的一种总线标准,该总线专门用于音频设备之间的数据传输,广泛应用于各种多媒体系统。它采用了沿独立的导线传输时钟与数据信 的设计,通过将数据和时钟信 分离,避免了因时差诱发的失真,为用户节省了购买抵抗音频抖动的专业设备的费用。
- 
I2S特点 
 1)支持全双工/半双工
 2)支持主/从模式
 3)和PCM相比,I2S更适合立体声系统。I2S的变体也支持多通道的时分复用,因此可以支持多声道。
- 
I2S三个主要信 
 1)串行始终SCLK,也叫位始终(BCLK),对应数字音频的每一位数据,SCLK都有一个脉冲。SCLK的频率=2 * 采样频率 * 采样位深。
 2)帧时钟LRCK(也称WS),用于切换左右声道的数据。LRCK为‘1’表示传输右声道数据,为“0”则是左声道。LRCK的频率 = 采样频率
 3)串行数据(SDATA),就是用二进制补码表示的音频数据,(MSB —> LSB:数据由高位到低位依次传输)
 4)一般还有MCLK,主时钟。引用:I2S协议详解 
SPI
- 
SPI简介 
 Serial Peripheral interface 串行外围设备接口
 SPI是Motorola首先在其MC68HCXX系列处理器上定义的
 SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信 处理器和数字信 解码器之间
 SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线引用:SPI详细解释 
USB
- 
给USB等IO设备等写数据的过程
 参考:USB协议基本知识
 参考:USB协议简介
SDIO
- 
SDIO协议概述 
 Secure Digital Input and Output ,即安全数字输入输出接口
- 
SDIO特点 
 1)与多媒体卡系统规格书版本4.2全兼容。支持三种不同的数据总线模式:1位(默认)、4位和8位
 2)与较早的多媒体卡系统规格版本全兼容(向前兼容)
 3)与SD存储卡规格版本2.0全兼容
 4)与SD I/O卡规格版本2.0全兼容:支持两种不同的数据总线模式:1位(默认)和4位
 5)完全支持CE-ATA功能(与CE-ATA数字协议版本1.1全兼容)。 8位总线模式下数据传输速率可达48MHz
 6)数据和命令输出使能信 ,用于控制外部双向驱动器引用:SDIO协议 
DMA
- 
DMA概述 
 Direct Memory Access,即直接存储器访问。
 DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输
- 
DMA定义 
 DMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。节省了CPU的资源来做其他操作
- 
DMA传输方式 
 主要涉及四种情况的数据传输:
 1)外设到内存
 2)内存到外设
 3)内存到内存
 4)外设到外设
- 
DMA传输参数 
 1)数据的源地址
 2)数据传输位置的目标地址
 3)传递数据多少的数据传输量
 4)进行多少次传输的传输模式引用:DMA原理 
C / C++
- 
宏函数定义写一个交换数据,不用temp 参考:宏定义swap(x, y) 实现任何数据类型交换 
- 
宏定义写循环 参考:定义一个循环的 loop 宏方法 
- 
一个.c文件从编写到运行到开发板上的整个过程 
 预处理 → 编译 → 汇编 → 链接
 参考:一个C语言程序到执行完文件的全过程
- 
怎么理解C++的封装、继承、多态/strong> 
 封装:可以隐藏实现细节,使得代码模块化 —— 代码重用
 继承:可以扩展已存在的代码模块(类) —— 代码重用
 多态:允许将父对象设置成和一个或更多的他的子对象相等的技术 —— 接口重用
 引用:C++封装、继承、多态
- 
fgets等读取文件的函数 
 引用:fgets函数及其用法,C语言fgets函数详解
- 
open函数传入什么参数么模式数怎么写/strong> open函数具体使用那个,和具体应用场景相关,如目标文件存在,使用两个参数的open,如果目标文件不存在,需要open创建,则第三个参数表示创建文件的默认权限 引用:open函数详解与close函数详解 
- 
C语言标准函数库 
 引用:C语言标准库函数大全(ctype、time 、stdio、stdlib、math、string)
- 
C语言程序代码优化方法 
 1)选择合适的算法和数据结构
 2)使用尽量小的数据类型
 3)使用自加、自减指令
 4)减少运算的强度
 求余运算(a=a%8改为a=a&7)
 平方运算(a=pow(a,2.0)改为a=a*a)
 用移位实现乘除法运算
 5)延时函数的自加改为自减
 6)switch语句中根据发生频率来进行case排序引用:嵌入式面试题 
关键字
- 
volatile 
 作用:
 volatile 的作用 是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值
 volatile 可以保证对特殊地址的稳定访问使用场景: 
 1)并行设备的硬件寄存器(如:状态寄存器)
 2)一个中断服务子程序中会访问到的非自动变量
 3)多线程应用中被几个任务共享的变量引用:C语言关键字volatile详解 
- 
const 
 作用:
 1)const修饰全局/局部变量:
 限定全局变量的作用范围到其定义时所在的编译单元;
 指定了一个语义约束,即被修饰的全局变量不允许被修改,编译器会强制实施这个约束
 2)constant修饰指针3)const修饰函数参数 
 防止函数体内可能会修改参数原始对象
 4)const修饰函数返回值
 令函数返回一个常量,可以有效防止因用户错误造成的意外引用:C++ const关键字的总结 
- 
inline 
 作用
 解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题
 使用inline修饰符,表示为内联函数inline使用限制 
 inline只适合函数体内代码简单的涵数使用
 不能包含复杂的结构控制语句例如while、switch
 内联函数本身不能是直接递归函数(即,自己内部还调用自己的函数)inline仅是一个对编译器的建议 
 inline函数仅仅是一个对编译器的建议,最后能否真正内联,由编译器决定
 编译器如果认为函数不复杂,能在调用点展开,就会真正内联,并不是说声明了内联就会内联,声明内联只是一个建议而已建议:inline函数的定义放在头文件中 
 内联函数要在调用点展开,所以编译器必须随处可见内联函数的定义,这要求每个调用了内联函数的文件都出现了该内联函数的定义。
 因此,将内联函数的定义放在头文件里实现是合适的inline 是一种“用于实现的关键字” 
 关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用引用:C语言 – inline关键字的用法详解 
多线程编程
- 
怎样进行多线程多进程编程/strong> 
 并发技术,就是在同一时间同时执行多条任务的技术
 引用:多线程和多进程的区别
 参考:多线程与多进程
- 
进程和线程的区别/strong> 
 进程是资源分配的基本单位;
 线程是程序执行和调度的最小单位
 参考:线程和进程有什么区别
- 
生产者消费者模型,伪代码/思路 
  
 引用:生产者消费者模型—详解及代码实现
- 
父进程和子进程的区别/strong> 
 子进程是父进程的复制品,两个进程各自有自己的地址空间
 父进程先执行fork()系统调用,调用的结果是系统中多出了一个跟父进程内容完全一样的进程,这个新进程被称为子进程
 再执行exec(B )系统调用,这个调用可以让当前进程转而执行另一个可执行代码(一个新的程序)
 在父进程中可以使用子进程的进程ID(在执行fork()时的返回值中得到)来中止子进程的执行
 在fork之后,父进程先执行,一个时间片到达之后再执行子进程引用:父进程和子进程 
- 
死锁产生的条件及规避方法 
 产生死锁的4个条件
 1)互斥条件;
 2)请求和保持条件;
 3)不剥夺条件;
 4)环路等待条件。规避死锁的方法 
 1)破坏请求条件:资源一次性分配,确保不会再有请求;
 2)破坏保持条件:只要有一个资源得不到分配,也不给这个进程分配其他的资源;
 3)破坏不可剥夺条件:当某进程获得了部分资源,但得不到其它资源,则释放已占有的资源;
 4)破坏环路等待条件:资源有序分配法,每一个进程按编 递增的顺序请求资源,释放则相反引用:死锁面试题 
- 
线程的同步互斥 
 同步:
 是指散布在不同任务之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。最基本的场景就是:两个或两个以上的进程或线程在运行过程中协同步调,按预定的先后次序运行。比如 A 任务的运行依赖于 B 任务产生的数据。
 互斥:
 是指散布在不同任务之间的若干程序片断,当某个任务运行其中一个程序片段时,其它任务就不能运行它们之中的任一程序片段,只能等到该任务运行完这个程序片段后才可以运行。最基本的场景就是:一个公共资源同一时刻只能被一个进程或线程使用,多个进程或线程不能同时使用公共资源引用:多线程的同步与互斥(互斥锁、条件变量、读写锁、自旋锁、信 量) 
- 
并发编程 
 参考:并发编程面试题
- 
进程间通信方式 
 1)管道;
 2)命名管道;
 3)消息队列;
 4)共享内存;
 5)信声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!