嵌入式

这十年来我做过小的嵌入式系统,大的电信系统以及基于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)在能胜任工作的基础上,立即去涉猎其它领域的专业知识,丰富自己的知识体系、提高自己的综合素质,尤其是那些目标不在技术方面的朋友。

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

围观 48

工程更改(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探测点的布局位置,以及探针伸过去接触过孔、焊盘和其它测试点时的角度。

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

围观 207

成为一个正式的嵌入式主板开发工程师,是一个艰辛的过程,需要开发人员维护和管理系统的每个比特和字节。从规范完善的开发周期到严格执行和系统检查,开发高可靠性嵌入式系统的技术有许多种。

今天给大家介绍7个易操作且可以长久使用的技巧,它们对于确保系统更加可靠地运行并捕获异常行为大有帮助。

技巧1——用已知值填充ROM

软件开发人员往往都是非常乐观的一群人,只要让他们的代码忠实地长时间地运行就可以了,仅此而已。微控制器跳出应用程序空间并在非预想的代码空间中执行这种情况似乎是相当少有的。然而,这种情况发生的机会并不比缓存溢出或错误指针失去引用少。它确实会发生!发生这种情况后的系统行为将是不确定的,因为默认情况下内存空间都是0xFF,或者由于内存区通常没有写过,其中的值可能只有上帝才知道。

不过有相当完备的linker或IDE技巧可以用来帮助识别这样的事件并从中恢复系统。技巧就是使用FILL命令对未用ROM填充已知的位模式。要填充未使用的内存,有很多不同的可能组合可以使用,但如果是想建立更加可靠的系统,最明显的选择是在这些位置放置ISR fault handler。如果系统出了某些差错,处理器开始执行程序空间以外的代码,就会触发ISR,并在决定校正行动之前提供储存处理器、寄存器和系统状态的机会

技巧2——检查应用程序的CRC

对嵌入式工程师来说一个很大的好处是,我们的IDE和工具链可以自动产生应用程序或内存空间校验和(Checksum),从而根据这个校验和验证应用程序是否完好。有趣的是,在许多这些案例中,只有在将程序代码加载到设备时,才会用到校验和。

然而,如果CRC或校验和保持在内存中,那么验证应用程序在启动时(或甚至对长时间运行的系统定期验证)是否仍然完好是确保意外之事不会发生的极好途径。现在一个编程过的应用程序发生改变的概率是很小的,但考虑每年交付的数十亿个微控制器以及可能恶劣的工作环境,医疗仪器应用程序崩溃的机会并不是零。更有可能的是,系统中的一个缺陷可能导致某一扇区发生闪存写入或闪存擦除,从而破坏应用程序的完整性。

技巧3——在启动时执行RAM检查

为了建立一个更加可靠和扎实的系统,确保系统硬件正常工作非常重要。毕竟硬件会发生故障。(幸运的是软件永远不会发生故障,软件只会做代码要它做的事,不管是正确的还是错误的)。在启动时验证RAM的内部或外部没有问题,是确保硬件可以如预期般运作的一个好方法。

有许多不同的方法可用于执行RAM检查,但常用的方法是写入一个已知的模式,然后等上一小段时间再回读。结果应该是所读就是所写。真相是,在大多数情况下 RAM检查是通过的,这也是我们想要的结果。但也有极小的可能性检查不通过,这时就为系统标示出硬件问题提供了极好的机会。

技巧4——使用堆栈监视器

对许多的嵌入式开发者而言,堆栈似乎是一股相当神秘的力量。当奇怪的事情开始发生,工程师终于被难倒了,他们开始思考,也许堆栈中发生了什么事。结果是盲目地调整堆栈的大小和位置等等。但该错误往往是与堆栈无关的,但怎能如此确定?毕竟,有多少工程师真的实际执行过最坏情况下的堆栈大小分析?

堆栈大小是在编译时就静态分配好的,但堆栈是以动态的方式使用的。随着代码的执行,应用程序需要的变量、返回的地址和其它信息被不断存储在堆栈中。这种机制导致堆栈在其分配的内存中不断增长。然而,这种增长有时会超出编译时确定的容量极限,导致堆栈破坏相邻内存区域的数据。

绝对确保堆栈正常工作的一种方法是实现堆栈监视器,将它作为系统“保健”代码的一部分(有多少工程师会这样做?)。堆栈监视器会在堆栈和“其它”内存区域之间创建一个缓冲区域,并填充已知的位模式。然后监视器会不断的监视图案是否有任何变化。如果该位模式发生了改变,那就意味着堆栈增长得太大了,即将要把系统推向黑暗地狱!此时监视器可以记录事件的发生、系统状态以及任何其它有用的数据,供日后用于问题的诊断。
  大多数实时操作系统(RTOS)或实现了内存保护单元(MPU)的微控制器系统中都提供有堆栈监视器。可怕的是,这些功能默认都是关闭状态,或者经常被开发人员有意关闭。在网络上快速搜寻一下可以发现,很多人建议关闭实时操作系统中的堆栈监视器以节省56字节的闪存空间等等,这可是得不偿失的做法!

技巧5 - 使用MPU

在过去,是很难在一个小而廉价的微控制器中找到内存保护单元(MPU)的,但这种情况已经开始改变。现在从高端到低端的微控制器都已经有MPU,而这些 MPU为嵌入式软件开发人员提供了一个可以大幅提高其固件(firmware)鲁棒性(robustness)的机会。

MPU 已逐渐与操作系统耦合,以便建立内存空间,其中的处理都分开,或任务可执行其代码,而不用担心被stomped on。倘若真有事情发生,不受控制的处理会被取消,也会执行其他的保护措施。请留意带有这种组件的微控制器,如果有,请多加利用它的这种特性。

技巧6 - 建立一个强大的看门狗系统

你经常会发现的一种总是最受喜爱的看门狗(watchdog)实现是,在看门狗被启用之处(这是一个很好的开始),但也是可以用周期性定时器将该看门狗清零之处;定时器的启用是完全与程序中出现的任何情况隔离的。使用看门狗的目的是协助确保如果出现错误,看门狗不会被清零,即当工作暂停,系统会被迫去执行硬件重设定(hardware reset),以便恢复。使用与系统活动独立的定时器可以让看门狗保持清零,即使系统已失效。

对应用任务如何整合到看门狗系统中,嵌入式主板开发人员需要仔细考虑和设计。例如,有种技术可能可以让每个在一定时期内运行的任务标示它们可以成功地完成其任 务。在此事件中,看门狗不被清零,强制被复位。还有一些比较先进的技术,像是使用外部看门狗处理器,它可用来监视主处理器如何表现,反之亦然。对一个可靠的系统而言,建立一个强大的看门狗系统是很重要的。

技巧7 - 避免易失存储器分配

不习惯在资源有限环境下工作的工程师,可能会试图使用其编程语言的特性,这种语言让他们可以使用易失存储器分配。毕竟,这是一种常在计算器系统中使用的技术,在计算器系统中,只有在有必要时,内存才会被分配。例如,以C开发时,工程师可能倾向于使用malloc来分配在堆(heap)上的空间。有一个操 作会执行,一旦完成,可以使用free将被分配的内存返回,以便堆的使用。

在资源受限的系统,这可 能是一场灾难!使用易失存储器分配的其中一个问题是,错误或不当的技术可能会导致内存泄漏或内存碎片。更多资料企鹅爱吧物久零要奇伞武奇,如果出现这些问题时,大多数的嵌入式系统并没有 资源或知识来监视堆或妥善地处理它。而当它们发生时,如果应用程序提出对空间的要求,但却没有所请求的空间可以使用,会发生什么事呢?

使用易失存储器分配所产生的问题是很复杂的,要妥善处理这些问题,可以说是一个噩梦!一种替代的方法是,直接以静态的方式,简化内存的分配。例如,只要在 程序中简单地建立一个大小为256字节长的缓冲区,而不是经由malloc请求这样大小的内存缓冲区。此一分配的内存可在整个应用程序的生命周期期间保持,且不会有堆或内存碎片问题方面的顾虑。

以上嵌入式开发的教程可以让开发技术的人员获取更好嵌入式系统的办法。所有这些技术都是让设计者可以开发出可靠性更高嵌入式系统的秘诀。

来源:网络

围观 259

我走的电子开发道路其实和大多数人说的一样,基本的路线为模拟电子(熟练)→数字电路设计(掌握)→单片机(项目开发)→ARM硬件设计(项目开 发)→linux学习→linux驱动学习→ARM&linux底层开发(项目开发)→ARM&linux顶层开发(项目开发)→项目经 理。我现在还在路上折腾,现在将我的教训和心得拿来给大家分享,希望对于新手有借鉴。

嵌入式设计是个庞大的工程,今天就说说硬件电路设计方面的几个注意事项,首先,咱们了解下嵌入式的硬件构架。

我们知道,CPU是这个系统的灵魂,所有的外围配置都与其相关联,这也突出了嵌入式设计的一个特点硬件可剪裁。在做嵌入式硬件设计中,以下几点需要关注。

第一、电源确定

电源对于嵌入式系统中的作用可以看做是空气对人体的作用,甚至更重要:人呼吸的空气中有氧气、二氧化碳和氮气等但是含量稳定,这就相当于电源系统中各种杂波,我们希望得到纯净和稳定符合要求的电源,但由于各种因素制约,只是我们的梦想。这个要关注两个方面:

a、电压

嵌入式系统需要各种量级的电源比如常见的5v、3.3v、1.8v等,为尽量减小电源的纹波,在嵌入式系统中使用LDO器件。如果采用DCDC不仅个头大,其纹波也是一个很头疼的问题。

b、电流

嵌入式系统的正常运行不但需要稳定足够的电源,还要有足够的电流(其实就是功率达到要求),因此在选择电源器件的时候需要考虑其负载,我设计时一般留有30%的余量。

如果是多层板,电源部分在layout的时候需电源分割,这时需要注意分割路径,尽量将一定量的电源放置在一起。如果是双面板,则走线宽度需要注意,在板子允许的情况下尽量加宽。合适的退耦电容尽量靠近电源管脚。

第二、 晶振确定

晶振相当于嵌入式系统的心脏,其稳定与否直接关系其运行状态和通讯性能。常见的振有无源晶振,有源晶振,首先要确定其振荡频率,其次要确定晶振类型。

a、无源晶振

其匹配电容和匹配电阻的选择,这部分一般依据参考手册。在单片机设计中,经常使用插件晶振配合瓷片电容。在ARM中,为了减少空间和便于布线,经常使用四角无源晶振配合贴片电容。虽然我们对于固定晶振的匹配电路比较熟悉,但是为了达到万无一失,还是要看参考手册确定电容大小,是否需要匹配电阻等细节。

b、有源晶振

具有更好的更准确的时钟信号,但是相比之下,比无缘晶振价格高,因此这也是在硬件电路设计中需要关注的成本。

在做电路板设计时需要注意晶振走线尽量靠近芯片,关键信号远离时钟走线。在条件允许的情况下增加接地保护环。如果是多层板,也要讲关键信号远离晶振的走线。

第三、 预留测试IO口

在嵌入式调试阶段,在管脚资源丰富的情况下,我通常预留一个IO口连接led或者喇叭,为下一步软件的编写做铺垫。在嵌入式系统运行过程中适当控制该IO接口,从而判断系统是否正常运行。

第四、外扩存储设备

一 个嵌入式系统如果有电源、晶振和CPU,那么这就是我们熟悉的最小系统。如果该嵌入式系统需要运行大点的操作系统,那么不但需要CPU具有MMU,CPU 还需要外接SDRAM和NANDFLASH。如果该cpu具有SDRAM和NANDFLASH控制器,那么在硬件设计上不用过多的考虑地址线的使用。如果没有相关的控制器,那么需要注意地址线的使用。

这部分在LAYOUT的时候是一个重点,究其原因就是要使相关信号线等长以确保信号的延时相等,时钟和DQS的差分信号线走线。在布线的时候各种布线技巧需要综合使用,例如与cpu对称分布,菊花链布线、T型布线,这都需要依据内存的个数多少来进行选择,一般来说个数越多,布线越复杂,但是知道其关键点,一切迎刃而解。

第五、功能接口

一个嵌入式系统最重要的就是通过各种接口来控制外围模块,达到设计者预设的目的。常用的接口有串口(可用来连接蓝牙,wifi和3G等模块),USB接口、 网络接口、JTAG接口、音视频接口、HDMI接口等等。由于这些接口与外部模块连接,做好电磁兼容设计是重要的一项工作。除此之外,在LAYOUT的时候注意差分线的使用。

第六、屏幕

这个功能之所以单独列出来,是由于其可有可无。如果一个嵌入式系统只是作为一个连接器连接外围设备模块,通过相关接口连接到电脑主机或者直接挂在网络上,那么屏幕就不需要了。但是如果做出来的是一个消费类产品,与用户交互频繁,这就不得不唠叨几句。

电容屏幕是嵌入式屏幕的首选,在电路设计中需要注意触屏连接线和显示屏连接线的布局。在走线的过程中尽量短的靠近主控cpu,同时注意配对信号走差分 线,RGB控制信号走等长。各种信号走线间距遵循3W规则,避免相互干扰。 在屏幕的设计中,一定要确保功率和防止干扰,以防屏幕闪屏和花屏现象的出现。

以上就是我做嵌入式板子设计中的一些经验,有些经验是经过沉痛教训获得的。希望对你有所启发。

本文转自:玩转单片机,转载此文目的在于传递更多信息,版权归原作者所有。

围观 232

嵌入式设备网络化、u盘化、功能复杂化的趋势,使越来越多的、过去可以用裸奔实现的嵌入式产品,产生了应用操作系统的需求。

而人力成本的持续上升、芯片成本的连续下降,以及cpu性能的迅速提高,又为大面积应用操作系统提供了物质基础。

本文和大家一起讨论一下,从裸奔到操作系统,我们将面对什么挑战。

1、速度

我们首先面对的,将是cpu运行速度的问题,毋庸置疑,操作系统调度需要cpu开销,需要cpu有更高的速度来弥补;再者,嵌入式系统经常用于实时控制,需要较高的定时精度,缩短tick时间间隔有利于提高控制精度,嵌入式系统中经常使用1mS甚至更短的tick间隔。然而,tick间隔越短,调度开销就越高,同样需要更高的cpu速度来弥补。当前日益提高的嵌入式cpu的性能,甚至单片机都32位了,很好地回答了这个问题。

2、内存容量

先讨论一个问题,一个原先需要50K内存的裸奔程序,如果移植到自身开销1K内存的RTOS下面,需要增加多少内存?是51K吗?

有许多嵌入式操作系统,都把运行操作系统的内存开销作为主要性能指标,有些甚至声称不到1K内存就可以运行。但我们千万不要被误导,以为用操作系统需要的内存与裸机差不多,只要比裸奔程序多那么1K、2K就行了。操作系统会使应用程序所需要的内存暴增,使用操作系统所增加的内存需求,主要来自以下方面:

1) 运行操作系统本身需要的内存。
2) 创建线程控制块、消息控制块等操作系统组件需要的内存。
3) 每个线程配置独立的栈所增加的内存需求。

其中第一项很好理解,几乎所有操作系统都会给出这个指标。第二项也容易理解,不用操作系统的情况下,我们常常定义标志位或全局变量来在不同模块之间传递信息,需要的内存就很少。而操作系统模式下,需要用到同步、互斥、线程间交换数据等,这就需要使用信号量、邮箱等操作系统组件,信号量需要分配信号量控制块,邮箱需要分配邮箱控制块……,这些,都需要消耗可观的内存。许多操作系统标明的,仅仅是OS本身运行需要的内存,并不包括信号量控制块拉、邮箱控制块拉等等这些操作系统组件需要的内存。我们知道,一个仅运行OS的系统,是毫无意义的,真正实现产品功能的,是应用程序。而djyos的si版本,大约需要的10K内存,则包含了一定数量的事件控制块、信号量控制块等操作系统组件所需内存的条件下的,完全满足一个小型系统所需。

说了半天,其实也只讲了操作系统对内存需求的冰山一角,OS下编程,对内存需求的影响最大的,当属OS的多线程并发特性,这使得我们要为每一个线程分配独立的栈。下面我们定性分析一下栈独立化带来的内存需求变化。栈是用来保存函数参数和局部变量的,可以说,有函数调用,就有局部变量。在单线程环境下,应用程序需要的栈,几乎就是main函数需要的栈,而在多线程环境下,每个线程的栈是独立的,分别等于该线程的线程执行函数所需要的栈,而系统总的栈需求,就是所有线程的栈需求之和。

假设有一不使用OS的应用程序,main函数如下:

void main(void)
{
while(1)
{
func1(); //本函数需要10K栈
func2(); //本函数需要5K栈
func3(); //本函数需要9K栈
func4(); //本函数需要8K栈
func5(); //本函数需要9K栈
}
}

在超级循环中,分别调用了func1~func5这5个函数,他们的栈需求分别是10K、5K、9K、8K、9K。调用func1时,系统分配10K的ram作为栈,func1函数返回,这10K空间将被释放,并且再次分配给func2使用,所以,整个程序的栈需求,就是这5个函数中需要栈最多的那个函数需要的栈空间:10K。

如果要把这个程序移植到OS下,最简单的方法就是创建5个线程来调用func1~5这5个函数,这5个线程需要的栈分别是10K、5K、9K、8K、9K,而这5个栈是独立的,不能共用,程序总共需要的栈空间是(10+5+9+8+9)=41K,线程栈一般是从堆中动态分配的,考虑到动态分配本身的开销,硬件须准备50K以上的内存用于程序的运行栈。一下子增长到5倍,没想到吧。

可见,上操作系统,虽然操作系统本身不需要很大内存,但会极度增加应用程序的内存需求。做项目时,一是不要盲目上OS,要根据需求综合考虑,二是设计硬件系统时,应该充分考虑到内存方面的需求,配置充足的内存。

3、人

任何产品都是由人开发的,所以,讨论嵌入式产品开发的任何话题,都不能离开人的因素,科技以人为本嘛!从裸奔到操作系统,那么程序员,也将由编写裸奔程序转为在操作系统下编程。这些迅速、大量增加的程序员,他们可能习惯了在裸奔环境下编程,他们可能是化工、建筑、地质等不同行业的专家,他们也许已经上了年纪,没有太多的精力学习多线程编程等知识。然而,涉及到专业的程序,仍然离不开他们,如何从技术上降低他们的入门门槛,是一个亟需考虑的问题。但是,普通的操作系统下,你不掌握线程控制技术,就无法编写正确的程序。djyos允许你按事件编程,没有任何跟线程相关的api函数,无需程序员掌握线程技术,客观上降低了裸奔到OS编程的转换技术门槛。

转自:玩转单片机

围观 253

嵌入式系统设计方法变化的背景

嵌入式系统设计方法的演化总的来说是因为应用需求的牵引和IT技术的推动,随着微电子技术的不断创新和发展,大规模集成电路的集成度和工艺水平不断提高。硅材料与人类智慧的结合,生产出大批量的低成本、高可靠性和高精度的微电子结构模块,推动了一个全新的技术领域和产业的发展。

在此基础上发展起来的器件可编程思想和微处理(器)技术可以用软件来改变和实现硬件的功能。微处理器和各种可编程大规模集成专用电路、半定制器件的大量应用,开创了一个崭新的应用世界,以至广泛影响着并在逐步改变着人类的生产、生活和学习等社会活动。

计算机硬件平台性能的大幅度提高,使很多复杂算法和方便使用的界面得以实现,大大提高了工作效率,给复杂嵌入式系统辅助设计提供了物理基础。

高性能的EDA综合开发工具(平台)得到长足发展,而且其自动化和智能化程度不断提高,为复杂的嵌入式系统设计提供了不同用途和不同级别集编辑、布局、布线、编译、综合、模拟、测试、验证和器件编程等一体化的易于学习和方便使用的开发集成环境。

硬件描述语言HDL(Hardware DescrIPtion Language)的发展为复杂电子系统设计提供了建立各种硬件模型的工作媒介。它的描述能力和抽象能力强,给硬件电路,特别是半定制大规模集成电路设计带来了重大的变革。目前,用得较多的有已成为IEEE为 STD1076标准的VHDL、IEEE STD 1364标准的Verilog HDL和Altera公司企业标准的AHDL等。

由于HDL的发展和标准化,世界上出现了一批利用HDL进行各种集成电路功能模块专业设计的公司。其任务是按常用或专用功能,用HDL来描述集成电路的功能和结构,并经过不同级别的验证形成不同级别的IP内核模块,供芯片设计人员装配或集成选用。

IP(Intellectual Property)内核模块是一种预先设计好的甚至已经过验证的具有某种确定功能的集成电路、器件或部件。它有几种不同形式。IP内核模块有行为(behavior)、结构(structure)和物理(physical)3级不同程度的设计,对应有主要描述功能行为的“软IP内核(soft IP core)”、完成结构描述的“固IP内核(firm IP core)”和基于物理描述并经过工艺验证的“硬IP内核(hard IP core)”3个层次。这相当于集成电路(器件或部件)的毛坯、半成品和成品的设计技术。

软IP内核通常是用某种HDL文本提交用户,它已经过行为级设计优化和功能验证,但其中不含有任何具体的物理信息。据此,用户可以综合出正确的门电路级网表,并可以进行后续结构设计,具有最大的灵活性,可以很容易地借助于EDA综合工具与其他外部逻辑电路结合成一体,根据各种不同的半导体工艺,设计成具有不同性能的器件。可以商品化的软IP内核一般电路结构总门数都在5000门以上。但是,如果后续设计不当,有可能导致整个结果失败。软IP内核又称作虚拟器件。

硬IP内核是基于某种半导体工艺的物理设计,已有固定的拓扑布局和具体工艺,并已经过工艺验证,具有可保证的性能。其提供给用户的形式是电路物理结构掩模版图和全套工艺文件,是可以拿来就用的全套技术。

固IP内核的设计深度则是介于软IP内核和硬IP内核之间,除了完成硬IP内核所有的设计外,还完成了门电路级综合和时序仿真等设计环节。一般以门电路级网表形式提交用户使用。

TI,Philips和Atmel等厂商就是通过Intel授权,用其MCS51的IP内核模块结合自己的特长开发出有个性的与Intel MCS51兼容的单片机。

常用的IP内核模块有各种不同的CPU(32/64位CISC/RISC结构的CPU或8/16位微控制器/单片机,如8051等)、32/64位 DSP(如320C30)、DRAM、SRAM、EEPROM、Flashmemory、A/D、D/A、MPEG/JPEG、USB、PCI、标准接口、网络单元、编译器、编码/解码器和模拟器件模块等。丰富的IP内核模块库为快速地设计专用集成电路和单片系统以及尽快占领市场提供了基本保证。

软件技术的进步,特别是嵌入式实时操作系统EOS(Embedded Operation System)的推出,为开发复杂嵌入式系统应用软件提供了底层支持和高效率开发平台。EOS是一种功能强大、应用广泛的实时多任务系统软件。它一般都具有操作系统所具有的各种系统资源管理功能,用户可以通过应用程序接口API调用函数形式来实现各种资源管理。用户程序可以在EOS的基础上开发并运行。它与通用系统机中的OS相比,主要有系统内核短小精悍、开销小、实时性强和可靠性高等特点。完善的EOS还提供各种设备的驱动程序。为了适应网络应用和 Internet应用。还可以提供TCP/IP协议支持。目前流行的EOS有3Com公司的Palm OS、Microsoft公司的Windows CE和Windows NT Embedded4.0、日本东京大学的Tron和各种开放源代码的嵌入式Linux以及国内开发成功的凯思集团的Hopen OS和浙江大学的HBOS。

嵌入式系统设计方法的变化

过去擅长于软件设计的编程人员一般对硬件电路设计“敬而远之”,硬件设计和软件设计被认为是性质完全不同的技术。

随着电子信息技术的发展,电子工程出身的设计人员,往往还逐步涉足软件编程。其主要形式是通过微控制器(国内习惯称作单片机)的应用,学会相应的汇编语言编程。在设计规模更大的集散控制系统时,必然要用到已普及的PC机,以其为上端机,从而进一步学习使用Quick BASIC,C,C++,VC和VB等高级语言编程作系统程序,设计系统界面,通过与单片机控制的前端机进行多机通信构成集中分布控制系统。

软件编程出身的设计人员则很少有兴趣去学习应用电路设计。但是,随着计算机技术的飞速发展,特别是硬件描述语言HDL的发明,系统硬件设计方法发生了变化,数字系统的硬件组成及其行为完全可以用HDL来描述和仿真。在这种情况下,设计硬件电路不再是硬件设计工程师的专利,擅长软件编程的设计人员可以借助于HDL工具来描述硬件电路的行为、功能、结构、数据流、信号连接关系和定时关系,设计出满足各种要求的硬件系统。

EDA工具允许有两种设计输入工具,分别适应硬件电路设计人员和软件编程人员两种不同背景的需要。让具有硬件背景的设计人员用已习惯的原理图输入方式,而让具有软件背景的设计人员用硬件描述语言输入方式。由于用HDL描述进行输入,因而与系统行为描述更接近,且更便于综合、时域传递和修改,还能建立独立于工艺的设计文件,所以,擅长软件编程的人一旦掌握了HDL和一些必要的硬件知识,往往可以比习惯于传统设计的工程师设计出更好的硬件电路和系统。所以,习惯于传统设计的工程师应该学会用HDL来描述和编程。 

嵌入式系统设计的3个层次

嵌入式系统设计有3个不同层次:

第1层次:以PCB CAD软件和ICE为主要工具的设计方法

这是过去直至现在我国单片机应用系统设计人员一直沿用的方法,其步骤是先抽象后具体。

抽象设计主要是根据嵌入式应用系统要实现的功能要求,对系统功能细化,分成若干功能模块,画出系统功能框图,再对功能模块进行硬件和软件功能实现的分配。

具体设计包括硬件设计和软件设计。硬件设计主要是根据性能参数要求对各功能模块所需要使用的元器件进行选择和组合,其选择的基本原则就是市场上可以购买到的性价比最高的通用元器件。必要时,须分别对各个没有把握的部分进行搭试、功能检验和性能测试,从模块到系统找到相对优化的方案,画出电路原理图。硬件设计的关键一步就是利用印制板(PCB)计算机辅助设计(CAD)软件对系统的元器件进行布局和布线,接着是印制板加工、装配和硬件调试。

工作量最大的部分是软件设计。软件设计贯穿整个系统的设计过程,主要包括任务分析、资源分配、模块划分、流程设计和细化、编码调试等。软件设计的工作量主要集中在程序调试,所以软件调试工具就是关键。最常用和最有效的工具是在线仿真器(ICE)。

第2层次:以EDA工具软件和EOS为开发平台的设计方法

随着微电子工艺技术的发展,各种通用的可编程半定制逻辑器件应运而生。在硬件设计时,设计师可以利用这些半定制器件,逐步把原先要通过印制板线路互连的若干标准逻辑器件自制成专用集成电路(ASIC)使用,这样,就把印制板布局和布线的复杂性转换成半定制器件内配置的复杂性。

然而,半定制器件的设计并不需要设计人员有半导体工艺和片内集成电路布局和布线的知识和经验。随着半定制器件的规模越来越大,可集成的器件越来越多,使印制板上互连器件的线路、装配和调试费用越来越少,不仅大大减少了印制板的面积和接插件的数量,降低了系统综合成本,增加了可编程应用的灵活性,更重要的是降低了系统功耗,提高了系统工作速度,大大提高了系统的可靠性和安全性。

这样,硬件设计人员从过去选择和使用标准通用集成电路器件,逐步转向自己设计和制作部分专用的集成电路器件,而这些技术是由各种EDA工具软件提供支持的。

半定制逻辑器件经历了可编程逻辑阵列PLA、可编程阵列逻辑PAL、通用阵列逻辑GAL、复杂可编程逻辑器件CPLD和现场可编程门阵列FPGA的发展过程。其趋势是集成度和速度不断提高,功能不断增强,结构趋于更合理,使用变得更灵活和方便。

设计人员可以利用各种EDA工具和标准的CPLD和FPGA等,设计和自制用户专用的大规模集成电路。然后再通过自下而上的设计方法,把用半定制器件设计自制的集成电路、可编程外围器件、所选择的ASIC与嵌入式微处理器或微控制器在印制板上布局、布线构成系统。

第3层次:以IP内核库为设计基础,用软硬件协同设计技术的设计方法

20世纪90年代后,进一步开始了从“集成电路”级设计不断转向“集成系统”级设计。目前已进入单片系统SOC(System o-n a chip)设计阶段,并开始进入实用阶段。这种设计方法不是把系统所需要用到的所有集成电路简单地二次集成到1个芯片上,如果这样实现单片系统,是不可能达到单片系统所要求的高密度、高速度、高性能、小体积、低电压、低功耗等指标的,特别是低功耗要求。

单片系统设计要从整个系统性能要求出发,把微处理器、模型算法、芯片结构、外围器件各层次电路直至器件的设计紧密结合起来,并通过建立在全新理念上的系统软件和硬件的协同设计,在单个芯片上完成整个系统的功能。有时也可能把系统做在几个芯片上。因为,实际上并不是所有的系统都能在一个芯片上实现的;还可能因为实现某种单片系统的工艺成本太高,以至于失去商业价值。目前,进入实用的单片系统还属简单的单片系统,如智能IC卡等。但几个着名的半导体厂商正在紧锣密鼓地研制和开发像单片PC这样的复杂单片系统。

单片系统的设计如果从零开始,这既不现实也无必要。因为除了设计不成熟、未经过时间考验,其系统性能和质量得不到保证外,还会因为设计周期太长而失去商业价值。

为了加快单片系统设计周期和提高系统的可靠性,目前最有效的一个途径就是通过授权,使用成熟优化的IP内核模块来进行设计集成和二次开发,利用胶粘逻辑技术GLT(Glue Logic Technology),把这些IP内核模块嵌入到SoC中。IP内核模块是单片系统设计的基础,究竟购买哪一级IP内核模块,要根据现有基础、时间、资金和其他条件权衡确定。

购买硬IP内核模块风险最小,但付出最大,这是必然的。但总的来说,通过购买IP内核模块不仅可以降低开发风险,还能节省开发费用,因为一般购买IP内核模块的费用要低于自己单独设计和验证的费用。当然,并不是所需要的IP内核模块都可以从市场上买得到。为了垄断市场,有一些公司开发出来的关键IP内核模块(至少暂时)是不愿意授权转让使用的。像这样的IP内核模块就不得不自己组织力量来开发。

这3个层次各有各的应用范围。从应用开发角度看,在相当长的一段时间内,都是采用前2种方法。第3层次设计方法对一般具体应用人员来说,只能用来设计简单的单片系统。而复杂的单片系统则是某些大的半导体厂商才能设计和实现的,并且用这种方法实现的单片系统,只可能是那些广泛使用、具有一定规模的应用系统才值得投入研制。还有些应用系统,因为技术问题或商业价值问题并不适宜用单片实现。当它们以商品形式推出相应单片系统后,应用人员只要会选用即可。

所以,3个层次的设计方法会并存,并不会简单地用后者取代前者。 初级应用设计人员会以第1种方法为主;富有经验的设计人员会以第2种方法为主;很专业的设计人员会用第3种方法进行简单单片系统的设计和应用。但所有的设计人员都可以应用半导体大厂商推出的用第3种方法设计的专用单片系统。

来源:嵌入式ARM

围观 324

嵌入式产品,与普通电子产品一样,开发过程都需要遵循一些基本的流程,都是一个从需求分析到总体设计,详细设计到最后产品完成的过程。但是,与普通电子产品相比,嵌入式产品的开发流程又有其特殊之处。它包含嵌入式软件和嵌入式硬件两大部分,针对嵌入式硬件和软件的开发,在普通的电子产品开发过程中,是不需要涉及的。嵌入式产品的研发流程具体如下图:


下面,针对嵌入式产品的开发过程中的各个阶段,我们进行详细探讨。

阶段1:产品需求

在这一个阶段,我们需要弄清楚的是产品的需求从何而来,一个成功的产品,我们需要满足哪些需求。只有需求明确了,我们的产品开发目标才能明确。在产品需求分析阶段,我们可以通过以下这些途径获取产品需求:

1、市场分析与调研,主要是看市场有什么需求,还有就是前沿的技术是什么(站在做一款产品的角度);

2、客户调研和用户定位,从市场广大客户那获取最准确的产品需求(要注意分析市场,产品生命周期,升级是否方便);

3、利润导向(成本预算);

4、如果是外包项目,则需要我们的客户提供产品的需求(直接从客户那获取,让客户签协议)。

当一个项目做完的时候,如果客户突然又增加需求,增加功能,将导致你的项目周期严重拖延,成本剧烈上升,并且测试好的产品可能要全部重新测试,原本的设计可能将不会满足当前的要求,所以做项目之前,最好要跟客户把需求确定下来,并且签定一份协议,否则,你辛苦多少个日日夜夜,得到的将是一个无法收拾的烂摊子!

阶段2:产品规格说明

在前一个阶段,我们搜集了产品的所有需求。那么在产品规格说明阶段,我们的任务是将所有的需求,细化成产品的具体的规格,就比如一个简单的USB转串口线,我们需要确定产品的规格,包括:

1、产品的外观;

2、产品支持的操作系统;

3、产品的接口形式和支持的规范;

等等诸如此类,切记,在形成了产品的规格说明后,在后续的开发过程中,我们必须严格的遵守,没有200%的理由,不能随意更改产品的需求。否则,产品的开发过程必将是一个反复无期的过程。

《产品规格说明》主要从以下方面进行考虑:

1、考虑该产品需要哪些硬件接口;

2、产品用在哪些环境下,要做多大,耗电量如何。如果是消费类产品,还跟设计美观,产品是否便于携带,以确定板子大小的需求,是否防水;

3、产品成本要求;

4、产品性能参数的说明(例如交换机,如果是百兆的速率,用于家庭和一般公司;如果是用于整个省的交换,那设计的速率肯定数十万兆以上了)所以说,产品性能参数的不同,就会影响到我们设计考虑的不同,那么产品的规格自然就不同了;

5、需要适应和符合的国家标准,国际标准,或行业标准。

阶段3:产品总体设计方案

在完成了产品规格说明以后,我们需要针对这一产品,了解当前有哪些可行的方案,通过几个方案进行对比,包括从成本、性能、开发周期、开发难度等多方面进行考虑,最终选择一个最适合自己的产品总体设计方案。

在这一阶段,我们除了确定具体实现的方案外,我们还需要综合考虑,产品开发周期,多少人月的工作量,需要哪些资源或者外部协助,以及开发过程中可能遇到的风险及应对措施,形成整个项目的项目计划,指导我们的整个开发过程。

阶段4:产品概要设计

产品概要设计主要是在总体设计方案的基础上进一步的细化,具体从硬件和软件两方面入手:

硬件模块概要设计

硬件模块概要设计,主要从硬件的角度出发,确认整个系统的架构,并按功能来划分各个模块,确定各个模块的的大概实现。首先要依据我们到底要哪些外围功能以及产品要完成的工作,来进行CPU 选型(注意:CPU一旦确定,那么你的周围硬件电路,就要参考该CPU 厂家提供的方案电路来设计)。然后再根据产品的功能需求选芯片,比如是外接AD还是用片内AD,采用什么样的通讯方式,有什么外部接口,还有最重要的是要考虑电磁兼容。

一般一款CPU 的生存周期是5-8年,你考虑选型的时候要注意,不要选用快停产的CPU,以免出现这样的结局:产品辛辛苦苦开发了1到2 年,刚开发出来,还没赚钱,CPU又停产了,又得要重新开发。很多公司就死在这个上面。

软件模块概要设计

软件模块概要设计阶段,主要是依据系统的要求,将整个系统按功能进行模块划分,定义好各个功能模块之间的接口,以及模块内主要的数据结构等。

阶段5:产品详细设计

硬件模块详细设计

主要是具体的电路图和一些具体要求,包括 PCB和外壳相互设计,尺寸这些参数。接下来,我们就需要依据硬件模块详细设计文档的指导,完成整个硬件的设计。包括原理图、PCB 的绘制。

软件模块详细设计

功能函数接口定义,该函数功能接口完成功能,数据结构,全局变量,完成任务时各个功能函数接口调用流程。在完成了软件模块详细设计以后,就进入具体的编码阶段,在软件模块详细设计的指导下,完成整个系统的软件编码。

一定要注意需要先完成模块详细设计文档以后,软件才进入实际的编码阶段,硬件进入具体的原理图、PCB实现阶段,这样才能尽量在设计之初就考虑周全,避免在设计过程中反复修改。提高开发效率,不要为了图一时之快,没有完成详细设计,就开始实际的设计步骤。

阶段7:产品调试与验证

该阶段主要是调整硬件或代码,修正其中存在的问题和BUG,使之能正常运行,并尽量使产品的功能达到产品需求规格说明要求。

硬件部分:

1、目测加工会得PCB 板是否存在短路,器件是否焊错,或漏焊接;

2、测试各电源对地电阻是否正常;

3、上电,测试电源是否正常;

4、分模块调试硬件模块,可借助示波器、逻辑分析仪等根据。

软件部分:

验证软件单个功能是否实现,验证软件整个产品功能是否实现。

阶段8:测试

功能测试(测试不通过,可能是有 BUG);

压力测试(测试不通过,可能是有BUG 或哪里参数设计不合理);

性能测试(产品性能参数要提炼出来,供将来客户参考,这个就是你的产品特征的一部分);

其他专业测试:包括工业级的测试,例如含抗干扰测试,产品寿命测试,防潮湿测试,高温和低温测试(有的产品有很高的温度或很低的温度工作不正常,甚至停止工作)。

有的设备电子元器件在特殊温度下,参数就会异常,导致整个产品出现故障或失灵现象的出现;有的设备,零下几十度的情况下,根本就启动不了,开不了机;有的设备在高温下,电容或电阻值就会产生物理的变化,这些都会影响到产品的质量。这里要引出一个话题,工业级产品与消费类产品有什么区别呢?工业级的产品就要避免这些异常和特殊问题,有的产品是在很深的海里工作,或者在严寒的山洞工作,或者火热沙漠工作,或者颠簸的设备上,比如汽车;或者是需要防止雷击;所以这就是工业级产品跟消费类产品的区别,消费类的产品就不需要做这么多的测试。

阶段9:产品

通过上一阶段完整测试验证,在此阶段,即得到我们开发成功的产品。在此阶段,可以比较实际的产品和最初的形成的产品规格说明,看经过一个完整的开发过程,是否产品完全符合最初的产品规格说明,又或者,中途发现产品规格说明存在问题,对它进行了多少修改呢?

下面说说嵌入式硬件开发流程,一般分为8个阶段:


嵌入式产品的硬件形态各异,CPU 从简单的4 位/8 位单片机到32 位的ARM处理器,以及其他专用IC。另外,依据产品的不同需求,外围电路也各不相同。每一次硬件开发过程,都需要依据实际的需求,考虑多方面的因素,选择最合适的方案来。

硬件阶段1:硬件产品需求

和普通的嵌入式产品需求一样。阶段1:产品需求。

硬件阶段2:硬件总体设计方案

一个硬件开发项目,它的需求可能来自很多方面,比如市场产品的需要或性能提升的要求等,因此,作为一个硬件设计人员,我们需要主动去了解各个方面的需求并分析,根据系统所要完成的功能,选择最合适的硬件方案。

在这一阶段,我们需要分析整个系统设计的可行性,包括方案中主要器件的可采购性,产品开发投入,项目开发周期预计,开发风险评估等,并针对开发过程中可能遇到的问题,提前选择应对方案,保证硬件的顺利完成。

硬件阶段3:硬件电路原理图设计

在系统方案确定后,我们即可以开展相关的设计工作,原理设计主要包括系统总体设计和详细设计,最终产生详细的设计文档和硬件原理图。

原理设计和PCB

设计是设计人员最主要的两个工作之一,在原理设计过程中,我们需要规划硬件内部资源,如系统存储空间,以及各个外围电路模块的实现。另外,对系统主要的外围电路,如电源、复位等也需要仔细的考虑,在一些高速设计或特殊应用场合,还需要考虑EMC/EMI等。

电源是保证硬件系统正常工作的基础,设计中要详细的分析:系统能够提供的电源输入;单板需要产生的电源输出;各个电源需要提供的电流大小;电源电路效率;各个电源能够允许的波动范围;整个电源系统需要的上电顺序等等。

为了系统稳定可靠的工作,复位电路的设计也非常重要,如何保证系统不会在外界干扰的情况下异常复位,如何保证在系统运行异常的时候能够及时复位,以及如何合理的复位,才能保证系统完整的复位后,这些也都是我们在原理设计的时候需要考虑的。

同样的,时钟电路的设计也是非常重要的一个方面,一个不好的时钟电路设计,可能会引起通信产品的数据丢包,产生大的EMI,甚至导致系统不稳定。

原理图设计中要有“拿来主义”!现在的芯片厂家一般都可以提供参考设计的原理图,所以要尽量的借助这些资源,在充分理解参考设计的基础上,做一些自己的发挥。

硬件阶段4:PCB图设计

PCB 设计阶段,即是将原理图设计转化为实际的可加工的PCB 线路板,目前主流的PCB设计软件有PADS、Candence 和Protel 几种。

PCB 设计,尤其是高速PCB,需要考虑EMC/EMI,阻抗控制,信号质量等,对PCB设计人员的要求比较高。为了验证设计的PCB 是否符合要求,有的还需要进行PCB 仿真。并依据仿真结果调整PCB的布局布线,完成整个的设计。

硬件阶段5:PCB加工文件制作与PCB打样

PCB 绘制完成以后,在这一阶段,我们需要生成加工厂可识别的加工文件,即常说的光绘文件,将其交给加工厂打样PCB空板。一般1~4 层板可以在一周内完成打样。

硬件阶段6:硬件产品的焊接与调试

在拿到加工厂打样会的 PCB 空板以后,接下来我们,需要检查PCB空板是否和我们设计预期一样,是否存在明显的短路或断痕,检查通过后,则需要将前期采购的元器件和PCB 空板交由生产厂家进行焊接(如果PCB电路不复杂,为了加快速度,也可以直接手工焊接元器件)。

当PCB 已经焊接完成后,在调试PCB之前,一定要先认真检查是否有可见的短路和管脚搭锡等故障,检查是否有元器件型号放置错误,第一脚放置错误,漏装配等问题,然后用万用表测量各个电源到地的电阻,以检查是否有短路,这样可以避免贸然上电后损坏单板。调试的过程中要有平和的心态,遇见问题是非常正常的,要做的就是多做比较和分析,逐步的排除可能的原因,直致最终调试成功。

在硬件调试过程中,需要经常使用到的调试工具有万用表和示波器,逻辑分析仪等,用于测试和观察板内信号电压和信号质量,信号时序是否满足要求。

硬件阶段7:硬件产品测试

当硬件产品调试通过以后,我们需要对照产品产品的需求说明,一项一项进行测试,确认是否符合预期的要求,如果达不到要求,则需要对硬件产品进行调试和修改,直到符合产品需求文明(一般都以需求说明文档作为评判的一句,当然明显的需求说明错误除外)。

硬件阶段8:硬件产品

我们最终开发的硬件成功。一个完整的,完成符合产品需求的硬件产品还不能说明一个成功的产品开发过程,我们还需要按照预定计划,准时高质量的完成,才是一个成功的产品开发过程。

来源:互联网(版权归原著作者所有)

围观 361

嵌入式软件开发流程

参照嵌入式软件的开发流程。第一步:工程建立和配置。第二步:编辑源文件。第三步:工程编译和链接。第四步:软件的调试。第五步:执行文件的固化。

在整个流程中,用户首先需要建立工程并对工程做初步的配置,包括配置处理器和配置调试设备。编辑工程文件,包括自己编写的汇编和C语言源程序,还有工程编译时需要编写的链接脚本文件,调试过程中需要编写存储区映像文件和命令脚本文件,以及上电复位时的程序运行入口的启动程序文件。

对后四种文件的理解很重要,其作用解释如下。

(1)链接脚本文件:在程序编译时起作用。该文件描述代码链接定位的有关信息,包括代码段,数据段,地址段等,链接器必须使用该文件对整个系统的代码做正确的定位。在SDRAM中调试程序、在FLASH中调试或固化后运行的链接脚本文件应加以区分。(在IDE开发环境中使用扩展名*.ld)

(2)命令脚本文件:在SDRAM中调试程序时起作用。在集成环境与目标连接时、软件调试过程中以及目标板复位后,有时需要集成环境自动完成一些特定的操作,比如复位目标板、清除看门狗、屏蔽中断寄存器、存储区映射等。这些操作可以通过执行一组命令序列来完成,保存一组命令序列的文本文件称为命令脚本文件(在 IDE开发环境中使用扩展名*.cs)。

(3)存储区映像文件:在SDRAM中调试程序时起作用。在软件调试过程中访问非法存储区在部分处理器和目标板上会产生异常,如果异常没有处理,则会导致软件调试过程无法继续,为了防止以上问题并调整仿真器访问速度以达到最合适的水平,提供这样一种用于描述各个存储区性质的文件叫存储区映像文件(在IDE开发环境中使用扩展名*.map)。

在程序的调试过程中可以选择使用存储区映像文件*.map和命令脚本文件*. cs配合程序的调试。

(4)启动文件:它主要是完成一些和硬件相关的初始化的工作,为应用程序做准备。一般,启动代码的第一步是设置中断和异常向量;第二步是完成系统启动所必须的寄存器配置;第三步设置看门狗及用户设计的部分外围电路;第四步是配置系统所使用的存储区分配地址空间; 第五步是变量初始化;第六步是为处理器的每个工作模式设置栈指针;最后一步是进入高级语言入口函数(Main函数)。

中断程序设计

中断调试方面可以采用类似矢量中断动态处理方式,让中断对应的确定地址代码调转到RAM的固定地址处,定义一个函数指针指向该固定地址,就可以随时通过替换RAM固定地址处的代码,实现动态改变中断处理函数。

具体方法是:

(1)将中断源函数指针定义在RAM中相对的固定地址,建立中断矢量表;

  void SetInterrupt (U32 vector, void (*handler)()){ InterruptHandlers[vector] = handler;}

(2)在程序中,调用具体某中断源的中断处理函数;

  如: SetInterrupt(IIC_INT,IICWriteIsr);

  /* 声明IIC中断处理函数,其中IIC_INT为 IIC中断源序号,IICWriteIsr为 IIC的写中断处理函数 */

(3)在0x18处的IRQ或0x1C处的FIQ中断入口函数中,获取中断源、清除中断挂起标志、通过已定义的中断源函数指针进入用户具体某中断处理程序。

void ISR_IrqHandler(void){ IntOffSet = (unsigned int)INTOFFSET; Clear_PendingBit(IntOffSet>>2) ;(*InterruptHandlers[IntOffSet>>2])();// 调用具体某中断处理程序}

采用动态的中断处理方法,在中断源较多的情况下,中断响应时间和程序性能得到优化。另外,在调试方面,此处理方法具有便于跟踪调试的优点,并且根据需要,可以方便变换中断处理函数。

中断调试

软件调试可以在SDRAM中或FLASH中进行。在SDRAM中,读写方便,访问速度快。一般软件调试应在RAM中完成,但当RAM空间小于FLASH程序空间,程序只能在FLASH运行和调试时,或者用户希望了解程序在FLASH中实际运行情况时,就可以在FLASH中进行程序调试。

进行中断调试时,应注意中断入口位于SDRAM中或FLASH中0x18或0x1c地址,链接脚本文件必须使整个系统的代码正确定位于0x0起始处,但SDRAM或FLASH对应的链接脚本文件及工程配置注意区别。

(1)程序在SDRAM中运行

在SDRAM中调试,使用SDRAM对应的链接脚本文件。调试过程需要以下几步:编译、链接工程;连接仿真器和电路板;下载程序(在IDE开发环境中使用扩展名*.elf);调试。

下载程序前必须启动命令脚本文件完成前述的一些特定的操作,命令脚本文件的启动在连接仿真器时自动进行,其中存储区映射应与程序在SDRAM中运行时相同,保证整个系统的代码正确定位于0x0起始处。下载程序的起始地址也为0x0,下载成功后便可进行调试工作。

(2)程序在FLASH中运行

在FLASH中调试,使用FLASH对应的链接脚本文件。调试过程需要以下几步:编译、链接工程;连接仿真器和电路板;程序格式转换(*.elf转换为*.bin);固化*.bin程序;调试。

连接仿真器后不需要下载程序,存储区映射由本身工程中启动文件运行完成,不需要命令脚本文件。在本环境调试过程中,可以设置两个硬件断点。

(3)程序从FLASH中调到SDRAM中运行

在某些应用场合,强调程序运行速度的情况下,希望程序在SDRAM中运行,这样就需要将FLASH中存储的程序,在系统上电后搬运到SDRAM某空间位置,然后自动运行。这种所谓的Bootloader技术,在DSP系统中常被采用。

调试过程分两步:

(a)首先将用户程序在SDRAM中调试通过,然后将*.bin文件固化到FLASH某一非0扇区地址空间;

(b)将自己编写的Bootloader搬运程序调试通过并将Bootloader.bin文件固化到FLASH的 0扇区地址空间,搬运程序在系统上电后,将(a)中FLASH某一非0扇区地址空间存储的程序,搬运到在SDRAM调试中同样的空间位置,实现程序在SDRAM中运行的目的。

另外注意,因为用户实际的程序中断入口必须位于FLASH的0x18或0x1c地址,所以Bootloader搬运程序还应具有中断入口的跳转功能,即把PC指针由此转向处于SDRAM空间的中断程序入口表,就是整个用户程序被搬运到SDRAM的那一位置。

如:LDR PC, =HandleIRQ

  // HandleIRQ位于SDRAM空间中断程序入口表

来源:网络、嵌入式ARM

围观 176

嵌入式软件开发编程规范很重要,很重要,很重要!

demi的头像

Ⅰ 写在前面

不知道大家有没有这样的感受:看到不规范(杂乱差)的代码,瞬间就没有看下去的欲望了。

相信大家看到标题都应该能明白编程的规范及原则对于每一个软件开发的工程师来说是多么重要。

初学者编写测试程序、小的模块程序也许不能感受它的重要性;但有经验及大型项目开发的人就知道程序的规范性对他们来说是有多么的重要。

Ⅱ 关于编程规范及原则

编程规范也就是编写出简洁、可维护、可靠、可测试、高效、可移植的代码,提高产品代码的质量。

本文针对嵌入式,主要结合C语言编程的规范给大家讲述。

1. 头文件

对于C语言来说,头文件的设计体现了大部分的系统设计,不合理的头文件布局是编译时间过长的原因。

有很多人将工程中所有的头文件包含在一个include.h文件中,然后在每一个.c源代码文件中包含include.h头文件,这样做可以让代码看上去简洁,但实际忽视了编译效率问题,而且代码的可移植性也不好。

原则:

A. 头文件中适合放置接口的声明,不适合放置实现;
B. 头文件应当职责单一;
C. 头文件应向稳定的方向包含。

规则:

硬件电路设计的几个注意事项!

demi的头像

嵌入式设计是个庞大的工程,今天就说说硬件电路设计方面的几个注意事项,首先,咱们了解下嵌入式的硬件构架。

我们知道,CPU是这个系统的灵魂,所有的外围配置都与其相关联,这也突出了嵌入式设计的一个特点硬件可剪裁。在做嵌入式硬件设计中,以下几点需要关注。

第一、电源确定

电源对于嵌入式系统中的作用可以看做是空气对人体的作用,甚至更重要:人呼吸的空气中有氧气、二氧化碳和氮气等但是含量稳定,这就相当于电源系统中各种杂波,我们希望得到纯净和稳定符合要求的电源,但由于各种因素制约,只是我们的梦想。这个要关注两个方面:

a、电压

嵌入式系统需要各种量级的电源比如常见的5v、3.3v、1.8v等,为尽量减小电源的纹波,在嵌入式系统中使用LDO器件。如果采用DCDC不仅个头大,其纹波也是一个很头疼的问题。

b、电流

嵌入式系统的正常运行不但需要稳定足够的电源,还要有足够的电流,因此在选择电源器件的时候需要考虑其负载,我设计时一般留有30%的余量。

页面

订阅 RSS - 嵌入式