嵌入式

找工作也是一门技能,有的人很快就找到自己喜欢的工作,有的人找了很久也没找到合适的工作。

下面给大家分享几点找工作过程中存在的“潜规则”内容。

1、面试的本质不是考试,而是告诉面试官你会做什么

经验不够的小伙伴特别容易犯的一个错误,不清楚面试官到底想问什么,其实整个面试中面试官并没有想难倒你的意思,只是想通过提问的方式来知道你会什么。

比如STM32单片机的代码从哪里开始执行?
没入门的说从main函数开始,大佬会从上电启动开始。

围绕着一个话题只要你能在某一方面回答得很深入很透彻,基本上面上的可能性会大大提高;

如果当你听到这个话题时,感觉不知道如何回答,或者说感觉很简单,几句话就说完了,那么基本上你很难面上,因为你的知识储备不够,说不出来关于技术相关的内容。

2、薪水要求高一点录取概率就大一点

我曾经面试一个嵌入式工程师,各种精通C语言,精通stm32等等等,然后我就问他你期望的薪水是多少呢?

他的回答是4K,先不说他简历上写的是真是假,但是有一点很明确,如果你在市场上去肉,别人都是卖30元一斤,而路边有个摆摊的只买10元一斤,那么你们会去买么?

另外,我想告诉大家的是,一般来说对于一家正规的技术型公司,真的不在乎多给工资,最重要的是人才;

或者我们换位思考一下,假设你是项目经理,你来招人帮你干事情,你会节约一点工资,去招技术差的,帮老板节约成本,自己慢慢来带人么,给自己找一大堆事情么?

而且,从心里角度来说,人们一般只会集中精力关注一个点,如果你的期望薪水高一点,那么他在考虑是否录取你时考虑的就是薪水问题,或者就是考虑你的技术问题,但是工资是老板发,技术是自己使用,所以从某方面来说如果有几个人与你技术差不多,但是从潜意识里,就会因为你的期望工资高而觉得你的技术好一点,最后录取你,这就像假设我们要求买一件羽绒衣服,同时看上了两件,一件800元,另一件1000元,我相信大多数人都会认为1000元这件质量好点,如果再加上买这件衣服的钱不是你出,那么你会选择那件呢?

最后提醒大家,期望薪水高一点并不是说无边界,那么到底多少合适呢?

可以从两个方面考虑一是工作年限,一般来说

初入行:8K到12K
1年到2年:10K到15K
3年到5年:13K到22K
5年以上:18K以上

当然,不同的地区有点差别,但差别应该不大

另一个方面是参考大公司的工资标准,打开招聘信息,查看大公司的招聘信息,一般来说都是给的一个区间值,你可以把区间值最大的那个值乘80%作为你的期望薪资的参考值。

3、简历上罗列了很多技能的很难面上

这里我就简单说一下为什么,简历上罗列很多技能可以反映如下几个问题:

1.不清楚对应岗位工程师的核心技术是什么,给面试官的第一感觉就是:外行;

2.罗列的技能越多面试官问的方向就越多,你很难每一样都精通,最后会成为问的每一个技能你都只会点皮毛;

3.完全暴露出你没有任何工作经验,我见过有的把熟练使用办公软件、外语等级、计算机二级什么的都写在上面;

那面试技能这里到底应该怎样写呢?从个人经验和及面试反馈来看,个人建议如下:

1.写两个精通或者深入研究的技术点,如:熟练某款MCU,有多个某平台项目实战等;

2.写三个熟练应用,这个最好写常用的框架;

3.写三个了解并能简单使用的技能;

总之技能这一栏要在潜意识里引导面试官去问你你已经准备好的话题;

4、笔试题做不来影响并不大,关键是要体现出你在认真对待

首先大家要明白一点的就是,在你认真对待笔试题的情况下,笔试题做得好与不好、正确与错误其实影响并不大,注意我这里说的是认真对待的情况下。

这一点估计没有多年工作经验或没有带过团队开发的人很难理解,其实大部分面试官招人重点看如下3点:

1.是否聊得来
2.主观能动性
3.逻辑思维注意:

我这里并不是没有任何基础的人具备上述三点就能面试,而是指已经基本会编程的情况下满足上述三点就很容易面试上;

5、对自己要自信,面试官只是比你早到公司几个月而已

首先强调一点,对自己自信,并不是不尊重面试官;

这里主要表达的核心思想是,在整个面试中你要让人感到你和面试官是平等的,面试官在挑选你,你也在挑选公司;

6、不写假简历,但必须扬长避短

其实这就是里我们常常说的如何包装简历,老老实实总是会吃亏的;诚实守信、不写假简历这是最基本的职业道德;

但是,扬长避短,适当的夸张一下自己的能力是很有必要的,这就如同一家公司在对外宣传自己的产品是一个道理;

好了,这一点我也不好在公开场合长篇大论,先具体、实际的了解情况,然后在根据实际情况包装简历;

7、老板是人精,谈理想时,别虚伪,要坦诚

这里一般是面试的最后一个环节,你一定要让人感觉你是一个真诚、实干的技术员,千万不能让人感觉你是一个浮躁、眼高手低的人;

8、不打没有把握的仗,必须充分准备

这是面试是否顺利非常非常重要的一个环节,也是很多浮躁的最容易犯的错误。

它的核心思想其实就是:面试必须系统化的认真的准备!

怎样系统化的认真的准备呢?

以下7个步骤是在我实际经验中总结出来的,提供给大家参考

1.最基本条件,概念上一定要懂的一些知识和技能。

2.系统化的知识点,对知识点系统化的梳理和系统化的看面试题,并且强行将知识点划分为3类,精通、熟练、了解,千万别东看一下西弄一下,最后会让你浮躁的心直接在面试中崩溃掉。

3.写简历,简历中必须在醒目的位置体现出技术点(hr就认几个关键词,决定是否通知你面试),如果投递出去的简历面试邀请率低于60%,肯定是简历写得有问题,最好找专业人士帮你看看简历。

4.模拟面试(三次),提高面试通过率。面试的成本其实挺高的,好不容易收到面试通知,千辛万苦赶车找路来。

到面试的地方,如果犯了常规的低级错误,其实很不划算,早一天找到工作就早一天赚到钱(程序员的工资平均在500左右一天)

5.实战学习面试(5次实战面试),出去面试,但目的不是为了面上,而是为了让你放松心情,不紧张,习惯与面试官进行技术沟通(其实很多人在这个阶段就会拿到offer)

面试完后马上回忆并记录面试中问了那些问题,自己大体是怎么回答的,然后与专业人士讨论这样回答是否恰当,必须保证下次遇到类似问题会回答得更好,否则面试很多次也不会有提高,因为在你回答得不好或者明显错误的地方面试官并不会给你指出来,这就是为什么,很多人出去面试说自己回答得很好,然后就让他等通知,然后。。。就没有然后了

6.正式面试,同样,每面试一次后马上与专业人沟通,最后你会发现每个面试官问的问题都大同小异,你会觉得面试so easy!当你拿到多个offer后,然后从中选一个,那感觉简直就像走上了人生巅峰!

7.通过试用期,虽然都说面试造飞机、工作拧螺丝,但是估计对于刚入行的人来说,还是有很多的技术没有接触或者不懂,这时不懂的一定要多问,业务上的多问同事,技术上的要先自己研究一下,如果还是不懂就要多请教专业的人,实在不懂再问同事,总而言之言而总之一定要积极主动!

9、选择大于努力的前提是先足够的努力才会有选择

很多人都在倡导选择大于努力,可更重要的往往更容易被忽略,那就是:只有足够的努力才会有选择。

这就形成了一个死循环,或者用我们程序员术语叫做:死锁,选择一家好的公司上班,对自己的发展前景很重要,但前提是你能拿到好公司的offer!

10、人生苦短,绝不将就,必须去自己真心想去的公司

我遇到过很多人,在跟他们聊天时,他们都有类似的心理:一点都不想在这里上班,但是工作又不好找,只好暂时做着,这一做就是好几年;每天带着一种不愿意的心情上班,是何种的煎熬,而且我相信也很难作出卓越的成绩,最多勉强把工作完成,这样做下去意义又何在!

参考来源:
https://www.cnblogs.com/newAndHui/p/12451882.html

本文转载自:网络
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 28

什么是eUSB2?

嵌入式USB2 (eUSB2) 规格是对USB 2.0规格的补充,前者通过支持USB 2.0接口在1V或1.2V而不是3.3V的I/O电压下工作,解决了接口控制器与高级片上系统 (SoC)工艺节点集成的相关问题。eUSB2 可让SoC体积更小、更节能,从而使工艺节点继续扩展,并提高在智能手机、平板电脑和笔记本电脑等应用中的性能。

eUSB2的重要性

随着智能手机和平板电脑等应用的尺寸越来越小、但组装元件越来越多,缩减接口尺寸也变得尤为重要。然而,不断缩减的SoC节点尺寸导致栅极氧化层越来越薄,只能支持更低的电压。对于使用USB 2.0接口的器件,上述趋势会给高级工艺节点的设计带来复杂的挑战。

当工艺节点达到7nm时,量子效应开始影响高信号电压(如3.3V)的输入与输出 (I/O),而且输入与输出将不再能够轻松地得到设备支持。许多设备到设备的接口已经支持低信号电压,但USB 2.0仍需要3.3V的I/O电压才能工作。为解决这一难题,USB开发者论坛 在2018年发布了eUSB2 规格。

USB 2.0和eUSB2的区别

USB 2.0有线接口在过去20年曾风靡一时,几乎现在所有的SoC都配备了USB 2.0接口。USB历代标准都完好地保留了原始3.3V I/O USB 1.0接口,以保持向后兼容性,从而实现了更广泛的应用和更大的生态系统,同时确保设备互操作性。

随着工艺节点到达5nm,维持USB 2.0 3.3V I/O信号所需的制造成本呈指数级增长。eUSB2作为对USB 2.0 规格的物理层补充,弥补了I/O电压间隙,因此,设计人员可在器件级别集成eUSB2接口,同时在系统级利用和重复使用USB 2.0接口。

eUSB2支持板载器件间连接(通过直接连接),也支持通过eUSB2转USB 2.0中继器(如 TUSB2E22 USB 2.0-eUSB2双路中继器)的外露连接器接口,从而进行电平转换,如图1所述。

图1:使用eUSB2中继器(如 TUSB2E22)的eUSB2应用

当工艺节点为7nm及以上时,USB 2.0可继续集成到 SoC中,而当工艺节点为5nm及以下时,eUSB2则更适合集成到SoC中。如图1所示,eUSB2还可集成到其他器件中,从而作为器件间接口与SoC轻松互连。USB 2.0将继续作为标准连接器接口。

eUSB2可显著降低I/O功率,提高电源效率,同时支持工艺节点继续扩展。表1展示了USB 2.0和eUSB2之间的特性差异。

表1:USB2.0和eUSB2的区别

eUSB2前景

由于系统功率大幅降低,eUSB2非常适合用于I/O电压较小的器件间通信。当使用先进的SoC和5nm及以下的工艺节点时,小型电子产品的设计人员可在系统设计中采用eUSB2,同时继续受益于USB 2.0接口的简易性、便于设计和广泛使用的特点。

围观 54

17条嵌入式C语言编程小知识总结

demi的头像

流水线被指令填满时才能发挥最大效能,即每时钟周期完成一条指令的执行(仅指单周期指令)。如果程序发生跳转,流水线会被清空,这将需要几个时钟才能使流水线再次填满。因此,尽量少的使用跳转指令可以提高程序执行效率,解决发案就是尽量使用指令的“条件执行”功能。

在嵌入式软件开发过程中,一般来说,花在测试和花在编码的时间比为3:1(实际上可能更多)。这个比例随着你的编程和测试水平的提高而不断下降,但不论怎样,软件测试对一般人来讲很重要。

很多年前,一位开发人员为了在对嵌入式有更深层次的理解,询问了这样的一个问题:我怎么才能知道并懂得我的系统到底在干些什么呢?

面对这个问题有些吃惊,因为在当时没有人这么问过,而同时代的嵌入式开发人员问的最多的大都围绕“我怎么才能使程序跑得更快”、“什么编译器最好”等肤浅的问题。

所以,面对这个不同寻常却异乎成熟的问题,我感到欣喜并认真回复了他:你的问题很有深度很成熟,因为只有不断地去深入理解才有可能不断地提高水平。为了鼓励这位执着的程序员,把10条关于嵌入式软件开发测试的秘诀告诉了他。下面我们一起来看看。

这十条秘诀在业界广为流传,使很多人受益。本文围绕这十条秘诀展开论述。

1、懂得使用工具

通常嵌入式系统对可靠性的要求比较高。嵌入式系统安全性的失效可能会导致灾难性的后果,即使是非安全性系统,由于大批量生产也会导致严重的经济损失。这就要求对嵌入式系统,包括嵌入式软件进行严格的测试、确认和验证。随着越来越多的领域使用软件和微处理器控制各种嵌入式设备,对日益复杂的嵌入式软件进行快速有效的测试愈加显得重要。

就像修车需要工具一样,好的程序员应该能够熟练运用各种软件工具。不同的工具,有不同的使用范围,有不同的功能。使用这些工具,你可以看到你的系统在干些什么,它又占用什么资源,它到底和哪些外界的东西打交道。让你郁闷好几天的问题可能通过某个工具就能轻松搞定,可惜你就是不知道。

那么为什么那么多的人总是在折腾个半死之后才想到要用测试工具呢?原因很多,主要有两个:
① 一个是害怕;
② 另一个是惰性;

害怕是因为加入测试工具或测试模块到代码需要技巧同时有可能引入新的错误,所以他们总喜欢寄希望于通过不断地修改重编译代码来消除bug,结果却无济于事。

懒惰是因为他们习惯了使用printf之类的简单测试手段。

下面来介绍一些嵌入式常用的测试工具
(1)、源码级调试器[Source-levelDebugger]
这种调试器一般提供单步或多步调试、断点设置、内存检测、变量查看等功能,是嵌入式调试最根本有效的调试方法。比如VxWorksTornadoII提供的gdb就属于这一种。

(2)、简单实用的打印显示工具 [printf]
printf或其它类似的打印显示工具估计是最灵活最简单的调试工具。打印代码执行过程中的各种变量可以让你知道代码执行的情况。但是,printf对正常的代码执行干扰比较大(一般printf占用CPU比较长的时间),需要慎重使用,最好设置打印开关来控制打印。

(3)、ICE或JTAG调试器[In- circuitEmulator]
ICE是用来仿真CPU核心的设备,它可以在不干扰运算器的正常运行情况下,实时的检测CPU的内部工作情况。像桌面调试软件所提供的:复杂的条件断点、先进的实时跟踪、性能分析和端口分析这些功能,它也都能提供。ICE一般都有一个比较特殊的CPU,称为外合(bond-out)CPU.这是一种被打开了封装的CPU,并且通过特殊的连接,可以访问到CPU的内部信号,而这些信号,在CPU被封装时,是没法 “看到”的。当和工作站上强大的调试软件联合使用时,ICE就能提供你所能找到的最全面的调试功能。但ICE同样有一些缺点:昂贵;不能全速工作;同样,并不是所有的CPU都可以作为外合CPU的,从另一个角度说,这些外合CPU也不大可能及时的被新出的CPU所更换。JTAG(JointTestActionGroup)虽然它最初开发出来是为了监测IC和电路连接,但是这种串行接口扩展了用途,包括对调试的支持。

(4)、ROM监视器 [ROMMonitor]
ROM监控器是一小程序,驻留在嵌入系统ROM中,通过串行的或网络的连接和运行在工作站上的调试软件通信。这是一种便宜的方式,当然也是最低端的技术。它除了要求一个通信端口和少量的内存空间外,不需要其它任何专门的硬件。
提供了如下功能:下载代码、运行控制、断点、单步步进、以及观察、修改寄存器和内存。因为ROM监控器是操作软件的一部分,只有当你的应用程序运行时,它才会工作。如果你想检查CPU和应用程序的状态,你就必须停下应用程序,再次进入ROM监控器。

(5)、Data监视器 [DataMonitor]
这种监视器在不停止CPU运行的情况下不仅可以显示指定变量内容,还可以收集并以图形形式显示各个变量的变化过程。

(6)、OS监视器 [OperatingSystemMonitor]
操作系统监视器可以显示诸如任务切换、信号量收发、中断等事件。一方面,这些监视器能够为你呈现事件之间的关系和时间联系;另一方面,还可以提供对信号量优先级反转、死锁和中断延时等问题的诊断。

(7)、性能分析工具 [Profiler]
可以用来测试CPU到底耗在哪里。profiler工具可以让你知道系统的瓶颈在哪里、CPU的使用率以及需要优化的地方。

(8)、内存测试工具 [MemoryTeseter]
可以找到内存使用的问题所在,比如内存泄露、内存碎片、内存崩溃等问题。如果发现系统出现一些不可预知的或间歇性的问题,就应该使用内存测试工具测测看。

(8)、运行跟踪器 [ExecutionTracer]
可以显示CPU执行了哪些函数、谁在调用、参数是什么、何时调用等情况。这种工具主要用于测试代码逻辑,可以在大量的事件中发现异常。

(9)、覆盖工具[CoverageTester]
主要显示CPU具体执行了哪些代码,并让你知道那些代码分支没有被执行到哪里。这样有助于提高代码质量并消除无用代码。

(10)、GUI测试工具 [GUITester]
很多嵌入式应用带有某种形式的图形用户界面进行交互,有些系统性能测试是根据用户输入响应时间进行的。GUI测试工具可以作为脚本工具有开发环境中运行测试用例,其功能包括对操作的记录和回放、抓取屏幕显示供以后分析和比较、设置和管理测试过程(Rational 公司的robot和Mercury的Loadrunner工具是杰出的代表)。
很多嵌入式设备没有GUI,但常常可以对嵌入式设备进行插装来运行GUI测试脚本,虽然这种方式可能要求对被测代码进行更改,但是节省了功能测试和回归测试的时间。

(11)、自制工具 [Home-madetester]
在嵌入式应用中,有时候为了特定的目的,需要自行编写一些工具来达到某种测试目的。本人曾经编写的视频流录显工具在测试视频会议数据流向和变化上帮了大忙,帮公司找到了几个隐藏很深的bug。

2、尽早发现内存问题

内存问题危害很大,不容易排查,主要有三种类型:内存泄露、内存碎片和内存崩溃。对于内存问题态度必须要明确,那就是早发现早“治疗”。在软件设计中,内存泄露的“名气”最大,主要由于不断分配的内存无法及时地被释放,久而久之,系统的内存耗尽。

即使细心的编程老手有时后也会遭遇内存泄露问题。有测试过内存泄露的朋友估计都有深刻地体验,那就是内存泄露问题一般隐藏很深,很难通过代码阅读来发现。有些内存泄露甚至可能出现在库当中。有可能这本身是库中的bug,也有可能是因为程序员没有正确理解它们的接口说明文档造成错用。

在很多时候,大多数的内存泄露问题无法探测,但可能表现为随机的故障。程序员们往往会把这种现象怪罪于硬件问题。如果用户对系统稳定性不是很高,那么重启系统问题也不大;但,如果用户对系统稳定很高,那么这种故障就有可能使用户对产品失去信心,同时也意味着你的项目是个失败的项目。

由于内存泄露危害巨大,现在已经有许多工具来解决这个问题。这些工具通过查找没有引用或重复使用的代码块、垃圾内存收集、库跟踪等技术来发现内存泄露的问题。每个工具都有利有弊,不过总的来说,用要比不用好。总之,负责的开发人员应该去测试内存泄露的问题,做到防患于未然。

内存碎片比内存泄露隐藏还要深。随着内存的不断分配并释放,大块内存不断分解为小块内存,从而形成碎片,久而久之,当需要申请大块内存是,有可能就会失败。如果系统内存够大,那么坚持的时间会长一些,但最终还是逃不出分配失败的厄运。在使用动态分配的系统中,内存碎片经常发生。
目前,解决这个问题最效的方法就是使用工具通过显示系统中内存的使用情况来发现谁是导致内存碎片的罪魁祸首,然后改进相应的部分。由于动态内存管理的种种问题,在嵌入式应用中,很多公司干脆就禁用malloc/free的以绝后患。

内存崩溃是内存使用最严重的结果,主要原因有数组访问越界、写已经释放的内存、指针计算错误、访问堆栈地址越界等等。这种内存崩溃造成系统故障是随机的,而且很难查找,目前提供用于排查的工具也很少。

总之,如果要使用内存管理单元的话,必须要小心,并严格遵守它们的使用规则,比如谁分配谁释放。

3、深入理解代码优化

讲到系统稳定性,人们更多地会想到实时性和速度,因为代码效率对嵌入式系统来说太重要了。知道怎么优化代码是每个嵌入式软件开发人员必须具备的技能。就像女孩子减肥一样,起码知道她哪个地方最需要减,才能去购买减肥药或器材来减掉它。

可见,代码优化的前提是找到真正需要优化的地方,然后对症下药,优化相应部分的代码。前面提到的profile(性能分析工具,一些功能齐全IDE都提供这种内置的工具)能够记录各种情况比如各个任务的CPU占用率、各个任务的优先级是否分配妥当、某个数据被拷贝了多少次、访问磁盘多少次、是否调用了网络收发的程序、测试代码是否已经关闭等等。

但是,profile工具在分析实时系统性能方面还是有不够的地方。一方面,人们使用profile工具往往是在系统出现问题即CPU耗尽之后,而 profile工具本身对CPU占用较大,所以profile对这种情况很可能不起作用。根据Heisenberg效应,任何测试手段或多或少都会改变系统运行,这个对profiler同样适用!

总之,提高运行效率的前提是你必须要知道CPU到底干了些什么干的怎么样。

4、不要让自己大海捞针

大海捞针只是对调试的一种生动比喻。经常听到组里有人对自己正在调试的代码说shit!可以理解,因为代码不是他写的,他有足够的理由去 shitbug百出的代码,只要他自己不要写出这种代码,否则有一天同组的其它人可能同样会shit他写的代码。为何会有大海捞针呢?肯定是有人把针掉到海里咯;那针为何会掉在海里呢?肯定是有人不小心或草率呗。

所以当你在抱怨针那么难找的时候,你是否想过是你自己草率地丢掉的。同样,当你调试个半死的时候,你是否想过你要好好反省一下当初为了寻求捷径可能没有严格地遵守好的编码设计规范、没有检测一些假设条件或算法的正确性、没有将一些可能存在问题的代码打上记号呢?

关于如何写高质量请参考林锐的《高质量c++/c编程指南》或《关于C的0x8本“经书》。

如果你确实已经把针掉在海里是,为了防止在找到之前刺到自己,你必须要做一些防范工作,比如戴上安全手套。同样,为了尽能地暴露和捕捉问题根源,我们可以设计比较全面的错误跟踪代码。

怎么来做呢?

尽可能对每个函数调用失败作出处理,尽可能检测每个参数输入输出的有效性,包括指针以及检测是否过多或过少地调用某个过程。错误跟踪能够让你知道你大概把针掉在哪个位置。

5、重现并隔离问题

如果你不是把针掉在大海了,而是掉在草堆里,那要好办些。因为至少我们可以把草堆分成很多块,一块一块的找。对于模块独立的大型项目,使用隔离方法往往是对付那些隐藏极深bug的最后方法。
如果问题的出现是间歇性的,我们有必要设法去重现它并记录使其重现的整个过程以备在下一次可以利用这些条件去重现问题。如果你确信可以使用记录的那些条件去重现问题,那么我们就可以着手去隔离问题。

怎么隔离呢?

我们可以用#ifdef把一些可能和问题无关的代码关闭,把系统最小化到仍能够重现问题的地步。如果还是无法定位问题所在,那么有必要打开“工具箱”了。可以试着用ICE或数据监视器去查看某个可疑变量的变化;可以使用跟踪工具获得函数调用的情况包括参数的传递;检查内存是否崩溃以及堆栈溢出的问题。

6、以退为进

猎人为了不使自己在森林里迷路,他常常会在树木上流下一些标记,以备自己将来有一天迷路时可以根据这些标记找到出路。对过去代码的修改进行跟踪记录对将来出现问题之后的调试很有帮助。

假如有一天,你最近一次修改的程序跑了很久之后忽然死掉了,那么你这时的第一反映就是我到底改动了些什么呢,因为上次修改之前是好的。那么如何检测这次相对于上次的修改呢?没错,代码控制系统SCS或称版本控制系统 VCS可以很好地解决这个问题。

将上个版本checkin下来后和当前测试版本比较。比较的工 具可以是SCS/VCS/CVS自带的diff工具或其它功能更强的比较工具,比如BeyondCompare和 ExamDiff。通过比较,记录所有改动的代码,分析所有可能导致问题的可疑代码。

7、确定测试的完整性

你怎么知道你的测试有多全面呢?覆盖测试(coveragetesting)可以回答这个问题。覆盖测试工具可以告诉你CPU到底执行了哪些代码。好的覆盖工具通常可以告诉你大概20%到40% 代码没有问题,而其余的可能存在bug.覆盖工具有不同的测试级别,用户可以根据自己的需要选择某个级别。

即使你很确信你的单元测试已经很全面并且没有 deadcode,覆盖工具还是可以为你指出一些潜在的问题。

看下面的代码:

if(i>=0&& (almostAlwaysZero==0||(last=i)))

如果almostAlwaysZero为非0,那么last=i赋值语句就被跳过,这可能不是你所期望的。

这种问题通过覆盖工具的条件测试功能可以轻松得被发现。总之,覆盖测试对于提高代码质量很有帮助。

8、提高代码质量意味着节省时间

有研究表明软件开发的时间超过80%被用在下面几个方面:调试自己的代码(单元测试)。调试自己和其他相关的代码(模块间测试)。调试整个系统(系统测试),更糟糕的是你可能需要花费10-200倍的时间来找一个 bug,而这个bug在开始的时候可能很容易就能找到。

一个小bug可能让你付出巨大的代价,即使这个bug对整个系统的性能没有太大的影响,但很可能会影响让那些你可以看得到的部分。所以我们必须要养成良好的编码和测试手段以求更高的代码质量,以便缩短调试的代码。

9、发现它,分析它,解决它

这世界没有万能的膏药。profile再强大也有力不从心的时候;内存监视器再好,也有无法发现的时候;覆盖工具再好用,也有不能覆盖的地方。

一些隐藏很深的问题即使用尽所有工具也有可能无法查到其根源,这时我们能做的就是通过这些问题所表现出来的外在现象或一些数据输出来发现其中的规律或异常。一旦发现任何异常,一定要深入地理解并回溯其根源,直到解决为止。

10、请利用初学者思维

有人这样说过:“有些事情在初学者的脑子里可能有各种各样的情况,可在专家的头脑里可能就很单一”。有时候,有些简单的问题会被想得很复杂,有些简单的系统被设计得很复杂,就是由于你的“专家思维”。当你被问题难住时,关掉电脑,出去走走,把你的问题和你的朋友甚至你的小狗说说,或许他们可以给你意想不到的启发。

总结

嵌入式调试也是一门艺术。就想其它的艺术一样,如果你想取得成功,你必须具备智慧、经验并懂得使用工具。只要我们能够很好地领悟Oracle这十条秘诀,我相信我们在嵌入式测试方面就能够取得成功。

来源:网络转载

围观 13

什么是嵌入式?什么是单片机?嵌入式和单片机有什么区别和联系呢?

本文针对这些问题整理了一篇文章,希望对大家理解单片机和嵌入式的基本概念,以及之间的区别有所帮助。

1、系统组成结构上的区别

(1)单片机基本结构

单片机由运算器、控制器、存储器、输入输出设备构成。

(2)嵌入式系统成部分
嵌入式系统一般由嵌入式微处理器、外围硬件设备、嵌入式操作系统、特定的应用程序组成。

嵌入式系统设计的第一步是结合具体的应用,综合考虑系统对成本、性能、可扩展性、开发周期等各个方面的要求,确定系统的主控器件,并以之为核心搭建系统硬件平台。

2、硬件组成上的区别

单片机是在一块集成电路芯片中包含了微控制器电路,以及一些通用的输入输出接口器件。从构成嵌入式系统的方式看,根据现代电子技术发展水平,嵌入式系统可以用单片机实现,也可以用其它可编程的电子器件实现。其余硬件器件根据目标应用系统的需求而定。

3、软件组成上的区别

制造商出厂的通用单片机内没有应用程序,所以不能直接运行。增加应用程序后,单片机就可以独立运行。嵌入式系统一定要有控制软件,实现控制逻辑的方式可以完全用硬件电路,也可以用软件程序。

4、主次关系方面的区别

单片机现在已经被认为是通用的电子器件了,单片机自身为主体。嵌入式系统在物理结构关系上是从属的,嵌入式系统被嵌入安装在目标应用系统内。嵌入式系统在控制关系上却是主导的,是控制目标应用系统运行的逻辑处理系统。

尽管可以用不同方式构成嵌入式系统,但是一旦构成之后,嵌入式系统就是一个专用系统。专用系统中,可编程器件的软件可以在系统构建过程中植入,也可以在器件制造过程中直接生成,以降低制造成本。

控制逻辑复杂的单片机会需要操作系统软件支持;控制逻辑简单的嵌入式系统也可以不用操作系统软件支持。

5、系统的联系

根据IEEE的定义,嵌入式系统是用来控制或监视机器、装置或工厂等大规模系统的设备。从定义我们可以看出,实际上以前的控制装置、单片机系统应该也属于嵌入式系统的范畴。
  
我们可以这样理解,嵌入式系统是一个大类,单片机是其中一个重要的子类。嵌入式系统顾名思义就是一个嵌入在其他系统中的系统。例如汽车系统中嵌入姿态控制系统,就可以使汽车驾驶更安全,更有效;电源系统内引入自动控制系统,能够让电源工作的更稳定。这里的姿态控制系统和电源的自动控制系统就属于嵌入式系统。
  
单片机形成的系统一般是用于自动化,工业控制功能的,这些功能一般不会独立运用,是需要和其他系统配合的,因此从广义上讲,单片机应用一般属于嵌入式系统的一个分支。

目前由于嵌入式系统应用广泛,因此还有不是单片机的嵌入式系统,例如手机,是在手机的基本功能上(通话、短信)加入了应用处理器,使其功能更加强大,但是由于制造工艺的问题,高端手机还不能做到全部一片集成(一片集成的那个是山寨机),但是也属于嵌入式系统的一个分支。

内容整理自网络,版权归原作者所有,如涉及作品版权问题,请联系删除!

围观 18

这十年来我做过小的嵌入式系统,大的电信系统以及基于web的系统。使用过C ++,Ruby,Java和Python等。这篇文章中的经验教训旨在帮助减少编码,测试和调试三个阶段的bug。

下面这些都是我经历过的会导致难点bug的问题:

1. 事件顺序。在处理事件时,提出下列问题会很有成效:事件可以以不同的顺序到达吗?如果我们没有接收到此事件会怎么样?如果此事件接连发生两次会怎么样?哪怕通常不会发生,但系统(或交互系统)其他部分的bug可能会导致事件发生呢。

2. 过早。这是第一点“事件顺序”的一个特例,但它确实会引起一些棘手的bug,因此我把它单独拎出来说明。例如,如果信令消息在配置和启动程序完成之前就被过早接收,那么可能就会有很多奇怪的行为发生。另一个例子:连接在被放进空闲列表之前就被标记为down。在调试这类问题时,我们总是假定在空闲列表中的时候连接被设置为down(但当时为什么不把它放到列表外面呢?)。这是我们思考的不足,没有考虑到有时候事情会过早发生。

3. 悄无声息的故障。一些最难跟踪的bug有部分是由那些静静失败并扩展而不是抛出错误的代码所导致的。例如,没有检查代码却返回错误的系统调用(如bind)。又如:解析代码在它遇到错误元素的时候只是返回而非抛出错误。在错误状态中持续了一段时间的调用,会使调试变得更难。最好一旦检测到故障就返回错误。

4. If。有若干条件的if语句,if (a 或 b) ,特别是当有链接的时候, if (x) else if (y),都给我引发了很多bug。即使if语句在概念上很简单,但当有多个条件要跟踪的时候依然很容易出错。这些天,我尝试重写代码使之更简单,以避免处理复杂的if语句。

5. Else。有一些bug是因为没有正确考虑到如果条件为false时会发生什么而引起的。几乎在所有的情况下,都应该有一个else部分来应对每一条if语句。此外,如果你在if语句的分支中设置变量,那么或许你在另一个分支中也要设置。与此种情况相关的是标记被设置的情况。只添加用于设置的标记的条件不难,但是很容易忘了添加当标记应该再次重置时的条件。留下一个永远设置的标志可能会导致之后接连不断的bug。

6. 改变假设。许多一开始最难预防的bug是因为改变了假设所造成的。例如,在开始时,可能每天只有一个客户事件。于是很多代码是在这样的假设下写下的。但是后来,设计改变了,允许每天有多个客户事件了。发生这种情况时,很难改变新设计影响到的所有情况。找到关于改变的所有显式依赖关系不难,难的是要找到所有隐性依赖于旧的设计的情况。例如,可能会有获取给定某一天所有客户事件的代码。其中的隐含假设是结果集永远不会超过客户的数量。关于这方面的问题我也没有很好的策略方法,如果各位有的话,还请不吝赐教。

7. 日志记录。可视化程序做什么至关重要,特别是当逻辑很复杂的时候。确保补充足够多的(但不要太多)日志记录,这样你就可以说明为什么程序要这么做。如果一切正常,那也没关系,但要是有问题发生,你会很庆幸自己添加了这些日志。

测试

作为一个开发人员,直到要测试了我才会去处理功能。至少,这意味着每一行新的或改变了的代码行至少已经被执行过一次。此外,单元测试和功能测试都很不错,但还不够。新的功能也必须进行测试,并在类似于产品的环境中探索。只有这样,我才能说我完成了一个功能。下面是我经历过的bug所教会我的关于测试的一些重要的经验教训:

1. 零和null。如果可行的话,确保总是用零和null来测试。对于字符串,这意味着要测试长度为零的字符串以及字符串为null两种情况。又如:测试TCP连接的断开,要在发送数据给它发送之前。不使用这些组合方法测试是导致bug出现的首位原因。

2. 添加和删除。通常,新的功能包括能够添加新的配置到系统中——例如,一个用于手机号码转换的新的配置文件。测试它能否添加新的配置文件是很自然的。但是,我发现我们很容易忘记去测试删除配置文件是不是同样ok。

3. 错误处理。处理错误的代码往往是难以测试的。最好有能检查错误处理代码的自动测试,但有时这是不可能的。我有时会使用的一招是临时修改代码,使得错误处理代码运行起来。要做到这一点最简单的方法是反转if语句——例如,从if error_count > 0改成error_count == 0。另一个例子是拼错数据库列名,从而导致期望的错误处理代码运行。

4. 随机输入。通常,揭露bug测试的一种测试方法是使用随机输入。例如,H.323协议的ASN.1解码使用二进制数据操作。通过发送随机字节去解码,我们发现了解码器中的几个bug。另一个例子是用测试呼叫来生成脚本,此时呼叫持续时间,接听延迟,第一方挂断等等都是随机生成的。这些测试脚本会暴露许多bug,特别是一起发生的事件会产生并拢干扰。

5. 检查不应该发生的动作。通常测试包括检查期望动作是不是发生了。但我们很容易忽视相反的情况——忘记检查不应该发生的动作是不是的确没有发生。

6. 拥有工具。我创建了自己的小工具,以使得测试更加简单。例如,当我用VoIP SIP协议工作时,我写了一个能够用正是我想要的标题和值回复的小脚本。这个工具使得测试很多边界情况变得容易起来。另一个例子是可以进行API调用的一个命令行工具。通过启动逐渐添加所需小功能,我得到了一些非常有用的工具。自己写工具的好处是,我得到的正是我想要的。

在测试中发现所有的bug,那绝对是不可能的。有一个案例中,我更改了数字相关性的处理,数字由两个部分组成:路由地址前缀(通常是不变的),以及从000到999动态分配的数字。问题在于当找到相关性时,动态分配的数字的第一个数字会在呈现在表格中之前遭到误删。也就是说637变成了37。这意味着,到100之前它都是可以工作的,因此,前面100个电话是正常的,但是接下来的900个都是失败。所以,除非我在重新启动之前能够测试超过100次(事实是我没有),否则我在测试时就不会发现这个问题。

调试

1. 讨论。帮助我最多的调试技术是与同事讨论问题。通常情况下,只是和同事说明问题,就会让我意识到问题的症结。此外,即使他们不是很熟悉有问题的代码,他们也往往能提出一些好点子。与同事讨论在处理最难的bug时特别有效。

2. 密切关注。通常,如果调试问题花了很长时间,往往是因为我做了错误的假设。例如,我认为问题发生在某一方法中,但事实却是它甚至从来没有到达那个方法。或者,被抛出的异常不是我以为的那个。或者,我认为软件的最新版本上正在运行,但其实是一个旧版本。因此,一定要核实细节,而不是假设。人们更容易看到自己希望看到的东西,而不是事实。

3. 最近的变化。当曾经可以正常工作的东西停止工作,那么这通常是因为最近改变的东西所导致的。在一个案例中,最近的改变只是日志记录,但是日志中的错误却导致了一个更大的问题。为了更容易找到这种回归,承认不同的提交会导致不同的变化,以及清楚说明这些更改会有所裨益。

4. 相信用户。有时,当用户报告问题的时候,我的本能反应是,“这是不可能的。一定是他们做错了什么事”。但我学会了不再用这种方式去回应。更多的时间,事实往往证明,他们所报告的的确是实际发生的情况。因此,这些天,我开始接受他们所报告的内容的表明价值。当然,我依然会仔细检查一切是否被正确地设置等等。我见过很多这样的情况,让我明白,因为不寻常的配置或意料之外的用法而导致不可思议的事情的发生,而我默认的假设是,他们是正确的,程序是错误的。

5. 测试修复。如果bug修复已准备就绪,那就必须进行测试。首先在修复前运行代码,并观察该bug。然后应用修复并重复测试案例。到此为止错误行为应消失。遵循这些步骤可以确保它确实是一个bug,并且此次修复的确可以解决这个问题。简单而有必要。

其他观察结果

现在工作于C++时所遇到的几类bug已经完全消失,像堆栈溢出,内存损坏,字符串问题和某种形式的内存泄漏。

其他问题,如循环错误和边界情况,我看到的要少得多。但是,这并不意味着那里没有bug。如果大家有什么有用的预防和发现bug的技术方法,欢迎留言。

作为过来人,最后还想说几句心灵鸡汤:

1、分享第一条经验:“学历代表过去、能力代表现在、学习力代表未来。”
2、一定要确定自己的发展方向,并为此目的制定可行的计划。
3、软件开发团队中,技术不是万能的,但没有技术是万万不能的!
4、详细制定自己软件开发专业知识学习计划,并注意及时修正和调整(软件开发技术变化实在太快)。
5、书籍是人类进步的阶梯,对软件开发人员尤其如此。
6、不要仅局限于对某项技术的表面使用上,哪怕你只是偶尔用一、二次。
7、在一种语言上编程,但别为其束缚了思想。“代码大全”中说:“深入一门语言编程,不要浮于表面”。
8、养成总结与反思的习惯,并有意识地提炼日常工作成果,形成自己的个人源码库、解决某类问题的通用系统体系结构、甚至进化为框架。
9、理论与实践并重,内外双修。
10、心态有多开放,视野就有多开阔。
11、尽量参加开源项目的开发、或者与朋友共同研制一些自己的产品,千万不要因为没有钱赚而不做。
12、书到用时方恨少,不要将自己的知识面仅仅局限于技术方面。

总结与反思:

(a)不要去做技术上的高手,除非你的目标如此。
(b)提高软件知识和技术只是问题的表面,本质是要提高自己认识问题、分析问题、解决问题的思想高度。软件专业知识的很多方法和原理,可以很容易地延伸、应用到生活的其它方面。
(c)在能胜任工作的基础上,立即去涉猎其它领域的专业知识,丰富自己的知识体系、提高自己的综合素质,尤其是那些目标不在技术方面的朋友。

内容来源网络,转载此文目的在于传递更多信息,版权归原作者所有。

围观 82

工程更改(ECO)将推高设计成本,造成产品开发大量延迟,进而延迟产品上市时间。然而,通过认真思考经常发生问题的七大关键领域,可以规避大多数ECO。这七大领域是:元器件选择,存储器,湿度敏感等级(MSL),可测性设计(DFT),冷却技术,散热器以及热膨胀系数(CTE)。

元器件选择

为了规避ECO,全面通读元器件规格书很重要。PCB设计师一般都会例行检查元器件的电气和工程数据以及产品寿命和可用性。但当元器件处于市场推广的早期阶段,数据手册上可能还没有全部的关键指标。如果元器件上市才几个月,或者只能提供小批量样品,那么当前可获得的可靠性数据可能没有普遍性,或不够详细。举例来说,最终可能无法提供足够多的可靠性数据,或有关现场失效率的质量保证数据。

不要轻信规格书中写的表面文章很重要,而是要积极联系元器件供应商,尽可能多地了解元器件的特性以及如何将这些特性应用于设计。

元件需要处理的最大期望电流或电压就是一个很好的例子。如果所选的元件不能处理足够的电流或电压,那么元件很可能烧坏。

让我们看另外一个例子--栅格阵列(LGA)封装的器件。除了电气和机械约束外,你可能需要考虑推荐的助焊剂类型、允许或不允许的回流焊温度以及允许的焊点空洞等级。

目前还没有专门与LGA器件相关的空洞方面的IPC标准。目前在一些情况下,空洞等级最高为30%的LGA器件被认为是可靠的。然而一般来说,最大为25%的较低空洞等级更好,20%最好了。

在缺少空洞数据的条件下,设计工程师必须依靠他们的经验、技巧和常识,利用不会马上停产、可以从多个渠道获得、市场上容易找到的元件开展他们的设计。

在元器件选择过程中进行额外的分析和计算同样非常重要,比如计算峰值性能时的电流或电压。一个元器件可能规定了某个峰值温度和电流值时的性能指标。然而,针对特定的设计,PCB设计师必须采取行动确保他或她亲自做了这些关键的计算。

工程师不仅要负责计算单个元器件,而且要考虑该元器件与特定设计中使用的其它元器件之间的关系。举例来说,这种计算对于发热量很高的模拟元件来说尤其重要。比如有许多模拟元件放置在电路板的同一面,并且彼此挨着。这些元器件会产生相当大的功率,因而与电路板的另外一面(自然是数字器件)相比产生的热量会高很多。在这种情况下,插满了模拟器件的那一面有可能发生阻焊层剥离现象。

元器件电路的模拟部分会产生大量热量。过热可能导致阻焊层剥离,在最坏情况下,可能烧坏元器件。

设计和版图工程师需要在版图设计阶段合作开展元器件的布局,避免元器件太靠近电路板边缘,或太靠近另外的元器件,避免相互间没留出足够的空间。在计算机上很容易设计元器件布局,但如果在版图中没有精确地创建元器件封装,那么贴片机可能无法完美地将这些器件紧邻放置。

同样的原则也适用于存储器的选择。由于不断有新一代更先进的DRAM和闪存上市,PCB设计师要想始终走在技术前沿、及时准确地判断不断变化的存储器规范如何影响更新的设计是极具挑战性的一项任务。

比如DDR2代DRAM有别于今天的DDR3器件,而DDR3器件将有别于未来的DDR4DRAM。在写这篇文章时,JEDEC已经宣布发行DDR4标准--JESD79-4。

PCB设计师需要随时关注DDR4的崛起,并与OEM客户保持紧密合作,因为他们在推出下一代嵌入式系统时很可能包含DDR4DRAM。他们必须很好地掌握新的特性和功能动态,避免设计上的满足感以及因此导致的工程更改单。另外一件需要注意的事是,存储器价格会发生波动。

湿度敏感等级(MSL)

湿度敏感等级(MSL)很容易被忽视。如果OEM厂商在设计中不顾及MSL,关键的MSL规范没有得到正确对待,那么用户很可能不会考虑MSL信息,电路在现场使用时也就可能无法正常工作。当实际MSL等级是3、4或5时,这种可能性更高。在这种情况下,烘烤可能无法正确完成,湿气可能乘虚而入,最终导致工程更改单。当涉及LGA时,PCB装配公司将不得不替换PCB上的这些封装。

可测性设计

可测性设计(DFT)对于生产过程中开展PCB测试和调试来说非常重要。在将元器件布局到电路板上时,重要的是密切留意DFT探测点的布局位置,以及探针伸过去接触过孔、焊盘和其它测试点时的角度。

来源:深圳市路远自动化设备有限公司

围观 223

页面

订阅 RSS - 嵌入式