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

1.1 ARM嵌入式系统简介

近年来,ARM嵌入式系列产品,如智能手机、车载MP4、车载导航仪和平板电脑等,已经成为大众广泛使用的产品。新型的嵌入式产品不断问世,各个IT公司纷纷投入巨资加紧研发流程,嵌入式技术人才需求猛增。

随着网络通信技术、计算机技术和微电子技术的迅速发展,嵌入式系统已经成为当前IT行业的焦点。同时在数字信息技术和网络技术高速发展的后PC时代,嵌入式系统因其体积小、可靠性高、功能强和灵活方便等许多优势,逐步渗透到工业、军事、医疗、汽车及日常生活的各个领域,在嵌入式相关行业技术改造、产品更新换代、加速自动化进程,以及提高产品效率等方面起到了极其重要的推动作用。

在汽车行业,各个零部件由纯机械产品向机电一体化、汽车电子智能化逐步转变。这些车载电子技术的应用改革,都离不开对ARM嵌入式系统的依赖,如汽车电子油门、电控发动机、车载IMMO系统、车载GPS导航、全景倒车雷达等。为了使车载ARM控制器具有资源管理、快速中断、实时响应等能力,提供多任务处理,以及更好地分配系统资源的功能,用户甚至还需要针对特定的ARM嵌入式硬件平台和实际的工程应用进行操作系统的移植。

1.1.1 ARM嵌入式的发展历程及其应用

ARM的英文全称是Advanced RISC Machine,用户既可以认为ARM是一个IT 行业公司的名称,也可以认为是一种“嵌入式微处理器核”技术的名称,甚至还可以认为是具有某种“嵌入式微处理器核”技术的一类芯片,以及嵌入式系统的总称。对于从事系统开发的嵌入式工程师而言,ARM通常是指带有ARM处理器的嵌入式系统。在本书所介绍的内容中,ARM是指搭载ARM处理器的嵌入式系统。

ARM公司是微处理器行业的一家知名企业,1990年11月成立于英国,是苹果电脑、Acorn电脑集团和VLSI Technology的合资企业。1991年,ARM公司推出了ARM6处理器家族,VLSI公司则是第一个将其成功应用在内部研发产品上的生产厂家。后来,陆续有其他IT巨头,包括TI公司、NEC公司、SHARP公司,以及ST公司等,都陆续获得了ARM公司的正式授权,将ARM处理器大面积地进行推广,使得ARM处理器在汽车电子、新能源汽车、车载网络、智能手机,以及其他消费电子中都得到广泛应用。一般情况下,目前有大约80%的电子消费终端都采用了ARM处理器,具体如图1.1所示。

当前ARM嵌入式芯片的出货量每年都较上一年增长20亿片以上。与其他半导体(微处理器)公司不同的是,ARM公司从来不制造或销售某一个具体型号的ARM嵌入式处理器芯片,而是将ARM嵌入式处理器的具体设计授权给相关的商务合作伙伴,如Intel公司、Philips公司、TI公司等。

各个授权合作公司根据自身对嵌入式芯片的设计能力、产品领域特点等因素对嵌入式芯片进行功能、资源性的裁剪,以满足嵌入式市场的需求。基于ARM嵌入式系统的低成本和高性能的解决方案,各个授权合作公司设计出多种多样的处理器芯片、微控制器,以及嵌入式片上系统(SOC),即所谓的“ARM知识产权授权”结构,如图1.2所示。

图1.1 ARM嵌入式在电子行业中的应用

图1.2 “ARM知识产权授权”结构图

一般而言,ARM嵌入式系统由3部分组成,即嵌入式系统硬件平台、嵌入式操作系统(代码)和嵌入式系统应用,如图1.3所示。

图1.3 嵌入式系统的组成

1)嵌入式系统硬件平台

嵌入式系统硬件平台主要是指各种嵌入式处理器和外围设备等,如基于ARM核的STM32XX处理器、51系列单片机等。

2)嵌入式操作系统(代码)

嵌入式操作系统是指在嵌入式硬件平台上运行的代码和操作系统。目前主流的嵌入式操作系统是基于C语言(或汇编语言,较少)的嵌入式Linux、μCLinux和μC/OS-II等。

一般而言,Linux操作系统具有比较完善的网络接口支持;μClinux操作系统常被用在一些不需要“内存管理单元”(MMU,Memory Management Unit)的嵌入式平台中;而μC/OS-II系统是典型的实时操作系统,可以满足对实时性要求比较高的场合,如汽车电子油门、车载高速CAN网络等,具有非常快的响应时间。

除了上述介绍的几种嵌入式操作系统外,在当前主流的消费电子产品中,还广泛使用Android、Meego等系统。这些嵌入式系统主要用在智能手机及平板电脑上。在实际的工程应用中,用户具体使用何种嵌入式操作系统应视具体的工程需求而定。

3)嵌入式系统应用

嵌入式系统应用是以嵌入式系统硬件平台的搭建、嵌入式操作系统的成功移植和运行为前提的。这一部分内容运行在嵌入式操作系统的上层,完成特定的功能目标。

通常情况下,不同的系统需要根据具体的项目需求设计不同的嵌入式应用程序。但是值得注意的是,在嵌入式系统中,系统应用并不是必需的。只有在一些复杂的工程设计中才会需要嵌入式系统应用,如对汽车整车通信协议的定义和控制等。

在一些要求不高或者相对简单的工程应用场合,嵌入式系统应用经常被合并到操作系统及其代码的实现过程中,即操作系统与应用代码由于相对简单而被糅合在一起。

1.1.2 ARM嵌入式的性能特性

截止2010年,内嵌ARM核的嵌入式系统产品累计已经超过200亿个。在日常生活中用户所接触到的智能手机、汽车电子、平板电脑等众多的消费电子产品中无不存在ARM嵌入式处理器的身影。从诞生到现今短短的时间内,ARM嵌入式系统之所以能取得如此巨大的成就,跟它自身优越的性能是密不可分的。

1.极低的系统功耗

ARM嵌入式系统相比其他处理器而言具有极低的系统功耗,这就使得它能广泛地被应用于手持式电子设备的设计场合。目前,ARM微处理器和内嵌ARM核的SOC芯片已经在手持终端,如智能手机、车载MP4、电动汽车的电池管理系统等设备中得到广泛应用。图1.4为具有自主研发产权的新能源电动汽车动力锂电池管理系统。

图1.4 新能源电动汽车动力锂电池管理系统

2.较短的开发周期

ARM嵌入式系统的开发周期完全是由ARM的商业模式决定的。ARM公司将成熟的ARM技术直接授权给其他合作芯片设计厂商,在很大程度上缩短了ARM嵌入式产品的开发周期。而这对于芯片设计厂商而言也是一个巨大的优势。

3.支持双指令集

绝大部分ARM处理器都可以支持ARM和Thumb两种不同的工作模式,分别用以支持32位的ARM指令集和16位的Thumb指令集。对于普通用户而言,这两种指令集都各有所长。

32位的ARM指令集在命令功能上相对更为丰富,性能也更好。在运行代码的过程中,实现同样的功能所需要的指令数(代码量)更少;而16位的Thumb指令集是ARM指令集的一个子集,因此,在实现相同的功能操作时需要较多的指令数(相比ARM指令集),但是使用Thumb指令集实现的程序代码所占据的程序空间相对较少,具有较高的代码执行效率。除此之外,由于16位的Thumb指令代码在译码的过程中相对比较简单,因此Thumb指令具有更低的系统功耗。

4.高效的系统总线

在ARM嵌入式系统中,处理器没有采用DSP(数字信号处理器)架构中的多级流水线机制,而是采用了一组专门针对ARM内核的片上系统SOC开发的总线规范,即AMBA总线(Advanced Microcontroller Bus Architecture)。

该总线规范由ARM公司设计,独立于ARM微处理器的制造工艺技术。在该总线规范中,定义了以下3种可供用户组合使用的不同类型的总线。

1)AHB(Advanced High-Performance Bus)

该类型的总线支持多种数据传输方式,以及多个总线主设备之间的数据传输。适用于高性能和高时钟频率的系统模块,如CPU处理器、片上存储器、DMA设备、DSP,以及其他协同处理器等。

2)ASB(Advanced System Bus)

该类型的总线同样也适用于高性能的系统模块。在不需要使用AHB的场合,用户也可以选择ASB作为系统总线。

3)APB(Advanced Peripheral Bus)

该类型的总线的主要特点是结构简单,低速,极低的功耗。该总线主要适用于低功耗,对实时性要求不高的外部设备,如对汽车门窗锁的控制等。

1.1.3 ARM嵌入式系统的开发要点

与传统的单片机相比,ARM嵌入式系统的整体系统性能和数据处理能力有了大幅提升。与之相应的,ARM嵌入式系统设计的复杂度和难度也有所提升,与传统的单片机设计方法也有着很大不同。

总体而言,ARM嵌入式系统的开发可以分为“基于ARM内核的芯片设计”和“基于ARMSOC的开发应用”。本书主要与读者讨论有关“ARM芯片的开发应用”,不涉及ARM芯片的设计。

对于用户而言,在实现对ARM嵌入式系统进行开发之前,首先应该对ARM嵌入式系统的概念和基本结构做一些了解,然后还需要熟悉ARM嵌入式指令集。虽然现在绝大部分嵌入式系统都使用C语言开发程序,但是绝大部分芯片的初始化启动程序仍然是使用汇编语言写的,以得到较高的代码执行效率和开机速度。因此,用户在熟练掌握C语言的基础上,了解一定的汇编语言知识也是必要的。除此之外,用户还需要结合所使用的ARM处理器芯片,掌握某一个集成开发环境的使用方法,务必做到熟练使用。

1.明确ARM嵌入式系统开发的过程

不同于通用计算机平台上应用软件的开发,在ARM嵌入式系统程序的开发过程中具有很多特点和不确定性,其中最重要的一点就是嵌入式软件代码和系统硬件的独立性。

由于嵌入式系统的层次结构和自身的灵活性、多样性,各个层次之间缺乏统一的接口标准,甚至每个嵌入式系统都各不一样。这样就给上层的嵌入式软件设计人员在嵌入式软件代码设计的过程中带来比较大的困难。软件设计人员必须建立在对底层硬件设计充分了解的基础上,才能设计出符合ARM嵌入式系统要求的应用层代码。

为了简化开发流程,提高开发效率,用户可以在应用与驱动(API)接口上设计一些相对统一的接口函数,就可以在一定程度上规范应用层嵌入式软件设计的标准,同时方便应用程序在跨平台之间的复用和移植。

2.熟悉开发工具环境里的库函数

对于ARM开发工具环境里所提供的库函数,用户需要对其功能、参数、结构、调用函数等有比较清楚的了解,其中最重要的3方面如下。

(1)考虑硬件对库函数的支持。

(2)符合目标系统上的存储器资源分布。

(3)应用程序运行环境的初始化。

举例来说,在嵌入式代码设计过程中,有一类动态内存管理函数,如malloc()等,其本身是独立于目标系统而运行的,但是它所使用的存储器空间需要根据具体的目标来确定,所以malloc()函数本身并不需要移植或裁剪,这也是一个特例。但那些设置动态内存区(地址和空间)的函数则是和目标系统的存储器分布直接相关的,需要进行移植。

需要补充说明的是,在ARM嵌入式系统开发过程中,库函数的使用并不是必需的。用户同样可以自行组织编写程序代码,用于实现与库函数一样的功能。相比自行编写代码而言,系统提供的库函数具有更好的稳定性和可移植性。

在本书后续章节中所编写的工程代码中,几乎都采用了STM32XX系列ARM处理器开发平台(Keil for ARM)所提供的库函数文件。

3.熟悉ARM嵌入式系统的调试操作

嵌入式系统不可避免地会涉及对输入/输出设备的操作,例如,文件操作函数需要访问磁盘IO,打印机函数需要访问字符输出设备等。在嵌入式调试环境下,所有的标准C库函数都是有效且有其默认行为的。一般情况下,部分目标系统硬件所不能支持的操作用户可以通过相应的调试工具来完成。

但是最终嵌入式系统的运行是需要完全脱离调试工具独立运行的,所以在程序移植的过程中,用户需要对这些库函数的运行机制有比较清楚的了解。特别是在系统出现故障甚至逻辑错误的时候,需要用户能够以最短的时间来排查、解决问题。

1.1.4 常用车载ARM嵌入式芯片STM32F103XX

STM32F103XX系列处理器是一个低功耗的ARM嵌入式芯片,具有逻辑门数少,终端延迟程度小,方便调试等特点。该ARM芯片主要是为需求较低,功耗和价格敏感的应用领域而专门设计的,具有较高的系统性能和数据处理能力,应用范围涉及从低端微控制器到复杂的片上操作系统,被广泛使用在汽车电子、智能手机、娱乐网络消费终端等领域。

STM32F103XX系列处理器使用了ARM V7-M体系结构,是一个可综合的、高度可配置的ARM嵌入式芯片。它内部采用了高效的哈佛存储结构,并且可提供1.25DMIPS/MHz的处理能力。尽管STM32F103XX系列处理器的处理能力相比其他处理器而言具有较大的提升,但其自身却具有极低的系统功耗,在一个具有32个物理中断的标准处理器上达到了突出的0.06mW/MHz的能效比。

为了降低器件的成本,STM32F103XX系列处理器采用了与系统部件紧耦合的实现方法,以缩小芯片的物理面积,特别是其内核面积比原有的ARM处理器芯片缩小了30%。除此之外,STM32F103XX系列处理器还实现了Thumb-2指令集架构,具有很高的代码密度,可降低系统对存储器的要求,并能达到几乎接近32位ARM指令集的性能。

针对嵌入式系统的开发,STM32F103XX系列处理器相比其他芯片具有以下优势:

● 较小的处理器内核、系统和存储器,大幅降低了处理器芯片的成本;

● 提供高效的电源管理机制,具有极低的系统功耗;

● 较强的处理器性能,基本满足所有工业级产品的应用需求;

● 极低的中断处理时间,完全满足高速、临界控制的应用场合;

● 可供选择的存储器保护单元(MPU)为嵌入式系统提供平台级的安全性;

● 对汇编代码基本不作任何要求,简化系统开发进程;

● 宽广的工程应用范围,适用于从超低成本的微控制器到高性能的片上系统。

由于系统具有极低的功耗,并且集成了丰富的片上系统资源,以及稳定的工作性能,绝大部分汽车生产厂商在生产汽车电子设备的过程中都选择了STM32F103XX系列处理器,如图1.5所示,小到汽车零部件信号的检测,如汽车电子仪表盘、轮胎压力检测仪等,大到整车控制系统,如汽车车载低速CAN网络、新能源汽车电池管理系统等,都采用了具有丰富系统片上资源的STM32F103XX系列处理器。

图1.5 STM32F103XX系列处理器在汽车电子中的应用 b4fce9P8tNT4vPL/dv64xW4aucqhHdmZmm718176S7K6Bop5eVGEQeOlLYFXVIU+



1.2 ARM嵌入式系统的开发环境

用户在开始进行ARM嵌入式系统开发之前,需要准备好相应的开发工具及其开发环境。选择一款适合实际工程应用的开发环境是非常重要的。一般而言,常见的ARM嵌入式系统开发环境配置有如下几项。

1.编译器/汇编器

通常情况下,当前几乎所有的C编译器套件都包含了相应的汇编/编译器,建议用户在进行ARM嵌入式系统开发过程中,软件代码使用C语言来实现;而在频繁与底层寄存器打交道时,则可以使用汇编语言。

2.指令系统模拟器

指令系统模拟器用于在软件开发早期的ARM嵌入式代码调试中。通过指令系统模拟器,用户可以避免由于硬件平台不成熟而带来的问题,从而大幅缩短软件代码的实现、调试周期。

3.在线仿真器或调试探测器

该系统的开发环境是连接在计算机和ARM开发板(或其他硬件调试平台)上的调试硬件。通常而言,与硬件调试平台之间的接口是JTAG或者SWD。

4.目标开发板

对于初次接触ARM嵌入式系统的用户而言,建议在早期开发的过程中使用目标开发板对需要开发的工程项目进行前期可行性验证,从而避免硬件电路设计中可能存在的问题,缩短项目开发周期。

5.跟踪捕捉仪

该开发环境是可选的硬件设备和周边软件,用户可以使用它来捕捉来自DWT及ITM的输出,并且以可读的形式显示出来。

6.嵌入式操作系统

嵌入式操作系统是指在ARM嵌入式芯片中运行的操作系统。需要注意的是,嵌入式操作系统也是一个可选的内容。一般情况下,在开发一些简单的嵌入式系统中可以不需要操作系统,而在开发一些复杂度比较高或者有高性能指标的ARM嵌入式系统时才需要运行相应的嵌入式操作系统。

目前,市场上常见的通用C编译器已经非常普遍。每一个编译器产品都具有各自的优势和应用场合,具体如表1.1所示。用户可以根据实际工程的需求,以及ARM处理芯片的类型来选择不同的C编译器产品。

表1.1 常见的ARM嵌入式系统C编译器

续表

在上述几种ARM嵌入式开发环境中,最流行、最为通用的是Keil公司推出的RealViewMicrocontroller Development Kit,简称RealView MDK或RVMDK。该公司推出的此款ARM开发平台可以追溯到曾在8051系列单片机开发行业中具有盛誉的Keil开发套件,并且包含了丰富的功能组件,诸如μVision集成开发环境、调试器/模拟器、C/C++编译器、RTX实时内核、启动代码和Flash编程算法等。同样,Keil公司也推出了专为ARM的嵌入式开发平台,即RealView MDK。

1.2.1 Keil MDK简介

Keil开发环境是德国知名公司Keil(现已并入ARM公司)开发的嵌入式微控制器软件开发平台,也是目前ARM嵌入式单片机开发的主流工具。在该软件平台中,μVision的界面与微软VC++的界面类似,具有友好的人机交互环境,启动界面如图1.6所示,并且在调试程序、软件仿真方面有比较强大的功能。

图1.6 RealView MDK启动界面

值得说明的是,Keil公司推出的这款ARM嵌入式系统开发平台特别适合刚入门的ARM嵌入式新手,它甚至可以完全独立于外部的硬件开发环境。在μVision开发工具链中包含了指令模拟器,用户可以通过使用该功能来模拟“纯粹”的ARM嵌入式代码,即用户不需要外部硬件平台的支持也可以在软件平台中模拟代码的运行,基本的界面框架如图1.7所示。

图1.7 RealView MDK用户操作界面

RealView MDK开发环境所支持的单机脱离硬件的调试功能对学习和开发基于内核的系统软件有比较大的帮助,特别适用于缺乏硬件平台支撑的开发工程。除此之外,RealView MDK还可以与GNU工具链联合使用。

用户使用Keil平台开发ARM嵌入式工程软件,开发周期与其他平台环境的开发周期是类似的,大致有以下几个步骤:

● 创建新的项目工程,选择正确的目标芯片,并对工程项目参数进行配置;

● 编写C语言代码或汇编程序代码,并添加到项目工程文件中;

● 对项目工程进行编译、连接和调试;

● 修改源代码中的语法错误和逻辑错误,重新编译至正确;

● 与硬件联机调试至语法和逻辑都正确无误。

在RealView MDK开发环境中,开发平台附带了部分工程项目的示例程序,包括ST公司的STM32系列单片机产品,以及Luminary Micro公司的Stellaris系列单片机。在这些示例代码中都统一使用了ARM芯片生产厂商所提供的驱动固件库。

对于普通用户而言,这种做法也是必要的,因为用户使用生产厂家所提供的驱动固件库可以避免编写代码对芯片外部寄存器进行操作,也在一定程度上避免了代码中的错误,缩短了嵌入式系统的开发周期。

在实际的项目开发流程中,用户并不需要完全从代码的第一行开始写起,可以很方便地通过开发系统所自带的代码模板进行编写,提高代码实现的效率和准确率。

1.2.2 Keil MDK的开发步骤

用户在正确安装了RealView MDK开发环境后,就可以从开始菜单或者桌面图标启动μVision集成开发环境。在默认情况下,RealView MDK会自动加载上一次打开时所运行的工程文件。

1.创建/打开工程文件

在Keil MDK开发环境中,用户可以通过选择“New Project”下拉菜单来创建一个新的工程,如图1.8所示。

图1.8 在菜单中创建新的工程

此时,系统会弹出一个对话框,要求用户为新建的项目工程起一个名字。在这里,用户可以创建一个名为“test”的文件夹,如图1.9所示。在该工程文件夹中,主要用于存放有关test测试工程项目的所有文件。

图1.9 将新创建的工程命名为“test”

如果用户需要打开已经存在的项目工程文件,则可以通过选择菜单“Project”|“OpenProject”来打开已经存在的工程。此时,系统会弹出一个打开文件对话框,供用户选择需要打开的项目工程文件的路径。

2.选择ARM嵌入式芯片

在创建完存放工程代码的文件夹后,用户就可以根据实际工程需要,选择需要的ARM嵌入式芯片。

需要注意的是,在项目开发过程中,并不是只需要一个源程序代码就可以完成对整个系统软件的开发,还需要在项目工程实现之前选择正确的ARM芯片的型号,加载对应的芯片启动代码(汇编语言实现,选择ARM芯片后系统自动加载),进而根据所选的具体芯片型号来确定项目工程编译、汇编和连接时的参数,并且指定具体的调试方式。

如果用户在系统芯片库中找不到实际所需要的处理器型号,也可以使用同一款兼容的处理器来代替。一般情况下,用户在选择具体的处理器芯片后系统会为芯片提供相应的启动代码,在弹出的对话框中单击“Yes”按钮就完成了对整个项目工程的建立。

3.添加源代码文件

在建立工程项目文件后,用户需要在该工程项目内添加源程序代码。通过选择菜单“File”|“New”或者单击工具栏上的“新建文件”按钮,就可以在项目工程窗口的右侧打开一个新的文本编辑窗口,用户可以在该窗口中输入程序代码。

需要说明的是,所谓ARM源程序代码就是一般的文本文件,只是后缀名根据编程语言的不同而各不相同。用户在编写源代码的时候不一定需要使用Keil软件来编写,也可以使用任意的文本编辑器甚至是记事本来编写,只要注意在完成源代码编写后需要将该文本保存为“.c”的后缀名文件就可以了。

通常情况下,Keil软件开发环境中的代码编辑器尚不能支持中文字符,因此如果用户需要在源代码中输入中文,建议使用UltraEdit之类的第三方字符编辑软件进行代码输入。

在编辑完代码之后,用户需要将其保存为源文件,选择菜单“File”|“Save”或者单击工具栏的“保存文件”按钮可以实现对源文件的保存操作。

如果用户是第一次对当前源文件进行保存的,系统会出现一个保存文件的对话框。用户在选择合适的保存路径后,输入相应的文件名就可以了。

特别需要提醒用户注意的是,在保存文件的时候一定要输入文件的扩展名,如果是C程序编写的文件,其扩展名为“.c”;如果是汇编语言编写的程序,扩展名为“.asm”;另外,代码中出现的注解说明文件可以单独保存为“.txt”扩展名。

在源文件编写完成之后,用户还需要将编写好的源文件添加到新建的项目工程中去。在新建项目工程的左侧界面中,单击“Target1”选项,前面有一个“+”号,表示当前选项还包含了子选项,单击即可展开。

当用户单击“+”号展开下一层的子选项后,可以看到“Source Gode”选项,编辑代码的源文件将被添加到该目录结构中。具体操作为:单击选中“Source Gode”,再右键单击鼠标,出现一个下拉菜单,如图1.10所示。

选择其中的“Add Files to Group‘Source Gode’”,系统弹出一个文件对话框,用户可以在对话框中输入源代码文件存放的系统路径,单击“确定”按钮后就完成了对源文件的添加操作,具体如图1.11所示。

一般而言,在添加源文件操作的过程中,对话框下面的“源文件类型”默认的是C SourceFile(*.c)。在实际工程项目中,用户除了需要添加源代码文件外,还需要添加其他格式的文件,如汇编格式的源代码、系统库文件,以及目标文件等。

● 如果是选择添加“目标文件”,用户需要在对话框的下拉菜单中将文件类型选择为“Object File”;

● 如果是选择添加“汇编格式的源代码”,用户需要在对话框的下拉菜单中将文件类型选择为“asm source file”;

● 如果是选择添加“系统库文件”,用户需要在对话框的下拉菜单中将文件类型选择为“Library File”。

图1.10 添加源文件到项目工程中

图1.11 添加源代码对话框

需要提醒用户注意的是,用户在单击“Add”按钮添加文件后,添加文件对话框不会消失,以方便用户连续添加多个文件。在添加文件结束后,单击对话框中的“Close”按钮关闭当前窗口。

在添加文件的时候,由于对话框不会自动关闭,经常会被初学者误认为“添加文件操作没有成功”而再次双击添加同一个文件,引起不必要的错误。发生这种错误的时候,RealView MDK系统也会弹出相应的错误提示对话框,如图1.12所示。

用户在成功添加源代码文件后,单击“Source Group1”前面的“+”号就可以看到已经添加进去的源文件。双击文件名,则可以在代码区打开源程序代码文件,对其进行修改和编辑。

图1.12 重复添加源代码后的错误提示

4.编译程序代码

在程序代码编辑完之后就可以进入编译阶段,用户可以通过菜单、工具栏和浮动菜单等多种方式对源代码进行编译。同时,在Keil MDK开发平台中,用户还可以通过批处理文件进行相应的编译操作。一般情况下,实际的项目工程需要进行批处理编译的操作不是很多,有兴趣的读者可以通过Keil MDK的技术支持文档查看具体的操作步骤,在这里不再赘述。

在“Project”下拉菜单中,分别列出了对应的菜单编译命令和工具栏编译命令。其各自的功能定义如下。

● Clear Target:清除当前编译的结果。

● Build Target:编译当前被修改的文件并且对当前源代码文件进行编译操作。

● Rebuild All Target Files:重新编译所有的项目工程源文件并且编译应用程序。

● Batch Build:通过前面输出的批处理文件进行编译。

● Translate **.*:编译某一个源文件代码,其中**.*表示需要编译的源代码文件。

● Stop Build:停止编译当前文件。该选项按钮只有在编译运行的过程中才有效。

除了上述相关的代码编译菜单之外,用户可以在工程窗口“Target1”上单击右键,系统同样也会弹出相应的编译菜单,也包含了跟上述一样意义和功能的命令操作。

用户在单击运行编译命令后,Keil MDK界面中的输出窗口会输出相应的编译结果,如图1.13所示。当出现“0 Errors(s),0 Warning(s)”时,表示当前工程项目中的源代码已经通过了编译器的语法检查,并正确无误。

图1.13 运行编译后的输出窗口信息

在部分复杂的工程文件源代码中,编译之后可能会出现“0 Errors(s),* Warning(s)”的编译结果(*表示相应的阿拉伯数字),这表示当前工程文件已经通过系统编译器的编译,但仍存在部分警告。

一般情况下,这些警告(Warning)不会影响程序的正常执行,但也需要慎重对待。通常可能引起Warning警告的原因有“声明/定义变量后在代码中没有使用”等。

无论是错误还是警告,用户都可以双击输出窗口中有关错误/警告信息内容所在的行,快速跳转定位到错误/警告的代码位置。

5.程序代码的调试

一般而言,项目工程文件的源代码在通过编译器的编译后,只能说明当前的代码没有语法错误。但在实际的调试过程中,除了编译器能识别的语法错误外,还可能存在其他错误,如逻辑功能错误等,而从实际的工程开发经验来说,除非软件代码的功能非常简单,否则几乎所有的源程序代码都可能存在逻辑上的错误。用户必须通过调试才能发现这些逻辑上的问题并解决。

事实上,除了极为简单的程序代码外,绝大部分程序都要通过反复调试才能得到最终正确的结果。因此,从某种角度而言,源程序代码的调试是用来验证用户所编写的代码是否能够达到预期目的和功能的重要手段,往往也是程序开发过程中最为艰难,且耗时最长的阶段。

在一些功能比较复杂的程序代码中,特别是ARM嵌入式系统的代码的调试过程中,不仅与软件的源程序代码本身相关,还与外部的硬件环境、操作时序等密切相关。因此,只有完成对代码的软、硬件调试,才能实现嵌入式系统的最终开发。

在对工程项目成功进行汇编、连接之后,用户可以通过菜单“Debug”|“Start/Stop DebugSession”或者“Ctrl+F5”进入代码调试状态。此时,调试的界面与原工程项目在编辑状态下的界面有明显变化:Debug菜单中原来不能使用的命令选项(灰色)可以在调试状态下使用(黑色),RealView MDK的工具栏上也会弹出一个用于运行和调试的工具栏,如图1.14所示。其中,Debug菜单上的绝大部分命令都可以在工具栏上找到对应的快捷按钮。

在Keil MDK开发平台中,常用的Debug菜单命令如下。

● Start/Stop Debug Session:开始或停止调试操作。

● Run:一直运行到下一个活动的断点(停止点)。如果没有断点,则一直循环运行。

● Step:以行为单位,单步执行代码。

● Step Over:跳过函数体继续执行,即将函数作为一条语句执行。

● Step out of current Function:跳出当前正在执行的函数。

● Run to Cursor Line:执行到光标所在的代码行。

● Stop Running:停止运行当前正在调试的代码。

● Breakpoints:在当前的调试代码行打开断点设置对话框。

● Insert/Remove Breakpoints:在当前的调试代码行插入/删除一个断点。

● Enable/Disable Breakpoints:激活当前代码行的断点或使得当前的断点无效。

● Disable All Breakpoints:使得当前调试代码中所有的断点都无效。

● Kill All Breakpoints:删除程序中所有的断点。

图1.14 MDK调试界面

用户在使用程序调试的过程中,必须明确两个重要概念,即全速执行和单步执行。全速执行是指一行程序代码执行完了后紧接着执行下一行程序代码,中间不停留。全速执行的方式具有较快的执行速度,并且可以看到当前调试代码的总体效果,即可以直观地评价最终运行结果是正确的还是错误的,但如果调试的结果是错误的,则用户很难确认错误出现在具体的哪一行代码中。

单步执行则是在调试过程中每次只执行一行程序代码,执行完该行程序代码后立即停止,等待命令执行下一行程序代码,此时,所有寄存器的参数值都保持当前运行的状态。用户可以方便地去观察当前代码执行完以后得到的结果是否与当初软件功能的设计思路一致。在调试结果出现错误的情况下,可以比较方便地发现代码中的错误地方。

在实际项目工程调试过程中,这两种调试方法都需要使用,并且灵活地将两者结合在一起可以提高代码的调试效率。 RP/1wYy/xoT/xgcQvVT8yJ+S+1oYWtAVY++1pqElfBYDiQsgEpjU2kNvJ0ML7DEZ



1.3 ARM嵌入式系统的硬件构成

由于ARM公司成功的商业模式,使得ARM在嵌入式市场上取得了巨大的成功。基于ARM技术的微处理器系统占据了32位RISC微处理器75%以上的市场份额。目前嵌入式行业主流的ARM微处理器包括Cortex、ARM7、ARM9、Xscale等几个系列,这些系列的架构特点如表1.2所示。

表1.2 常见ARM微处理器系列

对于上表中所列出的各种型号ARM嵌入式微处理器,都利用ARM公司的IP授权为ARM内核定制了各种各样的设备。各个芯片开发商在此基础上形成了上述ARM微处理器芯片。同样,用户也可以结合图1.15查看ARM处理器的分类。

图1.15 ARM嵌入式处理器的分类

1.3.1 ARM嵌入式处理器结构

一般而言,ARM嵌入式芯片主要由32位ALU、31个32位通用寄存器和6个状态寄存器、32×8位乘法器、32×32位桶形移位寄存器、指令译码及控制逻辑、指令流水线和数据/地址寄存器组成,如图1.16所示。

图1.16 ARM嵌入式处理器的结构

在ARM处理器结构中,使用了流水线技术以提高处理器指令的运行速度。在流水线操作中,允许多个操作同时进行,以及处理和存储系统连续操作。以3级流水线为例,指令的执行分为以下3级。

1)取指级

在取指级中,处理器主要完成程序存储器中指令的读取,并放入指令流水线中等候处理。

2)译码级

在译码级中,对指令进行译码,为下一个周期的操作运行准备数据路径所需要的控制信号。在译码级操作中,处理器占用“译码逻辑”而不使用“数据路径”。

3)执行级

在执行级指令中,处理器使用“数据路径”,寄存器堆栈被读取,操作数在桶形移位寄存器中进行移位操作,ALU(算术运算寄存器)产生相应的运算结果并回写到目的寄存器中。ALU的计算结果根据指令要求更改状态寄存器的条件位。

1.3.2 ARM嵌入式处理器中的指令

指令是指用来指示ARM嵌入式处理器进行操作的命令。下面这行代码就是一条常用的ARM指令。

该指令用来将寄存器R1中的值加上0x33,然后将计算的结果保存到寄存器R0中。需要注意的是,在汇编语言中,分号“;”用来对代码进行注释,以增加代码的可读性和可维护性。

一般情况下,不同类型的ARM处理器会支持不同的指令集。在常用的ARM嵌入式系统中,处理器可以支持两种不同的指令模式和指令集:32位的ARM指令集(ARM模式)和16位的Thumb指令集(Thumb模式)。

需要提醒用户注意的是,虽然ARM嵌入式系统开发中大多数应用程序都采用了C语言进行编程,但也不能忽视汇编语言的功能。因为汇编语言是所有编程语言中效率最高、最直接的编程方法。通过汇编语言,用户可以直接对ARM处理器底层的寄存器进行操作。

在ARM指令集中就是以汇编程序语言为基础设计的。在基于ARM的嵌入式系统开发中,即使大部分代码都可以用C语言或者其他高级语言来实现,但系统的引导程序、启动代码仍必须使用汇编语言来实现。在本书的第2章,将详细向读者介绍有关ARM指令集的相关内容。

1.3.3 ARM硬件配置

用户在进行ARM嵌入式系统开发之前,需要对ARM处理器的硬件配置有一定的了解。在这里,针对常用的车载ARM嵌入式芯片STM32F103XX,以Cortex-M3内核为例,详细介绍ARM的硬件配置。

Cortex-M3是一个32位ARM处理器内核。内部的数据宽度是32位的,寄存器也是32位的,存储器的接口同样也是32位的。与常用的ARM嵌入式处理器一样,Cortex-M3采用了哈佛结构,拥有独立的指令总线和数据总线,可以同时进行取址操作和数据访问操作。

采用哈佛结构的数据/指令存储方式,处理器在访问数据的时候不再占用数据总线,从而提升了系统处理的性能。为进一步提高ARM处理器的处理能力,CM3的内部结构中包含了多条总线接口方式,每条总线都专门为特定的应用场合进行综合优化,并可以多条总线并行工作。

图1.17 Cortex-M3中的寄存器组

1.CM3中的寄存器组

在CM3处理器中包含了R0~R15寄存器组,如图1.17所示。其中,R13为堆栈指针SP。需要注意的是,SP寄存器有两个,但在同一时刻,用户只能看到其中的某一个,也就是所谓的“banked”寄存器。

其中,R0~R12为通用寄存器,都是32位的寄存器,主要用于ARM处理器内部的数据操作,但在ARM指令集中,并不是所有的语句都可以访问R0~R12寄存器。其中,绝大部分的16位Thumb指令只能访问R0~R7寄存器,而32位的Thumb-2指令则可以访问所有的寄存器。

2.嵌套向量中断控制器

Cortex-M3在ARM内核上搭载了一个终端控制器,即嵌套向量终端控制器(NVIC,NestedVectored Interrupt Controller),它与ARM内核紧密耦合,并提供如下功能:

● 支持系统嵌套中断;

● 支持向量中断;

● 支持动态调整中断优先级;

● 较短的中断延迟;

● 可屏蔽系统中断。

3.存储器映射

总体而言,Cortex-M3可以支持4GB的存储空间,并且被划分为若干区域,具体如图1.18所示。

图1.18 存储器映射成若干区域

从图1.18中可以看出,与其他ARM处理器不同的是,在Cortex-M3内核中,系统预先定义了存储器映射框架。通过将片上外设的寄存器映射到外设区,就可以实现以访问内存的方式来访问外部存储器,从而控制外设的工作。

4.存储器保护单元

在Cortex-M3中有一个可选的存储器保护单元。通过存储器保护单元可以对特权级访问和用户级访问分别实现不同的访问限制。在系统运行的过程中,当检测到权限犯规(Violated)时,存储器会产生一个fault的异常。这个异常可以由fault异常的服务例程来分析,同时也可以对其进行更正。 RP/1wYy/xoT/xgcQvVT8yJ+S+1oYWtAVY++1pqElfBYDiQsgEpjU2kNvJ0ML7DEZ

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