导读:本篇笔记将总结关于嵌入式软件面试的一些东西,东西太多,不会全部展开,仅做个人总结之用,各位道友也可参考参考。
首先说个大概的,嵌入式软件需要掌握什么东西?
1) 对单片机的熟悉程度(包括中断系统、各种外设模块、时钟系统等)
2) 对通信协议的熟悉程度(常见的有SPI、UART、I2C等)
3) 掌握基本的数据结构(如队列、栈、链表)
4) 掌握基本的算法(多种排序算法,数据结构中需要的一些算法)
其实嵌入式的东西很庞杂,不是一下子就能说清的,只能想到哪写到哪了。
对单片机的熟悉程度,这个就要考你的基本功了,比如单片机运行到main函数之前做了什么(首先是从启动文件的复位中断进入,然后初始化时钟,进入main函数之前还得初始化一些全局变量)?单片机的中断机制是怎样的(这个和向量表有很大关系)?固件升级原理(一份BootLoader程序,一份APP,这个其实不难,鱼鹰有专门的笔记讲述,如果你的简历没有写这个的话可能不会问这个,
STM32固件升级之基础知识(一)
)?是否使用过DMA,原理是什么(DMA传输方式,怎么设置,
数据传输还用 CPU?不如交给 DMA 吧!
)?
通信协议的话,主要不是上层的通信协议,而是物理层面的通信协议,比如串口通信需要掌握一帧格式(起始位、数据域、奇偶校验位、停止位等);SPI通信的四种模式,你又是如何确定使用哪种模式的?I2C通信格式(起始信号、结束信号、应答信号等)?如果说你学过USB,可能会问你USB采用什么编码、有几种端点模式、简单介绍枚举过程(但也别太简单)?更高级的可能问你关于网络这块的知识(具体鱼鹰也不知道,因为还没系统学过,这里推荐《TCP/IP详解》)
数据结构,比如最常接触的栈、队列、链表(单向、多向链表)的原理,而数据结构肯定会涉及到一些算法操作,比如出栈、入栈;出队、入队;插入、删除等操作,而比较纯粹的算法是排序算法,其中有冒泡算法、快速排序算法等(这里推荐《大话数据结构》),注意这些知识常以笔试形式出现,所以一定要能写出来(关于笔试推荐《剑指Offer》)。
鱼鹰最弱的应该是笔试了,或者说算法。在嵌入式软件开发过程中,用到的算法其实并不多,但是要你自己用笔写出来还是有很大的难度的,鱼鹰这方面的能力确实欠缺,因为我一般喜欢深入理解思考后就把细节记录下来,然后选择遗忘的(遗忘不是说全部不记得了,而是说只记得大概,细节记不住而已),所以说面试前不来个系统的刷题,临时抱佛脚一下,基本笔试是没戏的。
但是笔试成绩我觉得只是一个方面,一般来说笔试之后会有面试(社招一般笔试、面试紧邻的,校招的话如果你的笔试成绩不合格,那么连面试资格都没有),所以如果笔试成绩不理想的话,一定要好好准备面试(这里插一句,面试前,一定一定要上网查找公司的背景信息,起码要知道公司是做什么产品的,鱼鹰就在这里吃了一个亏,之前对这个不重视,有的公司查过,有的公司没查过,刚好没查过的公司突然就问到这个问题,很尴尬,因为这体现了你对这次面试的尊重,而不是在浪费面试官的时间)。面试的话,就随你发挥了,只要你对自己的技术有信心,那么面试应该不会太难,一般来说,面试官问的都是简历上的东西,所以简历的内容不要造假,否则回答不出来就麻烦了。
现在就来具体聊聊几个一般人不知道的知识:
01、你是怎么接收、发送串口数据的?
这个问题其实比较宽泛,一般经验少的会说使用查询方式,但是查询方式效率是非常低下的,所以如果你只能回答这个,100分的题你只能得个30分。如果你说用中断方式,那么请问你具体是如何处理的?如果你回答说一个字节接收完之后再接收下一个字节,那么可以得个50分。
紧接着又问你,你是怎么接收一帧数据的(这个其实不应该由面试官问,而是由你自己补充全面),如果你说采用帧头、帧尾判断的方式接收的,那么这道题还是给你50分,但是你说用空闲中断,那么70分以上,如果你说用DMA+空闲中断的方式接收的,那么90分以上(这是我认为最好的方式了,可能会有其他更好的方式也说不定)。
那么现在说说空闲中断,为什么你说了空闲中断之后,一下子从不及格到及格了?
空闲中断,顾名思义,就是串口空闲后产生的中断。我们都知道,数据一般是按照数据帧来发送的,即一个数据帧一个数据帧的发送,如果两帧发送之间能间隔一段时间,那么在接收端就可以产生空闲中断(关于这个空闲中断,以后可能会专门写一篇笔记介绍),有了空闲中断有什么好处?
1) 可以接收不定长数据(这是最明显的好处)
2) 不需要复杂的帧格式(比如帧头、帧尾可以不要)
3) 一个数据帧接收错误,不会影响到下一帧数据的接收
有了空闲中断,可谓好处多多(有的单片机没有空闲中断,那就没办法,当然也可以舍弃一个定时器资源来获得空闲中断的效果),所以当初了解到这个之后,就一直使用这种方式接收了。
但是空闲中断虽好,如果你每接收一个字节都要CPU干预,还是效率太低,那么这时候就得配合DMA了。
怎么配合?比如说你一个数据帧的最大长度是10个字节,设置串口接收缓存区为20个字节,那么你可以设置DMA传输长度为20,这样DMA每从串口传输一个字节,传输长度就会自减,当产生空闲中断时,只要你知道开始设置的传输长度和剩余的传输长度,那么就可以得到你已经接收的数据长度,之后你再重新设置新的接收长度即可进行下一次数据帧的接收。
如此一来,接收一个数据帧只要CPU干预一次就够了,就是在接收完数据帧的时候由空闲中断通知CPU进行后续处理即可(注意不是DMA中断),极大的减少了CPU工作时间。
有的时候,数据量很大,CPU来不及处理,那么你可以通过以下方式解决:
1) 增加消息队列(非常好的解决方式)
2) 增加两帧之间的发送时间(对于实时性要求很高的可能不合适)
3) 前面两种方式叠加
02、LCD显示屏上的按键有多种触发方式,比如触摸、实体按键,以后还可能增加其他方式,你会怎么设计结构,让其兼容适应不同的环境?
如果是你,你会怎么考虑?
鱼鹰当初的答案是:软件层次上设计三层。
第一层:和硬件底层驱动相关的
第二层:中间层,负责对接底层驱动和上层应用
第三层:上层调用接口
这个答案我不知道到底好不好,但就以我现有的知识介绍吧。
一般开发人员的软件设计只有第一层和第三层(即应用层直接访问底层函数),很少有第二层,事实上设计第二层很有必要,为什么这么说呢,就像题目所说的,一旦你将触摸换成了按键,那么所有用到这个按键程序的地方,你都得进行修改,虽然不是很难,但是也麻烦,并且增加了出错的可能性,但是有了中间层就不一样了,你只要修改这个中间层的代码就可以了,你的应用层根本不需要修改。所以中间层的设计很关键,要尽可能的把关键信息抽象化,这样才不会导致明明已经设计了中间层,还是免不了大面积修改,那么就得不偿失了(这里的中间层可以使用函数指针或者使用一个函数封装一个底层函数,而你的函数(指针)原型就得好好考虑清楚了)。
03、FIFO队列中,有一个后面接收的数据,但是想让它更快处理,应该怎么办?
FIFO队列的特点就是先进先出,为什么这个问题反着来?既然你都是顺序处理了,为啥你还要插队?但是实际上确实可能出现插队的情况,那该怎么办?这个问题如果是以前的自己可能回答不出来,但是当鱼鹰把uCOS II 源码看了个遍之后,就知道该怎么做了。
uCOS II的消息队列的源码中,有个函数的选项,就可以选择你插入队列的数据放在队头还是队尾。按照队列的特点,肯定是要插入到队尾的,但是题目要求更快处理,那么插入到队头是最好的方式,所以这个问题的答案是,将数据插入到队头,这样既可保持队列的特性,又能处理一些紧急的消息,一举两得。
从这里也可以知道,阅读源码虽然看似费时费力,但是对你的思想、思维是有很大拓展意义的,与其停留在表明不明所以,遇到操作系统问题到处问人,不如静下心来好好看看源码,对你的技术水平是会有很大的提高的。
|