购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.2 软件系统开发

软件与硬件的完美结合,带给了人们对产品的美好体验。硬件是软件的底层基础,是软件能够运行指令的平台,软件的指令相对于硬件自身而言是相应的组合逻辑和时序逻辑。软件实现了具体的功能,不同的行业软件有对应的不同功能,是用户需求的体现。硬件是固定的基础,而软件则灵活多变,能够对复杂的逻辑进行有效的逻辑处理。硬件系统是软件能够运行的前提,软件赋予硬件生命,使硬件丰富多彩,软件与硬件彼此在自己的领域完成自己的使命,彼此成就对方,呈现出系统的智能,达到了完美的结合。

确定硬件开发平台后,就可以着手软件的开发了。目前广泛应用的操作系统有Windows平台(XP、Win7、Win8和WP7等)、Linux平台(Fedora、Ubuntu、CentOS、Debian、Redhat和OpenSUSE等)、Android、iOS、Mac OS、Unix、VxWorks、uC/OS II、MQX、eCos。广泛应用的编程语言有汇编语言、Basic、Pascal、C语言、C++语言、C#、JAVA、Forth、Delphi、Lisp、Python、Lua、SQL和PHP等。在产品的开发过程中,需要根据客户产品的需要、产品所属领域来确定产品软件开发的操作系统平台和相应的编程语言。从目前智能手机的格局看,iOS、Android、WP三分天下;Android平台几乎占据了Smart TV的江山;Windows平台占据了桌面操作系统的霸主地位;因Linux的开源和免费特性,其在嵌入式产品领域得到了相当广泛的应用。

软件系统的开发根据开发的层面和开发环境的需求,可以大致分为无操作系统的软件开发和有操作系统的软件开发。

2.2.1 无操作系统的软件开发

无操作系统的软件开发一般是单片机层面的软件系统开发。单片机是具备一些特殊功能的集成芯片,它的功能实现需要将要完成的逻辑功能用单片机能够看懂的语言描述给它。描述的过程就是编程控制芯片各个引脚在恰当的时间输出相应的电平值(输出高电平或低电平),进而控制与单片机相连的外围电路的电气状态。对于单片机的开发,可以选择汇编语言和C语言。随着芯片制造工艺的不断提升,芯片的性能正逐步增强,从编程的便利性、代码的可移植性和代码的可读性等综合考虑,目前用C语言进行单片机软件系统的开发应用越来越广泛。

常用的单片机按照公司的系列分类主要有C8051、凌阳系列、STC、AVR、PIC、MSP430、TI CC25**系列Soc无线单片机、Freescale系列及ARM(无操作系统时);按照位数分为8位、16位和32位;MSP430在低功耗要求的产品中得到了广泛应用;Freescale在稳定性有严格要求的应用中得到了广泛应用,例如,在遵循国家电网公司企业标准《电力用户用电信息采集系统型式规范第二部分:集中器型式规范》Q/GDW 375.2—2012和《电力用户用电信息采集系统技术规范第二部分:集中抄表终端技术规范》Q/GDW 374.2—2012的电力系统集中器的设计方案中,Freescale系列单片机得到了广泛应用。每类单片机都有其对应的开发环境,其中Keil、IAR Embedded Workbench开发环境的应用最为广泛,Keil的开发环境界面如图2-1所示,IAR的开发环境界面如图2-2所示。

图2-1 Keil的开发环境界面

图2-2 IAR的开发环境界面

根据需求分析确定硬件系统设计所采用的主设计方案,根据需求选定单片机开发方案后,需要根据产品所属领域、硬件系统的功能、性能和用户接口等进行单片机电路的总体设计和详细设计。单片机的工作流程是根据所要实现的功能编写一系列有序的组合逻辑,就如同我们要给别人传递信息,我们所说的、所写的都要是别人能够明白的语言或文字,别人才可以明白其意思一样,对单片机来说,单片机有单片机界的语言,单片机能够识别并按照其工作的语言是机器语言,对于我们而言机器语言晦涩难懂。为了将我们的思路、我们想要单片机工作的流程传递给单片机,需要进行编辑、翻译,这个工作就落在编译器身上了,像Keil、IAR这类的开发环境所承担的工作任务都必须包含语言编辑的功能、语言语法的差错功能、翻译功能(即编译)、逻辑综合能力(需要将多部分的逻辑指令综合起来考虑)。单片机的编程就是通过定义其内部资源来操作外围电路,使各个模块进行协调有序的工作。程序不是从上到下以固定顺序编写的,而是依据我们的思路,需要什么函数就定义什么函数,需要什么变量就定义什么变量,思路清晰,布局合理。编写程序就是一个不断丰富程序功能,不断修改程序各个模块,最终达到对内外部资源的合理调度完成任务的过程。编写程序时,可采用模块化编程,即把要完成的事情分成几个模块,把这几个模块分别写成子函数,需要的时候在不同的子函数和主函数中调用就可以了;通过合理的调用分配,使程序最终形成一个环,不断地循环来执行定义的指令。

单片机软件系统的开发与硬件密切相关,单片机的程序的任务是在完成组合逻辑的过程中,控制与自己相连接的外围电路的工作,根据输入信号判断逻辑工作状态,做出不同的逻辑响应并输出相对应的逻辑输出。从术语上来讲,单片机程序开发执行的四个步骤是编辑、编译、链接和执行。编辑的过程就是用我们能够懂的语言,如C语言,编写逻辑指令,我们编写的逻辑指令称为源代码。在单片机的软件开发过程中,对于一个复杂的、大的软件系统,一般开始时无从下手,我们可以对要实现的功能进行模块划分,每一个要实现的功能都有一个对应的代码模块相对应;可以把通用的一些函数写成头文件的形式,供所有用到该代码模块的函数模块调用;对于功能模块单独用到的一些函数,可以单独定义成功能模块头文件。在编辑的过程中,对单片机来说,需要首先初始化单片机的公共资源,而后针对要实现的功能,在已初始化单片机寄存器、已定义变量的基础上根据要实现的功能及代码模块不断添加要初始化的寄存器变量和按需定义的数据类型等。需要什么资源,在单片机许可的范围内就可以定义什么资源,并定义相对应的变量来使用它。在main的入口开始,不断地丰富逻辑组合,一个代码模块一个代码模块地完成,用函数来实现不同功能模块的出入口,在集成开发环境的帮助下,就可以逐步地完成源代码的编写。编译器可以将源代码转换成机器语言,在编译过程中,会找出错误并给出错误报告。编译器能够找出程序中很多无效或无法识别的错误及结构错误,从而保证我们给单片机下发的指令都是编译器能够翻译的,进而使单片机能够识别、执行相应的指令。开发环境中的链接器会将源代码文件中由编译器产生的各种模块组合起来,再从代码提供的程序库中添加必要的代码模块,将它们组合成一个可执行的文件。在开发环境中完成编译后,就需要单片机来读并执行我们所要求的指令。

对于一个复杂的单片机软件系统,在读别人的源码时,需要先弄明白单片机软件系统的结构框图,弄清楚软件系统的输入/输出信号及各部分子功能的工作逻辑状态,再逐步读各个子功能工作流程的逻辑代码并弄清楚各子功能模块之间的输入/输出接口。任何软件系统都只有一个main函数,阅读代码时,先从main函数入手,再逐步切入,层层剥皮。

2.2.2 有操作系统的软件开发

操作系统(Operation Systems,OS)是一个软件系统,使计算机变得好用(将人类从烦琐、复杂的对机器掌控的任务中解脱出来),使计算机运作变得有序(操作系统掌控计算机上的所有事情)。操作系统是掌控计算机上所有事情的软件系统,操作系统的功能包括:替用户及其应用管理计算机上的软、硬件资源;保证计算机资源的公平竞争和使用;防止对计算机资源的非法侵占和使用;保证操作系统自身正常运转。

操作系统的设计就是将方方面面的技术和设计有机合并起来,构建一个掌控整个计算机的巨无霸软件系统。操作系统经历了状态机操作系统(1940年以前)、单一操作员和单一控制端操作系统(20世纪40年代)、批处理操作系统(20世纪50年代,代表:IBM的FORTRAN监视系统FMS、IBSYS,密歇根大学的UMES)、多道批处理操作系统(20世纪60年代,经典代表:IBM OS/360)、分时操作系统(20世纪70年代,代表:MULTICS操作系统)、实时操作系统(商业代表有:VxWorks和EMC的DART系统)、现代操作系统(1980年以后)。

嵌入式系统是以应用为中心,以计算机技术为基础,软、硬件可裁剪,功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。嵌入式系统开发具备系统内核小、专用性强、系统精简、系统软件的实时性强、软件开发走向标准化、与应用有机结合、程序一般都固化在存储器中等特点。

按照程序开发的层面及公司所提供的工作岗位,嵌入式软件开发工程师一般分为应用软件工程师、内核开发工程师和驱动开发工程师。在操作系统的基础上,应用软件工程师看到的是一个没有硬件的纯粹的软件世界;内核开发工程师一般负责操作系统的裁剪、移植等与操作系统相关的开发工作;驱动开发工程师与底层硬件接口直接打交道,与上层应用开发接口直接打交道,驱动沟通着硬件开发和应用软件开发,在有操作系统的情况下,驱动的架构都是由相应的操作系统定义的,驱动开发工程师需要按照相应的架构设计驱动,再整合入操作系统的内核,可见,驱动开发工程师起到了硬件工程师和应用软件开发工程师之间的桥梁和纽带作用。

用C#、Java、Python等语言在上位机桌面操作系统上进行的开发和在嵌入式系统iOS、Android、Linux、MQX等上进行的功能开发都属于应用程序的开发;为一个新开发的硬件系统编写相对应的驱动程序,并良好地融入内核来驱动设备完成相应的功能属于驱动程序的开发;操作系统是应用程序和驱动程序得以运行的关键,根据产品的需求对操作系统进行裁剪、移植是内核开发工程师的工作职责。Linux是一套免费使用和自由传播的符合POSIX标准的类Unix操作系统,是一个基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的操作系统。这个系统由世界各地的成千上万的程序员设计和实现,其目的是建立不受任何商品化软件版权制约的、全世界都能自由使用的Unix兼容产品。Linux由于具有内核强大且稳定,易于扩展和裁剪,丰富的硬件支持等诸多优点,在嵌入式系统中得到了广泛的应用。本节以ARM平台Linux软件开发为例简要说明带操作系统的嵌入式软件开发的流程。

1.开发环境搭建

对于嵌入式Linux的开发,我们开发的设备称为目标机,搭建开发环境的平台称为宿主机。对于搭建开发环境,可以在现有操作系统的基础上装Linux系统,也可以在虚拟机下装一个Linux开发环境,相比而言,在虚拟机下的开发环境更加方便、便利。在该例中,虚拟机软件采用Oracle VM VirtualBox,Linux采用Ubuntu-12.04.2-desktop-i386。

在Linux平台下,编译内核、Bootloader、Qtopia图形界面及应用程序,均需要交叉编译工具链,该例采用arm-linux-gcc-4.4.3.tar.gz。为便于Windows与Linux系统的资源共享,需要在开发目标机和宿主机上安装NFS服务器,配置samba服务器和设置ftp。Linux下的开发应用较普遍的是vim编辑器,vim默认的配置使用起来不方便,不能让人满意,因此需要用户自己来配置,这里安装并配置ctags和cscope(ctags和cscope能大大提高编辑和阅读代码的便利性)。

2.Bootloader移植

Bootloader是在操作系统内核运行之前运行的一段引导程序,用来完成整个Linux系统的加载启动任务。系统在上电或复位时从地址0x00000000处开始执行,在这个地址上设定的是系统的Bootloader。Bootloader的功能类似于BIOS,通过Bootloader可以初始化硬件设备、建立内存空间的映射图,从而将系统的软、硬件带到一个合适的环境状态,以便为最终调用操作系统内核准备好正确的环境。u-boot是德国DENX小组开发的用于多种嵌入式CPU的Bootloader程序,它不仅支持嵌入式Linux系统的引导,当前它还支持NetBSD、VxWorks、QNX、RTEMS、ARTOS和LynxOS嵌入式操作系统。u-boot支持的处理器包含MIPS、x86、ARM、NIOS、XScale、PowerPC系列,应用非常广泛,该例中用到的u-boot版本是u-boot-2009。

3.驱动程序和Linux内核的移植

驱动针对的对象是存储器和外设(包括CPU内部集成的存储器和外设),Linux下的驱动分为3个基础大类:字符设备驱动、快设备驱动和网络设备驱动。该例中采用的Linux版本号为2.6.32.2。

4.文件系统移植

嵌入式系统的文件系统主要有Ext2/Ext3、Romfs、Ramdisk、Cramfs、Jffs/Jffs2、Tmpfs和YAFFS/YAFFS2。YAFFS(Yet Another Flash File System)文件系统是专门针对NAND闪存设计的嵌入式文件系统,目前有YAFFS和YAFFS2两个版本,两个版本的主要区别之一在于YAFFS2能够更好地支持大容量的NAND FLASH芯片。在该例的文件系统中,采用的是YAFSS2文件系统。

5.应用程序开发

嵌入式应用程序是为了完成某项或某几项特定的任务而被开发的运行于特定的操作系统上的程序,需要根据客户的需求开发相应的应用程序。该例的应用程序能够自适应地从2个DB9串口、USB接口读取不同外部设备传递过来的信息,并通过RJ45以太网接口,以Socket包的形式发送到上位机服务器。

2.2.3 软件开发的一般流程

软件系统开发的流程大致可分为需求分析、总体设计、概要设计、详细设计阶段、编码阶段、测试阶段和发布阶段7个阶段。软件系统开发流程如图2-3所示。SPP(Software Project Planning)指计划策划,计划策划的核心是工作量估算;SQA(Software Quality Assurance)指软件质量保证;SCM(Software Configuration Management)指软件配置管理,是所有活动的基础,一切制品必须放入配置库,主要解决版本和变更;SPTO(Software Project Tracking and Oversight)指软件项目跟踪与监控。

图2-3 软件系统开发流程

1.需求分析

需求分析需要明确要开发系统的功能,系统由哪几个大功能模块组成,大功能模块有哪些小功能模块。在需求分析阶段会对前期的需求进行归纳整理并给出软件系统设计的可行性分析。在这个阶段会出一个软件需求说明书SRS(Software Requirements Specification)。

2.总体设计

在这个阶段会给出软件总体结构图,对软件功能模块进行划分并对主要模块功能进行描述。总体设计说明系统主要的输入/输出项目、处理的功能性能要求,简要地说明系统的运行环境,说明系统的基本设计概念和处理流程(尽量使用图表形式)。在总体设计时,一般用一览表及框图的形式说明系统元素(各层模块、子程序、公用程序)的划分,扼要地说明各个系统元素的标识符功能,分层次地给出各元素之间的控制与被控制关系。在这个阶段会出一个软件总体设计说明书GD(General Design)。

3.概要设计

概要设计将系统功能模块初步划分,并给出合理的研发流程和资源要求。概要设计主要有接口设计、运行模块设计、系统数据结构设计及系统出错处理设计。接口设计包括用户接口、外部接口及内部接口的设计。用户接口说明将向用户提供的命令和它们的语法结构,以及软件的回答信息;外部接口说明系统同外界的所有接口的安排,包括软件与硬件之间的接口、系统与各支持软件之间的接口关系;内部接口说明本系统之内的各个系统元素之间的接口安排。运行模块设计包含运行模块之间的组合逻辑关系,外界对系统控制的方法和步骤,以及每回总运行模块组合占用各种资源的时间。在概要设计阶段就需要确认系统数据的结构,并设计系统数据出错时的处理机制。在概要设计阶段输出的文档有概要设计说明书HLD(High Level Design)、数据流图DFD(Data Flow Diagram)及用户界面UI(User Interface)。

4.详细设计阶段

详细设计应把具体的模块以最简洁的方式(黑箱结构)提供给编码者,使得系统的模块化达到最大。一份好的详细设计说明书,可以使编码的复杂性减到最低,严格地讲,详细设计说明书应把每个函数的每个参数的定义都精精细细地提供出来,一个大型的软件系统在完成详细设计说明书时,就可以说一个项目完成了一半。在这个阶段输出的文件是详细设计说明书DD(Detailed Design)。

5.编码阶段

在规范化的研发流程中,编码工作在整个项目流程里最多不会超过1/2,通常需要花费1/3的时间,前期需求分析、概要设计、详细设计完成得好,编码效率就会高。在编码过程中,不同模块之间的进度协调和协作是很重要的,编码时的相互沟通和应急的解决方法都是相当重要的,bug永远存在,程序的完善是一个不断修复bug的过程。在这个阶段输出的文件有测试用例(Test Case)、源代码(Coding)和单元测试报告(UT Test Result)。

6.测试阶段

测试的方法有很多,按照测试的输入范围,可以分为抽样测试和全覆盖测试;按照测试条件,可以分为正常情况测试和异常情况测试;按照测试范围,可以分为模块测试和整体联调;按照测试执行方,可以分为内部测试和外部测试。测试是软件系统开发中一个相当重要的步骤,需要花费相当长的时间。在这个阶段输出的文件有测试用例(Test Case)和测试报告(Test Result)。

7.发布阶段

软件系统开发完成,发布软件的正式版本。在这个阶段输出的文件有下发通知单、软件下发说明和测试报告(Test Report)。 jqVfYikJq7BRH74plS09yO9pjKT9ge9hnGObK62lVWDE77c0bFankAaDOdreQ547

点击中间区域
呼出菜单
上一章
目录
下一章
×