当前位置:首页 > 嵌入式软件
  • Mentor Graphics整合汽车技术平台,致力系统开发

      根据美国商业资讯报导,Mentor Graphics CorporaTIon宣布,该公司已经将近期收购的MontaVista汽车技术平台与Mentor® Embedded资讯娱乐基础平台及Sourcery™ CodeBench和SourceryAnalyzer开发工具进行整合。   新的Mentor Embedded汽车技术平台(ATP)完全符合Yocto Project 1.3和GENIVI 3.0规范,并且将继续追踪支援GENIVI即将推出的新版本。   嵌入式软件开发人员如今可以在采用LTTng(下一代Linux追踪工具套件)的Linux汽车技术平台上利用Mentor Embedded Sourcery Analyzer工具来轻松直觉地分析并除错Linux作业系统与汽车应用软件之间复杂的相互作用。   利用符合Yocto Project 1.3规范的新汽车技术平台(ATP)产品,一线供应商及汽车制造商(OEM)可以轻松客制和设定Linux核心,并挑选合适的Linux车载资讯娱乐系统元件。由于符合GENIVI 3.0规范以及飞思卡尔(Freescale) i.MX 6与瑞萨(Renesas) R-CAR H1硬件平台的要求,一线供应商和原汽车制造商可以将一整套性能优越的标准汽车元件运用到车载资讯娱乐系统的开发中。此外,他们还将受惠于对驱动程式和BSP的增强开发,包括提升视讯和音讯性能,从而为车载资讯娱乐系统的关键组成部分—多媒体应用程式—提供更有力的支援。   Mentor Graphics开放原始码嵌入式解决方案部门总经理Mark Mitchell表示:“在整合后的Mentor Embedded新汽车技术平台(ATP)上,汽车一线供应商和汽车制造商可以最佳化硬件性能并对扩展后的汽车级中介软件加以充分运用。”   透过在标准化组织里担任执行董事等高阶职位,Mentor Graphics继续引领以车载资讯娱乐系统应用为方向的Linux标准化发展,并为国际汽车工程师学会(SAE InternaTIonal)、AUTOSAR(汽车开放系统架构)和GENIVI Alliance等众多技术合作组织做出积极贡献。如今的汽车年销量已达4500多万辆,制造商们也意识到车载资讯娱乐系统是实现产品差异化进而吸引更多消费者的关键。   汽车制造商需要将各类技术整合在一起,如语音辨识、触控式萤幕、网页浏览、全球定位系统(GPS)以及汽车和智慧手机之间的连接,而这一切都依赖于嵌入式软件。Mentor建立一支经验广泛而丰富的专业服务团队,他们与客户密切合作,在竞争激烈的汽车市场定义和开发可客制的差异化车载资讯娱乐系统解决方案。   Mentor Graphics® Embedded软件事业部致力于汽车、工业、智慧能源、医疗设备和消费电子产品等不同应用的嵌入式软件开发。嵌入式软件开发人员利用产业领先的Sourcery CodeBench和Mentor Embedded Linux产品等可客制的Linux商务软件,开发适用于最新处理器和微控制器的系统。系统开发人员还利用存储器占用少、低功耗的Nucleus®即时作业系统来进行即时控制系统的开发。

    时间:2020-09-04 关键词: graphics mentor 嵌入式软件 微控制器 控制系统 汽车电子

  • 汽车电子软件开发岗是个不错的选择

    汽车电子软件开发岗是个不错的选择

     本人从事汽车电子软件开发,有着几年的嵌入式软件开发经验。而且我就是学的车辆工程专业,那个当下不被看好的专业。软件的开发又分为应用层软件开发和底层软件开发,接下来的内容以应用层软件开发展开。 汽车电子软件开发的工作内容? 首先,汽车软件属于嵌入式软件开发,跟互联网行业软件开发差别很大。如果用简单一句话总结就是:设计控制器的代码来实现汽车所需要的功能。例如自动感应的雨刮器,随车转向头灯。看见代码两个字不要怕,不要想象成当码农的场景。 其中大部分代码都是基于图形化设计,且自动生成代码。然后将生成的代码与底层软件等代码集成到一起。编译下载到控制器,实现想要的汽车功能。 展开介绍一下,这其中核心要素就是需要实现什么样的功能,也就是具体的开发需求。然后就是根据需求搭建逻辑,使用simulink或targetlink按照相应的标准和规范进行代码的图形化设计和自动生成,将相关的优化参数设置好,自动生成的代码在一定程度上比手写更加规范。然后把自动生成的代码集成到整个软件工程中去。这其中难点就是逻辑的实现,也就是你的算法。 举个最简单的例子来说:控制汽车大灯的延时关闭,当检测到钥匙离开汽车,并且大灯在开启状态。车门关闭后大灯延时30秒关闭。自行想一下,用simulink如何实现。   以上是比较通俗的理解,其中有很多的规范和流程还需要学习,流程是标准的V流程(自行百度),V流程开发就离不开选择各种开发工具进行组合以实现各环节的要求。目前开发工具类型很多,互相重叠或互补。好机遇,例如全新开发类的ECU软件工作。 当下对于刚入行的人来说是比较难得的机会。因为软件的架构要从无到有一点点搭建起来,所以你参与的过程中可以熟悉整个软件工程。但是对于大部分的工作内容可能是维护类的(前期整个软件工程已经建立完毕,你只需要修改相关的功能),你需要做的就是先熟悉整个现有软件的结构,对照需求清楚每个功能的实现。再根据具体的需求进行维护和修改。 为什么推荐汽车电子软件开发? 虽目前汽车行业不景气,但在制造业中汽车行业还是算相对好的了,对于车辆工程或者机械工程的学生,如果没有转型的能力,还是建议选择汽车行业。那如何选择一个具体的方向呢。 汽车行业热度不减的就是智能驾驶,车联网和新能源相关的BMS,驱动了吧,但是据我所知,大部分国内OEM(自主+合资)这两部分的业务都是外包的形式。OEM做的是提具体的功能需求,样品的测试。剩下的具体实现以及各种问题的解决均由供应商来做,好在很多供应商现在是国内的科技公司。所以在OEM搞这两个方向就是负责需求管理或者测试工作在或者就是部件的排布布置工作。那么相比于这两个方向,汽车电子软件开发的技术含量也不低,优于其他传统方向,以上是其中一方面。 另一方面,传统的电子软件开发,国内南北号称最好的一些自主研发中心,有些主要软件部门是最近几年才真正成立或者从其他部门分剥出来的。因为以前主要软件都是被那么几个供应商垄断的,不仅仅从技术上垄断,也从规范和开发流程的经验上垄断。为了降成本,提高新趋势下的竞争力,全球都开始搞自主研发,需要人的坑儿指数级上升,萝卜就那么几颗。别看很多软件研发部门有上百人的规模,80%以上是应届毕业生或者前几届应届生。从另外一个角度来看,汽车上控制器无疑会越来越多,所以缺口比传统方向(底盘,车身,内外饰)要大很多。正因为缺口大一些薪资也要更高一些。   汽车电子软件方向的职业选择 主机厂OEM: 在OEM做电子软件工程师,无论是整车控制器还是车身控制器等。表面上软件开发和OEM两个工作性质差的有点远,其实不然,上面也提到了全球都开始搞自主研发。它的地位极其重要的,在车企中,需要有一部分人真正懂汽车电子软件,才能发展和提升自己的自主能力,这样才不会被供应商牵着鼻子走。尤其是相关部门规定了一部分企业的控制器软件的自主化率的必达指标,必须满足自主化率的要求。 主机厂电子软件工程师相比于其他的汽车工程师的不可替代性更高。举个例子来说,生产现场需要软件工程师,线束设计工程师,车身设计工程师,底盘设计工程师等应对装车问题。若是机械结构问题车身可以代表底盘工程师一起去现场解决,但出现电控软件问题,其他方向的汽车工程师是不懂软件的,只有软件工程师才能将问题解决。但线束的问题电子软件工程师可以帮着解决。同时你在OEM看到的是整个汽车,你遇到的问题也会是系统的问题。所以你了解的是整车.你以后职业生涯的路也不会很窄。 供应商Tier: 在供应商工作,你非常了解和熟悉的就是你负责的那个部件,对于其设计也会更加规范和详细,但缺少汽车的整体系统思想。一个主机厂一个供应商,各有优缺点,OEM搞得比较广,对于汽车的了解较深刻,跳槽时机会会多一些。在供应商做的比较精,同样路比较窄,还不一定能负责核心的工作。所以建议应届生先在OEM,然后跳槽去供应商,工龄超过五年的甚至可以直接作为主管。以上,大家最关注的是...竟然没谈钱。你随便去猎聘搜搜,就能知道啦,生涯上限普遍高于35万年薪。   哪些专业可以做,如何自学,自学之后能得到认可吗,可以去哪些企业?其实从事这个方向的专业本身就很多:计算机、自动化、车辆、电子信息,控制工程等。 关于自学方式,从车辆的角度说一下,类似专业同理。首先你要去学,推荐单片机学习:51单片机。学语言:《C语言程序设计》。MATLAB学习:《simulink仿真及代码生成技术入门到精通》。以上重要的是多加练习。也可以花一点时间去下载网络资源或者课程。 能找到什么样的企业? 进入汽车行业,简历的筛选大部分一是学校学历,另一个是专业。如果学校过关,车辆工程一定不是你被刷掉的原因(今年一汽大众除外)。面试时就靠你个人魅力和肚子里的墨水吧。其实求转型的前提下,这些后期问题都是无关紧要的。如果你不去学就没机会,你去学了,机会自然是有的,可能不是你的起点,也许两年,也许三年后才有机会,总之不准备就彻底没戏了。 然后是会不会得到认可? 只要你学懂了,脑子里有货。招聘的人多有技术参与,他很可能认可你,如果不懂,当你自信满满的介绍你的个人所学所长,其实也会被揭穿。而且,正因为你不仅仅了解汽车构造,还懂得电子控制,更会得到企业和同事的认可---最懂汽车的电子软件工程师,哈哈。

    时间:2019-10-19 关键词: 汽车电子软件 嵌入式软件 汽车电子

  • 物联网 – 以RSL10 SDK3.0提供一个嵌入式软件基础

    物联网 – 以RSL10 SDK3.0提供一个嵌入式软件基础

     您能跳过一些测试吗?您修复最后一个漏洞了吗?需要把日程安排好。您不是在开发硬件-这只是软件。 开发好的软件需要时间。就像烤蛋糕一样,许多原料必须在适当的时间组合在一起。编码标准、代码审核、持续集成、测试驱动的开发和静态分析只是几个例子。但时间呢? 今天的嵌入式软件开发人员比以往任何时候都更努力地在更短的时间内开发更多的东西,以跟上物联网(IoT)这个不断扩展的世界。 IoT这个术语基本上可以适用于当今任何具有联接性、感知/驱动或某种形式的远程数据处理的行业。它描述了当今几乎所有的嵌入式系统应用。IoT的爆发式增长给嵌入式软件开发人员带来了巨大的压力,要求他们在更短的时间内交付高质量的功能代码。 如今从零开始一个嵌入式软件开发项目并且仍然按期限完成是不可能的。项目的整个开发周期可能只是用于读取数据表和开发驱动程序,只留下很少或根本没有时间研究产品。 今天的嵌入式开发人员必须依靠半导体供应商提供软件基础,以便他们可以专注于最终应用程序。除了独立驱动程序之外,这基础还必须包括演示驱动程序或驱动程序组合的有时复杂使用的示例应用程序以及演示如何实现硬件最大价值的更高级别应用程序示例。 为帮助开发人员按时提供蓝牙低功耗应用软件项目,安森美半导体推出了支持RSL10无线电系统单芯片(SoC)的RSL10软件开发套件(SDK)3.0。 RSL10是行业功耗最低的蓝牙®低功耗无线电,但这硬件只是解决方案的一半。 RSL10 SDK 3.0使用Arm®的最新CMSIS-Pack标准来分发固件,并为嵌入式软件开发人员提供快速开发其终端应用特定软件的基础和工具。 RSL10 SDK 3.0 CMSIS-Pack软件栈 此图显示了RSL10 SDK 3.0 CMSIS-Pack软件栈。有三种不同的CMSIS-Pack提供不同的功能。 RSL10 CMSIS-Pack包含符合CMSIS标准的驱动程序FreeRTOS、蓝牙低功耗栈和硬件抽象层(HAL) - 基础。还提供了示例应用程序,可以轻易单独或组合地测试每个组件,以轻易地一次集成一个组件。对于网状网络,只需下载并安装RSL10蓝牙网状包(RSL10 Bluetooth Mesh Package),即可开始使用各种示例应用程序。也可通过Google Play商店下载我们的移动应用程序。 对于那些寻求完整的节点到云平台的人来说,蓝牙物联网开发套件CMSIS-Pack包含特定的传感器驱动程序,云支援和更高级别的应用程序示例。 安森美半导体基于Eclipse的集成开发环境(IDE)可免费下载,并支持ARM®Keil® µVision®和IAR Embedded Workbench®环境。 开发好的软件需要时间。安森美半导体提供该基础,因此您可以专注于开发好的软件并实现您的IoT应用的最大价值。

    时间:2019-09-03 关键词: 物联网 大数据 rsl10 sdk3.0 嵌入式软件

  • 嵌入式软硬件系统开发的解析

    嵌入式软硬件系统开发的解析

    嵌入式系统是用来控制或者监视机器、装置、工厂等大规模设备的系统。国内普遍认同的嵌入式系统定义为:以应用为中心,以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗等严格要求的专用计算机系统。  计算机作为20世纪人类社会最伟大的发明之一,近期也逐步迈入后PC时代。后PC时代的到来也标志着嵌入式产品的诞生,如手机、PDA、数控机床等。 中国拥有世界上最大的消费电子产品市场,手机、彩电、VCD、家用电器等的拥有量都居世界第一。随着经济水平的提高和消费结构的改变,人们对消费电子产品的要求越来越高,如产品的灵活性、可控性、耐用性、高性价比等,这些都可以通过合理、有效的嵌入式系统设计和优化来实现。另外,在现代化的医疗、测控仪器和机电产品中对系统的可靠性、实时性要求较高,更需要有专用的嵌入式系统的支持,这些需求都极大地刺激了嵌入式系统的发展和产业化的进程。嵌入式系统的发展将会更加完善信息产业的框架,成为信息产业发展的加速器。随着嵌入式系统复杂度的提高,软硬件的协同是嵌入式系统的关键。 嵌入式系统的定义 从产品的应用角度来说,嵌入式系统是控制、监视或者辅助设备机器和车间运行的装置。而众多不同专业的人士从各自不同的角度思考和定位嵌入式系统,所以目前对嵌入式系统的定义非常多。 嵌入式系统按照目前业界和学术界对嵌入式系统的普遍看法,是以应用为中心,以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。 嵌入式硬件系统 大多数嵌入式系统的硬件平台。它包括两部分: 1、以通用处理器为中心的协议处理模块,用于网络控制协议的处理; 2、以数字信号处理器(DSP)为中心的信号处理模块,用于调制、解调和数/模信号转换。     硬件系统结构 嵌入式系统的核心部件是各种类型的嵌入式处理器,目前据不完全统计,当前全世界嵌入式处理器的品种总量已经超过1000多种,流行体系结构有30几个系列。由于嵌入式系统设计的差异性极大,因此选择是多样化的。 嵌入式处理器的功耗、体积、成本、可靠性、速度、处理能力、电磁兼容性等均受到应用要求的制约。在选择处理器时要考虑的主要因素在于调查上市的CPU供应商、处理器的处理速度、技术指标、处理器的低工耗、处理器的软件支持工具、处理器是否内置调试工具、处理器供应商是否提供评估板等。 嵌入式软件系统 尽管嵌入式系统有着无比广阔的市场需求和发展前景,但嵌入式系统的发展多年来却经历了一个曲折和痛苦的历程。随着微处理器的产生,价格低廉、结构小巧的CPU和外设连接提供了稳定可靠的硬件架构,那么限制嵌入式系统发展的瓶颈就突出表现在了软件方面。 从运行平台来分,嵌入式软件可以分为: 1、运行在开发平台上的软件:设计、开发、测试工具等 2、运行在嵌入式系统上的软件:嵌入式操作系统、应用程序、驱动程序及部分开发工具 可用于嵌入式系统软件开发的操作系统很多,但选择一个适合的操作系统,关键是从操作系统提供那些开发工具、操作系统向硬件接口移植的难度、操作系统的内存要求、开发人员是否熟悉此操作系统及其提供的API、操作系统是否有提供硬件的驱动程序、操作系统是否具有可剪裁、操作系统的实时性等方面进行考虑。 嵌入式应用软件是实现嵌入式系统功能的关键,为了提高执行速度和系统可靠性,嵌入式软件一般都固化在存储器芯片或单片机本身中,而不是存储于磁盘等载体中,软件代码要求高质量、高可靠性和高实时性。 嵌入式系统的特点与应用 嵌入式系统的硬件和软件都必须量体裁衣,与通用型处理器相比,嵌入式处理器的最大不同是将大部分工作用在为特定用户群设计的系统中,它通常都具有低功耗、体积小、集成度高等特点,能够把很多任务集成在芯片内部,从而有利于嵌入式系统设计趋于小型化,使得移动能力大大增强。 嵌入式处理器的功耗、体积、成本、可靠性、速度、处理能力、电磁兼容性等均受到应用要求的制约。 嵌入式微处理器具备4个特点: 1、对实时多任务有很强的支持能力 嵌入式系统能完成多任务并且有较短的中断响应时间,从而使内部的代码和实时内核的执行时间减少到最低限度。 2、具有功能很强的存储区保护功能 由于嵌入式系统的软件结构已模块化,而为了避免在软件模块之间出现错误的交叉作用,需要设计强大的存储区保护功能,同时也有利于软件诊断。 3、可扩展的处理器结构 可扩展的处理器结构能最迅速地开发出满足应用的最高性能的嵌入式微处理器。 4、功耗很低 用于便携式的无线及移动的计算和通信设备中,靠电池供电的嵌入式系统功耗是mW甚至μW级。

    时间:2019-07-24 关键词: 嵌入式开发 vcd 嵌入式硬件 嵌入式软件

  • RT-Thread启动嵌入式软件人才计划及开发者能力认证

    RT-Thread启动嵌入式软件人才计划及开发者能力认证

      睿赛德科技宣布全面启动嵌入式软件人才计划,并推出业内首个IoT OS工程师能力认证——RAC(RT-Thread开发者能力认证,RT-Thread Ability Certification),旨在推动嵌入式及物联网人才的培养和发展,为企业的人才需求建立参考标杆。 据预计,到2020年,中国物联网市场规模将达2万亿元,并且还将保持高速增长。然而市场上物联网人才的短缺可能会阻碍这种增长,传统企业的纷纷“触网”导致人才缺口持续扩大,相关报告指出,过去一年来市场对物联网技术的人才需求增长了35%。随着AI技术的发展,物联网结合AI相关人才的需求将会更加强烈。依托RT-Thread 12年多的技术沉淀和生态建设,睿赛德科技此次启动的嵌入式软件人才计划包括人才的培养、RAC能力认证和企业人才服务三大部分,构建物联网终端软件人才发展闭环,为填补物联网人才缺口贡献一己之力。 人才的培养 睿赛德科技将会开展线上线下的多种培训活动如线上学习营、大学生雄鹰计划、免费入门培训和收费培训,来满足不同阶段的软件爱好者的学习需求。 其中的收费培训, 将采取与专业培训机构合作的方式来展开。 培训内容将逐渐覆盖嵌入式系统、RT-Thread内核及组件、嵌入式AI、应用开发等。 RAC能力认证 由睿赛德科技官方组织的统一考试和认证,旨在培养和展现开发者分析问题、解决问题和嵌入式程序设计的能力,科学评价嵌入式软件设计人才,并为企业招聘、选拔人才提供参考标准。 RAC能力认证包含RCEA(RT-Thread Certified Embedded Associate,RT-Thread认证嵌入式工程师)、 RCEP(RT-Thread Certified Embedded Professional,RT-Thread认证嵌入式资深工程师)、RCEE(RT-Thread Certified Embedded Expert,RT-Thread认证嵌入式专家)三个等级。 企业人才服务 市场对软件人才的需求最终都落实到各个企业,依托RT-Thread活跃的开发者生态、广泛的芯片原厂和终端企业合作伙伴,针对有人才需求的企业,只要加入该人才计划,即可对接睿赛德科技的人才库,得到人才的推荐和人才评估指导,且每年可以接受一次RT-Thread官方提供的OS专业培训。 RT-Thread开发者能力认证 经过长期大量繁重的筹备工作,RT-Thread终于准备就绪,正式启动RAC能力认证。RAC能力认证针对物联网开发人员的技能提出了具体的要求,其涵盖C语言设计、数据结构、RTOS原理、TCP/IP 协议和网络编程、Cortex M处理器以及RT-Thread应用开发、嵌入式AI等知识,认证不仅仅考查开发者对嵌入式领域知识的掌握程度,还考查开发者的实际应用开发能力。 RCEA(RT-Thread认证嵌入式工程师)考试报名入口 https://www.rt-thread.org/page/rac.html (请在PC端将以上网址复制至外部浏览器打开) 先期开放的是RCEA认证考试,即日起,开发者可以登录官网报名。通过RCEA认证,将证明你掌握了嵌入式领域基础知识,掌握了RTOS的原理,具备基本的嵌入式开发及调试能力,并能将RT-Thread应用于项目之中。 通过RCEA认证的开发者将会根据开发者的意愿展示于官网,并且获得相应的认证证书,同时也可在官网查询到对应的证书编号,证书永久有效。 睿赛德科技发布的嵌入式软件人才计划及RT-Thread开发者能力认证,将会大大加速物联网产业人才的培养,提升开发人员的技能,建立企业物联网人才选用标准。在迎接IOT和AI产业实际落地进程中,让我们一起成为AIOT时代的开创者和建设者! 相关咨询服务 o如果您是相关培训机构,并有意愿开设相关培训课程,请拨打:147 2107 7260,或加微信:RT-Thread2006 洽谈合作。 o如果您是相关企业,并希望加入嵌入式软件人才计划(培训/人才输送),请拨打:147 2107 7260,或加微信:RT-Thread2006 洽谈咨询。

    时间:2019-03-26 关键词: 物联网 行业资讯 睿赛德科 嵌入式软件

  • 首发:周立功教授《嵌入式软件工程方法与实践丛书》在北航正式出版开售

    近日,由周立功教授主导撰写的《嵌入式软件工程方法与实践丛书》前三本,共计200万字,在全国嵌入式系统联谊会10周年技术研讨会上正式发布,目前已由北京航空航天大学出版社出版,于京东商城盛大发售。 目前,《嵌入式软件工程方法与实践丛书》已完成以下三本的撰写: l《面向AWorks框架和接口的编程》(上) l《程序设计与数据结构》 l《面向AMetal框架和接口的编程》 一、《面向AWorks框架和接口的编程》(上)     1、内容介绍 代码的优劣不仅直接决定了软件的质量,还将直接影响软件成本。软件成本是由开发成本和维护成本组成的,而维护成本却远高于开发成本,蛮力开发的现象比比皆是,大量来之不易的资金被无声无息地吞没,造成社会资源的严重浪费。为何不将复杂的技术高度抽象呢?如果实现了就能做到让专业的人做专业的事,AWorks就是在这样的背景下诞生的。由于其中融入了更多的软件工程技术方法,因此就能做到将程序员彻底从非核心域中解脱出来,专注于核心竞争力。 AWorks制定了统一的接口规范,并对各种MCU内置的功能部件与外围器件进行了高度的抽象,因此无论你选用的是ARM还是DSP,只要以高度复用的软件设计原则和只针对接口编程的思想为前提,应用软件就可实现“一次编程、终生使用、跨平台”,AWorks所带来的最大价值就是不需要重新发明轮子。 2、适读人群 本书作为AWorks的基础教材,重点介绍ZLG在平台战略中所推出的AWorks开发平台,适合从事嵌入式软件开发、工业控制或工业通信的工程技术人员使用,也可作为大学本科、高职高专电子信息、自动化、机电一体化等专业的教学参考书。 3、京东链接     长按二维码识别打开 二、《程序设计与数据结构》     1、内容介绍 本书是C程序设计的进阶书籍,在介绍C语言基础知识的同时,重点强调了软件设计的思想:共性与可变性分析、面向对象的编程思想等,并提供了详尽的范例程序。使读者体会到思想的重要性,面向对象编程并不局限于特定语言,使用C语言同样可以进行面向对象的编程。 本书分为4章: 第1章,主要介绍C语言的基础知识,并提及了共性与可变性分析; 第2章,主要介绍C语言的进阶用法,特别是结构体及函数指针; 第3章,主要介绍算法与数据结构,包含链表、哈希表、队列等; 第4章,主要介绍面向对象的编程思想,包含面向对象的基础概念、虚函数的妙用、状态机设计等。 2、适读人群 本书既可作为高等院校本科、高职高专电子信息工程、自动化、机电一体化及计算机专业的教材,也可作为电子及计算机编程爱好者的自学用书,还可作为软件开发工程技术人员的参考书。 3、京东链接     长按二维码识别打开 三、《面向AMetal框架和接口的编程》     1、内容介绍 人与人之间的差别不完全取决于知识和经验,思维方面的差异才是决定了每个人未来高度的关键所在。AMetal是ZLG在平台战略中推出的开发平台,适用于小资源MCU(Cortex-M0、Cortex-M3等),《面向AMetal框架和接口的编程》对AMetal框架进行了详细的介绍,深入浅出,列举了大量的范例程序。 通过阅读这本书,读者不仅可以深入理解AMetal,将AMetal快速应用于实际项目中,更重要的是,可以学习到高度复用的软件设计原则和面向接口编程的开发思想,聚焦自己的“核心域”,改变自己的编程思维,实现企业和个人的共同进步。 2、适读人群 本书适合从事嵌入式软件开发、工业控制或工业通信的工程技术人员使用,也可作为大学本科、高职高专电子信息、自动化、机电一体化等专业学生的教学参考书,使学生在掌握MCU及各类外设使用方法的同时,还可以学习到在嵌入式开发中使用C实现面向对象的编程思想。 3、京东链接     长按二维码识别打开

    时间:2018-11-28 关键词: 周立功 c程序设计 嵌入式软件

  • 基于JAVA的工业控制移动数据通信解决方案

    基于JAVA的工业控制移动数据通信解决方案

    J2ME技术目前在手机行业取得了较大成功,已经成为手机增值开发平台的业界事实标准,它创造性解决了不同软硬件平台上统一应用开发的问题把这个思路引入到工业控制无线数传终端,具有广阔的市场前景在工业控制系统中利用J2ME技术,不但可以降低系统的开发难度、实现嵌入式环境中基于服务级的互操作,而且可使系统具有很好的灵活性和可靠性使无线数传终端实现了模块化、构件化设计,大大提高了系统的可扩展性与可扩充性JAVA嵌入式软件具有标准的程序接口和协议,可解决应用互联带来的各种问题,消除不同软件、硬件系统之间的异构问题,可支持各种通讯协议、各种通讯服务模式、传输各种数据内容、数据格式翻译、流量控制、数据加密、数据压缩等;JAVA嵌入式软件还可解决安全控制、并发控制、可靠性保证、效率保证等,实现了数据资源的有效共享,并能提供基于不同平台的丰富的开发接口、支持流行的开发工具 在工业控制系统中使用J2ME技术的优势:提供了一种独立于厂商的服务平台,使得不同厂商的现场控制系统可以相互兼容将工业控制系统中每个设备提供的功能都可以映射成J2ME服务,使其不仅可以被现场总线使用,而且还可以被支持J2ME的任何设备(如PDA)来访问;简化网络编程,提高系统的安全性;将Java技术应用到无线数传终端产品中主要具有以下几个方面的好处:将Java技术应用到无线数传终端产品中主要具有以下几个方面的好处:可以容易地连接到Internet,这样系统变成了开放的,提高了设备的可访问性;使工业控制系统中的设备可以与家用消费电器和自动化设备通信,增强设备的功能。1、产品简介 基于JAVA的工业控制无线数传终端是根据工业控制领域行业用户需求特点专门设计开发的具有良好的扩展性和可移植性产品提供完整的PPP 协议及上层TCP/IP 协议,具有路由功能,提供100BaseT以太网接口、RS232、RS485等多种标准接口产品具有性能高、体积小、供耗低、组网灵活、配置简单、扩展性强的特点,支持实时数据采集、远程监控、营业网点接入等各种行业应用可广泛应用于工业现场控制、数据采集、交通监控、远程业务点接入等多种领域,也可以内置于控制面板,智能仪表等设备中,充分满足行业用户开展无线数据应用的需求无线数传终端产品系列包括:(1)无线数传终端内建TCP/IP 功能及标准的串行端口功能,集成工业级GPRS/CDMA1X 模块,并提供完备的电源系统,使用方便简洁GPRS 无线数传终端CDMA1X 无线数传终端。(2)嵌入式开发板内建TCP/IP功能及标准的串行端口功能,用户可灵活选配GPRS/CDMA1X模块,自定义产品尺寸该嵌入式开发板便于二次开发和快速整合到用户原有系统,并通过软硬件整体解决方案满足行业用户快速开发无线网络应用的需要。2、技术来源 中联科技开发的无线数传终端产品核心技术来源于国家“863”计划《无线移动自组织互联网技术及实验系统研制》技术成果,产品具有两方面的核心技术:(1)具有完整的嵌入式TCP/IP协议和GPRS、CDMA公众无线数据网络通信(2)具有针对应用的J2ME开放开发平台目前,相关产品多集中在以PC机为架构扩展通信模块,利用PC上的资源来完成相应工作的公用市场,其中代表性产品就是GPRS、CDMA无线上网卡其特点是产品价格较高,同时应用对行业没有深入渗透,难以形成行业规模产业目前移动数据网络设备处于一个新兴的蓬勃发展阶段,由于GPRS、CDMA公众无线数据网络采用TCP/IP 技术,因此相应的行业工控终端首先要解决TCP/IP 相关技术的长期积累国内目前的技术方案多采用传统8051单片机增加简单的PPP协议来实现,而我们开发的无线数传终端产品是在已成熟的宽带路由器和SNMP 网管设备等产品的基础上发展起来的全新系列产品,硬件采用全新的ARM7 32位嵌入式RISC CPU,处理能力及系统资源提高10倍以上;软件上采用完整的嵌入式OS及TCP/IP协议包,整体方案具有如下技术优势:(1)完整TCP/IP协议,具有100BaseT网络接口及完整的IP 路由功能(2)针对应用具有TCP 可靠连接方式,专为金融交易应用而设计(3)内嵌WEB Server 配置方式,方便直观(4)支持TELNET、SNMP等网络管理功能,适合行业应用(5)支持远程维护,具有远程配置、远程升级和重启动的功能目前公司在嵌入式TCP/IP技术、产品及市场方面都取得了较大成功。3、产品结构和工作原理 产品以32位嵌入式处理器为核心,可对数据进行处理,采用嵌入式实时多任务操作系统,支持协议转换和透明数据传输,可提供各种应用定制的嵌入式软件的代码空间,根据具体设备应用,可在嵌入式专用处理器上开发新软件,还可提供定制的中心主机软件系统从硬件上主要分为电源、移动通信模块、嵌入式RISC CPU、存储系统和逻辑控制电路、接口驱动电路等五个部分,如图所示接口驱动支持同步和异步通信,采用和集成第三方的移动通信模块。图1:系统结构示意图系统软件包括实时操作系统、TCP/IP协议栈、数据加密、串行数据流到TCP/IP的协议转换、接口驱动程序等4、产品功能特点(1)多媒体数据处理功能无线数传终端集现场图像监视,现场声音监听和数据采集传输多媒体监控功能于一体设备集成视频频编码压缩功能,支持M-JPEG或MPEG-4的编解码技术进行视频编解码,可以串口外接摄像头,能够随时随地拍摄照片,完成实时视频信号的压缩、语音信号和数据的编码,并经过设备打包传送到远端的监控中心,为用户提供高质量的实时图像,可以广泛应用于变电站、邮电、石油、水利等系统的无人值守机房及其它环境监控。(2)支持协议转换与透明传输透明传输模式是工业控制领域适用范围最广、通用性最强的一种工作模式在透明传输模式下,设备与监控中心的数据传输采用TCP 连接方式,不解析从串口收到的任何数据,直接将数据作为TCP 或UDP 的数据进行打包发送,而对具体数据的解析分别由后端数据采集终端设备和前端数据中心的相关服务器进行处理同时,为了满足SCADA 系统要求,设备也可配置命令串反向控制数据采集设备,按用户所需改变数据采集设备的工作方式;定义数据成帧的方式,即设备直接将数据按要求的格式封装成规定的帧,然后通过TCP/UDP传送到上位机数字设备分为支持TCP/IP的设备和非TCP/IP设备两大类TCP/IP设备包括采用Windows 系列操作系统的 PC、笔记本电脑和采用嵌入式操作系统的 PDA;而传统的工业控制设备主要是非TCP/IP设备,如RS-232、RS-422、RS-485、CNC、PLC 串行设备或模拟传感器设备。(3)移动数据网络底层使用的通信协议是TCP/IP,而传统的工业控制设备不支持TCP/IP协议工业控制系统中通常采用实时、可靠的数据传输协议,如CAN、TTP等,这些工业控制底层的通信协议也不支持TCP/IP因此,来自这些工业控制设备的数据,只有通过适当的协议转换,才可以实现与TCP/IP 网络的连接 项目开发具有协议转换功能的嵌入式TCP/IP协议栈用户上位系统向无线数传终端发送工作指令和数据时,数据经由嵌入式TCP/IP协议栈进行协议转换,打成IP数据包,再以数据包的形式发送到移动数据网络嵌入式TCP/IP协议栈使用户可在缺少TCP/IP协议栈功能的工业控制设备(如单片机、可编程控制器PLC)通过PPP、FTP、TelNet、Direct Socket、SerialNet、E-Mail等方式实现数据传输。(4)支持金融卡信息交换格式标准(ISO8583)ISO8583 是POS 机或ATM 柜员机等金融设备常用的一个标准,它定义了数据的封装格式等在8583应用模式下,无线数传终端与后端终端设备遵循一致的消息格式定义方式,IP 数据终端 解析串口收到的消息,并按照约定的命令格式识别消息,检查校验和提取消息字段中特定的命令字,执行相关操作,完成一次完整的命令处理设备工作在在8583 模式下,设备按照约定执行相关操作,包括:网络配置、建立TCP连接、发送数据、接收数据等,提取8583格式封装的业务数据,并进行相应的传输,可以保证金融终端设备与数据中心间数据交互的完整性,能够满足工控、金融等行业的需求。(5)支持路由功能设备通过以太口可与多个工业控制设备相连,提供无线路由功能,让物理位置比较近的多个终端同时连接上无线网络,实现终端设备与数据中心的双向数据传输在此模式下,设备完成以太接口所连局域网到无线网络之间的NAT 路由而设备的串口用作控制台配置接口,设备对串口接收到的数据作为标准的控制台命令处理,实现对IP 数据终端的配置管理。(6)提供AT 扩展命令集很多工业控制产品直接输出AT 命令,控制外接设备无线数传终端作为一个带TCP/IP 功能的扩展数据终端,从串口接收数据终端发来的类AT 命令,并执行相应的操作无线数传终端支持所有标准的AT命令,主要用于控制数据通信模块;同时IP 数据终端还根据应用扩展实现了以下命令:设置数据通信参数、激活/断开数据通信连接、发送/接收短消息、激活/终止TCP连接、发送/接收TCP报文、发送/接收UDP报文等AT扩展命令还可根据用户的需求进行定制。(7)提供多种标准通信接口提供100BaseT以太网接口、PCMCIA、RS232、USB、RS485等多种标准接口,同时开发相应的通信组网协议软件和物理层驱动软件,以适应工业控制设备及实验现场仪器分布式处理结构网络连接的需要。(8)采用嵌入式高性能处理器为了支持多媒体数据业务,采用处理能力强大32位的嵌入式处理器,提供强大的处理能力,并能够满足未来应用功能的升级同时采用实时多任务编程技术和交叉开发工具技术来控制功能复杂性,简化应用程序设计、保障软件质量和缩短开发周期。(9)小尺寸、微功耗和低成本通过选用最佳的编程模型和不断改进算法,采用Java编程模式,优化编译器性能,满足小尺寸、微功耗和低成本的特性 典型应用领域移动数据通信正逐步进入传统的工业控制领域利用移动数据通信技术可以为工业监控系统搭建远程数据传输平台无线数传终端利用最新的移动通信网络作为传输介质,可以与众多的RTU终端、DTU终端、PLC终端、单片机终端、工控机、GPS车载定位仪、仪器仪表、POS终端等工业控制设备无缝连接各种远程工业控制设备通过移动数据网络连接到数据中心,实现实时浏览温度,设置点,报警或者其他监控功能,并使数据采样更加实时准确,用户可以在异地远程控制监控设备,使工业控制更加高效率,有助于实现行业管理现代化、数据采集自动化等目标 。工业控制无线数传终端产品具有支持多媒体数据传输的特点,不仅能满足工业遥控、遥调、遥测、遥信功能,而且还能实现对工控现场远程图像实时监控,即“遥视”功能,可集中管理各工业控制设备的工作状态,满足工业控制自动化发展的要求设备能够应用在电力、自来水、天然气等领域表计的计量,还可实现自动测量读取、自动计量发送、远程信息处理、远程设备监控,以及安防、车辆调度、公众流量业务、工业处理自动化等任何需要统一管理服务终端的应用方案中,可广泛用于金融、保险、证券、商业、公安、多媒体通信、税务、气象、石油等行业。例如,在环保系统中,常常需要对众多的污染排放点进行实时监测,大部分监测数据需要实时发送到管理中心的后端服务器进行处理由于监测点分散,分布范围广,而且大多设置在环境较恶劣的地区,通过电话线传送数据往往事倍功半利用GPRS网络进行无线数据传输,成为环保部门选择的通信手段亮点之一污染监测设备将采集到的污染数据和告警信息,通过GPRS网络,及时发送到环保监察部门,可以实现对排污单位或个人的及时管理,大大提高了工作效率,为环境保护提供了崭新方式。无线数传终端在环保系统的应用无线数传终端在工业控制领域的主要应用有:(1)城市配电网系统与自动化抄表、变电站设备监测(2)自来水、煤气管道、闸门、泵站与水厂监控(3)供热系统实时监控和维护级(4)环境保护系统数据采集(5)三防与水文监测(6)气象数据采集(7)无人值守如仓库监控(8)无人值守站机房监控和远程维护(如移动基站、微波、光纤中继站等)

    时间:2018-08-31 关键词: java j2me 异构 总线与接口 嵌入式软件

  • 基于DSP的导弹仿真器嵌入式组件设计

    基于DSP的导弹仿真器嵌入式组件设计

    0 引 言 在某新型机载武器系统的研制过程中,作为确保战备部队尽快掌握新装备形成战斗力的关键因素,需要设计一种能达到测试训练目的的导弹仿真器。而该系统设计的核心任务是开发一套能够模拟产生与弹载飞行控制组件进行同步ARINC-429(HB6096-86)信息交换、发送遥测数据、模拟产生时序逻辑控制信号、设置故障代码并能进行故障模式处理等一系列对产品进行测试训练工作的嵌入式组件。 1 系统框架设计 由于该组件为典型的弹载嵌入式系统,使用空间有限、环境条件苛刻,既要求系统运行稳定可靠,又要求具有较强的数据运算能力。综合考虑设计需求,决定采用“DSP+可编程逻辑器件+429通讯接口+信号匹配及调理+故障模拟装置”作为系统的硬件总体框架。限于篇幅,本文只就DSP扩展电路、429通讯接口以及FPGA的逻辑功能加以介绍。系统硬件原理框图如图1所示。 图1 系统硬件原理框图 1.1 DSP及扩展电路设计 选用TI公司98年推出的军品级SMJ320F240数字信号处理器[1],在高效软件算法的配合下完全可以承担嵌入式组件控制处理核心的任务。 SMJ320F240扩展电路包括时钟电路、复位电路、数据存储器扩展电路。SMJ320F240DSP的片内RAM为544字节,为满足系统要求,在计算机板上外扩了32K的DRAM、DRAM采用cycrsj公司的cy7c199-25DMB,容量为32K、8位数据,读出时间为25ns,将两片32K、8位数据存储器拼为32K、16位数据存储器通过72LS00译码电路,将32K16位数据存储器地址空间定为高32K,即8000~FFFF。 1.2 ARINC-429通讯接口设计 就一般的429通讯接口的设计方法而言,通常采用双口RAM作为传输通道的数据缓冲器。但这种设计方法并不适用于本系统。因为上述设计方法只考虑了数据成批的实时传输,即429传输每帧数据均为20×32bit,一般的双口RAM 缓冲区都很大,上下半区可以分别存放很多帧数据并成批的读取,无法实时对每一帧数据进行处理,不符合交换信息协议对每帧数据实时处理这一要求。 针对系统的设计需求,采用新的设计思路,组建以F240、FPGA、DEI1016[2]为构架的智能通讯接口模块。FPGA选用Altera公司的EPF10K20RC208器件,利用VHDL编写逻辑模块来开辟适当缓冲区为数据帧提供实时传送的平台,数据传输操作靠FPGA逻辑程序在后台完成数据的发送接收,CPU则在前台完成数据处理[3]。 数据通讯模块的控制逻辑以F240提供的I/O操作信号IS和读写信号RD、WR以及地址A2、A1为输入来为DEI1016产生操作信号。控制逻辑和F240同时监视DEI1016的RX1RDY、RX2RDY、TX429RDY等3个状态信号以供软件查询和由控制逻辑产生INT中断请求。 1.3 FPGA逻辑设计 在确定了依靠FPGA大规模可编程逻辑器件作为F240与DEI1016实时通讯的传输环节后,将FPGA逻辑程序划分为5部分进行设计:CPU接口模块、429芯片接口模块、429数据发送缓冲区模块、429数据接口缓冲区模块、32位精确定时计数器模块。逻辑框图如图2所示。 a) CPU接口模块:充当FPGA内部各模块与CPU(SMJ320F240)总线之间的桥梁。CPU把数据总线,地址总线,控制总线挂在CPU接口模块上,CPU接口模块通过地址译码分别选通FPGA内不同的模块与CPU通讯。 b) 429芯片接口模块:主要负责与429芯片DEI1016通讯,DEI1016的数据总线、控制总线连接到这个模块上,该模块根据不同的操作控制DEI1016的控制总线或者响应DEI1016的控制信号,同时通过并行数据总线发送(接收)DEI1016的数据。 c) 429数据发送缓冲区模块:负责接收CPU传过来的待发送的数据和发送启动命令并把这些数据传给429芯片接口模块和启动429芯片接口模块的发送时序。该缓冲区能容纳20个32位数据。 d) 429数据接收缓冲区模块:负责响应429芯片接口模块的接收数据中断信号并把接收到的数据存在内部RAM中,CPU可以通过CPU接口模块查询429数据接收缓冲区已接收的数据个数并且可以随时读取缓冲区中的数据。该缓冲区能容纳20个32位数。 图2 FPGA逻辑设计框图 由此看出,发送429数据几乎是不占机时,将数据放入缓冲区即可。在接收429数据时,该过程完全由逻辑程序在后台运行,不占用CPU的机时,为前后台不同任务的并行操作提供了条件。 2 时序软件设计 2.1 运行环境 在仿真调试阶段软件运行在CCS2000集成开发环境中,使用WinTech仿真器通过JTAG仿真接口在线仿真调试,操作系统为WinXP。在烧录至FlashEEPROM后,软件运行于F240片上系统。 2.2 结构及详细设计 时序软件是嵌入式组件乃至整个导弹仿真器的控制核心,完成对全弹逻辑时序的控制以及对故障的响应。软件工作流程以时序控制为主线实时调度,依次完成系统初始化、故障识别、模拟测试信号的输入输出,同时调用中断服务程序完成与飞控组件的信息交换。软件按模块结构划分为时序控制、中断服务和故障测试三个单元。 2.2.1 中断服务单元 在中断处理周期内完成符合导引头与飞控组件信息交换协议的429信息传输控制,包括429交换信息和遥测信息的实时发送、接收,数据的打包、解包及处理,实现与飞控算法回路的闭合。 中断处理周期是指:利用周期为30ms、占空比为1:1的同步方波信号正负电平产生中断控制信号,来同步信息交换过程。在同步信号的正电平15ms工作周期内,模拟导引头发送20个信息字组成的遥测信息帧。嵌入式组件向遥测系统发送的信息字共有60个。在同步信号的负电平15ms周期内,嵌入式组件与飞控组件完成一帧20个字的信息交换过程。 中断服务单元处理流程如图3所示。429数据接收、发送、数据打包、解包的相关算法模块,限于篇幅这里不再赘述。 2.2.2 时序控制单元 完成导弹正常测试逻辑的控制,包括系统初始化、精确定时,利用DSP的数字I/O资源模拟与其它组件、设备的信息交联,D/A则用来模拟舵偏角反馈信号给设备。其中初始化函数void TargetInit(void) 完成了对DSP、FPGA资源的初始化(中断资源、系统时钟/定时器资源、I/O端口资源、内存等,FPGA缓冲区的清零、寄存器的置位)。函数SetTimerCounter(0)用于系统定时器清零,函数void sleep(unsigned long time)用于系统延时,精度1us。时序测试点的状态判读和信号设置靠对DSP I/O端口资源的读写来完成,在CPLD的逻辑程序SConIO.vhd中定义了信号的端口地址和偏移量。 2.2.3 故障测试单元 完成对故障设置装置20余种代码的识别,该单元在流程处理上不是独立的,而是嵌入到时序控制和中断服务单元中,按预定的故障测试流程输出超出设备判别指标的相关错误信息,处理流程如图4所示。 图3 中断服务单元处理流程 图4 故障测试单元流程 3 问题及解决途径 在设计调试中断服务程序时,遇到的突出问题就是系统实时性要求与CPU处理能力间存在的差距。由于系统同步信号中断对429数据传输与处理的时间要求非常严格,特别是15ms负半周,不但要完成数百个包括浮点参数运算在内的数据实时处理,还要管理429数据的接收与发送。象F240这样的定点DSP运算效率显然难以胜任。为此,在设计中断服务程序模块时采取了如下措施: a) 在中断服务流程中,合理安排CPU查询缓冲区状态的时间点,待CPU将接收到的上一帧数据和待发送的下一帧数据处理完毕后,再查询缓冲区的数据个数,接满后由CPU读走进行处理,从而实现了接收数据与处理数据的并行操作; b) 数据传输操作主要靠FPGA逻辑程序在后台进行,CPU在前台完成数据处理; c) 在429参数打包、解包处理过程时,对频繁使用的二进制加权处理方法进行改进,不再调用C标准算法库math.h中的pow( )函数,取而代之自定义的移位运算函数,pow( )是通用的C整型/浮点型运算库函数,F240调用它势必会占用大量的机器周期,而移位操作在实现二进制加权功能的同时,运算速度却能成倍提高。 为证明措施的有效性,使用DL716数字记录仪对DSP两个空闲I/O通道在同步信号正负半周产生的电平反转状态变化进行实时采集测量,得到系统在中断处理过程的耗时见表1(统计了测量6次的数值)。测试结果表明,系统在同步信号中断负半周的运行时间大幅缩短至13.5ms左右,不仅排除了中断和数据帧丢失的可能性,而且满足了信息交换协议对时序控制和数据的处理要求。 表1 中断处理时间对照表 4 结 论 作为嵌入式系统在国防科技领域内推广使用的典型范例,该组件目前已成功应用于某型导弹仿真器中,在各类复杂的使用环境下均显示了良好的性能,对于用户尽快掌握新装备形成战斗力具有非常重要的现实意义。 本文创新点:采用DSP+FPGA嵌入式系统构架,遵循弹载电子设备对于体积和性能的设计要求,同时采取并行处理和软件算法优化等措施,满足了系统对于集成化、功能性、可靠性、实时性的要求。 参考文献: [1] TMS320F/C240 DSP Controllers Reference GuidePeripheral Library and Specific Devices[M], Texas Instruments, 1999.6. [2] DDC Data Sheet (DEI1016 ARINC429 Transceiver) [ Z].DDC Inc, 2004 [3] 徐欣,于红旗,易凡.基于FPGA的嵌入式系统设计[M].北京:机械工业出版社,2005 [4] 缪云青,李永刚.FPGA器件在嵌入式系统中的配置方式探讨[J].微计算机信息,2006,11:161~162

    时间:2018-07-02 关键词: DSP 嵌入式开发 实时处理 导弹仿真器 嵌入式软件

  • 为嵌入式软件建立统一软件系统框架的方法详介

    嵌入式系统硬件与软件发展的不平衡 嵌入式系统是整合了计算机硬件和软件的集合体,它是通过可编程器件的计算和控制能力完成特定功能的系统。越来越多的嵌入式系统要求有连接网络、多媒体信息处理和无线移动通信的能力。然而,飞速发展不断有突破的嵌入式系统硬件技术与相对发展较慢的软件技术形成明显对比。 认为摩尔定律很快会遭遇物理极限的预测不断被突破,半导体工艺正在向纳米级进军,使计算器件集成度更高、速度更快、体积更小、功耗更低。随着系统芯片(SoC)技术的发展和成熟,越来越多的嵌入式系统将采用硅知识产权(SIP),利用ASIC或半定制器件(FPGA/CPLD)技术把CPU核和外围器件整合到一个芯片中。这将极大的提升硬件系统设计的灵活性、可靠性,以及提高硬件开发的速度和降低系统的成本。 硬件技术的飞速发展和体系 结构的不断改进,在很长一段时间内对嵌入式系统软件工程师而言,似乎并未产生很大影响,他们仍然沿用传统的软件设计方法和调试方法。近几年,随着硬件复杂性的增加和对系统功能和性能需求的大幅度提高,特别是要求系统具有灵活方便的网络连接、轻巧节电的无线移动和功能强大的多媒体信息处理等能力,使软件开发工作量急剧增长,甚至可以占到全部工作的70~80%以上。这样的系统不再是单枪匹马可以完成的,需要集合一个开发团队协同工作才能完成。嵌入式系统软件的开发,越来越成为制约嵌入式系统开发的瓶颈。 嵌入式系统软件的特点及其开发途径 嵌入式系统软件从简单到复杂可以千差万别,天地悬殊。虽然它们结构相对简单,但是不同系统对不同的性能往往有特定的要求,有的要求非常苛刻和严格。对简单系统可以用传统方法,从底层用汇编语言编写程序,利用在线仿真器(ICE)、在线调试器(ICD)等开发工具进行调试软件。但是对那些复杂的嵌入式系统,特别是有多个控制环路、并需要在优化级可控的情况下能预测其运行状态时,不利用实时操作系统和嵌入式系统开发平台进行开发,是很难或者几乎不可能达到预定要求的。 利用嵌入式系统开发平台开发嵌入式系统软件,往往需要针对不同的硬件编写实时操作系统内核移植代码。通过编译、链接、定址将操作系统映像固化到(EP)ROM或者Flash(闪存)中。 对于大的开发项目,可以购买商业化的实时操作系统和嵌入式系统开发套件,甚至将软件开发外包给一些专业的嵌入式软件开发商,但是这需要投入少则几万,多则上百万元人民币购买软件,有些还需要对开发出来的每一件产品再缴纳相应的授权使用费。对于更多大量的小项目而言,显然不能走这条路,使用源代码开放的嵌入式操作系统才是合适的选择。 软件编程接口规范和标准化 硬件器件与软件模块相比,具有很高的可置换性,这是因为硬件器件的功能特性、电气特性、机械特性等都有明确的定义,这种组件单元标准化的特点是硬件技术的发展始终快于软件发展的原因。在软件技术方面,中间件和面向对象技术在一定程度上正是类比硬件而发展起来的,然而还远未成熟,至今在嵌入式系统软件的开发中还没有能真正地使用起来。 在传统单片机系统软件开发时代,代码的可重用性极差,系统的开发极大程度地依赖于软件编程人员的编程技巧。这是因为软件开发的灵活性造成的。只要正确的使用编程语言和软件开发工具,不同的软件设计人员对于同一种需求会开发出不同的软件。正是这种灵活性,导致了很多的软件不具有移植性。 软件要具有优良的体系结构和良好的移植性,必须将开发的操作系统纳入一个严格定义的框架。至少需要考虑以下几个方面: 高级语言和将汇编语言模块化—为了使系统具有高的可移植性,尽量使用C或者Embedded C++来开发系统软件。 模块化——将系统功能分成模块。模块设定的合理方法是:根据硬件能力,自下而上的综合。 提供标准接口—提供了POSIX 1003.1规范的操作系统就具有了UNIX系统的标准接口。Linux和QNX就是实现了POSIX规范的操作系统。符合软件应用编程接口(API)规范,就可以比较容易地移植UNIX系统的应用软件。 严格的体系结构层次——按层次划分,依次是应用软件→操作系统→功能级抽象→寄存器级抽象→硬件。其中,寄存器级抽象层(rHAL)直接与硬件相关,它封装微控制器和外围设备的寄存器接口及其行为。一般而言,它需要定义完整的寄存器序列名称。功能抽象层(fHAL)封装硬件的功能行为,通常把其定义成若干可以执行命令的函数。 软件系统体系结构 运行于特定硬件平台的操作系统是系统资源的管理者,作为软件的操作系统也是系统资源的使用者。操作系统内核是一个自治的软件环境,不依赖于任何其他的软件模块。内核通常提供进程调度(SCHED)、内存管理(MM)、文件系统(FS)、进程间调用(IPC)和网络(NET)等功能模块。这些模块之间相互有不同程度的依赖关系。其中进程调度和内存管理处于核心地位,反映了操作系统对计算机主机资源的管理。另外,文件系统是操作系统的信息中心,反映了操作系统对计算机存储介质的管理。操作系统往往把计算机的外部设备映射到文件系统,利用统一的文件系统访问接口实现对外部设备的访问。进程间调用和网络通常是可选模块。 体系结构的各层之间有不同的功能和责任。寄存器级封装反映了实现同一个功能可用不同的元器件。针对不同的芯片要编写合适的驱动程序。这些驱动程序一般不具有可移植性,因为它们是同级,实现对不同器件的功能级接口。例如,NE2000成为以太网事实的接口标准,兼容NE2000的以太网控制器,可以使用NE2000驱动程序,而不一定要开发专门的驱动程序。如果是不兼容的以太网控制器,寄存器的布局和命令会有不同,并无法映射寄存器。折衷的办法是梳理出功能级抽象层所必需的基本操作,建立功能级的实现框架。针对不同的硬件,使用同一种实现框架可以保证功能级抽象的质量,并且可以提高移植的效率。 结语 纵观软件的发展,从批处理到面向过程的编程,到面向对象的编程,再到面向框架的编程,体现了需求的拉动和技术的发展。嵌入式系统正经历一个快速发展阶段,嵌入式系统硬件技术的发展已超过了软件技术。软件技术的滞后,造成了软件的高成本和低开发效率,这已成为制约嵌入式系统发展的瓶颈。只有建立统一的清晰的操作系统层次的标准接口,实现软件构件的可重用性,才能够大幅度提高嵌入式系统的软件的开发效率。 参考文献: 1 Red Hat Inc. ‘eCos Reference Manual.’ www.redhat.com. 2 ARM Limited. ‘ARM Firmware Suite Version 1.3 Reference Guide.’ www.arm.com. 3 Labrosse. J. J., 邵贝贝译.‘ mC/OS-II, The Real-Time Kernel. ’清华大学出版社.

    时间:2018-07-02 关键词: 嵌入式开发 嵌入式软件

  • 基于仿真的嵌入式软件白盒覆盖测试系统设计

    基于仿真的嵌入式软件白盒覆盖测试系统设计

    引言随着嵌入式系统的广泛应用,人们对嵌入式系统软件的质量提出了更高的要求,而作为保证软件质量最有效手段的测试技术,也越来越受到关注。目前嵌入式软件的开发语言以C等高级语言为主,因此,对这些高级语言的测试显得尤为重要。目前实用的嵌入式系统测试平台卞要由国外厂商开发,比较具有代表性的测试平台有Telelogic公司的Logi-scope .Metrowerk公司的CodeTest, Windriver公司的CoverageScope和IPL公司的Cantata等。国外厂商的嵌入式系统测试平台功能较强,技术较先进,但一套测试系统价格往往高达数万到十多万美元,极大增加了嵌入式系统的开发成木,无法得到普遍的应用,影响了国内嵌入式系统的开发质量。国内的嵌入式系统测试平台有基于目标开发的测试系统。电子科技大学研究了基于目标的嵌入式软件测试系统,实现了对汇编语言进行自动插装,并实现基木的覆盖测试功能。但由于嵌入式软件需要基于硬件电路进行调试,当软件程序写入硬件电路后,如果电路工作不正常甚至无法工作,则难以断定问题所在,这就限制了嵌入式软件测试必须按照先硬件后软件的模式进行。木系统实现了基于仿真的嵌入式C语言软件覆盖测试分析。通过有效的词法语法分析、自动插装、测试用例的生成和加入、动态仿真运行及覆盖报告分析等模块对源代码进行覆盖分析,缩短了嵌入式系统开发周期,有效地解决了传统手工测试程序运行效率低、繁琐等问题,保证了嵌入式软件系统高效稳定的运行。1嵌入式软件测试系统框图嵌入式软件测试系统的结构框图如图1所示。它卞要由5部分组成:程序的预处理过程(包括词法语法分析)程序的自动插装过程、测试用例的加入、动态仿真运行及覆盖报告分析。被测试程序首先经过预处理。由于源程序中存在宏定义次件包含和条件编译等预处理命令,因此在进行词法分析前必须进行预处理,将宏展开,以利于查找变量词法分析是将预处理阶段产生的中间代码分解成单独的词的表示,语法分析是将输入字符串识别为单词符号流,卞要用来确定插装的位置,在一些关键的字段和函数处插2功能模块设计2. 1词法语法分析模块(1)预处理在源程序中,空白符测匕格符、回车符和换行符等编辑性字符除了出现在文字常数中之外,在别处任何地方出现都没意义,而注释部分出现在程序中的任何地方。对于这些不是程序必要组成的部分,预处理时可以将其剔掉。( 2)词法分析将预处理阶段产生的中间代码分解成单独词的表示,并将词的基木信息表,如词的行号、词的列号及词的类型等信息,为语法分析做准备。词的类型有:普通变量标识符擞字表、关键字表运算符表。( 3)语法分析语法分析的卞要任务是在词法分析识别出的单词符号串的基础上,分析并判断程序的语法结构是否符合语法规则。由于木系统分析的程序是经过嵌入式软件编译器编译的,因此认为不存在语法上的错误,只是通过语法分析得到程序结构及函数信息,为插装做准备。2. 2插装模块程序插装概念由J.G.H uang教授首次提出,简单地说就是借助向被测程序中插入操作来实现测试目的。在调试程序时,常常要在程序中插入一些打印语句,希望执行程序时打印出所关心的信息。通过这些信息进一步了解执行过程中程序的一些动态特性。比如,程序的实际执行路径,或是特定变量在特定时刻的取值。从这一思想发展出的程序插装技术能够按用户的要求,获取程序的各种2. 4覆盖率分析通过动态仿真运行模块,覆盖信息被写入文件中,读取存放记录文件,分别对语句块数和执行分支数进行计算。根据覆盖率公式,结合计算的结果,得到测试语句覆盖汾支覆盖与程序的有效代码率并GUI显示。将测试的结果与测试用例库生成的测试用例期望值作比较,得出测试结论。2. 4. 1语句覆盖率算法分析语句覆盖是软件测试中最基木的覆盖标准,因此在测试时应将每个语句至少执行1次。在 T estImp系统中得到语句覆盖率的算法流程如图3所示,通过词法分析后,读单独的词语,如遇到能产生分支的关键词(for .if .else .switch .goto .return .break .continue .do :`{”和“}’,)则继续往卜判断,否则返回继续读词语。如果是能产生分支的关键词,则将关键词对应的当前标号(flagif }flagelse .flagwhile,flagfor }flagswitch)推进栈中的account单元保存,并将当前标号加1。当读取到关键词之后第1个气”时,标志fflag加1,且判断是否大于1:如果大于1,则将此时的行号推入到栈当前位置中的mine单元中保存;否则直接返回读词。如果是+}”标号,则判断链表的节点是否大于。,如果是且为1,则用“}”当前行数减去保存栈中“{”的行数,然后减去最近嵌套内层的总行数即得到该层对应行数;如果链表节点大于1,则判断链表节点数与对应层数是否相等,如果相等则计算出该层的总行数,即用此时+}”行数减去栈中保存“{”的总行数,然后保存该层总行数,并用总行数减去最近嵌套内层行数之和,即得到该层行数对应记录。如果链表节点数与对应层数不相等,则将对应层数加1循环作判断。当所有的词语全部读取完毕后,读取动态执行时写入的插装文件,读取关键词标号,取对应关键词链表中的行数与总行数变量相加,直至插装文件读取完毕,此时可以输出被覆盖语句数。2.4.2分支覆盖率算法分析分支覆盖率的计算一般也需要达到一定的指标。在T estImp系统中得到分支覆盖率的算法流程如图4该系统实现如下几个模块:①分析模块。用打开文件菜单选择要分析的源文件,并进行词法分析。在词法分析过程中,对关键词、符号擞字变量等用不同的标记,并去除源文件中的注释,给出每个词的行数和列数。语法分析并没有生成可见的语法树,只是形成提供插装的结构信息。②插装模块。选择自动插装菜单,系统会读取词法语法分析的结果,根据图2算法流程实现对源程序的自动插装,插装点有for ,if ,else ,case ,goto ,return ,break ,con-tinue .do ,while语句后及程序开始与结束处插入记录函数指针,并在程序最后插入插装函数体。③编译器配置模块。根据不同嵌入式软件选择不同的编译环境,该部分需在使用该系统之前对各种嵌入式编译软件进行配置,在木系统中有Visual C + + ,ARM编译器ADS ,Keil环境沛福环境,Borland C环境,DSP编译器CCS。④覆盖率报告。木系统已实现的覆盖率报告有语句覆盖与分支覆盖,并将覆盖率通过二维图形形式体现。后续将实现条件覆盖、多条件判定覆盖、多条件覆盖,M C/DC潞径覆盖等覆盖率报告。C服告生成及帮助文档。将测试覆盖结果与测试前生成设定的覆盖率指标进行比较得到测试结果。如果覆盖率没有达到要求,则继续增加测试用例,以提高测试覆盖率。另外有帮助文档,提供使用说明、注意事项及应用范围等。4实验结果在实验中,采用1个AT 89C51单片机键盘识别系统作为实验对象。在该系统中,通过AT 89C51的P1口连接1个4x4的知阵键盘,并通过P0. 4 } P0. 6所连接的74LS138扩展连接到型号位7SEG-MPXGCA的6位LED选通端上,可以显示所按卜键盘的编号,将RXD和T XD连接到串口。实验过程中,将测试源程序进行分析并自动插装,然后通过单片机的Keil编译器对插装后的源程序进行编译,得到.hex文件,添加到Proteus6. 9仿真软件原理图中的AT 89C51单片机中,点击运行按钮后可以执行程序。此时可以在Proteus6. 9界而中输入生成的测试用例。本实例中的测试用例是键盘按键的输入,只需点击Proteus6. 9原理图中的键盘。此时插装后的程序会将插装的信急通过串口传送到TestImp测试系统的联机串口传送界而中,并将其保存在指定文件中,为覆盖测试做准备。为该系统设计的基木测试用例是按卜单个1号键。在此测试用例卜,手工运行推算出语句覆盖率和分支覆盖率分别为55. 6%和42. 80}0 ,在测试系统运行后,得出的语句覆盖率和分支覆盖率分别为55. 6%和42. 8 0}o。测试结果如图5所示。实验结果表明:在特定的测试用例卜,对嵌入式系统应用木文设计的基于仿真嵌入式软件白盒覆盖测试系统与理论上推导出来的语句和分支覆盖率指标完全相同。

    时间:2018-06-27 关键词: 嵌入式开发 高级语言 白盒覆盖测试 嵌入式软件

  • 嵌入式软件的基本测试方法

    随着制造行业的再一次崛起,嵌入式软件目前在软件行业中越来越多,2004年软件行业最火爆的三个项目是:嵌入式开发,软件培训以及软件外包。由于嵌入式软件与其他产品息息相关,这给嵌入式软件的测试工作带来了极大的困难,软件的测试工作不能够等程序烧到或者固化到芯片中才开始进行测试,这就太晚了,本文结合自己的一些经验提出自己的看法,希望大家一起讨论。搞好开发前的原型设计原型开发目前在开放流程中受到了更多的重视,同样嵌入式软件也是非常需要的。比如说一个录音机版面的设计,可以定义好版面上面的按键以及每个按键的功能。然后画出状态转化图,写清楚每个按键何时可以触发,触发后由哪个状态转入别的其他状态。原型设计好了,组织专家,工程师进行评审,尽可能多的找出原型中不合理需要改进的地方;改进以后,有必要可以进行再一次的评审工作。每一次评审工作需要记录评审建议是否需要解决?如何解决以及实际解决情况。进行设计和开发工作设计和开发工作需要设立里程碑。每个里程碑结束前都需要进行评审工作。由于嵌入式软件的运行环境不同,受到很大的限制,所以在进行开发之前需要进行编程规范工作,编码的时候需要严格按照编码要求进行工作,每一个条款都需要认真执行和审查。现在业界提供许多关于嵌入式软件开发的标准,大家可以通过网站搜索,最好能够购买业界一些比较著名的标准。目前市场上也提供许多关于代码检验的工具。为什么一直提出代码编码规范?这是因为嵌入式软件的质量与代码规范是十分重要的。举个例子,著名的阿里亚火箭失事,专家进行详细的调查工作,最后发现问题出在代码上。代码是符合标准C语言的,但是在运行过程中由于程序员将一个长整形变量赋给了一个短整形变量,造成内存溢出,这是导致火箭失事的关键所在。(int8 a;int32 b;…a=b;)代码测试当程序开发完毕,需要进行测试工作,但是在程序烧入或固化芯片之前如何进行测试呢?这里介绍一种方法:比如程序时使用C语言进行开发的,请将所有的操作都封入在函数中,函数的定义都在相应的头文件中定义(.h),然后设计测试用例,书写测试代码,测试代码包含相应头文件,可以对函数进行检测。测试案例往往分为两类:一种是功能测试,主要测试函数的功能;另外一种是错误参数测试,主要检查程序对进行错误参数进行检验。功能测试这种测试的运行往往需要通过仿真器辅助完成,比如类似录音机软件程序,分别测试播放,加大(减小)音量,停止,暂停(取消暂停),快速前进,快速后退,录音对应的功能是否能够正常运行。错误测试主要测试函数在调用参数无效的时候,系统是否会按照规定返回正确的错误代码。比如function test(int Tid)测试的时候给出一个错误的序列号(Tid),看程序是否返回正确的错误代码。对于函数function test1(int t)需要进行特出的处理t 定义为1-100我们可以按照边界值法和等价分类法进行测试上边界:-1,0,1下边界:99,100,101中边界:50所以测试用例集合为(-1,0,1,50,99,100,101),其中-1,101为错误测试用例,其他为正确测试用例功能组合测试在进行完功能测试后,我们可以进行功能组和测试,还是拿录音机程序做个例子。我们可以定义将音量增加到10,快速前进,检查音量,看是否还是为10;播放,暂停,试图调整音量,检查调整音量的功能是否可以被成功执行。烧入固化测试当以上测试都通过后可以将程序烧入芯片或者固化,进行最后在实际环境中进行测试工作。最后需要指出的是,虽然目前市场上嵌入式测试工具比较多,最有名气的就是CodeTest,但是价格都非常昂贵,一般都需要上千美金,中小型企业可以根据自己的情况多想办法,如果大家有啥好的别的方法,可以告诉我(xianggu@yahoo.com),大家一起讨论。希望中国的嵌入式产品质量越来越高。

    时间:2018-06-27 关键词: 嵌入式开发 编程规范 评审 嵌入式软件

  • 嵌入式软件系统测试中的仿真系统结构设计

    嵌入式软件系统测试中的仿真系统结构设计

    1 嵌入式系统概述嵌入式系统是以计算机技术为基础,以应用为中心,并且软硬件可裁剪,适用于应用系统对功能、可靠性、成本、体积、功耗有严格要求的专用计算机系统。嵌入式软件是基于嵌入式系统设计的软件,是计算机软件的一种,同样由程序及文档组成,可细分成系统软件、支撑软件、应用软件三类。嵌入式软件大量应用于家用、工业、商业、通讯和国防领域。我国目前在嵌入式应用软件方面具有优势。在嵌入式系统中,软件的工作量约占全部工作量的80%,其中测试与验证的工作量占软件工作量的70%。1.1 嵌入式软件特点和测试难点嵌入式系统开发有其自身的特点。通常,在嵌入式系统软件中,底层驱动程序、操作系统和应用程序的界线是不清晰的,有时甚至混编在一起。这主要是因为嵌入式系统中软件对硬件的依赖性造成的。由于嵌入式软件对硬件的依赖性,软件测试时必须最大限度地模拟被测软件的实际运行环境,以保证测试的可靠性。底层程序和应用程序界限的不清晰增加了测试难度。测试时,只有在确认了嵌入式系统平台及底层程序正确的情况下才能进行应用程序的测试,而且在系统测试时,对错误的检测定位较为困难。软件的专用性也是嵌入式软件的一个重要特点。由于嵌入式软件设计是以一定的目标硬件平台为基础、面向固定任务进行的,因此,一旦被加载到目标系统上,功能必须完全确定。这个特点决定了嵌入式应用软件的继承性较差,延长了系统的测试时间,增加了测试费用。嵌入式软件的另外一个重要特点就是实时性,这是从软件执行的角度考虑的,也就是说嵌入式软件的执行要满足一定的时间约束。嵌入式系统中,应用软件自身算法的复杂度和操作系统任务调度,决定了系统资源的分配和消耗。因此,对系统实时性进行测试时,要借助一定的测试工具对应用程序算法复杂度和操作系统任务调度进行分析测试。1.2 嵌入式软件测试方法软件测试是软件开发中的一个重要环节,嵌入式软件也不例外。图1给出了嵌入式软件测试的一般流程。根据不同的指标,软件测试方法[1]有不同的划分方法。根据软件开发过程中测试所处的不同阶段可分为模块测试、集成测试和系统测试;根据是否需要运行目标代码分为动态测试和静态测试;根据目标代码的可见性可分为白盒测试(结构测试)和黑盒测试(功能测试)。在软件测试中,每种测试方法都不是孤立的。为了最经济、最有效地达到测试目的,各种测试方法往往互相嵌套。例如,在软件的单元测试阶段,可以用黑盒测试和白盒测试的方法分别进行动态测试。而在系统测试阶段,只能使用黑盒测试方法进行测试。为了更有效地进行嵌入式软件的系统测试,提出了嵌入式软件系统测试中具有交互式错误检测定位功能的仿真系统架构设计方案。使用此仿真系统不仅可以按照第一类测试方法[2]和第二类测试方法[3]辅助进行系统测试,而且还可以利用仿真系统的交互式学习功能,不断积累错误定位经验,实现错误检测定位,为测试人员和开发人员节省大量时间。这是其他测试方法所不具备的。2 仿真系统结构设计嵌入式软件的硬件载体大部分为专用计算机设备,并且通常没有外围设备用于测试过程中的监测或观察。而有些嵌入式软件还会存在交互式操作。在被测软件移植到目标机上的实际硬件环境以后,由于与嵌入式系统平台和底层程序融为一体,对系统进行黑盒测试时,错误定位将变得非常困难。因此根据嵌入式软件的特点,提出了一个具有交互式错误检测定位功能的仿真系统结构模型。图2为仿真系统分层结构图。仿真系统在设计上采用分层结构、分层设计、分层实现的方式,每一层的内部实现对其他层透明。仿真系统由硬件驱动、交互操作模块、驱动模块、桩模块、分析模块和人机界面六个部分组成。下面分别介绍各个模块的功能。(1)硬件驱动部分负责驱动硬件,向上一层提供底层硬件的操作接口。仿真系统通过硬件驱动为嵌入式软件提供相应的通信接口,用于嵌入式软件和仿真系统之间的数据交换。通信接口根据具体嵌入式软件的接口设计实现,一般为各种通讯协议。各通讯协议模块之间松散耦合,且具备可扩展性,保证硬件接口的改变不会影响上层的功能实现。(2)交互操作模块负责与嵌入式软件的交互操作。此部分可裁剪,主要根据嵌入式软件是否需要交互操作而定。其主要功能需要根据特定的软件设计实现。(3)驱动模块负责封装与仿真系统测试数据有关的处理逻辑,向人机界面提供独立于体系结构的操作接口。系统测试阶段除了正常的功能和性能测试,更应该进行意外测试和破坏性测试,即测试系统正常执行情况下不该发生的激发活动和人为的破坏性测试,进一步验证系统性能。而驱动模块则将测试用例中各种测试数据传输给被测嵌入式软件。(4)桩模块为嵌入式软件提供各种必要的输入数据。嵌入式软件的正常运行需要必要的外界输入数据,以完成系统的正常运行和交互。无论这些输入数据通过什么方式提供,桩模块都应该为嵌入式软件模拟各种输入数据。对于系统测试来说,输入数据也应该包括正常数据和非法数据两种。(5)分析模块包括测试结果、预期结果和故障模型三部分。测试结果为执行测试用例以后被测软件执行的结果;预期结果为测试开始之前,测试人员针对不同测试用例输入的预期结果;故障模型中包括对各种故障的定位。故障模型在一个测试结束后,积累的错误定位模型可以通过外部接口导出,既可以用作其他测试系统的故障模型,也可以导出Word或Excel文件,用于开发人员进行分析总结。分析模块在得到测试结果以后,首先与预期结果比较。如果相同,则测试通过;否则在故障模型中搜索相应的故障,并定位故障。如果故障模型中没有相应的错误定位,分析模块直接将未通过测试的测试结果和测试用例反馈给测试人员,由测试人员进行定位。当错误定位以后,测试人员根据测试实例修改故障模型,增加错误判断事件。通过不断循环,故障模型部分的各种故障定位逐渐增加,仿真系统在不断学习过程中实现错误定位。(6)人机界面用于各种数据、结果的输入和显示,以及交互操作的人工输入界面。3 铁路微机联锁系统测试被测铁路微机联锁2乘2取2系统运行在CPU(486DX)上,属于典型的嵌入式软件。逻辑图如图3所示。被测嵌入式软件运行在图3中A系和B系的CPU中,通过以太网接收人工下达的联锁命令,经过处理后通过DP协议网络传输给输出模块,控制现场设备。A、B系中只能以一个系为主系,主从系的切换可以通过手动切换实现,也可以自动切换。3.1 测试实施测试实施之前,首先编制测试用例,并针对每个测试用例给出预期结果和可能产生的错误以及相应错误的故障定位。把这些数据输入仿真系统的分析模型中,为即将进行的测试工作做准备。在测试实施过程中,首先利用此仿真系统按照第一类测试方法进行测试,验证铁路联锁2乘2取2系统被测软件是‘工作的‘,也就是软件的功能是按照预先的设计执行的。然后按照第二类测试方法进行测试,验证软件是不工作的。使用仿真系统设计并实施了很多在实际软硬件环境中不可能实现的测试用例。举例说明如下:(1)非法数据的输入。正常运行的系统,操作人员不可能发送错误的联锁命令给被测软件,输入模块也不可能产生测试需要的各种非法输入数据。使用仿真系统的驱动模块和桩模块,可以很轻松地发送任何组合形式的非法数据,以测试铁路联锁2乘2取2系统被测软件的安全性。结合分析模块的使用,具体实施过程为:通过人机界面输入超长非法测试数据6,244,244,80,0,17,1,0,80,0,255,255,255,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0给被测软件,预期结果为无测试结果数据返回,即嵌入式软件将非法数据过滤掉,不进行任何操作。仿真系统通过人机界面提示测试通过,实际情况也确实是微机联锁系统未进行任何操作,便将超长的非法数据过滤了。通过人机界面输入固定码的非法测试数据170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,预期结果为无测试数据返回,即嵌入式软件将非法数据过滤,不进行任何操作。仿真系统通过人机界面提示测试通过,而实际情况是微机联锁单元出现了死机现象。针对这种情况,修改预期结果内容为“无测试数据返回且与被测应用软件正常通讯”,而在故障模型中增加了“与被测应用软件无任何通讯”项,以修正仿真系统的错误定位为微机联锁单元死机。同理也要修改前面超长非法测试数据的预期结果和故障模型的内容。如此反复,仿真系统的分析模型也在不断完善中。(2)通信容量测试。铁路联锁2乘2取2系统被测软件中的基本功能包括系统通信最大I/O模块总数为100。在正常测试过程中,一般无法为测试搭建如此大规模的硬件测试环境,即使可以搭建,也会因为性价比较低而不实施此项测试。使用仿真系统,可以通过桩模块和驱动模块轻松实现100个I/O模块的通信量,同时可以省去购置I/O硬件模块的费用。(3)铁路联锁系统软件需要满足IEC61508标准[4]中SIL4的要求。通过仿真软件驱动模块重复发送联锁命令,可以很容易地测试铁路联锁2乘2取2系统中的软件是否满足SIL4的要求,而这些测试如果单纯用人工输入进行测试是不可能实现的。交互操作模块则可以在测试过程中完成软件与人必需的交互操作功能。被测软件第一次测试结束后,开发人员根据仿真系统的错误定位集中修改软件中的BUG,然后提交进行第一次回归测试。经过在第一次测试中人机交互的不断完善,仿真系统的分析模型趋于成熟,在回归测试过程中能很快定位错误,为测试及开发人员节省了大量时间,缩短了软件开发周期。3.2 测试结果通过使用仿真系统对铁路联锁2乘2取2系统被测软件实施测试,共发现涉及软件故障安全原则的致命问题和严重问题10个,涉及软件漏洞安全的致命问题和严重问题5个,涉及功能未实现的致命问题和严重问题6个,涉及可靠性的致命问题1个,一般和提示问题30个。针对嵌入式软件的特点提出的具备交互式错误检测定位功能的仿真系统架构模型,实现了在系统测试过程中检测定位软件错误,解决了嵌入式软件系统测试过程中,由于被测程序与嵌入式系统平台和底层程序融合在一起,错误不容易定位的问题。通过在铁路微机联锁测系统试项目中的应用,发现了很多关键性问题,并且为测试人员和开发人员节省了大量时间,加快了测试进度,在回归测试阶段表现尤为明显。事实表明,此仿真系统架构模型不仅可以应用于嵌入式软件的系统测试,也可以应用于非嵌入式软件的黑盒测试。在以后的研究中,将应用人工智能学科的学习理论,实现仿真系统分析模块的自动学习功能,以实现在测试过程中自动定位软件错误,而无需人工干预。

    时间:2018-06-27 关键词: 嵌入式开发 仿真系统 结构设计 嵌入式软件

  • 嵌入式软件正在成为产业创新和结构优化的重要推动力

    嵌入式软件正在成为产业创新和结构优化的重要推动力

    电子信息产业在本质上是个创新型产业,在很大程度上依赖研发创新的支持。从世界范围看,研发创新做得好的区域,往往能够形成电子信息产业发展的环境,形成支撑产业持续发展的核心动力,成为全球领先的电子信息产业基地,如美国的硅谷等。中国电子信息产业发展中“大而不强”的问题比较突出,如产品附加值低、产业链关键与核心环节薄弱等,产业发展在总体上处于价值链的低端。但目前这种局面正在发生改变,在研发——制造——销售这一产业价值链中,研发环节的增值能力大大高于其它环节,随着芯片和电子元器件等硬件的逐渐趋同,嵌入式系统(通信设备、消费电子、工业电子、医疗电子等)核心竞争力也就是产品的增值效应主要靠嵌入式软件实现,中国越来越多的企业正抓住嵌入式软件研发这个核心环节,实现以研发创新引领产业发展,比如以华为、中兴为代表的网络通信领域,以海尔、海信为代表的数字家庭领域,以东软、迈瑞为代表的医疗电子领域,以沈阳机床为代表的数控机床领域,以南瑞、许继为代表的电力自动化领域等等,不但中国产品在国内市场具有强大的竞争力,还在全球市场攻城拔寨,成为“中国制造”向“中国创造”产业升级有力的推动者。嵌入式软件成为信息化与工业化融合的有力推手党的十七大提出的“发展现代产业体系,大力推进信息化与工业化融合”的战略方针,以“工业软件”为主题的推进工作正如火如荼的进行,信息技术与工业技术、IT设备与工业装备的融合,开始产生新的科技成果,形成新的生产力,如利用嵌入式软件开发的具有车身控制电子的汽车、数字医疗设备、数控技术和数控机床,机器人技术及机器人,先进发电、输电和大型工程施工成套设备,大型自动化成套设备等。特别是以智能化、数字化、虚拟化、网络化、敏捷制造为方向,对传统企业设计、生产流程进行再造,实现生产信息化成为融合的关键所在,运用数控(CNC)、可编程序控制(PLC)、分布式控制(DCS)、现场总线控制(FCS)、先进控制(APC)、柔性制造单元和柔性制造系统FMC、FMS等先进加工控制技术推广精益生产、敏捷制造、虚拟制造、网络化制造,实现生产过程的自动化和生产结果的优质、低耗和高效,嵌入式软件以其附加值高、创新能力强的优势在辐射和带动产业结构优化、产业层次提升的过程中正发挥强大的催化作用。嵌入式软件增值效应正在各个领域不断显现随着数字家庭、消费电子、医疗电子、汽车电子、工业控制电子等设备逐步走向智能化和网络化应用,其中采用的芯片、外设等硬件逐步趋同,产品的核心竞争力体现在嵌入式软件的设计和功能上,高端产品的利润正越来越多的由嵌入式软件贡献,使得嵌入式软件的增值效益倍增。● 汽车应用潜力无限汽车已经逐步进入了电脑控制的时代。一个应用是车身控制系统,如发动机控制和底盘、安全系统、动力传动系统等,另一个应用是车载信息娱乐系统,如以无线的方式(3G、WiFi或4G)与全球定位系统(GPS)相连,与手机等便携式设备同步并可访问这些设备。随着汽车电子向网络化、智能化、舒适化趋势发展的不断深入,并在SoC技术的推动下,汽车电子正朝着高端应用发展,汽车电控系统功能不断扩展、逻辑渐趋复杂、子系统间通信频率不断提高是汽车电子技术的发展趋势。● 医疗电子更加智能化随着人们生活质量的不断提高,市场对医疗电子产品的需求越来越大,包括计算机断层扫描仪、磁共振仪、高档超声波诊断仪器等医疗影像领域高端产品,以及家用化、便携化、低功耗的中低端产品。各种电子技术将应用于最新的医疗设备开发中,嵌入式软件需要更加强大来提供可靠的架构、行业标准支持、多个图形界面选项、完善的网络支持。

    时间:2018-06-27 关键词: 数字家庭 嵌入式开发 核心竞争力 嵌入式软件

  • 嵌入式软件架构设计

    模块划分模块划分的"划"是规划的意思,意指怎样合理的将一个很大的软件划分为一系列功能独立的部分合作完成系统的需求。C语言作为一种结构化的程序设计语言,在模块的划分上主要依据功能(依功能进行划分在面向对象设计中成为一个错误,牛顿定律遇到了相对论),C语言模块化程序设计需理解如下概念:(1) 模块即是一个.c文件和一个.h文件的结合,头文件(.h)中是对于该模块接口的声明;(2) 某模块提供给其它模块调用的外部函数及数据需在.h中文件中冠以extern关键字声明;(3) 模块内的函数和全局变量需在.c文件开头冠以static关键字声明;(4) 永远不要在.h文件中定义变量!定义变量和声明变量的区别在于定义会产生内存分配的操作,是汇编阶段的概念;而声明则只是告诉包含该声明的模块在连接阶段从其它模块寻找外部函数和变量。如:/*module1.h*/int a = 5; /* 在模块1的.h文件中定义int a *//*module1 .c*/#include "module1.h" /* 在模块1中包含模块1的.h文件 *//*module2 .c*/#include "module1.h" /* 在模块2中包含模块1的.h文件 *//*module3 .c*/#include "module1.h" /* 在模块3中包含模块1的.h文件 */以上程序的结果是在模块1、2、3中都定义了整型变量a,a在不同的模块中对应不同的地址单元,这个世界上从来不需要这样的程序。正确的做法是:/*module1.h*/extern int a; /* 在模块1的.h文件中声明int a *//*module1 .c*/#include "module1.h" /* 在模块1中包含模块1的.h文件 */int a = 5; /* 在模块1的.c文件中定义int a *//*module2 .c*/#include "module1.h" /* 在模块2中包含模块1的.h文件 *//*module3 .c*/#include "module1.h" /* 在模块3中包含模块1的.h文件 */这样如果模块1、2、3操作a的话,对应的是同一片内存单元。一个嵌入式系统通常包括两类模块:(1)硬件驱动模块,一种特定硬件对应一个模块;(2)软件功能模块,其模块的划分应满足低偶合、高内聚的要求。多任务还是单任务所谓"单任务系统"是指该系统不能支持多任务并发操作,宏观串行地执行一个任务。而多任务系统则可以宏观并行(微观上可能串行)地"同时"执行多个任务。多任务的并发执行通常依赖于一个多任务操作系统(OS),多任务OS的核心是系统调度器,它使用任务控制块(TCB)来管理任务调度功能。TCB包括任务的当前状态、优先级、要等待的事件或资源、任务程序码的起始地址、初始堆栈指针等信息。调度器在任务被激活时,要用到这些信息。此外,TCB还被用来存放任务的"上下文"(context)。任务的上下文就是当一个执行中的任务被停止时,所要保存的所有信息。通常,上下文就是计算机当前的状态,也即各个寄存器的内容。当发生任务切换时,当前运行的任务的上下文被存入TCB,并将要被执行的任务的上下文从它的TCB中取出,放入各个寄存器中。嵌入式多任务OS的典型例子有Vxworks、ucLinux等。嵌入式OS并非遥不可及的神坛之物,我们可以用不到1000行代码实现一个针对80186处理器的功能最简单的OS内核,作者正准备进行此项工作,希望能将心得贡献给大家。究竟选择多任务还是单任务方式,依赖于软件的体系是否庞大。例如,绝大多数手机程序都是多任务的,但也有一些小灵通的协议栈是单任务的,没有操作系统,它们的主程序轮流调用各个软件模块的处理程序,模拟多任务环境。单任务程序典型架构(1)从CPU复位时的指定地址开始执行;(2)跳转至汇编代码startup处执行;(3)跳转至用户主程序main执行,在main中完成:a.初试化各硬件设备;b.初始化各软件模块;c.进入死循环(无限循环),调用各模块的处理函数用户主程序和各模块的处理函数都以C语言完成。用户主程序最后都进入了一个死循环,其首选方案是:while(1){}有的程序员这样写:for(;;){}这个语法没有确切表达代码的含义,我们从for(;;)看不出什么,只有弄明白for(;;)在C语言中意味着无条件循环才明白其意。下面是几个"著名"的死循环:(1)操作系统是死循环;(2)WIN32程序是死循环;(3)嵌入式系统软件是死循环;(4)多线程程序的线程处理函数是死循环。你可能会辩驳,大声说:"凡事都不是绝对的,2、3、4都可以不是死循环"。Yes,you are right,但是你得不到鲜花和掌声。实际上,这是一个没有太大意义的牛角尖,因为这个世界从来不需要一个处理完几个消息就喊着要OS杀死它的WIN32程序,不需要一个刚开始RUN就自行了断的嵌入式系统,不需要莫名其妙启动一个做一点事就干掉自己的线程。有时候,过于严谨制造的不是便利而是麻烦。君不见,五层的TCP/IP协议栈超越严谨的ISO/OSI七层协议栈大行其道成为事实上的标准?经常有网友讨论:printf("%d,%d",++i,i++); /* 输出是什么?*/c = a+++b; /* c=? */等类似问题。面对这些问题,我们只能发出由衷的感慨:世界上还有很多有意义的事情等着我们去消化摄入的食物。实际上,嵌入式系统要运行到世界末日。中断服务程序中断是嵌入式系统中重要的组成部分,但是在标准C中不包含中断。许多编译开发商在标准C上增加了对中断的支持,提供新的关键字用于标示中断服务程序(ISR),类似于__interrupt、#program interrupt等。当一个函数被定义为ISR的时候,编译器会自动为该函数增加中断服务程序所需要的中断现场入栈和出栈代码。中断服务程序需要满足如下要求:(1)不能返回值;(2)不能向ISR传递参数;(3) ISR应该尽可能的短小精悍;(4) printf(char * lpFormatString,…)函数会带来重入和性能问题,不能在ISR中采用。在某项目的开发中,我们设计了一个队列,在中断服务程序中,只是将中断类型添加入该队列中,在主程序的死循环中不断扫描中断队列是否有中断,有则取出队列中的第一个中断类型,进行相应处理。/* 存放中断的队列 */typedef struct tagIntQueue{int intType; /* 中断类型 */struct tagIntQueue *next;}IntQueue;IntQueue lpIntQueueHead;__interrupt ISRexample () {int intType;intType = GetSystemType();QueueAddTail(lpIntQueueHead, intType);/* 在队列尾加入新的中断 */}在主程序循环中判断是否有中断:While(1){If( !IsIntQueueEmpty() ){intType = GetFirstInt();switch(intType) /* 是不是很象WIN32程序的消息解析函数? */{/* 对,我们的中断类型解析很类似于消息驱动 */case xxx: /* 我们称其为"中断驱动"吧? */…break;case xxx:…break;…}}}按上述方法设计的中断服务程序很小,实际的工作都交由主程序执行了。硬件驱动模块一个硬件驱动模块通常应包括如下函数:(1)中断服务程序ISR(2)硬件初始化a.修改寄存器,设置硬件参数(如UART应设置其波特率,AD/DA设备应设置其采样速率等);b.将中断服务程序入口地址写入中断向量表:/* 设置中断向量表 */m_myPtr = make_far_pointer(0l); /* 返回void far型指针void far * */ m_myPtr += ITYPE_UART; /* ITYPE_UART: uart中断服务程序 *//* 相对于中断向量表首地址的偏移 */*m_myPtr = &UART _Isr; /* UART _Isr:UART的中断服务程序 */(3)设置CPU针对该硬件的控制线a.如果控制线可作PIO(可编程I/O)和控制信号用,则设置CPU内部对应寄存器使其作为控制信号;b.设置CPU内部的针对该设备的中断屏蔽位,设置中断方式(电平触发还是边缘触发)。(4)提供一系列针对该设备的操作接口函数。例如,对于LCD,其驱动模块应提供绘制像素、画线、绘制矩阵、显示字符点阵等函数;而对于实时钟,其驱动模块则需提供获取时间、设置时间等函数。C的面向对象化在面向对象的语言里面,出现了类的概念。类是对特定数据的特定操作的集合体。类包含了两个范畴:数据和操作。而C语言中的struct仅仅是数据的集合,我们可以利用函数指针将struct模拟为一个包含数据和操作的"类"。下面的C程序模拟了一个最简单的"类":#ifndef C_Class#define C_Class struct#endifC_Class A {C_Class A *A_this; /* this指针 */void (*Foo)(C_Class A *A_this); /* 行为:函数指针 */int a; /* 数据 */int b;};我们可以利用C语言模拟出面向对象的三个特性:封装、继承和多态,但是更多的时候,我们只是需要将数据与行为封装以解决软件结构混乱的问题。C模拟面向对象思想的目的不在于模拟行为本身,而在于解决某些情况下使用C语言编程时程序整体框架结构分散、数据和函数脱节的问题。我们在后续章节会看到这样的例子。总结本篇介绍了嵌入式系统编程软件架构方面的知识,主要包括模块划分、多任务还是单任务选取、单任务程序典型架构、中断服务程序、硬件驱动模块设计等,从宏观上给出了一个嵌入式系统软件所包含的主要元素。请记住:软件结构是软件的灵魂!结构混乱的程序面目可憎,调试、测试、维护、升级都极度困难。

    时间:2018-06-26 关键词: 嵌入式开发 软件架构 嵌入式os 嵌入式软件

  • 软总线架构在实时多任务软件系统中的设计应用

    软总线架构在实时多任务软件系统中的设计应用

    1.引言随着大型嵌入式系统向着集成化和多元化方向的发展,嵌入式软件系统的复杂度也日益增大。在集成多个硬件工作模块组成的复杂系统中,要求软件系统能同时测控多个模块的同步工作,软件设计要求做到实时多任务。针对软件设计的要求,采用基于实时多任务操作系统提供的底层任务调度机制,建立软件架构成为较好的选择。本文提出了基于实时多任务操作系统,建立软件架构时采用软总线提供数据驱动层的架构模式。针对实时多任务操作系统,分析任务调度与数据驱动层。针对资源共享与任务进程独立性等问题,提出软总线在共享数据维护上的优势。2.任务调度、共享资源与软总线结构研究2.1 嵌入式开发任务调度和资源共享目前主要的实时多任务操作系统(VxWorks,嵌入式Linux,WinCE)的任务调度均采用对于不同优先级抢占式调度,对同优先级采用时间片轮转调度的方法。为使低优先级任务能得到运行,软件需要能阻塞高优先级任务,同时也要能使被阻塞的任务重新就绪运行。操作系统对进程间通信资源的操作能产生这样的效果,所以在架构软件时,常借助进程间通信资源的使用。然而采用这样的方式,调度灵活性较差,同时低优先级任务对进程间通信资源的占用也始终处于劣势。任务进程较多复杂软件系统中,无法避免的会出现多进程共用资源的情况,事实上进程通信资源也是一种多进程共用的资源。进程可以对自身资源进行管理,但对于这些共享的资源,就无法只由共享者中的某一个进行管理。而这个管理却是必要的,否则进程内部的意外可能通过这些资源蔓延到其他进程,如:进程内部意外的对资源地址赋空,就会使其他共享该资源的进程在使用该资源时崩溃。这就要求在系统设计时,有独立于各个进程之外的总体的对资源管理的模块。2.2 软总线结构在此,本文提出软总线结构来架构复杂的软件系统,以解决任务调度和资源管理上的困难。软总线是封装了操作系统对于进程间通信资源,共享内存等有多个进程共同使用的资源操作的模块。该模块为任务进程模块提供标准的资源申请、使用及回收接口,任务进程使用该接口及协议的标识进行资源的共享。首先,软总线封装了各种进程可能共享的资源,独立于进程之外对资源进行管理,使共享资源对于任务进程透明,任务进程无法直接操作资源。这样的处理方式使得资源本身不能被任务进程修改或破坏。任务进程获取的数据,实际是总线上数据的副本,而所有关于总线上数据的更新都需要总线模块的认证,以避免出错。总线模块在操作系统底层调用的基础上,通过封装资源、提供接口,构建了一个数据驱动层。同时,由于软总线的封装,使得在构建软件系统时,对进程的调度需要通过软总线来实施。如果在总线模块处加载系统的调度策略,可以更灵活有效地对每个资源进行任务的调度。使得一方面降低了在开发初期为任务进程设置合理优先级的难度,一方面也使得不同任务能在不同的资源处能有更为灵活的优先策略。综合以上两点,以软总线架构底层数据驱动的方式构建实时多任务软件系统,可以有效地保护和管理共享资源并更为简单灵活对系统进行调度。3.软总线软件架构方案本设计基于Vxworks操作系统,试验平台包括通信、存储、复接、硬件总线与主控计算机等硬件电路板,及与硬件相对应的软件功能模块。3.1 软件架构整体方案本设计中,软总线封装的操作系统对于内存、信号量以及消息队列的创建、删除及使用等操作。上层与硬件功能对应的软件任务模块需要通过软总线进行对资源操作。具体的结构如图1 所示:对于功能模块本地化的资源,不强制要求使用软总线操作。图1 软总线架构设计框图3.2 软总线详细设计对于软总线结构的架构方式,设计关键节点就是软总线模块。该模块负责对操作系统的资源封装和上层功能模块的资源使用请求处理。本设计中,将软总线分成两个主要的部分:资源池和管理表。资源池是软总线模块开辟的内存区域,在内存池上进行系统其他功能模块的共享资源的创建。软总线引入了以下操作特性:资源创建于软总线的资源池,功能模块通过标示符来间接地使用资源,资源使用需要经过软总线的验证,多个进程对同一资源会有不同的操作方式和优先级,不同的资源有不同的调度策略。针对这些特性,就需要有相应的管理系统。该系统需要维护资源与标示符之间的关联、任务进程对资源的相关操作参数、资源特有的调度策略等。本文设计中软总线主要使用四个表格存储关联信息,其详细设计图如图2:图2 软总线详细设计图3.3 资源使用调度详细设计为了保证资源的安全性,系统要求进程在使用资源的时候先进行进程注册和资源申请。同时,系统对资源使用的行为进行比较严格的检测。因此,进程使用资源分为三步:进程注册,进程申请资源及进程使用资源。进程注册是在进程建立的时候,同时将进程信息写入软总线的进程表加以保存。进程申请资源通常在进程建立以后第一次工作时完成,类似对资源的初始化。进程申请资源要求进程在软总线已经注册,同时要求进程对资源的参数限定符合该资源。进程使用标识符来标示所要使用的资源,如果该资源不存在,这以该进程给定的参数在资源池中建立和初始化该资源并关联进程;如果资源存在,比对参数,如果一致,直接关联进程,否则出错处理。出错处理产生以“标识符_进程编号”为标识的副本,以进一步的使用,当然同时会有出错提示。资源使用要求进程和资源已经关联。同时使用的过程中,进程操作的是数据的副本,而对资源的更新是要受到系统的检测的。这次,副本数据的更新是实时的,这样就避免出现同步的问题。资源调度也会在资源获取前依据资源调度表中的信息进行。进程对资源申请和使用的详细调度如图 3 所示:图3 进程对资源申请和使用的详细调度图3.4 系统验证和安全性模拟实验经过验证,该系统*能模块使用软总线提供的接口操作资源,其速度和效率不低于使用未封装的资源。同时,软总线的封装使得资源对功能模块透明,而且使用资源时还要求对其进行较强的验证,因此资源的安全性及系统的健壮性得到了较大幅度的提高。为了验证系统的安全性健壮性,我们进行了安全测试。在测试中,模拟了系统可能出现的各种安全漏洞。同时,与使用非软总线结构,对资源不进行强验证的系统进行比较。结果如表1:如上表所示,使用软总线架构,系统具有更强的安全性和健壮性。4.结束语本文介绍了使用软总线封装系统资源,设计实时多任务嵌入式软件的架构方式。通过实际的工程实践,给出软总线的设计方案。文章通过理论分析和实验对比指出了这种架构方式在处理多任务调度和资源共享上相对普通架构的优势。

    时间:2018-06-21 关键词: 实时多任务 总线与接口 软总线 嵌入式软件

  • 嵌入式系统集成开发平台的设计与实现

    嵌入式系统集成开发平台的设计与实现

    0引言嵌入系统开发已经趋于规范化,但是嵌入式系统的开发并不像在普通PC机上进行软件开发那样容易,它同样需要一个高度集成的开发平台,来降低开发的难度。目前市场上的嵌入式系统集成开发平台特点是: ( 1)多数嵌入式系统集成开发平台都是以Windows为系统环境,很少有以Linux为系统环境的;( 2)部分集成开发平台具有一定的开放性,许多功能作为插件供用户选择; ( 3)多数集成开发平台通用性较差,仅支持一个或者几个系列的微处理器; ( 4)目前嵌入式系统集成开发平台产品大都价格昂贵; ( 5)很少有集成开发平台集成有图形模块支持的功能。为了解决其它嵌入式集成开发平台的缺点,本文研究了嵌入式系统可视化集成开发平台,ESGIDE ( Embedded system graphical integrated development environment),其最大特点是具有图形化人机交互功能和ARM CPU工作方式自动初始化。所谓图形化人机交互,是指把将要裁剪和配置的系统级软件(比如bootloader、kernel、通用I /O输入、输出等)化整为零,封装成不同功能的形象化图形模块,开发者根据自己开发的系统需要,选择不同图形模块,动态生成bootloader、kernel、I /O等系统级的源代码,不需要开发者自己输入,这大大简化了开发步骤,减轻了程序员的负担,减少了操作的复杂度,提高了开发效率。另一方面,ARM系列CPU应用比较广泛,不同型号的CPU在开发时需要对使用的内部资源进行初始化。传统的做法是开发者确定工作方式,确定工作方式字,然后手动编程。我们采用开发模式是:以定时器应用为例,将定时器的个数,工作方式确定,时钟频率的确定,是否允许中断等编写成对话框模式,开发者只要选中其中的方式,初始化控制字自动生成,编写代码自动生成,同样大大简化了开发步骤,减轻了程序员的负担。面向对象技术是当前实现软件模块化、提高软件复用性最优的方法,现在成为计算机领域中的一种主流技术,本文提出利用面向对象的技术来设计一种嵌入式软件IDE,对嵌入式软件开发中的各个对象的类进行分析与设计,架构一个通用的开发模型,根据硬件配置自动产生基本的系统软件方案。只需要系统中的每个对象类的属性及其操作设置,自动搭建交叉编译环境,降低操作系统裁减和移植的难度,产生驱动程序的基本框架。开发人员只需要配置好各个模块的基本信息,将更多精力集中在系统的应用上。1嵌入式软件的开发流程与常见的PC和服务器软件不同,嵌入式软件主要是对设备内部各部分的运行进行协调,并不与设备使用者发生直接接触。PC和服务器软件的运行环境是标准化的,而嵌入式软件的运行环境随电子设备的不同而改变,必须针对不同的电子产品进行专门的设计、开发和优化。由于嵌入式Linux操作系统在嵌入式开发中占据了主流,因此本文围绕针对移植有Linux操作系统的嵌入式开发流程进行讨论。典型的基于嵌入式Linux操作系统的嵌入式软件开发流程如下[1]:( 1)获取硬件系统的信息:如选取的微处理器体系,Flash型号、网卡型号及其他外设的信息等;( 2)建立交叉编译工具:一般的GCC工具都是针对X86体系的,为了能够生产目标板执行的代码必须建立交叉编译工具;( 3)开发Bootloader:建立启动系统的主引导程序;( 4)移植Linux内核:如基于Linux2.6内核移植;( 5)开发一个根文件系统:如rootfs的制作;( 6)开发特定硬件的驱动程序:如LCD,Keypad等;( 7)开发上层的应用程序:如QT GUI开发。对于开发过程的各个环节,有的提供了辅助的开发工具,有的需要完全依赖经验手工从底层开发,嵌入式软件开发依然停留在手工作坊式的方式,很难做到工程化管理。本文所设计的IDE将涵盖整个开发的各个重要环节,力求最大程度上降低开发难度,在集成化开发环境里完成主要工作。2 IDE面向对象的分析与设计对于运行嵌入式Linux操作系统的系统,根据其开发流程,利用面向对象技术分析设计出6个基本的大类,并给出对象之间的协作关系图,如图1、图2所示。这几个大类贯穿了嵌入式软件开发的重要环节。图1嵌入式软件IDE基本类图2基本对象类的协作图硬件系统信息类,承载了硬件系统的描述信息,比如选取何种体系的微处理器,处理器的工作频率设置,采用何种启动方式,是NandFlash,还是NorFlash或者EPROM等,用户通过设定这些参数,其他对象将获取其中的信息进行配置。嵌入式开发需要交叉编译,Linux环境下一般就是采用开源Gcc系列进行配置,环境搭建类管理交叉编译链的源代码,根据体系架构的信息自动生成运行脚本,在制定目录下生成完整的交叉编译链,这是嵌入式开发的基础。工程管理类,集成开发环境的主要目的就是同一组织文档,省却人工管理,自动编译运行源码,其中包含了文件操作,组织好源代码之间的关系,利用make技术进行编译,牵扯到大量全局环境参数的设定。引入控制字库类是方便部分程序的编写,比如Bootloader类需要对处理器初始化,基本的驱动控制器进行操作,其中包含了汇编指令级别和C语言的操作,开发人员往往需要对参考手册熟练掌握,大大降低了开发效率。控制字库尽量包含了常见的处理器系列的寄存器控制字库,只需选择某个具体功能,便可产生需要的指令源码。同样驱动程序开发中,也是频繁利用了C语言对寄存器进行操作。系统移植类涵盖了整个系统需要移植的模块,引导程序,操作系统内核和文件系统,各类封装了大量繁杂的细节内容,尽量以最简化形式帮助开发人员完成操作,重要的环节只需设定参数,其他交由对象自动执行。面向对象最重要的特征就是“高内聚度和低耦合性”,各个对象封装了细节操作,只需要有限的外部接口交换信息,这种柔性思想最大程度上提高了软件的复用性。本文所设计的IDE,根据体系结构的不同,所需修改的只是个别对象的内部数据和操作,整体架构不受任何影响[2,3]。图3给出了面向对象嵌入式集成开发平台的结构。图3面向对象的嵌入式集成开发平台结构框图3系统的具体实现目前可视化的面向编程语言种类比较多,从对面向对象技术的支持程度上来说,微软最新的VC#从封装性、类型安全性方面相当强大。重要的是,类层次清晰,编码容易,可以根据面向对象设计的框架轻松的进行转换,却和C ++一样强大。所以本文利用VC#设计了嵌入式软件IDE,对各个类编写详细代码。整个系统基本架构如图4所示。图4 IDE的系统架构图集成开发环境运行于Windows平台下,但需要Linux的强大命令集,在此,本文提出了Cygwin技术来模拟Linux运行环境,从而使得IDE的底层得到强大的各种命令支持,可以运行各种脚本文件。此技术属于开源项目,安装后需个别地方的细节修改。交叉编译工具链模块是IDE设计的核心,开发一个实用的编译器,需要花费大量的人力物力和财力,其可靠性也要经受时间的考验。幸运的是,GNU提供了免费的、功能强大的GCC工具链,它不仅可以编译Linux操作系统下的应用程序以及Linux内核,而且还是一款交叉编译器,支持ARM、PowerPC、x86、Intel960、M68等几乎所有知名的CPU厂家,而且国外大多数集成开发工具都从GCC移植而来。本文的交叉编译工具链模块并不是单独的针对某个体系结构,可以重定向,根据参数配置,生成某个系列的编译工具,如图5所示。图5交叉工具链模块软件设计的一个重要环节就是,要组织好源代码之间的关系,编译连接,这就要用到工程化的手段去管理源码。这是IDE设计中的桥梁。本文利用的Makefile技术对整个工程进行管理,主要就是针对驱动程序和应用程序的组织和编译。Makefile是Linux工程管理的一项成熟的技术,有一套完整的规则,只需要按照规则去编写Makefile文件,然后由make命令去解释执行。Cygwin中集成了Gnumake,因此只要编写好Makefile文件,只需一个make命令,就可以完成所有的编译连接工作,如图6所示。图6工程管理模块大多数的IDE都有这个命令,比如: Delphi的make,Visual C + +的nmake,Linux下GNU的make.可见,makefile都成为了一种在工程方面的编译方法。一个关键技术就是显示信息重定向到IDE指定的输出窗口,各种脚本运行信息都是标准控制台输出,因此需要将编译中的标准信息和错误信息进行重定向。通常是靠管道技术来解决这个问题,但嵌入式开发中许多编译过程长达数小时,信息往往需要进程结束才能完全显示。本文IDE则采用了管道技术加异步式读取技术,使得重定向和信息显示同时进行,及时反馈编译过程中的各种信息。Bootloader是嵌入式系统的引导加载程序,它的作用是初始化必要的硬件设备,创建内核需要的一些信息并将信息通过相关机制传递给内核,从而将系统的软硬件环境带到一个合适的状态,最终调用操作系统内核,真正起到引导和加载内核的作用[5]。Bootloader依赖于硬件实现,除了体系结构,还依赖于具体的嵌入式板级设备的配置,因此Bootloader是嵌入式开发移植最困难的部分,一般来说都是将已有的代码进行大量的修改,本文采用的是U-Boot 1.2.0,目前来说是比较通用的Bootloader.如图7所示,针对这部分移植,为了最大程度上帮助用户完成代码的修改,IDE提供不同类型的体系架构需要修改的源码的提示信息,以及某种配置下需要修改的提示信息,需要建立一个帮助文件数据库。通过控制字库模块添加需要的源码。其实一般来说,修改都是大同小异,最主要的是修改两个方面,何种方式启动,是Nadflash还是Norflash,如果是Nandflash启动,需要定义芯片配置函数,增加Nandflash拷贝数据到内存的代码。还有就是为了利用tft协议烧录内核到flash,需要针对某种网卡芯片进行修改。图7 Bootloaer移植模块简单来说,内核配置无非就是生成一个配置文件,由Makefile来读取,不同的架构,就会选择不同架构目录下的源码。但是内核配置比较繁杂,一般人员很难理清源码之间的关系,配置不好,不仅无法编译,即使勉强编译成功,也未必能够正常运行。而且,内核不单单是配置问题,还有部分源码根据需要必须修改,比如如果是Nandflash作为存储器,需要建立Nandflash分区表。对于内核配置,本文IDE提供利用模板来进行二次配置,建立模板数据库,根据用户的参数设定,提供符合条件的模板,如果模板基本符合要求,就可以利用模板进行编译,如果需要细节的修改,则调用内核配置工具来进行配置,内核配置工具利用make xconfig形式,产生图形化界面,当然需要X系统的支持,需要在Cygwin中安装、修改。对于内核源码修改,则需要帮助文件数据库,根据用户参数设置,产生需要的源码,添加到内核中去。如图8所示。图8内核移植模块根文件系统是Linux /Unix系统启动的一个重要组成部分,也是操作系统正常工作时候的必要组成部分,在启动时候内核需要跟文件系统来挂载。在现代Linux操作系统中,内核代码影像文件保存在根文件中,系统引导启动程序会从这个根文件设备商把内核代码加载到内存中取运行。如图9所示。图9根文件制作模块嵌入式根文件系统有RomFS,JFFS2,NFS,EXT2,RAMDISK,Cramfs等,每个系统都有自己的特点,最常用的就是Cramfs文件系统,Cygwin工具集中提供了Cramfs工具,mkcramfs.嵌入式根文件的最底层目录中,都有其具体的用途和目的,因此必须建立最基本的根目录。而且一些根目录下必须有固定的文件,如/bin,/ sbin,/ usr /bin,/ usr /sbin需要放置Linux命令工具,/ etc目录下需要系统配置文件,包括启动文件。因此,本模块要完成这么几个功能,提供必须的根目录,根目录下的文件,将根目录制作成某种跟文件系统,本文暂时提供Cramfs文件系统。嵌入式Linux命令工具集由BusyBox工具提供,它包含了很多标准Linux工具的单个可执行实现,本文的IDE提供了一个BusyBox的标准配置,只需要利用交叉工具链进行编译。4嵌入式微处理器内部资源驱动嵌入式微处理器有大量的内部I /O接口资源,如定时计数器、中断、DMA、开关量输入输出等,要选择其中的接口应用,首先要进行初始化,编写驱动程序。驱动程序编写模块和应用程序编写模块只要提供一个文本编辑器,利用工程管理部分去组织源码进行编译就可以。对于驱动程序的编写,Linux驱动程序都有一套固定的模式,比如字符型、块型、网络型数据结构都有区别,但每种类型的驱动程序架构都一样。另外驱动程序编写中最重要的就是根据每个接口资源确定的工作方式确定控制字,即使开发人员对某个体系下的各类CPU内部资源的控制字十分熟悉,也要经常参考手册才能准确无误。本文提出了驱动程序编写模式,一个是选择类型,自动生成某种类型的模板,在此模板上进行添加修改;第二就是利用控制字模块,在开发驱动程序过程中,开发人员可以选择某个体系结构下的针对某种具体寄存器的操作,然后会自动产生必要的代码,如图10、图11所示,只需要将代码嵌入到驱动程序源码中。图10是定时器的选择界面,开发者只要根据需求选择相应的定时器,确定其功能,初始值,然后选择确认按钮,初始化代码自动生成,如图11包含初始化控制字,非常快捷、便利。另外,如果驱动程序要添加到内核去,重新重新配置内核即可。图10定时器及其功能选择界面图11自动产生初始化代码界面5结语本开发平台具有友好的用户界面、文本编辑器、工程管理工具、交叉编译器、烧录和下载工具、图形化模块支持。本集成开发平台可以供学生、老师或者工程技术人员学习嵌入式linux的裁剪和移植,ARM系列CPU的开发和应用。利用本文研究的嵌入式软件IDE,针对ARM系列的2410平台进行了U-Boot、Linux2.6内核、根文件系统的配置和移植,编写出基本的网卡驱动程序,测试取得成功。

    时间:2018-06-18 关键词: 嵌入式开发 软件开发工具 esgide 嵌入式软件

  • 嵌入式系统基础之:嵌入式软件开发流程

    嵌入式系统基础之:嵌入式软件开发流程

    4.3嵌入式软件开发流程4.3.1嵌入式系统开发概述由嵌入式系统本身的特性所影响,嵌入式系统开发与通用系统的开发有很大的区别。嵌入式系统的开发主要分为系统总体开发、嵌入式硬件开发和嵌入式软件开发3大部分,其总体流程图如图4.15所示。在系统总体开发中,由于嵌入式系统与硬件依赖非常紧密,往往某些需求只能通过特定的硬件才能实现,因此需要进行处理器选型,以更好地满足产品的需求。另外,对于有些硬件和软件都可以实现的功能,就需要在成本和性能上做出抉择。往往通过硬件实现会增加产品的成品,但能大大提高产品的性能和可靠性。再次,开发环境的选择对于嵌入式系统的开发也有很大的影响。这里的开发环境包括嵌入式操作系统的选择以及开发工具的选择等。本书在4.1.5节对各种不同的嵌入式操作系统进行了比较,读者可以以此为依据进行相关的选择。比如,对开发成本和进度限制较大的产品可以选择嵌入式Linux,对实时性要求非常高的产品可以选择Vxworks等。由于本书主要讨论嵌入式软件的应用开发,因此对硬件开发不做详细讲解,而主要讨论嵌入式软件开发的流程。4.3.2嵌入式软件开发概述嵌入式软件开发总体流程为图4.15中“软件设计实现”部分所示,它同通用计算机软件开发一样,分为需求分析、软件概要设计、软件详细设计、软件实现和软件测试。其中嵌入式软件需求分析与硬件的需求分析合二为一,故没有分开画出。由于在嵌入式软件开发的工具非常多,为了更好地帮助读者选择开发工具,下面首先对嵌入式软件开发过程中所使用的工具做一简单归纳。嵌入式软件的开发工具根据不同的开发过程而划分,比如在需求分析阶段,可以选择IBM的RationalRose等软件,而在程序开发阶段可以采用CodeWarrior(下面要介绍的ADS的一个工具)等,在调试阶段所用的Multi-ICE等。同时,不同的嵌入式操作系统往往会有配套的开发工具,比如Vxworks有集成开发环境Tornado,WindowsCE的集成开发环境WindowsCEPlatform等。此外,不同的处理器可能还有对应的开发工具,比如ARM的常用集成开发工具ADS、IAR和RealView等。在这里,大多数软件都有比较高的使用费用,但也可以大大加快产品的开发进度,用户可以根据需求自行选择。图4.16是嵌入式开发的不同阶段的常用软件。图4.15嵌入式系统开发流程图图4.16嵌入式开发不同阶段的常用软件嵌入式系统的软件开发与通常软件开发的区别主要在于软件实现部分,其中又可以分为编译和调试两部分,下面分别对这两部分进行讲解。1.交叉编译嵌入式软件开发所采用的编译为交叉编译。所谓交叉编译就是在一个平台上生成可以在另一个平台上执行的代码。在第3章中已经提到,编译的最主要的工作就在将程序转化成运行该程序的CPU所能识别的机器代码,由于不同的体系结构有不同的指令系统。因此,不同的CPU需要有相应的编译器,而交叉编译就如同翻译一样,把相同的程序代码翻译成不同CPU的对应可执行二进制文件。要注意的是,编译器本身也是程序,也要在与之对应的某一个CPU平台上运行。嵌入式系统交叉编译环境如图4.17所示。小知识与交叉编译相对应,平时常用的编译称为本地编译。这里一般将进行交叉编译的主机称为宿主机,也就是普通的通用PC,而将程序实际的运行环境称为目标机,也就是嵌入式系统环境。由于一般通用计算机拥有非常丰富的系统资源、使用方便的集成开发环境和调试工具等,而嵌入式系统的系统资源非常紧缺,无法在其上运行相关的编译工具,因此,嵌入式系统的开发需要借助宿主机(通用计算机)来编译出目标机的可执行代码。由于编译的过程包括编译、链接等几个阶段,因此,嵌入式的交叉编译也包括交叉编译、交叉链接等过程,通常ARM的交叉编译器为arm-elf-gcc、arm-linux-gcc等,交叉链接器为arm-elf-ld、arm-linux-ld等,交叉编译过程如图4.18所示。2.交叉调试嵌入式软件经过编译和链接后即进入调试阶段,调试是软件开发过程中必不可少的一个环节,嵌入式软件开发过程中的交叉调试与通用软件开发过程中的调试方式有很大的差别。在常见软件开发中,调试器与被调试的程序往往运行在同一台计算机上,调试器是一个单独运行着的进程,它通过操作系统提供的调试接口来控制被调试的进程。而在嵌入式软件开发中,调试时采用的是在宿主机和目标机之间进行的交叉调试,调试器仍然运行在宿主机的通用操作系统之上,但被调试的进程却是运行在基于特定硬件平台的嵌入式操作系统中,调试器和被调试进程通过串口或者网络进行通信,调试器可以控制、访问被调试进程,读取被调试进程的当前状态,并能够改变被调试进程的运行状态。嵌入式系统的交叉调试有多种方法,主要可分为软件方式和硬件方式两种。它们一般都具有如下一些典型特点。n 调试器和被调试进程运行在不同的机器上,调试器运行在PC机(宿主机),而被调试的进程则运行在各种专业调试板上(目标板)。n 调试器通过某种通信方式(串口、并口、网络、JTAG等)控制被调试进程。n 在目标机上一般会具备某种形式的调试代理,它负责与调试器共同配合完成对目标机上运行着的进程的调试。这种调试代理可能是某些支持调试功能的硬件设备,也可能是某些专门的调试软件(如gdbserver)。n 目标机可能是某种形式的系统仿真器,通过在宿主机上运行目标机的仿真软件,整个调试过程可以在一台计算机上运行。此时物理上虽然只有一台计算机,但逻辑上仍然存在着宿主机和目标机的区别。下面分别就软件调试桩方式和硬件片上调试两种方式进行详细介绍。(1)软件方式。软件调试主要是通过插入调试桩的方式来进行的。调试桩方式进行调试是通过目标操作系统和调试器内分别加入某些功能模块,二者互通信息来进行调试。该方式的典型调试器有gdb调试器。gdb的交叉调试器分为GdbServer和GdbClient,其中的GdbServer就作为调试桩在安装在目标板上,GdbClient就是驻于本地的gdb调试器。它们的调试原理图如图4.19所示。gdb调试的工作流程。n 首先,建立调试器(本地gdb)与目标操作系统的通信连接,可通过串口、网卡、并口等多种方式。n 然后,在目标机上开启GdbServer进程,并监听对应端口。n 在宿主机上运行调试器gdb,这时,gdb就会自动寻找远端的通信进程,也就是GdbServer的所在进程。n 在宿主机上的gdb通过GdbServer请求对目标机上的程序发出控制命令。这时,GdbServer将请求转化为程序的地址空间或目标平台的某些寄存器的访问,这对于没有虚拟存储器的简单的嵌入式操作系统而言,是十分容易的。n GdbServer把目标操作系统的所有异常处理转向通信模块,并告知宿主机上gdb当前有异常。n 宿主机上的gdb向用户显示被调试程序产生了哪一类异常。这样就完成了调试的整个过程。这个方案的实质是用软件接管目标机的全部异常处理及部分中断处理,并在其中插入调试端口通信模块,与主机的调试器进行交互。但是它只能在目标机系统初始化完毕、调试通信端口初始化完成后才能起作用,因此,一般只能用于调试运行于目标操作系统之上的应用程序,而不宜用来调试目标操作系统的内核代码及启动代码。而且,它必须改变目标操作系统,因此,也就多了一个不用于正式发布的调试版。(2)硬件调试。相对于软件调试而言,使用硬件调试器可以获得更强大的调试功能和更优秀的调试性能。硬件调试器的基本原理是通过仿真硬件的执行过程,让开发者在调试时可以随时了解到系统的当前执行情况。目前嵌入式系统开发中最常用到的硬件调试器是ROMMonitor、ROMEmulator、In-CircuitEmulator和In-CircuitDebugger。n 采用ROMMonitor方式进行交叉调试需要在宿主机上运行调试器,在宿主机上运行ROM监视器(ROMMonitor)和被调试程序,宿主机通过调试器与目标机上的ROM监视器遵循远程调试协议建立通信连接。ROM监视器可以是一段运行在目标机ROM上的可执行程序,也可以是一个专门的硬件调试设备,它负责监控目标机上被调试程序的运行情况,能够与宿主机端的调试器一同完成对应用程序的调试。在使用这种调试方式时,被调试程序首先通过ROM监视器下载到目标机,然后在ROM监视器的监控下完成调试。优点:ROM监视器功能强大,能够完成设置断点、单步执行、查看寄存器、修改内存空间等各项调试功能。确定:同软件调试一样,使用ROM监视器目标机和宿主机必须建立通信连接。其原理图如图4.20所示。n 采用ROMEmulator方式进行交叉调试时需要使用ROM仿真器,并且它通常被插入到目标机上的ROM插槽中,专门用于仿真目标机上的ROM芯片。在使用这种调试方式时,被调试程序首先下载到ROM仿真器中,因此等效于下载到目标机的ROM芯片上,然后在ROM仿真器中完成对目标程序的调试。优点:避免了每次修改程序后都必须重新烧写到目标机的ROM中。缺点:ROM仿真器本身比较昂贵,功能相对来讲又比较单一,只适应于某些特定场合。其原理如图4.21所示。n 采用In-CircuitEmulator(ICE)方式进行交叉调试时需要使用在线仿真器,它是目前最为有效的嵌入式系统的调试手段。它是仿照目标机上的CPU而专门设计的硬件,可以完全仿真处理器芯片的行为。仿真器与目标板可以通过仿真头连接,与宿主机可以通过串口、并口、网线或USB口等连接方式。由于仿真器自成体系,所以调试时既可以连接目标板,也可以不连接目标板。在线仿真器提供了非常丰富的调试功能。在使用在线仿真器进行调试的过程中,可以按顺序单步执行,也可以倒退执行,还可以实时查看所有需要的数据,从而给调试过程带来了很多的便利。嵌入式系统应用的一个显著特点是与现实世界中的硬件直接相关,并存在各种异变和事先未知的变化,从而给微处理器的指令执行带来各种不确定因素,这种不确定性在目前情况下只有通过在线仿真器才有可能发现。优点:功能强大,软硬件都可做到完全实时在线调试。缺点:价格昂贵。其原理如图4.22所示。n 采用In-CircuitDebugger(ICD)方式进行交叉调试时需要使用在线调试器。由于ICE的价格非常昂贵,并且每种CPU都需要一种与之对应的ICE,使得开发成本非常高。一个比较好的解决办法是让CPU直接在其内部实现调试功能,并通过在开发板上引出的调试端口发送调试命令和接收调试信息,完成调试过程。如使用非常广泛的ARM处理器的JTAG端口技术就是由此而诞生的。JTAG是1985年指定的检测PCB和IC芯片的一个标准。1990年被修改成为IEEE的一个标准,即IEEE1149.1。JTAG标准所采用的主要技术为边界扫描技术,它的基本思想就是在靠近芯片的输入输出管脚上增加一个移位寄存器单元。因为这些移位寄存器单元都分布在芯片的边界上(周围),所以被称为边界扫描寄存器(Boundary-ScanRegisterCell)。当芯片处于调试状态时候,这些边界扫描寄存器可以将芯片和外围的输入输出隔离开来。通过这些边界扫描寄存器单元,可以实现对芯片输入输出信号的观察和控制。对于芯片的输入管脚,可通过与之相连的边界扫描寄存器单元把信号(数据)加载到该管脚中去;对于芯片的输出管脚,可以通过与之相连的边界扫描寄存器单元“捕获”(CAPTURE)该管脚的输出信号。这样,边界扫描寄存器提供了一个便捷的方式用于观测和控制所需要调试的芯片。现在较为高档的微处理器都带有JTAG接口,包括ARM7、ARM9、StrongARM、DSP等,通过JTAG接口可以方便地对目标系统进行测试,同时,还可以实现Flash编程,这是非常受欢迎的。优点:连接简单,成本低。缺点:特性受制于芯片厂商。其原理如图4.23所示。

    时间:2018-06-15 关键词: 嵌入式系统 基础教程 jtag 交叉编译 交叉调试 嵌入式软件

  • 嵌入式软件开发之:  映像文件存储器映射调整

    嵌入式软件开发之: 映像文件存储器映射调整

    13.4 映像文件存储器映射调整13.4.1 关于分散加载映像由域(Regions)和输出段(Output Sections)组成。每个域可以有不同的加载地址和执行地址。分散加载可以更加方便准确的指定映像存储器映射,为映像组件分组和布局提供了全面控制。它能够描述由载入时和执行时分散在存储器映射中的多个区组成的复杂映像映射。虽然,分散加载可以用于简单映像,但它通常仅用于具有复杂存储器映射的映像。要构建映像的存储器映射,必须向armlink提供以下信息:· 分组信息:决定如何将各输入段组织成相应的输出段和域;· 定位信息:决定各域在存储空间的起始地址。有两种方法可以配置指定映像文件的分组和定位信息:如果映像文件中地址映射关系比较简单,可以使用命令行选项;如果映像文件中地址映射关系比较复杂的情况,可以使用一个配置文件。使用该配置文件可以告诉链接器相关的地址映射关系。配置文件又叫Scatter文件,是一个文本文件,通过下面的链接选项来实现。-scatter filename1.为分散加载定义的符号当armlink使用Scatter文件创建映像时,它创建一些区相关符号。表13.2概括了这些符号的意义。表13.2 域相关符号符 号意 义Load$$region_name$$Base域的载入地址Image$$region_name$$Base域的执行地址Image$$region_name$$Length执行域字节长度(4的倍数)Image$$region_name$$Limit执行区末尾地址Image$$region_name$$ZI$$Base执行域中ZI段的执行地址Image$$region_name$$ZI$$LengthZI输出段的长度(4的倍数)Image$$region_name$$ZI$$Limit执行域中ZI段的末尾地址2.使用Scatter文件的优势链接程序的命令行选项提供了一些对数据和代码布局的控制,但要实现对布局的全面控制命令行输入的指令是远远不够的。在下面一些情况下,就需要使用Scatter文件对映像布局进行控制。① 需要实现复杂存储器映射系统中的代码和数据必须放在多个不同存储器区域中,这样连接器必须知道哪个段放在哪个储存器空间的详细信息。这种情况下,最好用Scatter文件实现代码映像的分散加载。② 系统中存在多种不同类型存储器许多系统包含多种不同类型存储器,如flash存储器、ROM、SDRAM和快速SRAM。分散载入描述可以将代码和数据放置在最适合的存储器类型中。例如,中断代码可能放在快速SRAM中,以加快中断响应时间,而不频繁使用的配置信息可能放在较慢的flash存储器中。③ 存储器映射I/O分散载入描述可以将数据精确定位在内存地址中,而避免数据和内存映射外围地址相冲突。④ 位于固定位置函数可以将特定函数放在存储器中的同一个位置,这样即使周围的应用程序已经被修改并重新编译,也可以使具有特定功能的函数地址保持不变。⑤ 使用符号识别堆和栈可以为堆和栈的位置定义符号,链接应用程序时可以指定该封闭模块的位置。随着目前嵌入式系统越来越复杂,系统中可能同时使用flash、ROM和RAM,所以建议在生产系统映像时使用Scatter文件。3.分散加载命令行选项可以使用下面的命令行选项使用分散加载文件。-scatter description_file_name使用该命令可以使链接器使用命令中给出的description_file_name文件生成最终的映像文件。4.简单存储器映像举例例如,一个实际系统的存储器映射如图13.7所示。图13.7 简单存储器映射为了实现图13.7的存储器映射,使用图13.8所现实的Scatter文件。5.复杂存储器映像实现举例一个复杂存储器映射如图13.9所示。图13.8 实现简单内存映射的Scatter文件图13.9 复杂存储器映射实例为了实现图13.9的存储器映射,使用以下程序所现实的Scatter文件。LOAD_ROM_1 0x0000 ;第一个加载时域的起始地址{ EXEC_ROM_1 0x0000 ;第一个运行时域的起始地址 { programl.o(+RO) ;放置program.o中所以的RO段 { SRAM 0x9000 ;运行时域的起始地址 { programl.o(+RW,+ZI) ;放置program.o中所有的RW和ZI段 }}LOAD_ROM_2 0x4000 ;第二个加载时域的起始地址{ EXEC_ROM_2 0x4000 ;运行时域的起始地址 { program2.o(+RO) } DRAM 0x18000 ;运行时域的起始地址 { program2.o(+RW,+ZI) }}上面两个例子中,简单存储器映射可以使用命令行选项实现,但第二个复杂存储器映射的例子却只能使用Scatter文件实现。13.4.2 Scatter文件语法分散载入描述文件是一个文本文件,它向 armlink 描述目标系统的存储器映射。如果从命令行加载Scatter文件,可以使用任意类型的文件扩展名。在Scatter文件中,用户可以指定以下存储器映像内容:· 每个载入区的载入地址和最大尺寸;· 每个载入区的属性;· 从每个载入区派生的执行区;· 每个执行区的执行地址和最大尺寸;· 每个执行区的输入节。描述文件的格式反映出载入区、执行区和输入节的层次结构。1.BNF的表示法和语法所谓BNF(Backus Naur Format)即Scatter文件所用的形式语言。表13.3概括了其所用的符号和语法规则。表13.3 BNF语法符 号说 明”引号用于表示BNF语法中的字符被用作普通字符。例如,定义B"+"C,它只能替换为模式B+C。而定义B+C可以替换为模式BC、BBC或BBBCA ::= B将A定义为B。例如,A::= B"+" | C 表示A相当于B+或C。在其组件方面,::=表示法用于定义高级结构。每个组件可能还有一个::=定义,对更简单的组件进行定义。例如,A::=B以及B::= C | D表示定义A相当于模式C或D续表符 号说 明[A]可选元素A。例如,A::= B[C]D 表示定义A可以扩展为BD或BCDA+元素A可以出现一次或多次。例如,A::= B+表示定义A可以扩展为B、BB或BBB等A*元素A可以不出现或多次出现A|B出现元素A或B,但不能同时出现(A|B)元素A和B组合在一起。这在使用 | 操作符时,或重复复杂模式时尤其适用。例如,A::=(B C)+ (D | E) 表示定义A可以扩展为BCD、BCE、BCBCD、BCBCE、BCBCBCD或BCBCBCE2.Scatter文件语法概述分散加载描述scatter_description被定义为一个或多个load_region_description模式:Scatter_description ::=load_region_description+加载域描述load_region_description 被定义为载入区名称,可以选择性地在其后跟随属性、尺寸说明符以及一个或多个执行区描述:load_region_description ::= load_region_name (base_address | ("+" offset)) [attributes] [max_size] "{" execution_region_description+ "}"执行域描述execution_region_description 被定义为执行区名称,是一种基址规范,可以选择性地在其后跟随属性、尺寸说明符以及一个或多个输入段描述:execution_region_description ::= exec_region_name (base_address | "+" offset) [attribute_list] [max_size | "–"length] "{" input_section_description* "}"输入段描述input_section_description被定义为源模块选择程序模式,可以在其后选择性地跟随输入节选择程序:input_section_description ::=module_select_pattern [ "(" ("+" input_section_attr | input_section_pattern) ([","] "+" input_section_attr | "," input_section_pattern))* ")" ]图13.10显示一个典型的分散载入描述文件的内容和组织结构。图13.10 典型的分散载入描述文件的内容和组织结构3.加载域描述一个加载域具有以下属性:· 名称:链接程序使用它识别不同的加载域;· 基址:载入视图中的代码和数据的起始地址;· 属性:可选;· 最大尺寸:可选;· 执行区列表:这些执行区标识执行视图中模块的类型和位置。图13.11显示了加载域的描述。BNF语法为:load_region_description ::=load_region_name (base_address | ("+" offset)) [attribute_list] [ max_size] "{" execution_region_description+ "}"语法说明如下。① load_region_name为加载域的名称。只有前31个字符有效。该名称仅用于识别每个域。注意load_region_name与执行域exec_region_name不同,load_region_name不用于生成Load$$region_name符号。② base_address是区中对象的链接地址。base_address必须是一个字对齐数值。③ +offset描述基址,它从前一个加载域的末尾偏移offset个字节。offset的值必须能被4整除。如果是第一个加载域,则+offset表示该域的基地址是从0之后的offset字节开始。④ attribute_list指定加载域内容的属性:· PI:位置独立;· RELOC:可重定位;· OVERLAY:重叠;· ABSOLUTE:绝对地址;· NOCOMPRESS:代码不被压缩。可以指定这些属性中的一项(除NOCOMPRESS外,其他4项属性为互斥关系)。默认的加载域属性是ABSOLUTE。具有PI、RELOC或OVERLAY属性之一的加载域可以有重叠的地址范围。对于ABSOLUTE加载域,armlink不允许重叠的地址范围。OVERLAY关键字允许在同一个地址有多个执行区。注意ARM在RVCT中不提供重叠机制。要在同一个地址使用多个执行区,必须提供自己的重叠管理程序。⑤ max_size:它指定加载域的最大尺寸。(如果指定了可选的max_size值,但分配给该区的字节超过max_size字节,armlink将生成错误。)⑥ execution_region_description:它指定执行区名称、地址和内容。4.执行域描述符执行域具有以下一些属性:·域名称;· 执行域基地址(支持绝对地址的或相对地址的);· 执行域的最大尺寸(可选);· 指定执行域属性;· 一个或多个输入段描述(放在本执行区中的模块)。图13.12显示了一个典型的执行域描述。执行域描述符中的BNF语法为:execution_region_description ::=exec_region_name (base_address | "+" offset) [attribute_list] [max_size | "–"length] "{" input_section_description+ "}"其语法说明如下。① exec_region_name 为执行域命名。(只有前31个字符有效。)② base_address是域中对象的链接地址。base_address必须是字对齐的。③ +offset是描述基址,它从前一个执行区的末尾偏移offset个字节。offset的值必须能被4整除。如果前面没有执行区(即,这是载入区中的第一个执行区),则+offset表示基址从它所在的载入区的基址之后offset个字节开始。如果使用+offset格式并且所在的加载域具有RELOC属性,则执行区继承该RELOC属性。但是,如果使用固定的base_address,则随后出现的offset不继承RELOC属性。④ attribute_list指定执行区内容的属性:· PI:位置独立。· OVERLAY:重叠。· ABSOLUTE:绝对地址。域的执行地址由base_designator指定。· FIXED:固定地址。执行域的加载地址和执行地址都由base_designator指定。base_designator必须是绝对基址,或者偏移量为+0。· EMPTY:它在执行区中保留一个已知长度的空白存储器块,通常用作堆或栈。· PADVALUE:指定填充字的默认值,如果在域定义中指定了该属性,则必须为该属性赋值。使用该属性的例子如下。EXEC 0x10000 PADVALUE 0xffffffff EMPTY ZEROPAD 0x2000通过该Scatter文件描述符,创建了一个长度为0x2000的域,该域中的所有内容用0xffffffff填充。注意所指定的域值必须以字为单位。· ZEROPAD 0:初始化一块内容全为0的内存区域,并将其作为一个输入段填充到ELF映像文件中。这样减少了在运行时将某段内存初始化为0的操作。注意只有根执行区可以使用ZEROPAD属性进行0初始化。对非根执行区使用ZEROPAD属性将出现警告信息,并且忽略该属性。· UNINIT:指示该段为不能被初始化为0。⑤ max_size为可选的参数,如果分配给域的存储器超过max_size字节,则它指示armlink生成错误。⑥ -length如果指定的长度为负值,则base_address是域的结束地址。它通常与EMPTY一起使用,以表示在存储器中变小的栈。当确定执行域属性时,注意以下几点。① PI、OVERPLAY、FIXED和ABSOLUTE为并列关系属性,某一个执行域只能为这4种属性之一。如果没有指定,ABSOLUTE为其默认属性。② 使用+offset格式的base_designator的执行区继承前一个执行区的属性(如果它是加载域中的第一个执行区,则继承所在加载域的属性,),或者具有ABSOLUTE属性。③ 不能为执行域显式指定RELOC属性。该属性只能从前面的执行域或父区继承才能具有RELOC属性。④ 被指定了PI或OVERLAP属性的执行域,不能有重叠的地址范围。但对于ABLOUTE和FIXED属性的执行域,ARM编译器不允许有重叠的地址范围。⑤ RW段默认使用压缩属性。如果不想链接器对该段进行压缩,必须在Scatter文件中使用NOCOMPRESS显示声明。⑥ UNINIT指定执行区中的ZI输出节(如果有)不被初始化为0。使用它可以创建包含未初始化数据或存储器映射I/O的执行区。5.输入段描述符输入段由以下部分组成。· 模块名称,如目标文件名称、库成员名称或库文件名称。模块名称可以使用通配符。· 输入段名称,或输入节属性,如READ-ONLY或CODE。图13.13显示了输入段描述符的基本组成。BNF语法为:input_section_description ::= module_select_pattern ["(" ("+" input_section_attr | input_section_pattern) ([","] "+" input_section_attr | "," input_section_pattern))* ")"]其语法说明如下。① module_select_pattern这是由文字文本构成的模式。“*”通配符匹配0个或多个字符,而“?”匹配任何单个字符。匹配不区分大小写。使用*.o可以匹配所有对象。使用*可以匹配所有目标文件和库。当满足下列条件之一时,链接器认为module_selector_pattern与输入段匹配。· 包含输入段的目标文件与module_selector_pattern匹配。· 包含输入段的库成员名称(不带路径名)与module_selector_pattern匹配。· 从其中提取段的库全名(包含路径名)。如果名称包含空格,使用通配符可以简化搜索。例如,使用*libname.lib匹配C:lib dirlibname.lib。另外,ARM链接器支持特殊的模块选择程序模式“.ANY”,允许将输入节分配给执行区,而无需考虑其父模块。使用.ANY以任意分配方式填充执行区。注意最好不要依赖编译程序生成的或ARM库代码使用的输入段名。因为,这些名称在每次编译之间可以变化,例如编译选项的改变或编译器版本发生变化,都可能引起输入段名称的变化。② input_section_attr输入段属性符定义了一个用逗号隔开的模式类别。该类表中的每个模式定义了输入段名称或输入段属性匹配方式。当匹配模式使用输入段名称时,它前面必须使用符号“+”,而符号“+”前面紧接的逗号可以省略。输入段属性不区分大小写。可以是下列属性之一:· RO-CODE;· RO-DATA;· RO,同时选择RO-CODE和RO-DATA;· RW-DATA;· RW-CODE;· RW,同时选择RW-CODE和RW-DATA;· ZI;· ENTRY,包含ENTRY点的节。可以识别以下同义词:· CODE代表RO-CODE;· CONST代表RO-DATA;· TEXT代表RO;· DATA代表RW;· BSS代表ZI。可以识别以下伪属性:· FIRST;· LAST。如果对输入段的排列顺序有特殊的要求,如特定的输入段必须是域中的第一个输入节,而包含校验和的输入段必须是最后一个输入段,可以使用FIRST和LAST标记执行区中的第一个和最后一个段。FIRST或LAST伪属性必须放在属性列表的最后。特殊的模块选择程序模式“.ANY”允许在不考虑其父模块的情况下,将输入段分配给执行域。使用一个或多个“.ANY”模式以任意分配方式填充执行域。在大多数情况下,使用单个“.ANY”相当于使用“*”模块选择属性。在分散载入描述文件中不能使用两个“*”选择属性。但是,可以使用两个变形的选择程序,例如,*A和*B,也可以将.ANY选择属性与模块选择属性一起使用。*模块选择属性的优先级比.ANY高。如果删除了文件中包含*选择属性的部分,.ANY选择属性才能在链接时起作用。在解析所有其他(非.ANY)输入段描述并且将输入段分配给最匹配的执行区之后,才解析使用.ANY模块选择程序模式的input_section_descriptions。如果有一个以上.ANY模式,则链接程序尽可能多地填充第一个.ANY,然后开始填充下一个.ANY。每个未被分配的剩余输入段将被分配给具有以下特性的执行区:· 最大的剩余空间(由max_size的值和已分配给该区的输入段的尺寸确定);· 匹配.ANY的input_section_description;· 与输入段的存储器属性相匹配的存储器访问属性(如果有);· input_section_pattern。13.4.3 Scatter文件典型用法1.创建启动域所谓启动域就是加载地址和执行地址相同的域。系统执行的初始入口点必须要在启动域中,否则链接器将报告以下错误。Entry point (0x00000000) lies within non-root region ER_ROM在Scatter文件中确定启动域可以使用下面两种方法。① 使用ABSOLUTE设置执行区属性,并且对第一个执行区及其所在的加载区使用相同的地址。为确保执行域地址和加载域地址相同,可以将加载域的起始地址和执行域的起始地址设为相同的值或者将第一个执行域的地址偏移量设为0。下面的例子,指定了一个启动域。BOOT 0x0000 ;加载域的起始地址在0x0{ EXER 0x0000 ;指定加载域和执行域的地址相同 { * (+RO) ;必须将启动域包含在内 } ;其他执行域}② 使用FIXED执行域属性,确保指定域的载入地址和执行地址相同。下面的例子显示了使用FIXED属性,将执行域的起始地址固定在ROM中。BOOT 0x0000 ;加载域的起始地址在0x0{ EXER 0x0000 ;指定加载域和执行域的地址相同 { * (+RO) ;必须将启动域包含在内 } EXER_INIT 0x8000 FIXED { init.o(+RO) }}③ 如果使用分散加载,负责创建执行域的代码和数据不能将其自身复制到另一位置,因此启动域必须包含以下内容。· _main.o和_scatter*.o:包含复制代码和数据的代码。· Region$$Table和ZISection$$Table段:包含要复制代码和数据的地址。· _dc*.o:执行代码压缩。可以使用armlinker产生的InRoot$$Sections符号放置启动代码。因为这些代码被定义为只读属性,所有如果Scatter文件中包含了“* (+RO)”,则表示启动域中包含了这些代码。或者显式的使用InRoot$$Sections符号在Scatter文件中对以上代码进行配置。下面的例子显示了如何在Scatter文件中使用InRoot$$Sections链接符号,放置启动域。LOADREG 0x8000 ;{ ROOT 0x8000 { * (InRoot$$Sections) ;放置启动域 } OTHER 0x100000 { * (RO,+RW,+ZI) } ;其他Scatter文件描述}2.为执行域确定固定地址可以在执行区分散加载描述中使用FIXED属性来创建根区,该根区在固定地址载入和执行。FIXED可以用于在单一加载域内(因此通常用于单个ROM设备)创建多个根区。例如,使用FIXED属性将函数或数据块(如常数表或校验和)放在ROM中的固定地址,这样就可以使用指针很方便的对其进行访问。下面的例子显示了如何放置单个目标内容。LOADREG1 0x0 0x10000{ EXECREG1 0x0 0x1000 ;启动域,包含初始化代码 { ;将初始化代码放在0x0地址 init.o (Init, +FIRST) * (+RO) ;随后排放余下的只读数据 } RAM 0x400000 0x2000 ;将可读可写数据放在0x400000地址 { * (+RW +ZI) } DATABLOCK 0x4FF00 FIXED 0xFF ;执行域放在 0x4FF00地址 { ;限制该域的最大长度为 0xFF data.o(+RO-DATA) ;将只读数据放在0x1FF00 和 0x1FFFF之间 }}通过上面的Scatter文件,可以将初始化代码放在0x0处,其后是其他RO代码和除了data.o对象中的RO数据之外的所有RO数据;所有全局的RW变量放在RAM中0x400000处;最好将data.o的RO-DATA只读数据表放在地址0x4FF00处,并指定其最大长度为0xFF。上例将代码或数据对象放在其各自的源文件中,然后放置目标文件域,这些操作方式是ARM公司建议的标准编码方式。为方便起见,可以使用编译指示#pragma和分散载入描述文件放置已命名的域。下面的例子创建模块dump.c并显式命名域。// file dump.c int a = 10; // 放入数据域 short b[100]; // 放入bss段 int const c[3] = {1,2,3}; // 放入.constdata段 int func1(int a) {return a*1;} // 放入.text段 #pragma arm section rwdata = "foo", code ="foo" int x = 5; // 在foo的数据域 char *s = "abc"; // s3在code段, "abc" 在 .constdata int func2(int x) {return x+1;} // 放入foo的.text段 #pragma arm section code, rwdata // 返回使用下面的Scatter文件指定上面的代码在内存中的放置位置。如果代码和数据段的名称相同,则首先放置代码段。FLASH 0x10000000 0x2000000{ FLASH 0x10000000 0x2000000 { init.o (Init, +First) ; 放置初始化代码 * (+RO) ; } RAM 0x0000 { vectors.o (Vect, +First) ; 放置向量表 * (+RW,+ZI) ; } DUMP 0x08000000 { dump.o (foo) ; }}通过上面的Scatter文件,将init中的初始化段放在0x10000000地址,并将除foo外的只读数据func1和c[]放在该初始段的后面;接下来的执行域RAM放置向量表;最后的DUMP域放置由#pragma指定的段dump。3.在代码映像中保留空白域可以在Scatter中使用 EMPTY 属性为栈保留一个空白存储器块。该存储块不构成载入区的一部分,但指定在执行时使用。由于它创建为虚 ZI区,所以 armlink 使用以下符号访问它:· Image$$region_name$$ZI$$Base;· Image$$region_name$$ZI$$Limit;· Image$$region_name$$ZI$$Length。如果指定的长度为负值,则Image$$region_name$$ZI$$Limit被视为域的结束地址。它是绝对地址,不是相对地址。下面例子显示了如何在Scatter文件中预留一个空白区域。LOADREGION 0x700000 ; 加载域的起始地址在0x700000{ ; STACK 0x7000000 EMPTY –0x10000 ; 该域的结束地址为0x700000,因为其长度为负 ;region ; { ; 预留空白区放置栈 } HEAP +0 EMPTY 0x10000 ; 栈的起始地址在上个预留区域介绍地址 ; ; { ; 预留空白区域放置堆 } ; rest of scatter description...}在上面的例子中定义了一个执行域STACK 0x7000000 EMPTY -0x10000,它从地址 (0x7000000-0x1000)开始,在地址0x7000000结束。在此示例中,链接程序生成符号:Image$$STACK$$ZI$$Base = 0x6ff0000Image$$STACK$$ZI$$Limit = 0x7000000Image$$STACK$$ZI$$Length = 0x1000Image$$HEAP$$ZI$$Base = 0x7000000Image$$HEAP$$ZI$$Limit = 0x7010000Image$$HEAP$$ZI$$Length = 0x1000EMPTY属性仅适用于执行区。如果在载入区定义中使用EMPTY属性,则链接程序生成警告信息并忽略该属性。链接程序检查用于EMPTY区的地址空间不与任何其他执行区重叠。4.使用OVERLAY关键字在ARM以前的编译器中,没有提供地址空间的重叠管理。如果有运行时域地址空间重叠,需要用户自己提供地址空间重叠的管理机制。但在RVDS的编译器中,提供了运行时域属性关键字OVERLAY,用户可以使用该关键字生成自己的重叠空间。下面例子显示了如何使用OVERLAY关键字,生成运行时域的重叠空间。LOADREG 0x8000{ ; STATIC_RAM 0x0 ; 静态RAM区,包含大部分的RW和ZI { * (+RW,+ZI) } OVERLAY_A_RAM 0x1000 OVERLAY ; 重叠区... { module1.o (+RW,+ZI) } OVERLAY_B_RAM 0x1000 OVERLAY { module2.o (+RW,+ZI) } ;}5.在Scatter文件中使用预处理伪操作可用在Scatter文件的第一行加上需要编译器进行预处理的操作。语法格式如下所示。#! <preprocessor> [pre_processor_flags]LOAD_FLASH ( 0x8000 + ( 0x2 * 0x400 )) ;例如:#! armcc -E联接器可以对预处理的表达式进行简单的计算,可以识别简单的运算符如+、-、×、/、AND和OR,如:#define AN_ADDRESS (BASE_ADDRESS+(ALIAS_NUMBER*ALIAS_SIZE))同时,也可以在Scatter文件头加一些预处理的伪操作,如:#define ADDRESS 0x20000000#include "include_file_1.h"#define BASE_ADDRESS 0x8000#define ALIAS_NUMBER 0x2#define ALIAS_SIZE 0x400在Scatter文件中,使用预处理的更详细的信息,请参见ARM相关文件。13.4.4 等效的简单映像分散载入描述前面介绍了分散加载的命令行选项,如-ro-base、-rw-base、-reloc、-split、-ropi和-rwpi。但在实际编程时,因为使用Scatter文件可以产生更清晰的内存映像视图,所以最好使用Scatter文件对映像进行加载。本节详细介绍如何将各分散加载的命令行选项,替换为Scatter文件。1.-ro-base address选项的替换使用-ro-base address命令行链接产生的内存映像由一个加载域和三个执行域组成。执行域放在存储器映像中的相邻位置。选项中的address指定了加载域和第一个执行域的起始地址(加载域和第一个执行域的起始地址相同)。下面的例子显示了与“-ro-base 0x8000”命令行选项等价的Scatter文件。LOADREG 0x8000 ;定义加载域的起始地址0x8000{ ; ROM +0 ;定义第一个执行域的起始地址,该地址与加载域的起始地址相同,为0x8000 ; { *(+RO) ;该域放置所有的RO段 } RAM_RW +0 ;定义第二个执行域,起始地址为0x8000+ROM段大小 ; { *(+RW) ;将所有的RW代码放置在该段 } RAM_ZI +0 ;定义ZI段 ;ZI段的起始地址为0x8000+ROM段的大小+RAM_RW段的大小 ; { *(+ZI) ;放置所有的ZI段 }}上例中的Scatter文件创建的映像由一个加载域和三个执行域组成。加载域的起始地址为0x8000。三个执行域分别为ROM、RAM_RW和RAM_ZI,它们分别包含RO、RW和ZI输出段。RO和RAM_RW为启动域,RAM_ZI在执行时动态创建。ROM的执行地址是0x8000,通过对执行区描述使用+offset格式的基址指定程序,所有三个执行域在存储器映射中相邻放置,即前一个执行域的末尾放置后一个执行域。如果链接程序时,将-ro-base选项和-ropi混合使用,则可以生成位置无关代码。下面的例子显示了与-ro-base 0x8000 -ropi等效的Scatter文件。LOADREG 0x8000 PI ;加载域的地址为0x8000,并指定该加载域的属性为PI{ ROM +0 ;第一执行域的地址为0x8000,而且该执行域继承了加载域的PI属性 ;所有该域的执行地址是可变的 { *(+RO) ;放置所有的RO段 } RAM_RW +0 ABSOLUTE ;使用ABSOLUTE属性代替PI属性 { *(+RW) ;放置RW段 } RAM_ZI +0 { *(+ZI) }}执行域ROM从LOADREG加载域继承 PI 属性。下一个执行域 RAM_RW 被标记为 ABSOLUTE 所以其不再具有PI属性。另外,因为RAM_ZI 域使用了+0的偏移量,所以它从 RAM_RW域继承 ABSOLUTE 属性。2.-ro-base和-rw-base选项的替换使用-ro-base和-rw-base选项链接的映像也由一个加载域和三个执行域组成,它与类型1生成的映像十分相似,只是此类映像的RW执行区与RO执行区不相邻。在-ro-base选项中指定加载域的起始地址,在-rw-base选项中指定执行域的地址。下面的例子显示与使用-ro-base 0x8000 -rw-base 0x040000等效的分散载入描述。LOADREG 0x8000 ;定义加载域的起始地址为0x8000{ ROM_RO +0 ;定义第一个执行域的起始地址为0x8000 { * (+RO) ;在该域中放置所有的RO段 } RAM_RW 0x040000 ;第二个执行域名为RAM_RW,起始地址为0x40000 { * (+RW) ;放置所有的RW段 } RAM_ZI +0 { * (+ZI) ;放置所有的ZI段 }}该Scatter文件创建的映像有一个名为LOADREG的加载域,载入地址是0x8000。该映像有3个执行区,分别为ROM、RAM_RW和RAM_ZI,它们分别包含RO、RW和ZI输出段。其中,RO域是启动域,执行地址是0x8000,RAM_RW执行域与第一个执行域RAM_RW不相邻。其执行地址是0x040000。紧随其后的执行区RAM_ZI放置所有的ZI数据。另外,也可以将-rw-base和位置无关选项-rwpi配合使用,将RW输出节的执行区标记为位置独立。下面的例子显示了使用-ro-base 0x8000 -rw-base 0x40000 -rwpi等效的Scatter文件。LOADREG 0x0x8000 ;定义加载域的起始地址为0x8000{ ROM +0 ;定义第一执行域,其起始地址为0x8000 { *(+RO) ;放置所有RO段 } RAM_RW 0x40000 PI ;设置第二执行域的属性为PI属性 { *(+RW) } ER_ZI +0 ;继承了PI属性 { *(+ZI) }}第一个执行域ROM从加载域LOADREG继承ABSOLUTE属性。第二个执行区RAM_RW标记为PI属性。另外,因为ER_ZI区的偏移为+0,所以它从RAM_RW区继承PI属性。3.-reloc -split选项的替换使用-split选项生成的映像由两个加载域和三个执行域组成。使用以下的链接选项重新分割并定位加载域。· -reloc组合使用-reloc -split生成具有两个加载域的映像,并且使加载域具有RELOC属性。· -ro-base address1指定包含RO输出段的域的载入地址和执行地址。· -ro-base address2指定包含RW输出段的域的载入地址和执行地址。· -split将默认的单一加载域(包含RO和RW输出段的加载域)分成两个加载域。一个载入域包含RO输出段,另一个包含RW输出段。下面的例子显示了与使用-ro-base 0x8000 -rw-base 0x040000 -split等效的Scatter文件。LOADREG1 0x8000 ;指定第一个加载域的起始地址为0x8000{ ROM +0 { *(+RO) }}LOADREG2 0x040000 ;第二个加载域的起始地址为0x40000{ RAM_RW +0 { *(+RW) ;放置所有的RW段 } RAM_ZI +0 { *(+ZI) }}使用上例中的Scatter文件创建的内存映像有两个加载域,分别为LOADREG1和LOADREG2,它们的起始地址分别为0x8000和0x040000。该映像文件有三个执行域,分别为ROM、RAM_RW和RAM_ZI,它们分别包含RO、RW和ZI输出段。ROM的执行地址是0x8000。RAM_RW执行域与ROM不相邻。其执行地址是0x040000。执行域RAM_ZI紧随RAM_RW域放置。可以使用-reloc选项和-split选项配合使用,指定两个加载域具有RELOC属性。下面的例子显示与使用-ro-base 0x8000 -rw-base 0x040000 -reloc -split等效的Scatter文件。LOADREG 0x010000 RELOC{ ROM + 0 { * (+RO) }}LOADREG 0x040000 RELOC{ RAM_RW + 0 { * (+RW) } RAM_ZI +0 { * (+ZI) }}

    时间:2018-06-13 关键词: 基础教程 映像文件 存储器映射 分散加载 嵌入式软件

  • 嵌入式软件开发之:编译器的缺省行为

    嵌入式软件开发之:编译器的缺省行为

    13.2 编译器的缺省行为多数嵌入式应用程序最初都是在原型环境下开发的。无论什么样的原型仿真环境与最终产品环境都是有差异的。因此,考虑如何将嵌入式应用程序从其所依赖的开发工具或调试环境中移植到在目标硬件上独立运行是非常重要的。开始编写嵌入式应用程序时,开发者可能并不清楚目标硬件的具体规格。如,目标系统使用了什么样的外围设备、存储器映射情况甚至不能确定处理器的型号。为在了解这些详细信息前能够继续软件的开发,RVCT工具提供了很多默认的操作,使用户能编译和调试与目标系统无关的应用程序代码。下面详细介绍这些编译选项,只有深入了解这些编译选项设置,才能使开发更顺利的进行。13.2.1 Semihosting1.Semihosting简介在RVCT C库中,对某些ISO C功能的支持由主机调试环境提供。提供该功能的机制被称为Semihostin[1]。大多数的ARM调试系统都支持Semihosting机制,如ReslView Debugger AXD等。调试系统提供这种机制是非常有用的,因为用于开发使用的硬件系统经常没有最终系统的所有输入和输出设备。在这种情况下,Semihosting可让主机代替目标系统提供这些设备的功能。举例来说,此机制可以用于启用C库中的函数(例如,printf()和scanf())使用主机的屏幕和键盘,而不使用目标系统的屏幕和键盘。半主机由一组已定义的SWI操作来实现。应用程序调用相应的SWI,然后由调试代理程序(Debug Agent)处理SWI异常。调试代理程序完成系统与主机之间的通信。图13.1显示了Semihosting机制的处理过程。图13.1 Semihosting机制的处理过程在很多情况下,Semihosting SWI由库函数内的代码调用。应用程序也可以直接调用。支持ARM C库中Semihosting的详细信息,请参阅ARM相关文档。2.Semihosting软件接口ARM和Thumb SWI指令包含一个软中断号,该中断号可以被应用程序使用。此编号可以由系统中的SWI处理程序进行解码。有关SWI处理程序的详细信息,请参阅本书中ARM异常处理一节。Semihosting使用固定的中断号调用相应的处理程序。用于Semihosting的SWI是:· 0x123456(在ARM状态下);· 0xAB(在Thumb状态下)。注意用户在编写自己的中断处理程序时,避免使用Semihosting已经使用的中断向量号。调试代理通过SWI的中断向量号识别该软中断是目标系统提出的Semihosting请求。具体是何种Semihosting请求(键盘输入请求或屏幕显示请求),通过向寄存器r0传递不同的参数进行区分。所有其他参数通过一个数据块进行传递。该数据块的地址通过寄存器r1传递给中断处理程序。软中断的处理结果放在r0中返回,也可以通过显式的返回值或传递数据块的指针带回程序的处理结果。即使未返回结果,也假定r0是被使用的。用r0传递的可用Semihosting操作编号分配如下:· 0x00-0x31 这些编号由ARM公司使用;· 0x32-0xFF 这些编号由ARM公司保留,以备将来使用;· 0x100-0x1FF 这些编号保留给用户应用程序。注意虽然这些编号ARM公司不使用,用户可以使用这些编号编写自己的SWI操作,但建议使用其他 SWI 编号,而不要使用Semihosting SWI 编号和这些Semihosting的预留操作类型编号。· 0x200-0xFFFFFFFF这些编号未定义。当前未使用并且不推荐使用这些编号。在以下部分中,操作名称之后的括号中的编号是调用Semihosting操作时放入r0的值。例如,SYS_OPEN(0x01)。如果从汇编语言代码中调用SWI,最好使用semihost.h中定义的操作名称。可以用 EQU 伪操作定义操作名称。例如:SYS_OPEN EQU 0x01SYS_CLOSE EQU 0x023.Semihosting需求函数Semihosting需要的函数列表如表13.1所示。如果使用默认的Semihosting功能,用户不需要编写任何其他代码。也可以重新实现部分的输入/输出函数,使这些函数和标准Semihosting混合使用。表13.1 Semihosting函数列表函 数 名 称描 述SYS_OPEN (0x01)打开文件SYS_CLOSE(0x02)关闭使用SYS_OPEN打开的文件SYS_WRITEC (0x03)向控制台输出字符SYS_WRITE0 (0x04)将空终止的字符串写入控制台SYS_WRITE (0x05)写入主机上的文件续表函 数 名 称描 述SYS_READ (0x06)将文件内容读取到缓存器SYS_READC (0x07)从控制台读取字节SYS_ISERROR (0x08)确定返回代码是否错误SYS_ISTTY (0x09)检查文件是否连接到交互设备SYS_SEEK (0x0A)搜索到文件中的某个位置SYS_FLEN (0x0C)返回文件的长度SYS_TMPNAM (0x0D)返回文件的临时名称SYS_REMOVE (0x0E)删除主机上的文件SYS_RENAME (0x0F)重命名主机上的文件SYS_CLOCK (0x10)执行开始后的厘秒数SYS_TIME (0x11)1970 年 1 月 1 日到现在的秒数SYS_SYSTEM (0x12)将命令传递给主机命令行解释程序SYS_ERRNO (0x13)获得 C 库 errno 变量的值SYS_GET_CMDLINE (0x15)获得用于调用可执行程序的命令行SYS_HEAPINFO (0x16)获得系统堆参数SYS_ELAPSED (0x30)获得自执行开始的目标滴答声数目SYS_TICKFREQ (0x31)确定滴答声的频率13.2.2 C 库结构从概念上来讲,C库函数可被化分成两类,一类为ISO C语言的规范部分,该部分的主要功能是向用户提供一个调用接口;另一类为ISO C语言规范提供支持。图13.2显示了这两类函数在C库中的结构。图13.2 C库的函数结构对部分ISO C功能的支持是由主机调试环境在支持函数的设备驱动程序级别提供的。例如,RVCT C库通过写入调试器控制台窗口来实现ISO C printf()系列函数。通过调用__sys_write()来提供该功能。这是一个执行半主机SWI的支持函数,使字符串被写入到控制台。13.2.3 默认存储器映射对于没有描述存储器映射的映像(Image),RVCT根据默认存储器映射放置代码和数据。默认的存储器映射如图13.3所示。图13.3 默认存储器映射结合图13.3,可以看出默认的存储器映射使用以下规则:· 链接映像,在地址0x8000加载并运行。首先放置所有的RO(只读)段,其次是RW(读写)段,然后是ZI(零初始化)段。· 堆(Heap)直接从ZI段的顶端地址算起,因此,其准确位置在链接时决定。· 栈(Stack)的起始地址在应用程序启动过程时由Semihosting操作提供。具体Semihosting操作设置的值由调试系统的不同而不同。① RealView ARMulator ISS(RVISS)设置为配置文件peripherals.ami中设定的值。默认值是0x08000000。② Multi-ICE将该地址设置为调试器内部变量top_of_memory的值。默认值是0x00080000。13.2.4 链接程序放置规则链接程序遵守一组规则,以决定代码和数据位于存储器中的什么位置,如图13.4所示。链接程序放置遵循以下规则:① 映像首先按属性组织:RO段在最低的存储器地址,其次是RW段,然后是ZI段。每一种属性中,代码在数据之前。② 链接程序按名称的字母顺序放置输入段(Section)。输入段名称即汇编程序AREA伪操作定义的名称。图13.4 链接程序放置规则③ 在输入段中,独立对象的代码和数据,按照对象文件在链接程序命令行中被指定的顺序放置。要精确放置代码和数据,ARM公司建议不要过分依靠这些规则。相反,必须使用分散加载机制来完全控制代码和数据的放置。请参阅下一章的调整映像存储器映射以适应目标系统硬件存储器的实际要求。13.2.5 应用程序启动多数嵌入式系统中,执行主任务前,执行初始化序列来设置系统。默认的RVCT初始化序列如图13.5所示。图13.5 默认RVCT初始化序列在进入用户代码(main())前,初始化序列可分成三个功能块:__main直接跳转到__scatterload;__scatterload负责建立运行时的映像存储器映射,而__rt_entry(运行时的入口)则负责初始化C库。__scatterload执行代码和数据复制以及ZI数据的清零。对于ZI数据的清零和未改变的RW数据来说,这一步总是要做的。__scatterload跳转到__rt_entry。它设置应用程序的栈和堆,初始化库函数及其静态数据,并调用任何全局声明的对象的构造函数(仅C++)。然后__rt_entry跳转到应用程序入口main()。主应用程序结束执行时,__rt_entry将库关闭,然后把控制权交还给调试器。RVCT中,函数main()有一个特殊含意。main()函数的存在强制链接程序链接到__main和__rt_entry中的初始化代码。没有main()函数,就不会链接到初始化进程,那么一些标准C库功能就不会得到支持。[1] 在一些ARM的中文参考文献中,将Semihosting译为半主机。

    时间:2018-06-13 关键词: ARM 基础教程 编译器 semihosting 缺省行为 嵌入式软件

  • 嵌入式软件开发之: 基于ARM处理器的嵌入式系统设计

    嵌入式软件开发之: 基于ARM处理器的嵌入式系统设计

    本章主要介绍嵌入式应用程序的设计方法。本章中的一些实例程序是以ARM公司的Realview2.2为开发平台。由于目前嵌入式应用环境相差非常大,这里主要是通过这些实例程序来更直接地介绍嵌入式应用系统的开发方法,具体的代码因具体的嵌入式环境不同而有所差异。13.1 基于ARM处理器的嵌入式系统设计ARM系列处理器是RISC(Reducded Instruction Set Computing)处理器。很多基于ARM的高效代码的程序设计策略都源于RISC处理器。和很多RISC处理器一样,ARM系列处理器的内存访问也要求数据对齐,即存取“字(Word)”数据时要求四字节对齐,地址的bits[1:0]=0b00;存取“半字(Halfwords)”时要求两字节对齐,地址的bit[0]=0b0;存取“字节(Byte)”数据时要求该数据按其自然尺寸边界(Natural Size Boundary)定位。ARM编译程序通常将全局变量对齐到自然尺寸边界上,以便通过使用 LDR和STR指令有效地存取这些变量。这种内存访问方式与多数CISC(Complex Instruction Set Computing)体系结构不同,在CISC体系结构下,指令直接存取未对齐的数据。因而,当需要将代码从CISC体系结构向 ARM处理器移植时,内存访问的地址对齐问题必须予以注意。在RISC体系结构下,存取未对齐数据无论在代码尺寸或是程序执行效率上,都将付出非常大的代价。注意在ARM11处理器上,新增加了支持非内存对齐数据访问的硬件,此结构在本章中不作讨论。下面将从4个方面详细讨论在ARM体系结构下的程序设计:· 未对齐指针;· 结构体中的未对齐字段;· 用于半字存取的Load指令;· 移植代码并检测非对齐存取。13.1.1 未对齐的数据指针C和C++编程标准规定,指向某一数据类型的指针,必须和该类型的数据地址对齐方式一致,所以ARM编译器期望程序中的C指针指向存储器中字对齐地址,因为这可使编译器生成更高效的代码。比如,如果定义一个指向int数据类型的指针,用该指针读取一个字,ARM 编译器将使用LDR指令来完成此操作。如果读取的地址为4的倍数(即在一个字的边界)即能正确读取。但是,如果该地址不是4的倍数,那么,一条LDR指令返回一个循环移位结果,而不是执行真正的未对齐字载入。循环移位结果取决于该地址相对于字的边界的偏移量和系统所使用的端序(Endianness)。例如,如果代码要求从指针指向的地址0x8006载入数据,即要载入0x8006、0x8007、0x8008和0x8009 4个字节的内容。但是,在ARM处理器上,这个存取操作载入了0x8004、0x8005、0x8006和0x8007字节的内容。这就是在未对齐的地址上使用指针存取所得到的循环移位结果。因而,如果想将指针定义到一个指定地址(该地址为非自然边界对齐),那么在定义该指针时,必须使用__packed限定符来定义指针:例如:__packed int *pi; // 指针指向一个非字对其内存地址使用了__packed限定符限定之后,ARM编译器将产生字节存取命令(LDRB或STRB指令)来存取内存,这样就不必考虑指针对齐问题。所生成的代码是字节存取的一个序列,或者取决于编译选项、跟变量对齐相关的移位和屏蔽。但这会导致系统性能和代码密度的损失。值得注意的是,不能使用__packed限定的指针来存取存储器映射的外围寄存器,因为ARM编译程序可使用多个存储器存取来获取数据。因而,可以对实际存取地址附近的位置进行存取,而这些附近的位置可能对应于其他外部寄存器。当使用了位字段(Bitfield)时,ARM程序将访问整个结构体,而非指定字段。13.1.2 结构体中未对齐字段与全局变量位于其自然尺寸边界相同,结构体(Structure)中的域字段(Filed)也如此。也就是说编译程序经常要在字段间插入填充字节(Padding)来确保域字段对齐。当编译程序插入填充字节时,编译器将产生以下警告信息。#1301-D: padding inserted in struct mystruct可以使用-remark编译选项使编译器产生备份信息,或使用-diag_warning选项选择编译器产生的备份信息。如果不希望编译器产生填充字节,可以使用__packed限定符来创建字段之间没有填充字节的结构,且这些结构需要非对齐存取。如果ARM编译器能够确定所访问结构体的对齐方式,那么它就可以自动识别所存取结构体中的字段的对齐方式。在这些情况下,编译程序尽可能地采用更有效的对齐字或半字存取方式。否则,编译器将使用多个对齐存储器存取(LDR、STR、LDM和STM)与固定移位和屏蔽相结合来存取存储器中的字节。对非对齐元素的存取是通过内联还是通过调用一个函数来完成,由编译程序-Ospace(默认,调用一个函数)和-Otime(执行非对齐存取内联)选项来控制。例如:创建一个名为foo.c源文件。__packed struct mystruct {int aligned_i;short aligned_s;int unaligned_i;};struct mystruct S1;int foo (int a, short b){S1.aligned_i=a;S1.aligned_s=b;return S1.unaligned_i;}使用armcc -c -Otime foo.c编译。所生成的代码为:MOV r2,r0LDR r0,|L1.84|MOV r12,r2,LSR #8STRB r2,[r0,#0]STRB r12,[r0,#1]MOV r12,r2,LSR #16STRB r12,[r0,#2]MOV r12,r2,LSR #24STRB r12,[r0,#3]MOV r12,r1,LSR #8STRB r1,[r0,#4]STRB r12,[r0,#5]ADD r0,r0,#6BIC r3,r0,#3AND r0,r0,#3LDMIA r3,{r3,r12}MOV r0,r0,LSL #3MOV r3,r3,LSR r0RSB r0,r0,#0x20ORR r0,r3,r12,LSL r0BX lr其中,“|L1.84|”为结构体mystruct在内存中的地址。从上例可以看出,所有对结构体域成员的访问都是通过字节访问实现的,所以这种不对齐内存访问无论从代码占用的存储器空间,还是代码的执行时间上都要付出一定的代价。然而,开发者可以给编译器提供更多的信息,使其知道结构体内哪个字段是对齐的,哪个字段不是。为此,必须将未对齐字段声明为__packed,并从struct本身除去__packed属性。通过这种方法可以保证对struct中自然对齐成员的快速访问。而且,哪个字段是未对齐的也更清楚,但这样就增加了访问struct结构的难度,当用户从结构中增加或删除字段时需要特别小心。修改上例中结构体的定义,来减少访问结构体的开销。具体代码如下所示。struct mystruct {int aligned_i;short aligned_s;__packed int unaligned_i;};struct mystruct S1;对修改后的程序进行编译,产生的汇编代码如下所示。MOV r2,r0LDR r0,|L1.32|STR r2,[r0,#0]STRH r1,[r0,#4]LDMIB r0,{r3,r12}MOV r0,r3,LSR #16ORR r0,r0,r12,LSL #16BX lr从编译后的汇编代码不难看出,对结构体内符号自然边界对齐的域,编译器直接使用相应的Load/Store指令进行访问,而只有那些非自然边界对齐的域,编译器才进行附加处理。这样,从时间和空间两方面减小了程序的开销。同一原理也适应于联合体结构(unions)。使用在存储器中未对齐的联合组件的__packed属性。13.1.3 用于半字存取的非对齐 LDR指令一些特殊情况下,ARM编译程序可以生成非对齐LDR指令。特别是编译程序从存储器中载入半字时将使用该方法。这是因为,通过使用相应地址,所需的半字可以载入到寄存器的高半段(bits[31:16]),然后通过移位,将有效数据移到寄存器的低半段(bits[15:0])。这样做的目的是通过减少内存访问次数来减少程序的执行时间。通过上面的方法,程序只需要一次存储器的访问,而使用LDRB指令做同样的操作需要两次存储器的存取,而且还要为将这两个字节合并在一起添加特殊的代码。在ARM体系结构v3和其早期版本中,通常使用该方法进行所有的半字载入。但在ARMv4及其以后版本中,出现了专门的半字载入指令,这种方法逐渐被取代。但是,非对齐LDR指令仍可能会出现,比如在一个充填结构中存取一个非对齐short域类型。注意在RVCT中已经不再支持ARMv3架构。13.1.4 移植代码并检测非对齐内存访问在非RISC体系结构的处理器上执行的代码中,可能会存在使用指针访问非自然边界对齐的数据类型。这种操作,在ARM体系结构中是不允许的。这就给代码的移植带来很大困难。用户必须识别并更改此类内存访问代码才能使其在RISC体系结构的处理器上正确执行。识别非对齐存取可能会很困难,因为使用非对齐地址进行的载入或存储操作会产生不正确的动作。追踪到底是哪部分的C源程序造成了这个问题是很困难的。具有完整存储器管理单元(MMUs)的ARM处理器,例如ARM920TTM,支持内存对齐检测功能,用户可以通过设置MMU使处理器检测每一次的内存访问以确保其被正确地对齐。如果出现非对齐内存访问,MMU将产生数据中断。这样就给追踪出错代码带来了很大的方便。对于一些简单的没有MMU的内核,如ARM7TDMI,最好的方法是在ASIC(Application Specific Integrated Circuit)/ASSP(Application Specific Standard Product)内部实现对齐检测。可以增加专门的ARM内核扩展硬件,由其监控每次数据的访问的内存大小和存取地址总线的最低有效位。在非对齐存取的情况下,可以通过配置ASIC/ASSP产生中断信号(ABORT)。ARM公司建议在需要运行移植代码设备中包含这样的ASIC/ASSP逻辑。如果在设计系统时,将系统设计成为当出现非对齐的内存访问时产生异常,则必须安装数据中断异常处理程序(Data Abort Handler)。出现非对齐存取时,程序进入数据中断处理程序,并由此识别位于返回地址(在LR中保存的地址)减8(r14-8)的出错数据存取指令。一旦出现数据中断异常,必须通过改变C源程序来修复非对齐的数据访问。使用下列指令可有条件地完成修复:#ifdef __arm #define PACKED __packed#else #define PACKED#endif: PACKED int *pi;:由于代码大小和性能上的开销,最好尽可能少采用存取非对齐数据。ARM编译器支持--pointer_alignment和--min_array_alignment与内存对齐相关的编译选项,详见ARM相关文档。

    时间:2018-06-13 关键词: 嵌入式系统 数据指针 基础教程 arm处理器 未对齐字段 嵌入式软件

首页  上一页  1 2 3 下一页 尾页
发布文章

技术子站

更多

项目外包