ARM嵌入式实验开发环境熟悉实验 - 图文
更新时间:2024-04-19 00:56:01 阅读量: 综合文库 文档下载
嵌入式实验开发平台熟悉实验
一
实验目的
? ? ? ? ?
了解本课程使用的嵌入式开发平台UP-NetARM2410-S的基本组成、配置 熟悉ADS1.2 开发环境 学会ARM 仿真器的使用
使用ADS 编译、下载、调试并跟踪一段已有的程序 了解嵌入式开发的基本思想和过程。
二 实验内容
本次实验要求自己配置好实验环境;然后使用ADS 集成开发环境,新建一个简单的工程文件,并编译这个工程文件。学习ARM 仿真器的使用和开发环境的设置。下载已经编译好的文件到嵌入式控制器中运行。学会在程序中设置断点,观察系统内存和变量,为调试应用程序打下基础。
三 实验设备及工具
? ?
硬件:ARM 嵌入式开发平台、PC 机Pentium100 以上、用于ARM920T 的JTAG 仿真器、串口线。
软件:PC 机操作系统Win2000 或WinXP、ARM ADS1.2 集成开发环境、仿真器驱动程序、超级终端通讯程序。
四 基础知识
1
嵌入式开发平台
硬件平台是基于ARM体系结构,由北京博创兴业科技有限公司开发的UP-NetARM3000和UP-NetARM2410-S实验仪器。UP-NetARM3000的CPU为ARM7TDMI内核的三星S3C44B0X01芯片,由于没有MMU(内存管理单元)只能运行uClinux,UP-NetARM2410-S的CPU为ARM920T内核的三星S3c2410芯片,由于有MMU可以运行标准的ARM-LINUX内核,本实验室配备的实验开发平台就是UP-NetARM2410-S。现对实验平台做个简要介绍,其硬件配置资源如表1所示:
表1 UP-NetARM2410-S的硬件配置
配置名称 CPU FLASH 型号 说明 ARM920T结构芯片三星S3c2410X 工作频率203MHz SAMSUNG K9F1208 64M NAND SDRAM EtherNet网卡 LCD 触摸屏 LED USB 接口 UART/IrDA AD AUDIO 扩展卡插槽 GPS_GPRS扩展板 IDE/CF卡插座 PCMCIA和SD卡插座 PS2 IC卡座 DC/STEP电机 CAN BUS Double DA 调试接口
HY57V561620AT-H AX88796 LQ080V3DG01 SX-080-W4R-FB ZLG7290 4个HOST /1个DEVICE 32M×2=64M 两片,10/100M自适应 8寸16bit TFT FM7843驱动 四个共阴极LED 由AT43301构成USB HUB 2个RS232,1个RS485,1个IrDA 从处理器的UART2引出 由S3C2410芯片引出 IIS总线,UDA1341芯片 168Pin EXPORT SIMCOM的SIM100-E模块 笔记本硬盘,CF卡 PCMCIA型号为DWL-650 PC键盘和鼠标 AT24CXX系列 DC由PWM控制,STEP由74HC573控制 由 MCP2510和TJA1050构成 MAX504 JTAG 3个电位器控制输入 44.1KHz音频 总线直接扩展 支持双道语音通信 由ATMEGA8单片机控制 由ATMEGA8单片机控制 两个10位DAC端口 14针、20针 UP-NetARM2410-S实验开发平台的外观图如图1所示:
图1 UP-NetARM2410-S
该实验平台的各模块功能如图2所示:
图2 UP-NetARM2410-S
与微机连接示意图:
图3 UP-NetARM2410-S的连接示意图
该硬件平台的基本架构如图4所示:
图4 UP-NetARM2410-S的架构示意图
(1)核心板
? ? ?
CPU: ARM920T结构芯片,工作频率202MHz ,SAMSUNG公司的S3c2410X FLASH:64M NAND型,SAMSUNG的K9F1208 RAM:64MB SDRAM,HY57V561620AT-H
? 200管脚精密插座
图5 UP-NetARM2410-S的核心板
S3c2410芯片介绍:
S3c2410X芯片集成了大量的功能单元,包括:
1).
内部1.8V,存储器3.3V,外部IO3.3V,16KB数据CACH,16KB指令CACH,MMU; 2). 内置外部存储器控制器(SDRAM 控制和芯片选择逻辑); 3). LCD控制器(最高4K色 STN和256K彩色TFT),一个LCD专用DMA; 4). 4路带外部请求线的DMA;
5). 三个通用异步串行端口(IrDA1.0, 16-Byte Tx FIFO, and 16-Byte Rx FIFO),2通道SPI; 6). 一个多主IIC总线,一个IIS总线控制器;
7). SD主接口版本1.0和多媒体卡协议版本2.11兼容; 8). 2个USB HOST ,一个USB DEVICE(VER1.1); 9). 4个PWM定时器和一个内部定时器; 10).看门狗定时器; 11).117个通用IO; 12).24个外部中断; 13).电源控制模式:标准、慢速、休眠、掉电; 14).8通道10位ADC和触摸屏接口; 15).带日历功能的实时时钟;
16).芯片内置PLL; 17).设计用于手持设备和通用嵌入式系统; 18).16/32位RISC体系结构,使用ARM920T CPU核的强大指令集; 19).ARM带MMU的先进的体系结构支持WINCE、EPOC32、LINUX;
20).指令缓存(cache)、数据缓存、写缓冲和物理地址TAG RAM,减小了对主存储器带宽和性能的影响;
21).ARM920T CPU 核支持 ARM 调试的体系结构;
22).内部先进的位控制器总线(AMBA2.0, AHB/APB) .
图6 S3c2410X芯片
芯片封装如下图所示:
图7 FBGA封装
(2)主板
?
USB口: 包括一个USB Device接口和4个USB Host接口。前者直接来自处理器,后者是处理器的Host接口经过由AT43301构成的USB HUB电路扩展出来的4个Host接口;
jtag调试口 :20针标准口,14针简易口;
AUDIO:44.1KHz音频, 采用UDA1341芯片构成,可放音和录音,通过IIS总线连接到处理器,具有功放电路驱动喇叭,板载MIC和音频IO插座;
2410-S平台上通过一片ATMEGA8单片机作为控制器,驱动PS2接口、IC卡接口和板载KEYPAD。 ATMEGA8单片机通过IIC总线和ARM处理器连接;
LED:四个共阴极LED ,由通过IIC总线扩展连接的ZLG7290控制;
AD :3个电位器控制输入,8个通道经过跳线设置可全部作为外部模拟电压输入,由S3C2410芯片管脚引出 ; ? ? ? ? ? ? ?
DC/STEP电机:直流电机信号来自PWM输出,步进电机信号来自EXIO扩展, EXIO扩展电路由74HC573构成,分配专用地址段,和IDE接口在同一BANK;
IDE/CF卡插座:类似于计算机主板上一个IDE接口上的主从两个IDE设备一样,IDE接口直接出自扩展总线,由软件完成驱动控制;
SD卡插座:直接来自s3c2410的SD控制器;
CAN总线:由控制器MCP2510和驱动器TJA1050构成,SPI总线接口;
DA电路:由两片MAX504组成,提供两路10bit数模转换输出,也是SPI总线接口;
串口:包括两个RS232接口,处理器的UART0和UART1经过MAX3232芯片电压转换后用DB9插座输出;
168Pin的扩展插座:该插座和计算机的内存条插座规格一致,用户可以据此设计合适的扩展板。扩展槽上包含扩展总线的所有信号,可复用的系统资源以及开发平台尚未使用的空置资源。
以太网卡:包括两个相同的网卡电路,芯片型号AX88796,10M/100M自适应。 LCD:8寸16bitTFT,640X480分辨率,型号是LQ080V3DG01.S3C2410处理器内含LCD控制器,这使得LCD部分的电路非常简单,LCD控制器的信号线经过驱动电路后即可连接LCD模块;
触摸屏:采用ADS7843完成AD转换,通过SPI总线和处理器接口。同样为了兼容性,平台上设计了多个触摸屏接插位置,并保留了依靠2410 CPU AD单元的另一套触摸屏接口方案。
(3)显示装置
? LCD:8寸16bitTFT,640X480分辨率,型号是LQ080V3DG01.S3C2410处理器内含
LCD控制器,这使得LCD部分的电路非常简单,LCD控制器的信号线经过驱动电路后即可连接LCD模块;
?
触摸屏:采用ADS7843完成AD转换,通过SPI总线和处理器接口。同样为了兼容性,平台上设计了多个触摸屏接插位置,并保留了依靠2410 CPU AD单元的另一套触摸屏接口方案。
? ? ? ? ?
? ?
?
2 嵌入式系统开发流程
嵌入式系统开发已经逐步规范化,在遵循一般工程开发流程的基础上,嵌入式开发有其自身的一些特点,如图8所示为嵌入式系统开发的一般流程。主要包括系统需求分析(要求有严格规范的技术要求)、体系结构设计、软硬件及机械系统设计、系统集成、系统测试,
最后是产品发布。
需求分析系统体系结构设计机械系统设计硬件设计软件设计系统集成系统测试产品发布 图8 嵌入式系统开发流程
(1)系统需求分析:确定设计任务和设计目标,并提炼出设计规格说明书,作为正式设计指导和验收的标准。系统的需求一般分功能性需求和非功能性需求两方面。功能性需求是系统的基本功能,如输入输出信号、操作方式等;非功能需求包括系统性能、成本、功耗、体积、重量等因素。
(2)体系结构设计:描述系统如何实现所述的功能和非功能需求,包括对硬件、软件和执行装置的功能划分,以及系统的软件、硬件选型等。一个好的体系结构是设计成功与否的关键。在这一步往往需要选定主要的芯片、确定EOS、确定编程语言、选择开发环境(编程语言和开发环境在确定EOS时也就跟着确定了)、确定测试工具和其它辅助设备。
(3)硬件/软件协同设计:基于体系结构,对系统的软件、硬件进行详细设计。为了缩短产品开发周期,设计往往是并行的。嵌入式系统设计的工作大部分都集中在软件设计上,采用面向对象技术、软件组件技术、模块化设计是现代软件工程经常采用的方法。
(4)系统集成:把系统的软件、硬件和执行装置集成在一起,进行调试,发现并改进单元设计过程中的错误。
(5)系统测试:对设计好的系统进行测试,看其是否满足规格说明书中给定的功能要求。
3 嵌入式软件交叉开发环境
嵌入式系统的设计与开发大部分工作都集中在软件方面。如图9所示,由于资源有限,不能采取自举开发方式,嵌入式系统在开发过程一般都采用 “宿主机/目标板”的交叉开发模式,即利用宿主机(PC机)上丰富的软硬件资源及良好的开发环境和调试工具来开发目标板上的软件,然后通过交叉编译环境生成目标代码和可执行文件,通过串口/USB/以太网等方式下载到目标板上,利用交叉调试器在监控程序运行,实时分析,最后,将程序下载固化到目标机上,完成整个开发过程。
图9 宿主机/目标板交叉开发硬件环境
如图10所示,整个软件开发过程基本包括以下几个步骤: (1)源代码编写:编写源C/C++及汇编程序; (2)程序编译:通过专用编译器编译程序; (3)软件仿真调试:在SDK中仿真软件运行情况;
(4)程序下载:通过JTAG、USB、UART方式下载到目标板上; (5)软硬件测试、调试:通过JTAG等方式联合调试程序; (6)下载固化:程序无误,下载到产品上生产。
代码编写 C源程序交叉编译 OBJ文件交叉库函数 交叉链接 系统镜像文件 重定向与下载调试 目标板
图11 嵌入式软件开发流程图
3.1. 交叉编译
交叉开发环境是指:实现编译、链接、调试应用程序代码的环境与运行应用程序代码的环境不同,分散在不同设备上。提供实现编译、链接、调试应用程序代码的环境的设备称为宿主机,运行应用程序代码的设备称为目标机,
嵌入式的交叉编译就是利用运行在宿主机上的编译器编译某个源程序生成在目标机上运行的目标代码的过程,包括交叉编译和交叉链接等过程。通常ARM的交叉编译器为Arm-elf-gcc,交叉链接器为Arm-elf-ld。 3.2. 交叉调试
嵌入式系统的调试有四种基本方法:
(1)模拟调试(Simulator):直接在主机上进行调试,使用软件模拟目标运行环境,主要进行语法和逻辑上的调试。
(2)软件调试(Debugger):主机和目标板通过某种接口(通常是串口)连接,主机上提供调试界面,待调试软件下载到目标板上运行。这种方式的先决条件是要在主机和目标板
之间建立通信联系。
(3)BDM/JTAG调试(BDM/JTAG Debugger):这种方式调试除了主机和目标板之外,还需要一个额外的调试装置,该装置与目标板通过BDM/JTAG等调试接口相连,与主机通过串口、并口、网口或USB相连。待调试的软件通过该调试装置下载到目标板上运行。 (4)全仿真调试(Emulator):仿真器完全或部分取代目标板上的部件(例如机械部分或MCU),因而目标系统对开发者来说完全是透明的、可控的。由于仿真器自成体系,调试时既可以连接也可以不连接(Stand alone)目标板。
交叉调试器和仿真软件用于完成宿主机与目标机应用程序代码的调试。交叉调试器用于对嵌入式软件进行调试和测试。嵌入式系统的交叉调试器在宿主机上运行并且通过串口或网络连接到目标机上。调试人员可以通过使用调试器与目标机端的Monitor协作,下载要调试的程序到目标机运行和调试。
基于本实验箱的嵌入式系统开发框架如图12所示
图12
嵌入式系统开发框架
4 嵌ARM JTAG 调试原理
4.1 介绍目的
本节主要介绍ARM JTAG调试的基本原理。基本的内容包括了TAP (TEST ACCESS PORT) 和BOUNDARY-SCAN ARCHITECTURE的介绍,在此基础上,结合ARM7TDMI详细介绍JTAG调试原理。
4.2 IEEE Standard 1149.1 - Test Access Port and Boundary-Scan Architecture
既然是介绍JTAG调试,还是让我们从IEEE的JTAG调试标准开始吧。JTAG是JOINT TEST ACTION GROUP的简称。IEEE 1149.1标准就是由JTAG这个组织最初提出的,最终由IEEE批准并且标准化的。所以,这个IEEE 1149.1这个标准一般也俗称JTAG调试标准。 接下来的这一部分,主要简单的介绍了TAP (TEST ACCESS PORT) 和BOUNDARY-SCAN ARCHITECTURE的基本构架。虽然不是很全面,但对了解JTAG的基本原理来说,应该是差不离了。如果希望更全面深入的了解JTAG的工作原理,可以参考IEEE 1149.1标准。 4.2.1 边界扫描
在JTAG调试当中,边界扫描(Boundary-Scan)是一个很重要的概念。边界扫描技术的基本思想是在靠近芯片的输入输出管脚上增加一个移位寄存器单元。因为这些移位寄存器单元都分布在芯片的边界上(周围),所以被称为边界扫描寄存器(Boundary-Scan Register Cell)。当芯片处于调试状态的时候,这些边界扫描寄存器可以将芯片和外围的输入输出隔离开来。通过这些边界扫描寄存器单元,可以实现对芯片输入输出信号的观察和控制。对于芯片的输入管脚,可以通过与之相连的边界扫描寄存器单元把信号(数据)加载倒该管脚中去;对于芯片的输出管脚,也可以通过与之相连的边界扫描寄存器“捕获”(CAPTURE)该管脚上的输出信号。在正常的运行状态下,这些边界扫描寄存器对芯片来说是透明的,所以正常的运行不会受到任何影响。这样,边界扫描寄存器提供了一个便捷的方式用以观测和控制所需要调试的芯片。另外,芯片输入输出管脚上的边界扫描(移位)寄存器单元可以相互连接起来,在芯片的周围形成一个边界扫描链(Boundary-Scan Chain)。一般的芯片都会提供几条独立的边界扫描链,用来实现完整的测试功能。边界扫描链可以串行的输入和输出,通过相应的时钟信号和控制信号,就可以方便的观察和控制处在调试状态下的芯片。 利用边界扫描链可以实现对芯片的输入输出进行观察和控制。下一个问题是:如何来管理和使用这些边界扫描链?对边界扫描链的控制主要是通过TAP (Test Access Port)Controller来完成的。在下一个小节,我们一起来看看TAP是如何工作的。 4.2.2 TAP (TEST ACCESS PORT)
在上一节,我们已经简单介绍了边界扫描链,而且也了解了一般的芯片都会提供几条边界扫描链,用来实现完整的测试功能。下面,我将逐步介绍如何实现扫描链的控制和访问。 在IEEE 1149.1标准里面,寄存器被分为两大类:数据寄存器(DR-Data Register)和指令寄存器(IR-Instruction Register)。边界扫描链属于数据寄存器中很重要的一种。边界扫描链用来实现对芯片的输入输出的观察和控制。而指令寄存器用来实现对数据寄存器的控制,例如:在芯片提供的所有边界扫描链中,选择一条指定的边界扫描链作为当前的目标扫描链,并作为访问对象。下面,让我们从TAP(Test Access Port)开始。
TAP是一个通用的端口,通过TAP可以访问芯片提供的所有数据寄存器(DR)和指令寄存器(IR)。对整个TAP的控制是通过TAP Controller来完成的。TAP总共包括5个信号接口TCK、TMS、TDI、TDO和TRST :其中4个是输入信号接口和另外1个是输出信号接口。一般,我们见到的开发板上都有一个JTAG接口,该JTAG接口的主要信号接口就是这5个。下面,我先分别介绍这个5个接口信号及其作用。
(1)Test Clock Input (TCK)
TCK为TAP的操作提供了一个独立的、基本的时钟信号,TAP的所有操作都是通过这个时钟信号来驱动的。TCK在IEEE 1149.1标准里是强制要求的。
(2)Test Mode Selection Input (TMS)
TMS信号用来控制TAP状态机的转换。通过TMS信号,可以控制TAP在不同的状态间相互转换。TMS信号在TCK的上升沿有效。TMS在IEEE 1149.1标准里是强制要求的。
(3)Test Data Input (TDI)
TDI是数据输入的接口。所有要输入到特定寄存器的数据都是通过TDI接口一位一位串行输入的(由TCK驱动)。TDI在IEEE 1149.1标准里是强制要求的。
(4)Test Data Output (TDO)
TDO是数据输出的接口。所有要从特定的寄存器中输出的数据都是通过TDO接口一位一位串行输出的(由TCK驱动)。TDO在IEEE 1149.1标准里是强制要求的。
(5)Test Reset Input (TRST)
TRST可以用来对TAP Controller进行复位(初始化)。不过这个信号接口在IEEE 1149.1标准里是可选的,并不是强制要求的。因为通过TMS也可以对TAP Controller进行复位(初始化)。
事实上,通过TAP接口,对数据寄存器(DR)进行访问的一般过程是: (1)通过指令寄存器(IR),选定一个需要访问的数据寄存器; (2)把选定的数据寄存器连接到TDI和TDO之间;
(3)由TCK驱动,通过TDI,把需要的数据输入到选定的数据寄存器当中去;同时把选定的数据寄存器中的数据通过TDO读出来。
接下来,让我们一起来了解一下TAP的状态机。TAP的状态机如图13所示,总共有16个状态。在图中,每个六边形表示一个状态,六边形中标有该状态的名称和标识代码。图中的箭头表示了TAP Controller内部所有可能的状态转换流程。状态的转换是由TMS控制的,所以在每个箭头上有标有tms = 0 或者 tms = 1。在TCK的驱动下,从当前状态到下一个状态的转换是由TMS信号决定。假设TAP Controller的当前状态为Select-DR-Scan,在TCK的驱动下,如果TMS = 0,TAP Controller进入Capture-DR状态;如果TMS = 1,TAP Controller进入Select-IR-Scan状态。
图13 TAP Controller State Transitions
这个状态机看似很复杂,其实理解以后会发现这个状态机其实很直接、很简单。观察图1,我们可以发现,除了Test-Logic Reset和Test-Run/Idle状态外,其他的状态有些类似。例如Select-DR-Scan和Select-IR-Scan对应,Capture-DR和Capture-IR对应,Shift-DR和Shift-IR对应,等等。在这些对应的状态中,DR表示Data Register,IR表示Instruction Register。记得我们前面说过吗,寄存器分为两大类,数据寄存器和指令寄存器。其实标识有DR的这些状态是用来访问数据寄存器的,而标识有IR的这些状态是用来访问指令寄存器的。
在详细描述整个状态机中的每一个状态之前,首先让我们来想一想:要通过边界扫描链来观察和控制芯片的输入和输出,需要做些什么?如果需要捕获芯片某个管脚上的输出,首先需要把该管脚上的输出装载到边界扫描链的寄存器单元里去,然后通过TDO输出,这样我们就可以从TDO上得到相应管脚上的输出信号。如果要在芯片的某个管脚上加载一个特定的信号,则首先需要通过TDI把期望的信号移位到与相应管脚相连的边界扫描链的寄存器单元里去,然后把该寄存器单元的值加载到相应的芯片管脚。下面,让我们一起来看看每个状态具体表示什么意思?完成什么功能?
(1)Test-Logic Reset
系统上电后,TAP Controller自动进入该状态。在该状态下,测试部分的逻辑电路全部被禁用,以保证芯片核心逻辑电路的正常工作。通过TRST信号也可以对测试逻辑电路进行复位,使得TAP Controller进入Test-Logic Reset状态。前面我们说过TRST是可选的一个信号接口,这是因为在TMS上连续加5个TCK脉冲宽度的“1”信号也可以对测试逻辑电路进行复位,使得TAP Controller进入Test-Logic Reset状态。所以,在不提供TRST信号的情况下,也不会产生影响。在该状态下,如果TMS一直保持为“1”,TAP Controller将保持在Test-Logic Reset状态下;如果TMS由“1”变为“0”(在TCK的上升沿触发),
将使TAP Controller进入Run-Test/Idle状态。
(2)Run-Test/Idle
这个是TAP Controller在不同操作间的一个中间状态。这个状态下的动作取决于当前指令寄存器中的指令。有些指令会在该状态下执行一定的操作,而有些指令在该状态下不需要执行任何操作。在该状态下,如果TMS一直保持为“0”,TAP Controller将一直保持在Run-Test/Idle状态下;如果TMS由“0”变为“1”(在TCK的上升沿触发),将使TAP Controller进入Select-DR-Scan状态。
(3)Select-DR-Scan
这是一个临时的中间状态。如果TMS为“0” (在TCK的上升沿触发),TAP Controller进入Capture-DR状态,后续的系列动作都将以数据寄存器作为操作对象;如果TMS为“1” (在TCK的上升沿触发),TAP Controller进入Select-IR-Scan状态。
(4)Capture-DR
当TAP Controller在这个状态中,在TCK的上升沿,芯片输出管脚上的信号将被“捕获”到与之对应的数据寄存器的各个单元中去。如果TMS为“0” (在TCK的上升沿触发),TAP Controller进入Shift-DR状态;如果TMS为“1” (在TCK的上升沿触发),TAP Controller进入Exit1-DR状态。
(5)Shift-DR
在这个状态中,由TCK驱动,每一个时钟周期,被连接在TDI和TDO之间的数据寄存器将从TDI接收一位数据,同时通过TDO输出一位数据。如果TMS为“0” (在TCK的上升沿触发),TAP Controller保持在Shift-DR状态; 如果TMS为“1” (在TCK的上升沿触发),TAP Controller进入到Exit1-DR状态。假设当前的数据寄存器的长度为4。如果TMS保持为0,那在4个TCK时钟周期后,该数据寄存器中原来的4位数据(一般是在Capture-DR状态中捕获的数据)将从TDO输出来;同时该数据寄存器中的每个寄存器单元中将分别获得从TDI输入的4位新数据。
(6)Update-DR
在Update-DR状态下,由TCK上升沿驱动,数据寄存器当中的数据将被加载到相应的芯片管脚上去,用以驱动芯片。在该状态下,如果TMS为“0”,TAP Controller将回到Run-Test/Idle状态;如果TMS为“1”,TAP Controller将进入Select-DR-Scan状态。
(7)Select-IR-Scan
这是一个临时的中间状态。如果TMS为“0” (在TCK的上升沿触发),TAP Controller进入Capture-IR状态,后续的系列动作都将以指令寄存器作为操作对象;如果TMS为“1” (在TCK的上升沿触发),TAP Controller进入Test-Logic Reset状态。
(8)Capture-IR
当TAP Controller在这个状态中,在TCK的上升沿,一个特定的逻辑序列将被装载到指令寄存器中去。如果TMS为“0” (在TCK的上升沿触发),TAP Controller进入Shift-IR状态;如果TMS为“1” (在TCK的上升沿触发),TAP Controller进入Exit1-IR状态。
(9)Shift-IR
在这个状态中,由TCK驱动,每一个时钟周期,被连接在TDI和TDO之间的指令寄存器将从TDI接收一位数据,同时通过TDO输出一位数据。如果TMS为“0” (在TCK的上升沿触发),TAP Controller保持在Shift-IR状态; 如果TMS为“1” (在TCK的上升沿触发),TAP Controller进入到Exit1-IR状态。假设指令寄存器的长度为4。如果TMS保持为0,那在4个TCK时钟周期后,指令寄存器中原来的4bit长的特定逻辑序列(在Capture-IR状态中捕获的特定逻辑序列)将从TDO输出来,该特定的逻辑序列可以用来判断操作是否正确;同时指令寄存器将获得从TDI输入的一个4bit长的新指令。
(10)Update-IR
在这个状态中,在Shift-IR状态下输入的新指令将被用来更新指令寄存器。 说了那么多,下面,让我们先看看指令寄存器和数据寄存器访问的一般过程,以便建立一个直观的概念。
①、系统上电,TAP Controller进入Test-Logic Reset状态,然后依次进入:Run-Test/Idle ", Select-DR-Scan ", Select-IR-Scan ", Capture-IR ", Shift-IR ", Exit1-IR ", Update-IR,最后回到Run-Test/Idle状态。在Capture-IR状态中,一个特定的逻辑序列被加载到指令寄存器当中;然后进入到Shift-IR
在Shift-IR状态下,通过TCK的驱动,可以将一条特定的指令送到指令寄存器当中去。每条指令都将确定一条相关的数据寄存器。然后从Shift-IR ", Exit1-IR ", Update-IR。在Update-IR状态,刚才输入到指令寄存器中的指令将用来更新指令寄存器。最后,进入到Run-Test/Idle状态,指令生效,完成对指令寄存器的访问。
②、当前可以访问的数据寄存器由指令寄存器中的当前指令决定。要访问由刚才的指令选定的数据寄存器,需要以Run-Test/Idle为起点,依次进入Select-DR-Scan ", Capture-DR ", Shift-DR ", Exit1-DR ", Update-DR,最后回到Run-Test/Idle状态。在这个过程当中,被当前指令选定的数据寄存器会被连接在TDI和TDO之间。通过TDI和TDO,就可以将新的数据加载到数据寄存器当中去,同时,也可以捕获数据寄存器中的数据。具体过程如下。在Capture-DR状态中,由TCK的驱动,芯片管脚上的输出信号会被“捕获”到相应的边界扫描寄存器单元中去。这样,当前的数据寄存器当中就记录了芯片相应管脚上的输出信号。接下来从Capture-DR进入到Shift-DR状态中去。在Shift-DR状态中,由TCK驱动,在每一个时钟周期内,一位新的数据可以通过TDI串行输入到数据寄存器当中去,同时,数据寄存器可以通过TDO串行输出一位先前捕获的数据。在经过与数据寄存器长度相同的时钟周期后,就可以完成新信号的输入和捕获数据的输出。接下来通过Exit1-DR状态进入到Update-DR状态。在Update-DR状态中,数据寄存器中的新数据被加载到与数据寄存器的每个寄存器单元相连的芯片管脚上去。最后,回到Run-Test/Idle状态,完成对数据寄存器的访问。
上面描述的就是通过TAP对数据寄存器进行访问的一般流程。会不会还是觉得很抽象?让我们来看一个更直观的例子。现在假设,TAP Controller现在处在Run-Test/Idle状态,指令寄存器当中已经成功的写入了一条新的指令,该指令选定的是一条长度为6的边界扫描链。下面让我们来看看实际如何来访问这条边界扫描链。图14所示的是测试芯片及其被当前指令选定的长度为6的边界扫描链。由图14可以看出,当前选择的边界扫描链由6个边界扫描移位寄存器单元组成,并且被连接在TDI和TDO之间。TCK时钟信号与每个边界扫描移位寄存器单元相连。每个时钟周期可以驱动边界扫描链的数据由TDI到TDO的方向移动一位,这样,新的数据可以通过TDI输入一位,边界扫描链的数据可以通过TDO输出一位。经
过6个时钟周期,就可以完全更新边界扫描链里的数据,而且可以将边界扫描链里捕获的6位数据通过TDO全部移出来。
图14 测试芯片及其当前选定的边界扫描链
图14表示了边界扫描链的访问过程。图15.1 表示了芯片和边界扫描链的初始化状态,在测试状态下,芯片的外部输入和输出被隔离开了,芯片的输入和输出可以通过相应的边界扫描链来观察和控制。在图15.1中,扫描链里的每个移位寄存器单元的数据是不确定的,所以在图中用X表示,整个扫描链里的数据序列是XXXXXX。要从TDI输入到测试芯片上的数据序列是:101010. 同时要从TDO得到芯片相应管脚上的状态。现在TAP Controller从Run-Test/Idle状态经过Select-DR-Scan状态进入到Capture-DR状态,在Capture-DR状态当中,在一个TCK时钟的驱动下,芯片管脚上的信号状态全部被捕获到相应的边界扫描移位寄存器单元当中去,如图15.2所示。从图15.2中我们可以看出,在进入Capture-DR状态后,经过一个TCK时钟周期,现在扫描链中的数据序列变成了:111000. 在数据捕获完成以后,从Capture-DR状态进入到Shift-DR状态。在Shift-DR状态中,我们将通过6个TCK时钟周期来把新的数据序列(101010)通过TDI输入到边界扫描链当中去;同时,将边界扫描链中捕获的数据序列(111000)通过TDO输出来。在进入到Shift-DR状态后,每经过一个TCK时钟驱动,边界扫描链从TDO输出一位数据;同时,从TDI接收一位新的数据。图15.3所示的是在Shift-DR状态下,1个TCK时钟周期后的扫描链的变化。图15.4所示的是在Shift-DR状态下,2个TCK时钟周期后的扫描链的变化。此时,扫描链已经从TDI串行得到了两位新数据,从TDO也串行输出了两位数据。在TCK时钟的驱动下,这个过程一直继续下去。图15.5所示的是在经过6个TCK时钟周期以后扫描链的情况。从图15.5中我们可以看到:边界扫描链当中已经包含了新的数据序列:101010. 在TDO端,经过6个TCK时钟驱动以后,也接收到了在Capture-DR状态下捕获到的数据序列:111000. 到目前为止,虽然扫描链当中包含了新的数据序列:101010,但测试芯片的管脚上的状态还是保持为:111000. 下一步,需要更新测试芯片相应管脚上的信号状态。要实现更新,TAP Controller从Shift-DR
状态,经过Exit1-DR状态,进入到Update-DR状态。在Update-DR状态中,经过一个周期的TCK时钟驱动,边界扫描链中的新数据序列将被加载到测试芯片的相应管脚上去,如图15.6所示。从图16.6可以看出,测试芯片的状态已经被更新,相应管脚上的状态序列已经从111000变为101010. 最后从Update-DR状态回到Run-Test/Idle状态,完成对选定的边界扫描链的访问。
(1)初始化状态
(2)CAPTURE-DR
(3)SHIFT-DR + 1 TCK
(4)SHIFT-DR + 2 TCK
(5)SHIFT-DR + 6 TCK
(6)UPDATE-DR 图15 边界扫描链的访问过程
在看完上面这个例子以后,对TAP Controller的状态机应该大概了解了吧?对如何访问边界扫描链应该也有个直观的概念了吧?虽然上面的这个例子只是说明了如何访问边界扫描链,对其它的数据寄存器、指令寄存器的访问过程也是类似的。要实现对指令寄存器的访问,不同的是TAP Controller必须经过不同的状态序列:Run-Test/Idle ",
Select-DR-Scan ", Select-IR-Scan ", Capture-IR ", Shift-IR ", Exit1-IR ", Update-IR ", Run-Test/Idle.
4.2.3 指令寄存器、公共指令以及数据寄存器
在IEEE 1149.1标准当中,规定了一些指令寄存器、公共指令和相关的一些数据寄存器。对于特定的芯片而言,芯片厂商都一般都会在IEEE 1149.1标准的基础上,扩充一些私有的指令和数据寄存器,以帮助在开发过程中进行进行方便的测试和调试。在这一部分,我将简单介绍IEEE 1149.1规定的一些常用的指令及其相关的寄存器。与ARM7TDMI相关的私有指令和寄存器将在后面的部分专门介绍。
(1)指令寄存器:
指令寄存器允许特定的指令被装载到指令寄存器当中,用来选择需要执行的测试,或者选择需要访问的测试数据寄存器。每个支持JTAG调试的芯片必须包含一个指令寄存器。
(2)BYPASS指令和Bypass寄存器:
Bypass寄存器是一个一位的移位寄存器,通过BYPASS指令,可以将bypass寄存器连接到TDI和TDO之间。在不需要进行任何测试的时候,将bypass寄存器连接在TDI和TDO之间,在TDI和TDO之间提供一条长度最短的串行路径。这样允许测试数据可以快速的通过当前的芯片送到开发板上别的芯片上去。
(3)IDCODE指令和Device Identification 寄存器:
Device identification寄存器中可以包括生产厂商的信息,部件号码,和器件的版本信息等。使用IDCODE指令,就可以通过TAP来确定器件的这些相关信息。例如,ARM MULTI-ICE可以自动识别当前调试的是什么片子,其实就是通过IDCODE指令访问Device Identification寄存器来获取的。
(4)INTEST指令和Boundary-Scan 寄存器:
Boundary-Scan寄存器就是我们前面例子中说到的边界扫描链。通过边界扫描链,可以进行部件间的连通性测试。当然,更重要的是可以对测试器件的输入输出进行观测和控制,以达到测试器件的内部逻辑的目的。INTEST指令是在IEEE 1149.1标准里面定义的一条很重要的指令:结合边界扫描链,该指令允许对开发板上器件的系统逻辑进行内部测试。在ARM JTAG调试当中,这是一条频繁使用的测试指令。
我们前面说过,寄存器分为两大类:指令寄存器和数据寄存器。在上面提到的Bypass寄存器、Device Identification寄存器和Boundary-scan寄存器(边界扫描链),都属于数据寄存器。在调试当中,边界扫描寄存器(边界扫描链)最重要,使用的也最为频繁。 4.3 ARM7TDMI 调试构架
在这个小节里,我将介绍一下ARM7TIMI的调试构架,让大家对ARM7TDMI JTAG调有个大概的认识。细节问题将在下一小节中介绍。
ARM7TDMI典型的调试系统结构如图16所示。一个调试系统一般包括三个部分:调试主机、协议转换器和调试目标。
调试主机一般是一台运行调试软件(例如ADS)的计算机。调试主机可以发出一些高层的调试命令,例如设置断点、访问内存等。协议转换器(例如MULTI-ICE),用来将调试主
机发出的高层调试命令转换为底层的ARM JTAG调试命令。调试目标一般就是指基于ARM7TDMI内核MCU目标开发板。经过协议转换器进行命令解释,主机上运行的调试软件就可以通过JTAG接口直接和ARM7TDMI内核对话。通过扫描链,可以把ARM/THUMB指令插入到ARM7TDMI的指令流水线当中去执行。通过插入特定ARM/THUMB指令,我们可以检查、保存或者改变内核和系统的状态。为了支持底层的调试,ARM7TDMI处理器提供了硬件上的扩展,。这些调试扩展包括:
(1)停止程序的运行
(2)检查和修改ARM7TDMI的内核状态 (3)观察和修改内存 (4)恢复程序的运行
图16 ARM7TDMI典型的系统调试结构
ARM7TDMI处理器的结构框图如下图所示:
图17. ARM7TDMI 处理器结构框图
从图17可以看到,ARM7TDMI处理器主要包括三大部分:
(1)ARM CPU Main Processor Logic
这部分包括了对调试的硬件支持; (2)Embedded ICE-RT Logic
这部分包括了一组寄存器和比较器,用来产生调试异常、设置断点和观察点; (3)TAP Controller
TAP Controller通过JTAG接口来控制和操作扫描链。
从图17,我们可以发现ARM7TDMI提供了4条扫描链:Scan Chain 0, 1, 2 & 3. (1)Scan Chain 0
通过扫描链0可以访问ARM7TDMI内核的外围电路,包括数据总线。通过该扫描链可以进行芯片间的测试(EXTEST)和芯片的内部测试(INTEST)。该扫描链长度为113位,具体包括:数据总线的0-31位,内核控制信号,地址总线的31-0位,EmbeddedICE-RT的控制信号。
(2)Scan Chain 1
扫描链1是扫描链0的子集,长度为33位,具体包括:数据总线的0
-31位、BREAKPT信号。扫描链1比扫描链0的长度短了很多,通过扫描链1可以更快的插入指令或者是数据到ARM7TDMI的内部。
(3)Scan Chain 2
扫描链2长度为38位,该扫描链是专门用来访问EmbeddedICE-RT内部的寄存器。通过访问EmbeddedICE-RT的内部寄存器,可以让ARM7TDMI进入调试状态、设置断点、设置观察点。
(4)Scan Chain 3
通过扫描链3,ARM7TDMI可以访问外部的边界扫描链。该扫描链用的很少,在此就不介绍了,想了解的网友可以参考ARM7TDMI手册。
在实际的调试过程中,扫描链1和扫描链2用的最多。基本上所有的调试动作都是通过这两条扫描链来完成的。
ARM7TDMI还提供了3个附加的信号:DBGRQ、DBGACK和BREAKPT. 这3个信号都被EmbeddedICE-RT控制,可以用来使得处理器从正常的运行状态进入调试状态或从调试状态返回到正常的运行状态。
(1)DBGREQ
调试请求,通过把DBGREQ置“1”,可以迫使ARM7TDMI进入调试状态。 (2)DBGACK
调试确认,通过DBGACK,可以判断当前ARM7TDMI是否在调试状态。 (3)BREAKPT
断点信号,这个信号是输入到ARM7TDMI处理器内核的。如果BREAKPT被置“1”,当前的内存访问被设置为断点。如果当前的内存访问是取指令的话,当该指令被执行的时候,
ARM7TDMI处理器自动进入调试状态;如果当前的内存访问是存取数据的话,在存储完成以后,ARM7TDMI处理器自动进入调试状态。 4.4 ARM7TDMI 调试原理
在这个小节里,我将详细介绍ARM7TIMI的调试原理,并对一些比较感兴趣的问题进行讨论。例如,如何设置断点?如何让ARM7TDMI进入调试状态? 在调试状态下,如何访问ARM7TDMI的内部寄存器?如何访问内存单元?
在继续之前,看看ARM7TDMI的正常运行状态和调试状态的区别。在正常运行状态下,ARM7TDMI由MCLK(Memory Clock)驱动,正常运行。在调试状态下,ARM7TDMI的正常运行被打断,并且和系统的其它部分隔离开来。在调试状态下,我们可以通过插入特定的ARM/THUMB的指令来读写ARM7TDMI的内部寄存器和修改内存的内容。在调试状态下,ARM7TDMI由内部的调试时钟DCLK(Debug Clock)驱动。DCLK比MCLK慢很多,所以在调试状态下,插入的ARM/THUMB指令的运行速度会比较慢(现对而言)。在完成需要的操作后,可以用RESTART JTAG指令让ARM7TDMI返回到正常运行状态,恢复原来的运行。 4.4.1 ARM7TDMI的指令寄存器及常用JTAG指令
ARM7TDMI的指令寄存器长度是4位,通过TAP和JTAG接口,可以把指令装载到指令寄存器当中去。在CAPTURE-IR状态下,固定值B0001总是被装载到指令寄存器当中去。在SHIFT-IR状态中,可以把ARM7TDMI支持的新指令从TDI串行输入,同时固定值B0001会从TDO串行输出。通过这个输出的固定值,可以判断当前的操作是否正确。在UPDATE-IR状态,新输入的指令被装载到指令寄存器当中去。最后回到RUN-TEST/IDLE状态后,新指令立即生效。
下面先来看看在ARM7TDMI调试当中经常用到的几条JTAG指令。
(1)IDCODE
该指令的二进制代码是1110。IDCODE指令将Device Identification Code寄存器连接到TDI和TDO之间。Device Identification Code寄存器的长度是32位,通过TAP就可以将ARM7TDMI的ID给读出来。ARM7TDMI的ID是0x1F0F0F0F. 在CAPTURE-DR状态下,器件的ID被捕获到ID寄存器里面。在SHIFT-DR状态下,先前捕获的ID通过TDO位移出来,总共需要32个TCK时钟周期。在UPDATE-DR状态下,ID寄存器不受任何影响。
(2)SCAN_N
该指令的二进制代码是0010。ARM7TDMI提供了4条扫描链,通过SCAN_N指令可以选择需要访问的扫描链。一般来说,需要访问Embedded ICE-RT的寄存器时,选择扫描链2;需要插入指令到ARM7TDMI内核去执行的时候,选择扫描链1。选择扫描链的过程如下:先把SCAN_N指令装载到指令寄存器当中去,该指令会将长度为4位的扫描链选择寄存器连接到TDI和TDO之间;然后进入到CAPTURE-DR状态,在这个状态下,固定值B1000将被捕获到扫描链选择寄存器当中去;在SHIFT-DR状态下,将需要选择的扫描链的号码通过TDI输入到扫描链选择寄存器当中去;在UPDATE-DR状态下,被选择的扫描链将被连接到TDI和TDO之间。在TAP被复位以后,默认状态下选择的是扫描链3。在使用SCAN_N选定了一条扫描链后,当前选定的扫描链会一直保持不变,直到在下一次调用SCAN_N选择另外的扫描链。
(3)BYPASS
该指令的二进制代码是1111。BYPASS指令将1-BIT 长的BYPASS寄存器连接到TDI和TDO之间。
(4)INTEST
该指令的二进制代码是1100。INTEST指令将通过SCAN_N选定的扫描链置于内部测试模式。
(5)RESTART
该指令的二进制代码是0100。RESTART指令用来使ARM7TDMI处理器从调试状态退回到正常的运行状态。
4.4.2 EmbeddedICE-RT Logic
在这个小节里,主要介绍通过扫描链2来访问EmbeddedICE-RT内部的寄存器。EmbeddedICE-RT内部包括了丰富的寄存器,通过这些寄存器,可以控制ARM7TDMI进入或者退出调试状态;可以设置断点和观察点。
先来看看EmbeddedICE-RT包括那些寄存器,下面这个表里罗列了EmbeddedICE-RT中包含的所有寄存器。不同的寄存器有不同的长度,而且被分配了一个长度为5的地址。其中Debug Control Register用来控制EmbeddedICE-RT;通过Debug Status Register可以查询当前系统的状态;Abort Status Register用来确定异常的产生原因:断点、观察点还是真的异常;Debug Comms Control Register和Debug Comms Data Register是用来控制和操作Debug Communication Channel的;后面的所有寄存器都是关于WATCH POINT的,设置断点和观察点就是通过设置这些寄存器来实现的。后面我将逐一的进行介绍。
表2. Mapping of EmbeddedICE-RT Registers
要访问EmbeddedICE-RT内部的寄存器,必须通过扫描链2来实现。扫描链的长度是38位,其中0-4位用来标识要访问的寄存器的5位宽的地址;5-36位为数据位;第37位用来标识对当前寄存器进行读操作还是写操作。如果是对当前寄存器进行写操作,5-36的数据位用来标识需要写入到寄存器的数据;如果对当前寄存器进行读操作,5-36的数据位用来存储从寄存器中读出的数据。假设我们现在想访问Debug Control Register,对其进行写操作,首先需要选择扫描链2,将其连接到TDI和TDO之间,然后通过扫描链2对Debug Control Register进行访问。其过程如下所述。通过TAP将SCAN_N指令写入到指令寄存器当中去, TAP状态转换如下:RUN-TEST/IDLE ", SELECT-DR-SCAN ", SELECT-IR-SCAN ", CAPTURE-IR ", SHIFT-IR ", EXIT1-IR ", UPDATE-IR ", RUN-TEST/IDLE,在SHIFT-IR状态下,将SCAN_N通过TDI写到指令寄存器中去;接下来,访问被SCAN_N指令连接到TDI和TDO直接的扫描链选择寄存器,通过将2写入到扫描链选择寄存器当中去,以将扫描链2连接到TDI和TDO之间,TAP状态转换过程如下:RUN-TEST/IDLE ", SELECT-DR-SCAN ", CAPTURE-DR ", SHIFT-DR ", EXIT1-DR ", UPDATE-DR ", RUN-TEST/IDLE,在SHIFT-DR状态下,将数值2通过TDI写到扫描链选择寄存器当中去。在通过扫描链2访问任何EmbeddedICE-RT内部寄存器之前,我们还需要用INTEST 指令将当前通过SCAN_N指令选择的扫描链置内部测试状态。写入INTEST指令的过程和写入SCAN_N指令的过程类似。在此就不多说了。好,至此,我们已经选择了扫描链2,并且将它置于内部测试状态。接下来,我们就可以通过扫描链2访问EmbeddedICE-RT内部寄存器了。下面,以写Debug Control Register为例,看看怎样实现访问。假设要将Debug Control Register的6位全部置“1”,按照扫描链2的格式,需要写入到扫描链2第序列应该为:
1,0000,0000,0000,0000,0000,0000,0011,1111,00000
在上面这个长度为38位的序列当中,低5位红色标识的数列是Debug Control Register的地址;最高位蓝色标识的1表示对Debug Control Register进行写操作;中间黑色表示的32位是要写入到Debug Control Register的数据,因为Debug Control Register长度为6,所以只有低6为的数据序列111111有效。要将上面长度为38位的序列写入到扫描链2中,TAP状态转换过程如下:RUN-TEST/IDLE ", SELECT-DR-SCAN ", CAPTURE-DR ", SHIFT-DR ", EXIT1-DR ", UPDATE-DR ", RUN-TEST/IDLE。在SHIFT-DR状态下,通过38个TCK时钟驱动,就可以将上面的序列串行输入到扫描练2当中去。在回到RUN-TEST/IDLE状态后,Debug Control Register的值就会被改写为111111。
我们已经知道如何访问EmbeddedICE-RT的内部寄存器了,下面让我们一起来了解了解各个寄存器的作用。
(1)Debug Control Register
从该寄存器的名称可以看出,该寄存器是用来控制调试的。下面这个表是Debug Control寄存器的格式。
DBGACK,用来控制DBGACK信号的值,通过Debug Control寄存器,可以设置DBGACK的值。个人的感觉是,不要人为的去设置这个值,让EmbeddedICE-RT自动控制。DBGRQ,是调试请求信号,通过将该信号置“1”,可以强制ARM7TDMI暂停当前的指令,进入调试状态。INTDIS用来控制中断。SBZ/RAZ任何时候都必须被置“0”。Monitor Mode Enable用来控
制是否进入Monitor模式,我没有用过这个控制位,按我个人的理解,该模式在调试当中一般不会用到。EmbeddedICE-RT Disable,很明显,这个控制位用来控制整个EmbeddedICE-RT,是启用还是禁用。如果禁用的话,ARM7TDMI将一直保持在正常的运行状态。总结一下,通过Debug Control寄存器,可以强制让ARM7TDMI进入调试状态。这是第一种让ARM7TDMI进入调试状态的方法,另外,也可以通过断点或者是观察点来进入调试状态,每当设置的断点或者观察点被触发后,ARM7TDMI自动进入调试状态。在我们调试的时候,第一步一般都是先用DBGRQ信号使得ARM7TDMI进入调试状态,然后将我们需要调试的程序装载到内存里去,接着在需要的地方设置断点和观察点,开始调试(单步运行、全速运行、让断点或者观察点触发)。
(2)Debug Status Register
从该寄存器的名称可以看出,该寄存器是用来保存当前低调试状态的。虽然参手册上说该寄存器可读可写,不过建议对该寄存器只进行读操作。该寄存器的长度位5,格式如下:
DBGACK信号用来标识当前系统是否处于调试状态,当ARM7TDMI进入调试状态后,该信号会被自动置“1”。所以,通过查询该位,就可以判断ARM7TDMI当前的状态。DBGRQ信号用来标识DBGRQ信号的当前状态,要设置DBGRQ信号请访问Debug Control寄存器。IFEN用来标识系统的中断控制状态:启用还是禁用?cgenL,可以用来判断当前对调试器(DEBUGGER)在调试状态下对内存的访问是否完成。
TBIT,该位用来判断ARM7TDMI是从ARM状态还是THUMB状态进入到调试状态的。 (3)Abort Status Register
该寄存器的长度为1,该寄存器用来判断一个异常的产生的原因:断点触发?观察点触发?还是一个真的异常?
(4)Watch Point 0/1 Address Value/Mask Register
Watch Point 0/1 Data Value/Mask Register Watch Point 0/1 Control Value/Mask Register
关于WATCH POINT的 6个寄存器,因为联系比较紧密,我在这里对这6个寄存器一并介绍。ARM7TDMI有两组WATCH POINT寄存器,所以总共有12个寄存器,在这里我只介绍其中的一组,另外一组的功能完全是一样的。看看上面提到的6个寄存器,其实是3对寄存器,其中3个是Value寄存器,另外3个是Mask寄存器,通过Mask寄存器的设置,可以屏蔽相应的Value寄存器的某些或全部数据位,在比较的时候不予以考虑。WP Address Value/Mask是用来监控地址总线的,WP Data Value/Mask是用来监控数据总线的。每组寄存器都与一个比较器相联系,该比较器的比较结果决定了断点条件是否满足。每次对存储空间进行访问,Watch Point的比较器都会判断当前访问的地址和WP Address Value寄存器的中的地址是否匹配?该地址中的数据和WP Data Value寄存器中的数据是否匹配? 如果地址和数据同时都匹配,BREAKPT信号会被置1,当前的内存访问被设置为断点。如果当前的内存访问是取指令的话,当该指令被执行的时候,ARM7TDMI处理器自动进入调试状态;如果当前的内存访问是存取数据的话,在存储完成以后,ARM7TDMI处理器自动进入调试状态。通过相应的MASK寄存器,可以使得比较器的使用很灵活。例如,我们只考虑地址是否匹配,可将WP Data Mask寄存器的值设置为:0xFFFFFFFF. 这样的话,数据部分总是被认为是匹配的,是
实际上起作用的就是地址和WP Address Value寄存器的值是否匹配;反过来,如果我们只希望考虑数据是否匹配,而不考虑地址是否匹配,可以将WP Address Mask寄存器的值设置为0xFFFFFFFF.
这样的话,地址部分总是被认为是匹配的,实际上起作用的就是数据和WP Data Value寄存器的值是否匹配。另外一个寄存器,WP Control Value/Mask是用来控制该组的WP寄存器的,同时提供些附加的比较条件(信息)。下面逐一介绍。
(5)WP Control Value/Mask Register
WP Control Value寄存器的长度为9位,WP Control Mask寄存器的长度为8位,因为WP Control Value寄存器的最高位是用来控制启用/禁止WP功能的,该位不可以被屏蔽。WP Control Mask寄存器的作用和前面的两种MASK寄存器的作用类似,这里不多说了。下面具体看看WP Control Value寄存器,其格式如下:
ENABLE: 如果该位置0的话,意味着断点触发条件永远不成立,也就是把全部断点都给disable掉了;
RANGE: 暂时不会用,呵呵; CHAIN: 暂时不会用,呵呵;
EXTERN: 外部到EmbeddedICE-RT的输入,通过该输入,可以使得断点的触发依赖于一定的外部条件;
nTRANS: 用来判断是在用户态下还是非用户态下,用户态下:nTRANS = 0,否则nTRANS = 1;
nOPC: 检测当前的周期是取指令还是进行数据访问;
MAS[1:0]: 和ARM7TDMI的MAS[1:0]信号进行比较,以探测当前总线的宽度是8位、16位还是32位;
nRW: nRW = 0, 当前的是读周期,nRW = 1,当前的是写周期。
在WP Control Value寄存器中用的比较多的是nPOC,用来区分当前的是一个取指令周期,还是普通的数据访问周期。断点和观察点是不一样的。断点用来标识某个地址上的一条指令,如果要将一个WATCH POINT寄存器组用作断点设置,首先需要置WP Control Value寄存器的nPOC位为0,用来表示:只有在当前的周期是进行取指令的前提下,才触发断点。观察点用来观察某个地址上的数据变化的,如果要将一个WATCH POINT寄存器组用作观察点使用,首先需要置WP Control Value寄存器的nPOC位为1,用来表示:只有在当前的周期是进行普通的数据访问的前提下,才触发观察点。
(6)WP Address Value/Mask Register和硬件断点
断点是用来标识某个地址上的指令的,所以要将一个WATCH POINT用作断点设置,首先需要将WP Control Value寄存器的nPOC位置0,用来表示:只有在当前的周期是进行取指令的条件下,才触发断点。要在一个地址设置一个断点,可以通过WP Address Value/Mask这两个寄存器来实现。假设,要在地址0x0040设置一个断点,可以将WP Address Value寄存器的值设置为0x0040,同时将WP Address Mask寄存器的值设置为0x0。另外,将WP Data
Mask设置为0xFFFFFFFF,这样可以屏蔽掉WP Data value寄存器的影响,在进行比较的时候,只考虑地址是否匹配。这样,每次ARM7TDMI从地址0x0040取指令的话,不管该指令是什么,断点就会被触发,ARM7TDMI会暂停当前的运行,自动进入调试状态,要清除该断点的话,只要改变WP Address Value寄存器的值,或者设置WP Control Value寄存器,禁止该功能。如果你想在所有地址的低16位的值为0x0040的地方设置断点,可以配合使用WP Address Mask寄存器,将它的值设置为0xFFFF,0000,这样的话,每次比较的时候,高16为的地址就会被屏蔽掉。其实这种使用方式应该是比较少的,比较多的情况是,屏蔽掉最低2位或者最低1位的地址。在ARM状态下,因为ARM指令的长度是32位的,所有指令地址的最低2位必须为0,所以,如果在ARM状态下,一般将WP Address Mask的低2位置1,在进行地址比较的时候,屏蔽掉地址低最低2位,确保断点是被设置在正确的地址上;如果类似,如果是在THUMB状态下,一般需要将WP Address Mask的最低1位置1。上面描述的是第一种设置断点的方式,这种方式是通过地址比较来实现断点的。这也是我们常说的硬件断点,这类断点可以被设置在任何地址(包括FLASH和SDRAM)。因为ARM7TDMI提供了两组WP Address Value/Mask寄存器,所以,可以支持两个硬件断点。下面让我们来看看断点的另外一种实现方式。
(7)WP Data Value/Mask Register和软件断点
在调试过程当中,通过WP Data Value/Mask寄存器也可以实现断点设置。利用WP Data Value/Mask如何实现断点设置呢? 和硬件断点的设置一样,首先需要将WP Control Value寄存器的nPOC位置0,用来表示:只有在当前的周期是进行取指令的条件下,才触发断点。 然后,将WP Address Mask寄存器的值设置为:0xFFFFFFFF, 这样可以屏蔽掉WP Address value寄存器的影响,在进行比较的时候,只考虑数据是否匹配。接下来,将WP Data Value寄存器的值设置为一个固定的值,例如:0xDEDEDEDE,将WP Data Mask寄存器的值设置为0x00000000。在需要设置断点的地方,将其内容替换为0xDEDEDEDE。这样,一但程序运行到该位置,尝试从该位置取指令或者数据的时候,因为取得的数据值和WP Data Value寄存器的值相同,ARM7TDMI会暂停当前的运行,自动进入调试状态。要清除该位置上的断点,我们只需要将该位置原来的指令恢复就可以了。这样,退出调试状态后,程序可以继续正常的运行。通过WP Data Value/Mask寄存器,我们可以在任何需要设置断点的地方,将其内容替换为一个固定的序列,就可以达到设置断点的目的。这种断点就是我们通常所说的软件断点。软件断点的设置方式使得ARM7TDMI可以支持任意数量的软件断点。但也决定了软件断点的局限性:软件断点不能设置在ROM/FLASH里面。因为软件断点的实现需要替换要设置断点的位置的内容,这点在ROM/FLASH做不到。(虽然从某种意义上来说,FLASH也是可读写的,但是需要特殊的指令)。
(8)WP Address Value/Mask Register和观察点
WP Data Value/Mask Register也可以用来设置观察点,用以观察某个地址的数据变化。每当系统访问(读写)完在被观察的地址的数据的时候,ARM7TDMI就会进入调试状态,这样,我们就可以马上检查该地址上的数据。要设置一个观察点,将WP Address Value寄存器的值设置为需要观察的数据的地址,将WP Address Mask寄存器的值设置为0x00000000,将WP Data Mask寄存器的值设置为0xFFFFFFFF。同时不要忘记设置WP Control Value寄存器:nPOC = 1(数据访问,而非取指令);还可以设置nRW,表示是对读操作进行观察,还是对写操作进行观察;另外,也可以通过MAS[1:0]设置合适的数据宽度(8位、16位、32位)。如果希望WP Control Value寄存器的某些位不起作用,可以恰当的设置WP Control Mask寄存器。例如,如果希望对读操作和写操作都进行观察,那么就可以设置WP Control
Mask寄存器的第0位为1。
在这一小节里,我们介绍了如何通过扫描链2访问EmbeddedICE-RT的内部寄存器以及EmbeddedICE-RT的内部寄存器的作用。同时我们还介绍了通过EmbeddedICE-RT内部寄存器使ARM7TDMI进入调试状态的3种方式:控制DBGRQ信号、断点、观察点。要使得ARM7TDMI推出调试状态,可以使用RESTART JTAG指令。
4.4.3 通过扫描链1访问ARM7TDMI的通用寄存器和系统存储空间
在这个小节里,我们将讨论如何通过边界扫描链1来访问处于调试状态的ARM7TDMI. 这个小节的所有讨论都基于这样的一个默认条件:ARM7TDMI已经进入到调试状态(DBGRQ、断点、观察点)。除非明确指出,否则都默认为ARM7TDMI处于调试状态。
边界扫描链1分布在ARM7TDMI的32数据总线周围,另外包括BREAKPT信号,总长度为33位。其扫描寄存器单元的分布如下表所示:
通过边界扫描链1的前32位,我们可以插入THUMB/ARM指令(不是JTAG指令)到ARM7TDMI的指令流水线当中去,让ARM7TDMI在DCLK的驱动下,执行这些指令。通过这种方式,我们可以检查和修改ARM7TDMI的通用寄存器和系统内存。为什么通过扫描链可以将指令插入到ARM7TDMI的流水线当中去? 可以访问ARM7TDMI的内部同意寄存器?这从边界扫描链1的结构可以得到答案。边界扫描链分布在ARM7TDMI32位数据总线的周围,每次ARM7TDMI取指令或者进行数据存储,都要通过32位数据总线进行。这样,通过边界扫描链1,就可以插入新指令或者新数据,同时也可以捕获出现在数据总线上的数据。在调试状态下,ARM7TDMI支持如下的这些指令:数据处理指令、load, store, load multiple, and store multiple指令、MSR,MRS指令。扫描链1中的第33位,BREAKPT输入,在调试过程当中有很重要的作用,主要体现在:
在ARM7TDMI刚进入调试状态的时候,通过读取该位的值,可以判断进入调试状态的原
因:如果BREAKPT = 0, 由断点触发;如果BREAKPT = 1, 由观察点触发。
在调试的时候,ARM7TDMI允许特定的指令以系统速度执行,由MCLK驱动。这是通过边
界扫描链1的BREAKPT位来完成的。如果BREAKPT置0,意味着下一条指令以调试速度执行(DCLK驱动);如果BREAKPT置1,意味着下一条指令以系统速度执行(MCLK驱动)。当执行到被标识为以系统速度执行的指令时,ARM7TDMI会同步于MCLK,由MCLK驱动该指令的执
行,在执行完毕后,ARM7TDMI会重新回到调试状态,后面的执行重新由DCLK驱动。关于扫描链1的BREAKPT的具体使用方式,在后面我会结合具体例子进行说明。
ARM7TDMI采用的是3级流水线,指令的执行分为3个阶段(如图18所示): (1)Fetch 取指令,从内存中取指令;
(2)Decode 译指令,解析指令中需要用到的寄存器; (3)Execute 执行指令。
图18 ARM7TDMI指令流水线
在插入ARM指令前,先通过JTAG指令SCAN_N选择边界扫描链1,并用JTAG指令INTEST将边界扫描链1置于INTEST状态。接下来,就可以通过JTAG接口将需要的指令或者数据放到ARM7TDMI 32位数据总线 (边界扫描链1) 上去。插入指令/数据的过程如下:TAP Controller的状态变化如下:RUN-TEST/IDLE ", SELECT-DR-SCAN ", CAPTURE-DR ", SHIFT-DR ", EXIT1-DR ", UPDATE-DR ", RUN-TEST/IDLE。在CAPTURE-DR状态下,可以通过边界扫描链1捕获ARM7TDMI 32位数据总线上的数据。在SHIFT-DR状态下,通过33个TCK时钟驱动,就可以将32位长的新指令或者需要的数据加上BREAKPT输入到扫描链1当中去。同时,在CAPTURE-DR状态下捕获的数据总线上的数据也可以通过TDO输出。到UPDATE-DR状态下,输入的指令/数据就会被放到32位的数据总线上去。回到RUN-TEST/IDLE状态后,插入的指令/数据会在DCLK的驱动下执行。另外提醒一点,因为扫描链1的第一位对应于D[0],而在将指令插入前将整个指令+BREAKPT共33位序列的比特顺序颠倒过来。这样,通过TDI先送入的是BREAKPT,然后是指令的第31位、30位、29位 ? 第0位。
下面,通过几个具体的例子,来看看如何通过插入ARM指令/数据来访问ARM7TDMI的内部通用寄存器和系统内存。
(1)读取通用寄存器R0的值:
要读取寄存器R0的值,可以用指令STR R0, [R0] = 0xE5800000来实现。该指令将寄存器R0的值存储到内存单元R0中去。因为在ARM7TDMI处于调试状态的时候,ARM7TDMI和外部是隔离开来的,所以该指令实际上不能访问内存单元,也不会对内存单元产生任何影响。使用指令STR R0, [R0] 的目的是使得寄存器R0的值出现在数据总线上,这样我们就可以通过扫描链1将其捕获,然后从TDO输出。指令STR R0, [R0]的执行需要2个指令执行周期(CYCLE)。在第1个指令执行周期,执行地址计算;在第2个指令执行周期,将寄存器R0的值放到数据总线上去。要读取寄存器R0的值,对边界扫描链1的操作过程如下(在下面描述的每一个步骤,TAP状态都是从RUN-TEST/IDLE状态出发,最后回到RUN-TEST/IDLE状态):
? 插入指令STR R0, [R0] & BREAKPT = 0:
——这步相当于指令STR R0, [R0]的取指令周期(3级流水线); ? 插入空指令MOV R0, R0 & BREAKPT = 0:
——这一步读取新指令MOV R0, R0,同时,相当于指令STR R0, [R0]的译指令周期(3
级流水线);
? 插入空指令MOV R0, R0 & BREAKPT = 0:
——这一步读取新指令MOV R0, R0,同时,插入的STR R0, [R0]指令开始执行(3级流水线)。在这一步,STR R0, [R0]指令处在第1个指令执行周期,在该周期,先执行地址计算;
? 通过扫描链1读出捕获的数据总线上的数据:
——在这一步,指令STR R0, [R0]继续执行,指令STR R0, [R0]处在第2个指令执行周期。在这一步,寄存器R0的值会被放到数据总线上去,指令STR R0, [R0]执行完毕。所以,在这一步,从扫描链中读出的数据就是寄存器R0的值。另外,在这一步,因为还处在STR R0, [R0]的指令执行周期内,所以访问扫描链1的时候,通过TDI输入的空指令实际上是会被ARM7TDMI忽略。
至此,我们成功获得寄存器R0的值。因为除了STR R0, [R0] 指令外,插入的另外2条指令都是空指令,所以后面我们可以不考虑这2条指令的执行结果。
(2)修改通用寄存器R0的值:
要修改寄存器R0的值,可以用指令LDR R0, [R0] = 0xE5900000来实现。该指令将内存单元 R0的值存储到寄存器R0中去。因为在ARM7TDMI处于调试状态的时候,ARM7TDMI和外部是隔离开来的,所以该指令实际上不能访问内存单元,也不会对内存单元产生任何影响。使用指令LDR R0, [R0] 的目的是:该指令要从内存单元R0中取数据放到数据总线上去,这样我们就可以通过扫描链1将任意需要的值放到数据总线上去,达到修改寄存器R0的目的。指令LDR R0, [R0]的执行需要3个指令执行周期(CYCLE)。在第1个指令执行周期,执行地址计算;在第2个指令执行周期,从内存单元R0中读取数据,并将数据放到数据总线上去;在第3个指令执行周期,将数据总线上的数据写到寄存器R0中去。要修改寄存器R0的值,对边界扫描链1的操作过程如下(在下面描述的每一个步骤,TAP状态都是从RUN-TEST/IDLE状态出发,最后回到RUN-TEST/IDLE状态):
? 插入指令LDR R0, [R0]& BREAKPT = 0:
——这步相当于指令LDR R0, [R0]的取指令周期(3级流水线);
", 插入空指令MOV R0, R0 & BREAKPT = 0: - 这一步读取新指令MOV R0, R0,同时,相当于指令LDR R0, [R0]的译指令周期(3级流水线);
? 插入空指令MOV R0, R0 & BREAKPT = 0:
——这一步读取新指令MOV R0, R0,同时,插入的LDR R0, [R0]指令开始执行(3级流水线)。在这一步,LDR R0, [R0]指令处在第1个指令执行周期,在该周期,先执行地址计算;
? 通过扫描链1将寄存器R0的新值放到数据总线上:
——在这一步,指令LDR R0, [R0]继续执行,LDR R0, [R0]指令处在第2个指令执行周期。在这一步,通过扫描链1,将R0的新值放到数据总线上去。对ARM7TDMI而言,相当于从系统内存中取得了所需的数据。
? 插入空指令MOV R0, R0 & BREAKPT = 0:
——在这一步,指令LDR R0, [R0]继续执行,指令LDR R0, [R0]处在第3个指令执行周期。在这一步,数据总线上的数据写到寄存器R0中去,完成对寄存器R0的修改,指令LDR R0, [R0]执行完毕。另外,在这一步,因为还处在LDR R0, [R0]的指令执行周期内,所以访问扫描链1的时候,通过TDI输入的空指令实际上是会被ARM7TDMI忽略。
至此,我们成功修改了寄存器R0的值。因为除了STR R0, [R0] 指令外,插入的另外2条指令都是空指令,所以后面我们可以不考虑这2条指令的执行结果。
(3)读内存:
在前面说过,当ARM7TDMI处于调试状态的时候,不能访问系统的存储空间,这是因为
在调试状态下,指令的执行是由DCLK驱动的。而对存储空间(内存)的访问需要MCLK的驱动。那在调试状态下,如何实现对存储空间的访问呢?这个时候,边界扫描链1的BREAKPT位就派上用场了。在通过扫描链1插入一条指令的时候,如果将BREAKPT位置1,意味这条指令的下面一条指令将在MCLK的驱动下执行,执行完毕后,自动返回调试状态。这样,通过扫描链1的BREAKPT位,我们就可以实现对系统存储空间的访问。让我们来看看要读取内存地址ADDR上的32位数据的大概步骤。首先,我们将要访问的地址ADDR写到寄存器R0当中去;然后用指令LDR R1, [R0]将地址ADDR处的32位长的数据拷贝到寄存器R1当中去;最后,将寄存器R1的值读出来,就得到了存储空间地址ADDR处的值。修改寄存器R0的值和读取寄存器R1的值的步骤在前面都详细介绍了,在下面,我只介绍结合BREAKPT如何用指令LDR R1, [R0] 来真正的访问系统存储空间,将地址R0处的内容拷贝到寄存器R1当中去。具体过程如下(在下面描述的每一个步骤,TAP状态都是从RUN-TEST/IDLE状态出发,最后回到RUN-TEST/IDLE状态):
? 插入空指令MOV R0, R0 & BREAKPT = 1:
——首先插入一条空指令,该指令的主要目的是将扫描链1的BREAKPT信号置1。这样,这条空指令的下一条指令将在MCLK的驱动下,回到正常状态下运行。
? 插入指令LDR R1, [R0]& BREAKPT = 0:
——因为上一条指令将扫描链1的BREAKPT置1了,所以,这条指令将在MCLK的驱动下,回到正常的系统状态下去执行;
? 将JTAG RESTART指令插入到ARM7TDMI的JTAG指令寄存器当中去:
——将RESTART插入到JTAG指令寄存器当中去有几个作用。一是,使ARM7TDMI重新同步于MCLK信号;二是,使刚才插入的指令LDR R1, [R0]在系统正常状态下,在MCLK的驱动下执行;三是,在系系统正常状态下执行完指令LDR R1, [R0]后,使ARM7TDMI自动返回到调试状态下;
在将RESTART写入到JTAG指令寄存器,并且在TAP Controller回到RUN-TEST/IDLE状态后,ARM7TDMI将会暂时返回到正常的运行状态。在正常的运行状态下,ARM7TDMI将以系统速度(MCLK驱动)完成指令LDR R1, [R0]的执行。执行完毕后,ARM7TDMI将自动返回
到调试状态。这样,寄存器R1中就已经有了地址ADDR处数值的一个拷贝了。最后需要做的就是通过前面介绍的方法,在调试状态下,将R1的值读出来。在需要访问内存的时候,需要注意的就是扫描链1中BREAKPT位的设置,以及JTAG RESTART指令的使用。
(4)写内存:
修改内存的过程和读取内存的过程类似,大概步骤如下:将内存地址ADDR写到寄存器R0当中去,将新的值写到寄存器R1当中去,最后利用指令STR R1 [R0]完成实际的内存访问。在将指令STR R1 [R0] 插入插入到扫描链0之前前,将扫描链1的BREAKPT位置1,以使得关键指令STR R1 [R0] 能在MCLK的驱动下,回到正常的系统状态下去执行,以便能正常访问系统存储。
在这个小节里,我们主要介绍了通过边界扫描链1如何访问ARM7TDMI的通用寄存器和系统存储空间。在我们的讨论当中,为了简单起见,我们使用了最简单的LDR和STR指令。在实际的调试过程中,可以使用LDM和STM指令,这样一次可以读写多个寄存器或者是多个地址上的数据,提高效率。从上面的讨论可以看出,在调试状态下,每次对通用寄存器和系统存储系统进行访问都需用多条指令来实现。每次插入一条指令到扫描链1中去,都需要33个TCK时钟周期。因为并口的速率限制,通过并口进行调试时,速度会比较的慢。如果使用USB接口或者网络接口,调试的速度将能够获得很大的提升。
五 实验过程
1
超级终端的建立
思考:建立超级终端的目的是什么?
(1)、运行Windows 系统下的超级终端(HyperTerminal)应用程序,新建一个通信终端(请见图19)。如图20所示,如果要求输入区号、电话号码等信息请随意输入;出现如图21所示对话框时,为所建超级终端取名为arm(也可以选择其它的名字),可以为其选一个图标,单击“确定”按钮。
请大家注意:在windows xp操作系统下,当初次建立超级终端的时候,会出现如下对话框:
图19 可能的选择
图20 创建超级终端
图21 创建超级终端
(2)、在接下来的对话框中选择ARM 开发平台实际连接的PC 机串口(如COM1)如图22所示,按确定后出现如图23所示的属性对话框,设置通信的格式和协议。这里波特率为115200,数据位8,无奇偶校验,停止位1,无数据流控制。按确定完成设置。
图22 创建超级终端
图23 创建超级终端
(3)、完成新建超级终端的设置以后,可以选择超级终端文件菜单中的保存,将当前设置保存为一个特定超级终端到桌面上,以备后用。用串口线将PC 机串口和平台UART0 正确连接后,就可以在超级终端上看到程序输出的信息了
2 JTAG安装过程
JTAG(Joint Test Action Group;联合测试行动小组)是一种国际标准测试协议(IEEE 1149.1兼容),主要用于芯片内部测试。现在多数的高级器件都支持JTAG协议,如DSP、FPGA器件等。标准的JTAG接口是4线:TMS、TCK、TDI、TDO,分别为模式选择、时钟、数据输
入和数据输出线。
JTAG最初是用来对芯片进行测试的,基本原理是在器件内部定义一个TAP(Test Access Port;测试访问口)通过专用的JTAG测试工具对进行内部节点进行测试。JTAG测试允许多个器件通过JTAG接口串联在一起,形成一个JTAG链,能实现对各个器件分别测试。现在,JTAG接口还常用于实现ISP(In-System Programmable;在线编程),对FLASH等器件进行编程。
JTAG编程方式是在线编程,传统生产流程中先对芯片进行预编程实现再装到板上因此而改变,简化的流程为先固定器件到电路板上,再用JTAG编程,从而大大加快工程进度。JTAG接口可对PSD芯片内部的所有部件进行编程. 在本实验将要利用JTAG多加载引导程序vivi进行烧写,所以必须安装其驱动。
具体步骤如下:
图24 创建超级终端
(1)连接电源,将5V电源线的连到UP-NETARM2410-S的电源接口;连接串口线,一端连接PC的串口,另一端连接到UP-NETARM2410-S的串口(上面的);
(2)把并口线插到pc机的并口,并把并口与JTAG相连,JTAG与开发板的14针JTAG口相连,打开2410-S电源.
(3)把整个GIVEIO目录拷贝到C:\\WINDOWS下,并把该目录下的giveio.sys文件拷贝到c:/windows/system32/drivers下。
(4)在控制面板里,选添加硬件>下一步>选-是我已经连接了此硬件>下一步>选中-添加新的硬件设备>下一步>选中安装我手动从列表选择的硬件>下一步>选择-显示所有设备>选择-从磁盘安装-浏览,指定驱动为C:\\WINDOWS\\GIVEIO\\giveio.inf文件,点击确定,安装好驱动。
3 利用JTAG烧写vivi
Bootloader (引导装载器)是用于初始化目标板硬件,给嵌入式操作系统提供板上硬件
资源信息,并进一步装载、引导嵌入式操作系统运行的固件。简单地说,bootloader就是在操作系统内核运行前运行地一段小程序。通过这段小程序,我们可以初始化必要的硬件设备,创建内核需要的一些信息并将这些信息通过相关机制传递给内核,从而将系统的软硬件环境带到一个合适的状态,最终调用操作系统内核,真正起到引导和加载内核的作用。在嵌入式系统开发过程中, Bootloader的编写往往是设计的主要难点。目前,Bootloader的开发通常都是基于一些开源的Bootloader(如vivi、U- Boot、Blob、ARMBoot、RedBoot等)而设计,它们在设计思路上有许多相通之处。
vivi是当前比较流行的,专门针对ARM9处理器而设计的一款Bootloader,它操作简便,同时提供了完备的命令体系。vivi是由韩国Mizi公司开发的一种Bootloader,适合于ARM9处理器,支持S3C2410x处理器,其源代码可以在http://www.mizi.com网站下载。和所有的Bootloader一样,vivi有两种工作模式,即启动加载模式和下载模式。当vivi处于下载模式时, 它为用户提供一个命令行接口,通过该接口能使用vivi提供的一些命令集。
下面利用JTAG烧写vivi的具体步骤(同时见图25-图27):
在d盘新建一目录bootloader,把sjf2410-s和要烧写的vivi拷贝到该目录下,在程序-附件-msdos下,进入该目录,运行sjf2410-s命令如下:sjf2410-s /f:vivi。在此后出现的三次要求输入参数,第一次是让选择Flash,选0;第二次是选择jtag对flash的两种功能,也选0;第三次是让选择起始地址,选0;此后就等待大约3-5分钟的烧写时间,当VIVI 烧写完毕后选择参数2,退出烧写。
图25 烧写vivi
图26 烧写vivi
图27 烧写vivi
4 映象文件(image)下载
(1) 关闭2410-S电源,拔出JTAG;打开超级终端,先按住PC机“Space”键,然
后启动2410-S电源,进入vivi>
图28 image下载
(2) 按照以下命令重新分区:
vivi>bon part 0 128k 192k 1216k 4288k:m 64704k(64M flash1208)
图29 image下载
回车后,超级终端会出现如下分区信息,并检查是否有坏的块。
图30 image下载
(3)耐心等待片刻,等检查完flash内是否有坏块后,会在超级终端出现提示符,如下图所示。
图31 image下载
(4)在提示符号下输入:part save,回车保存好分区.
图32 image下载
(5)在vivi>后键入load flash vivi x 回车,点击超级终端“传送”下拉菜单,选择”发送文件”,把引导程序vivi下载到vivi分区,保证系统掉电后还能再引导。
图33 image下载
图34 image下载
图35 image下载
(6)在vivi>后键入load flash ucos x 然后回车。
图36 image下载
(7)然后打开超级终端上方的“传送”菜单并选择发送文件,如图37 所示,点击浏览按键,查找并进入到编译生成的映象文件夹下,打开system.bin.然后在发送文件对话框中的协议栏选择Xmodem,最后选择发送。
图37 image下载
(8)发送结束后,映象文件即下载到flash 中,然后,如图38 键入bootucos 命令再回车即可运行该镜像image程序。(请大家观察LCD或者听歌)
图38 image下载
(9)摁键盘“Space”键,然后摁一下2410-s上的复位按钮,重新启动,按照(6)、(7)的方法下载另外一个image文件执行。
(10)关掉2410-s的电源,摁键盘“Space”键,然后开2410-s的电源,看vivi能否启动?
问题思考:
①、重作3和4(4中略去(5)步),看会出现什么情况?这是为什么呢? ②、作3和4中的(1),然后键入:help,并回车,了解bootloader程序vivi的命令。以理解本实验操作意义。
③、本实验用的image文件是什么呢?它是怎么产生的呢?
5 额外实验
(1) 把实验用的ARM程序“Exp11 绘图的API函数”放在D盘,打开该目录,观察
其有哪些文件夹和文件。其中, Exp11 为工程文件。
图39 image生成
(2) 如果PC机安装了ARM集成开发环境ADS1.2,那么双击工程文Exp11就会打开
该工程(Project),如图40所示。其中生成目标Release生成的映象文件不包括调试信息;生成目标Debug生成的映象文件包括了所有的调试信息。点击菜单“Project”下的“make”选项,便生成了工程项目
图40 image生成
图41 image生成
(3)在文件夹Exp11_data下的Release 和Debug目录就可以分别找到包含调试信息和包含调试信息的映像文件system.bin。大家可以尝试把映像文件通过超级终端下载到目标机上执行。
图42 image生成
图43 image生成
图44 image生成
六 进一步阅读
具体ADS1.2的用法请参考在线帮助文档与《ARM体系结构与编程》第13章。 由于我们实验箱用的是S3C2410芯片,请大家查阅其Datasheet了解这款具体芯片的组成。
七 实验报告完成
我们围绕《串口通信》,加上开发环境的熟悉,大家完成《串口通信》实验报告一份。
正在阅读:
上海高一信息科技基本知识点整理(精华)08-15
幼儿园膳食工作计划范文5篇.doc04-27
2014-2015年上海市浦东新区第四教育署初二下学期期中数学05-16
工程项目管理10-14
2022年医师定期考核临床专业知识考试题库及答案(共五套)04-16
关于恩施市社区去行政化的调研04-02
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 实验
- 嵌入式
- 熟悉
- 图文
- 环境
- 开发
- ARM
- 备战2016高考2015年高考英语全国新课标卷(II)评析及2016高考英语
- 2007年高考数学试题及答案(山东理)
- 年产1200吨新型建筑材料添加剂项目可行性研究报告 - 图文
- 普通话等级复习资料:容易读错的字
- 数字影音后期制作项目 - 图文
- 法院法警队党风廉政建设自查报告2篇
- 数据结构复习资料--覆盖所有知识点
- 加热炉安全应急预案
- 宣城市2015届高三第二次调研测试高三文科综合试题 - 图文
- CAD实验报告
- 实验4 数据库的简单查询和连接查询实验
- 文件加密管理系统
- (黄冈专版)2018年七年级语文上册周周清6新人教版
- 王建:货币流动性过剩之谜待解
- 普通生物学2014真题
- 苯酚/丙酮国内外市场分析与技术进展
- 企业公司员工福利组织规章与办法汇总
- 谚语百谈
- 如何对待学生的告状
- 生命属于我们只有一次教学设计