将 851 应用程序迁移到 ARM Cortex-M 处理器上 作者 :Joseph Yiu 和 Andrew Frame Cortex-M 处理器系列包括广泛使用的 Cortex-M3 处理器 针对 FPGA 的 Cortex-M1 处理器 29 年初推出的 Cortex-M 处理器 ( 最小的 ARM 处理器 ) 和 21 年初推出的 Cor tex-m4 处理器 ( 支持浮点和数字信号处理增强指令 ) 这些处理器具有先进的功能特点和简单易用的编程模型, 对于想从 851 微控制器迁移到 ARM 架构的开发人员来说, 极具吸引力 本文是一篇入门指南, 目的是帮助 851 微控制器的开发人员了解 851 和 A R M C or tex-m 处理器系列在架构 软件和硬件设计上的主要差异, 从而加快迁移过程 架构概述对于一些嵌入式程序员 ( 尤其是那些习惯使用汇编语言编程的程序员 ), 首先要做的事情就是了解编程模型 寄存器 ARM Cortex-M 处理器具有一个 32 位寄存器库和一个 xpsr( 组合程序状态寄存器 ) 而 851 具有 ACC( 累加器 ) B DPTR( 数 的 RISC 架构, 处理器寄存器加载数据, 然后将数据传给 ALU 进行单周期执行 而 851 寄存器 (ACC B PSW SP 和 DPTR) 可在 SFR( 特殊功能寄存器 ) 的内存空间中访问 据指针 ) PSW( 处理器状态字 ) 和四个各含八个寄存器的寄存 器库 (R-R7) Registers in Cortex-M 为了确保普通的 C 函数能够用 R Processor status 作中断处理程序, 在需要处 Registers in 851 R1 APSR EPSR IPSR 理中断时,Cor tex-m 的寄存 R2 ACC B DPH DPL R3 xpsr 器 (R - R 3 R12 L R P C 和 PSW SP R4 xpsr) 会被自动压入堆栈, 而软 DPTR R5 件仅需在必要时将其他寄存器 R6 PRIMASK Bank R R1 R2 R3 R4 R5 R6 R7 R7 Interrupt 压入堆栈 虽然 851 具有 4 个寄 Masking Bank 1 R R1 R2 R3 R4 R5 R6 R7 R8 BASEPRI R9 Registers 存器库, 但是 ACC B DPTR 和 Bank 2 R R1 R2 R3 R4 R5 R6 R7 R1 FAULTMASK PSW 寄存器并不会自动压栈, 因 Bank 3 R R1 R2 R3 R4 R5 R6 R7 R11 Cortex-M3/M4 only 此通常需要通过中断处理程序 R12 对这些寄存器进行软件压栈 R13 (SP) R14 (LR) R15 (PC) 在 851 中, 一些指令会频繁使用某些寄存器, 如 ACC 和 DPTR 这种相关性会极大降低系统的性能, 而在 ARM 处理器中, 指令可 36 使用不同的寄存器来进行数据处理 内存存取和用作内存指针, 因此不会有这个问题 从根本上说,ARM 架构是一个基于加载 (Load) 和存储 (Store) CONTROL 内存空间 ARM 处理器具有 32 位寻址, 可实现一个 4GB 的线性内存空间 该内存空间在结构上分成多个区 每个区都有各自的推荐用法 ( 虽
xffffffff xe System region System components (NVIC) debug components xa x6 x4 x2 x Device region RAM region Peripheral region SRAM region CODE region Off chip peripherals Off chip memory peripherals SRAM Program flash xff x7f x Internal Memory Space Internal RAM (indirect addressing) Internal RAM Register banks Special Function Registers (SFR) (direct addressing) External Memory Space 64k byte program memory (Instruction accesses, MOVC accesses) 64k byte data memory (MOVX accesses) Memory Map in the ARM Cortex-M processors Memory Map in the 851 microcontrollers 然并不是固定的 ) 统一内存架构不仅增加了内存使用的灵活性, 而且降低了不同内存空间使用不同数据类型的复杂性 相反地,851 微控制器具有多个内存空间 内存空间的分割使得有效地利用全部内存空间变得困难, 而且需要借助 C 语言扩展来处理不同的内存类型 851 在外部 RAM 内存空间上最高支持 64KB 的程序内存和 64KB 的数据内存 理论上, 可以利用内存分页来扩展程序内存大小 不过, 内存分页解决方案并未标准化, 换句话说, 不同 851 供应商的内存分页的实现并不相同 这不仅会增加软件开发的复杂性, 而且由于处理页面切换所需的软件开销, 还会显著降低软件性能 在 ARM Cortex-M3 或 M4 上,SRAM 区和外设区都提供了一个 1MB 的位段区 (bit band region) 此位段区允许通过别名地址访问其内部的每个位 由于位段别名地址只需通过普通的内存存取指令即可访问, 因此 C 语言完全可以支持, 不需要任何特殊指令 而 851 提供了少量的位寻址内存 ( 内部 RAM 上 字节和 SFR 空间上 字节 ) 处理这些位数据需要特殊指令, 而要支持此功能,C 编译器中需要 C 语言扩展 ARM Cortex-M 处理器的内存映射包含多个内置外设块 例如,ARM Cortex-M 处理器的一个特性是具有一个嵌套矢量中断控制器 (NVIC) 此外, 系统区中内存映射有数个指定控制寄存器和调试组件, 以确保优异的中断处理并极大方便开发人员使用 堆栈内存堆栈内存操作是内存架构的重要组成部分 在 851 中, 堆栈指针只有 8 位, 同时堆栈位于内部的内存空间 ( 上限为 256 个字节, 并 由工作寄存器 ( 四个各由 R 至 R7 构成的寄存器库 ) 和内部数据变量共享 ) 堆栈操作基于空递增模型 xff SP current value N SP initial value x8 x Last stacked item at N -1 Register banks 与 851 不同的是,ARM Cortex-M 处理器使用系统内存作为堆栈, 采用满递减模型 SP current value N SP initial value determine by first word in vector table x Last stacked item at N Vector table 满递减堆栈内存模型更受 C 语言的支持 例如, 微控制器中的 SRAM 的使用可组织为 : 使用动态分配内存空间的 C 库和应用程序通常需要堆内存 尽管 C ortex-m 处理器的每次压栈需要 32 位的堆栈内存, 总 PUSH ACC xff SP new value N+ 1 Stacking in 851 PUSH R x SP new value N - 4 Stacking in ARM Cortex -M processor xffffffff x Stack New stacked item at N Register banks Heap Static data New stacked item at N - 4 Vector table RAM 37 RAM usage in ARM Cortex -M
的 RAM 使用仍然要比 851 小 851 的变量通常是静态地放在 IDATA 上, 而 ARM 处理的局部变量是放在堆栈内存上的, 因此, 只有当函数执行的时候, 局部变量才会占用 RAM 空间 此外,ARM Cortex-M 处理器提供有第二个堆栈指针, 以允许操作系统内核和进程堆栈使用不同的堆栈内存 这使得操作更可靠, 也使操作系统设计更高效 ( 堆栈指针切换是自动处理的 ) x43) /* define base address */ SomePeripheral->register2 = x3; /* Set register #2 to x3 */ 由于 ARM 处理器中外设总线协议的特性, 外设寄存器通常定义为 32 位, 即使只会用到其中几位 此外, 外设寄存器的地址是字对齐的 例如, 如果外设位于地址 x4 处, 那么对应外设寄存器的地址就是 x4 x44 和 x48 等 某些运行在主系统总线上的外设没有这个限制 外设 851 中的很多外设是通过特殊功能寄存器 (SFR) 来控制的 由于 SFR 空间只有 128 个字节, 而且其中一些已经为处理器寄存器和标准外设所占用, 剩余的 SFR 地址空间通常非常有限, 因此也就限制了可通过 SFR 控制的外设数量 虽然可以通过外部内存空间来控制外设, 但是与 SFR 存取相比, 外部存取通常需要更多的开销 ( 需要将地址复制到 DPTR, 数据必须通过 ACC 传输 ) xff x7f x Internal Memory Space Internal RAM (indirect addressing) Internal RAM Register banks Special Function Registers (SFR) (direct addressing) 851 Peripherals 在 ARM Cortex-M 处理器中, 所有外设都是内存映射的 由于所有寄存器都可用作指针或数据访问中的数据值, 因此效率非常高 在 C 语言中, 访问外设地址的一个简单方法就是使用指针, 如 : (*((volatile unsigned long *)(LED_ADDRESS))) = xff; // Output to LED ReceviedData = (*((volatile unsigned long *)(IO_INPUT_ADDRESS))); // Read from IO 此外, 您可以声明外设块的数据结构 使用数据结构, 程序代码只需要存储外设的基址, 而且每个寄存器访问可以利用带有立即数偏移量的加载或存储指令来执行, 因此效率会得到提高 例如, 具有四个寄存器的外设可以定义为 : typedef struct { volatile unsigned long register; volatile unsigned long register1; volatile unsigned long register2; volatile unsigned long register3; SomePeripheral_Type; #define SomePeripheral ((SomePeripheral_Type *) 异常 851 支持具有两个可编程优先级的矢量中断 一些较新的 851 支持四个级别和稍多的中断源 它们也支持嵌套中断 当中断发生时, 程序会保存返回地址, 然后跳转到矢量表中的固定地址 矢量表通常包含有另一个分支指令, 以便跳转至中断服务程序的实际开始位置 示例 : Interrupt sources In 851 Timer 2 UART Timer 1 Int1 Timer Int Vector table in 851 x2b x23 x1b x13 xb x3 x LJMP tim2_isr LJMP uart_isr LJMP tim1_isr LJMP int1_isr LJMP tim_isr LJMP int_isr LJMP reset Vector table in ARM Cortex-M x4 x Interrupt vectors System vectors NMI vector Reset vector Initial MSP 进入中断服务程序时, 需要通过软件代码将 PSW( 也可能包括 ACC 和 DPTR 等 ) 压入堆栈并切换寄存器库 ARM Cortex-M 处理器的中断处理由嵌套矢量中断控制器 (NVIC) 提供 NVIC 紧密地耦合到处理器内核, 支持矢量中断和嵌套中断 此外, 它还支持更多中断源 :Cortex-M/M1 支持最多 32 个 IRQ,Cortex-M3 支持最多 24 个 IRQ Cortex-M/M1 支持 4 个可编程优先级, 而 Cortex-M3 则支持 8 至 256 个级别, 具体数目视实现情况而定 ( 通常为 8 或 个级别 ) 与 851 不同的是,ARM Cortex-M 处理器的矢量表存储的是异常处理程序的开始地址 此外,Cortex-M 处理器支持 NMI ( 非屏蔽中断 ) 和一些系统异常 系统异常包括特别针对操作系统的异常类型和用于检测非法操作的故障处理异常 这些功能都是 851 上所没有的 851 中的中断服务程序需要通过 R E TI 指令来终止, 该指令与用于标准函数的 RET 指令不同 在 ARM Cortex-M 中, 中断服务程 38
序与普通的 C 函数完全相同 异常机制使用异常进入期间 LR 中生成的特殊返回地址代码来检测异常返回 软件简单了解架构情况后, 我们现在来讨论软件代码的移植 在很多情况下, 针对 851 编写的 C 代码需要进行大量的修改 很显然, 内存映射和外设驱动代码是不同的 除此之外, 我们还需要特别注意其他一些地方 : 指针 或者, 如果你正在使用 ARM RealView 编译器或 KEIL MDK- ARM, 那么可以使用编译器特有的位段功能 attribute ((bitband)) --bitband command line option 有关此功能的更多详细信息, 请参阅 ARM RealView 编译器用户指南 或 Keil 在线文档 数据类型 851 和 ARM 处理器的数据类型有一些差异 由于数据大小不同, 如果程序代码依赖于数据大小或溢出行为, 不做修改可能会无法工作 下表所示为常见数据类型的大小, 具体视编译器而定 这里是指 851 的 KEIL C 编译器和 ARM RealView 编译器 ( 也适用于 KEIL RealView 微控制器开发套件 ) Type char, unsigned char enum short, unsigned short int, unsigned int long, unsigned long Number of bits in 851 8 数据类型大小不同的另一个影响是在 ROM 中保留常数数据所需的大小 例如, 如果 851 程序中包含一个整数型常数数组, 那么你需要修改代码, 将该数组定义为短整型常数 否则, 代码长度可能会因为该数组从 位变成 32 位而增加 由于 851 架构的特性,851 的 C 编译器还支持一些数据类型和内存类型扩展 这些数据类型在 ARM 处理器上是不受支持的 示例 : 32 对于外设地址, 您可以按照前文所述将 SFR 数据类型替换为易失性内存指针 由于 851 指令集的特性,SFR 地址是硬编码在指令中的 在 ARM 微控制器中, 您可以将外设的寄存器定义为内存指针, 并将寄存器作为数据结构或数组来访问 这要比 851 灵活很多 浮点由于 851 的处理能力限制, 大 8 多数 851 C 编译器会将 双 8//32 (smallest is 精度 数据类型 (64 位 ) 作为 chosen) 单精度 (32 位 ) 来处理 而在 ARM 处理器中使用相同代码 32 时,C 编译器将使用双精度, 32 因此程序行为可能会发生变化 例如, 如果您只需要单精度, 就需要对以下从 Whetstone 中提取的代码进行修改 : X=T*atan(T2*sin(X)*cos(X)/(cos(X+Y)+cos(X-Y)-1.)); /* double precision on ARM*/ Y=T*atan(T2*sin(Y)*cos(Y)/(cos(X+Y)+cos(X-Y)-1.)); 对于单精度运算, 代码需要更改为 : X=T*atanf(T2*sinf(X)*cosf(X)/(cosf(X+Y)+cosf(X-Y)-1.F)); /* single precision on ARM*/ Y=T*atanf(T2*sinf(Y)*cosf(Y)/(cosf(X+Y)+cosf(X-Y)-1.F)); Number of bits in ARM Type bit sbit sfr sfr idata xdata bdata Description Bit addressable memory in x2 to x3c Bit addressable memory in SFR space Special Function Register -bit Special Function Register Specify data is in internal data memory Specify data is in external data memory Specify data is in bit addressable memory Cortex-M3 处理器的用户可以使用位段区来管理位数据 由于位段允许利用位段别名地址通过普通的内存存取指令来访问位数据, 因此可以将位数据声明为指向位段别名地址的内存 Number of bits 1 1 8 对于不需要双精度精确度的应用程序, 将代码更改为单精度能够提高性能以及缩短代码长度 中断处理程序为了使 851 C 编译器为中断处理程序产生正确的代码, 需要用到一些函数扩展 这可确保函数使用 RETI( 而非 RET) 来返回并确保将所有用到的寄存器保存到堆栈中 在 851 的 KEIL C 编译器中, 这是通过 interrupt 扩展来实现的 示例 : 39
void timer_isr (void) interrupt 1 { /* 851 timer ISR */ return; 在 ARM Cortex-M 处理器中, 中断服务程序被作为普通的 C 函数那样来编译 因此, 可以去掉 interrupt 扩展 在 AR M RealView 编译器中, 你也可以添加 irq 关键词来加以说明 示例 : irq void timer_isr (void) { /* ARM timer ISR */ return; 851 编译器的另一 C 扩展用于指定所使用的寄存器库 示例 : void timer_isr (void) interrupt 1 using 2 { /* use register bank #2 */ return; 同样,ARM 处理器不需要此扩展, 可以将其删除 可重入函数对于 851, 普通的 C 函数无法用作可重入函数 这是因为局部变量是静态的, 如果重入函数, 局部变量可能会遭到损坏 为了解决此问题, 一些 851 C 编译器支持 reentrant 扩展 例如, 使用 KEIL 851 C 编译器时, 可以将函数声明为 : void foo (void) reentrant { return; ARM 处理器的局部变量存储在堆栈中, 重入普通函数并不会出现问题, 因此可以删除 reentrant 扩展 非对齐数据在 ARM 微控制器编程中, 数据变量的地址通常必须是对齐地址 换句话说, 变量 X 的地址应该是 sizeof(x) 的倍数 例如, 字变量的地址最低两位应该是零 ARM Cortex-M/M1 要求数据对齐 Cortex-M3 处理器支持非对齐数据访问, 然而 C 编译器通常不会生成非对齐数据 如果数据不对齐, 那么访问数据将需要更多的总线周期, 因为 AMBA AHB LITE 总线标准 ( 在 Cortex-M 处理器中使用 ) 不支持非对齐数据 访问非对齐数据时, 总线接口必须将其拆分成数个对齐传输 在使用不同大小的元素来创建数据结构时, 你可能会尝试各元素的不同排列方式使该数据结构所需的内存最少 例如, 像下面这样的结构 : struct sample { short field1; // 2 bytes Int field2; // 4 bytes char field3; // 1 byte Int field4; // 4 bytes ; 通过重新排列结构中的元素, 可以使该结构所需的内存减小 : struct sample { short field1; // 2 bytes char field3; // 1 byte Int field2; // 4 bytes Int field4; // 4 bytes ; Address Address Memory layout field4 field2 field1 Memory layout field3 field 4 field 2 field1 field3 由于 Cortex-M/M1 不支持非对齐数据处理, 如果应用程序尝试使用非对齐传输, 会触发故障异常 C 程序通常不会产生非对齐传输, 但如果你手动安排 C 指针的位置, 就可以生成非对齐数据, 并导致 Cortex-M/M1 的故障异常 Cortex-M3 可以配置异常陷阱来检测非对齐传输, 从而强制非对齐传输生成故障异常 故障异常 ARM 处理器和 851 之间的一个主要差别在于,ARM 处理器通过故障异常来处理错误事件 内存或外设可能会发生错误 ( 总线错误响应 ), 检测到异常操作时, 处理器内部也可能会发生错误 ( 如无效指令 ) 错误检测功能有助于构建可靠的系统 常见故障包括 : - 内存 ( 数据或指令 ) 访问无效内存空间 - 无效指令 ( 例如指令内存损坏 ) - 不允许的操作 ( 例如尝试切换到 ARM 指令集, 而非 Thumb 指令集 ) - 违反 MPU 内存访问权限 ( 非特权程序尝试访问特权地址 ) 在 Cortex-M/M1 处理器中, 检测到任何错误时, 都将使用称为硬故障的异常类型 硬故障处理程序的优先级要高于除 NMI 之外的其他异常 您可以使用此异常来报告错误, 或者在必要时复位系统 4
Cortex-M3 处理器中有两个级别的错误处理程序 当错误发生时, 如果已启用第一级错误处理程序, 并且这些处理程序的优先级高于当前的执行级别, 就执行这些处理程序 如果未启用第一级错误处理程序, 或者这些处理程序的优先级并不高于当前的执行级别, 就调用第二级错误异常, 即硬故障异常 Error Bus fault Usage fault Memory Management Fault Escalation of faults Hard fault 此外,Cortex-M3 处理器包含有数个故障状态寄存器, 用于对故障进行诊断 对于 Cortex-M/M1, 由于进入硬故障异常时会将数个核心寄存器 ( 如 PC 和 PSR) 压入堆栈, 因此可通过堆栈跟踪获取基本调试信息 设备驱动程序和 CMSIS 微控制器厂商会以设备驱动程序库的形式提供很多外设控制程序代码 这类代码可显著缩短软件开发时间 即使你不直接使用该设备驱动程序代码, 它也可为设置和控制各种外设提供颇具价值的参考 在一些 ARM 微控制器厂商提供的设备驱动程序中包含 CMSIS (C o r tex 微控制器软件接口标准 ) CMSIS 是用于 Cortex-M 处理器的一套函数和定义 这些函数和定义是多个厂商共同采用的标准, 它使得在不同 Cortex-M 微控制器之间移植软件变得更容易 CMSIS 由以下内容组成 : - 寄存器定义, 包括 NVIC 中断控制 系统控制块 ( 用于处理器控制 ) SysTick 定时器 ( 用于嵌入式操作系统的 24 位减法计数器 ) - 一些用于 NVIC 中断控制的函数 - 一些实现处理器核心功能的函数 - 标准化的系统初始化函数例如, 如果希望禁用或启用所用中断, 你可以使用 CMSIS 函数 disable_irq 和 e n a b l e _ i r q 借助 CMSIS, 此代码可以在不同的 Cortex-M 微控制器上使用, 并且得到了 A R M 开发工具 (ARM RealView 开发套件和 KEIL MDK-ARM) GCC( 如 CodeSourcey G++) 和 IAR C 编译器的支持 此外,CMSIS 包含一些隐含函数, 让你可以产生一些特殊指令, 这些指令无法用普通 C 代码由 C 编译器来产生 例如, 您可以使用隐含函数来访问特殊寄存器和创建独占访问 ( 对于 Cortex-M3 的多处理器编程 ) 等 同样,CMSIS 使得所开发的软件可以在多个 C 编译器产品之间进行移植 CMSIS 对所有 Cortex-M 开发人员都非常重要, 尤其是那些为多个项目开发嵌入式操作系统 中间件和可重用嵌入式软件的人员 CMSIS 包含在微控制器厂商提供的设备驱动程序中, 也可以从 www.onarm.com 网站下载 混用 C 语言和汇编程序大多数情况下, 您可以完全用 C 语言来编写 Cortex-M 应用程序 即使你需要访问一些 C 编译器无法通过普通 C 代码生成的特殊指令, 也可以使用 CMSIS 提供的隐含函数, 或者根据需要在应用程序中使用汇编语言 您可以在单独的汇编程序文件中编写汇编代码, 也可以使用 C 编译器的特定方法将汇编代码混合在 C 程序文件中 使用 ARM( 和 KEIL) 开发工具时, 将汇编代码插入 C 编程文件的方法称为 嵌入式汇编程序 汇编代码声明为函数, 并可以被 C 代码调用 示例 : int main (void) { int status; status = get_primask(); while(1); asm int get_primask (void) { MRS R, PRIMASK ; Put interrupt masking register in R BX LR ; Return 有关嵌入式汇编程序的更多详细信息, 请参阅 RealView 编译器用户指南 使用 GCC 和 IAR 编译器时, 您可以使用内嵌汇编程序将汇编代码插入到 C 程序代码 请注意, 虽然包括 RVDS 和 KEIL MDK-ARM 在内的 ARM 开发工具中也包含内嵌汇编程序 Common tasks Disable all interrupt Enable all interrupt IDLE mode / Sleep 851 EA = ; EA = 1; PCON = PCON 1; Cortex-M/M3 with CMSIS disable_irq(); enable_irq(); WFI(); /* Wait for Interrupt */ Vendor specific sleep modes access available in device driver libraries. 41
功能, 但是 ARM 工具中的内嵌汇编程序仅支持 ARM 指令, 并不支持 Thumb 指令, 因此不能用于 Cortex-M 处理器 跟踪输出 ( 仅限 Cortex-M3/M4, 通常在使用 ETM 跟踪时使用 它包含 5 个信号 ) 在汇编程序和 C 语言混合环境中, 您可以通过汇编程序代码调用 C 函数, 也可以通过 C 函数调用汇编程序代码 数据传输的寄存器使用可参见 A R M 架构程序调用标准 (A A P C S) 的文档 此文档可以从 ARM 网站获取 在简单的情况下, 您可以使用 R-R3 作为函数的输入 (R 作为第一个输入变量, 以此类推 ), 并使用 R 来返回结果 函数应该保留 R4 至 R11 的值, 而如果你调用 C 函数, 那么返回时该 C 函数可能会更改 R-R3 和 R12 的值 调试调试和跟踪功能概述 ARM Cortex 微控制器可以使用 JTAG 或串行线协议来调试嵌入式应用程序 串行线协议是在 Cortex-M3 中引入的 该协议可以完成相同的调试任务, 却仅需要 2 根信号线 (JTAG 需要 5 根信号线 ) 大多数 Cortex-M 微控制器允许使用 JTAG 或串行线协议, 但并不允许使用两者 Cortex-M 处理器包含有一些断点和观察点比较器, 你还可以使用断点指令向程序代码中插入其他断点 调试器允许你暂停 重新启动和单步调试程序执行, 并允许你检查核心寄存器和内存中的数据 你甚至可以在处理器运行时访问系统内存 此外,Cortex-M3 处理器支持可选的嵌入式跟踪宏单元 (ETM) 借助 ETM,RealView Trace 或 Keil ULINK Pro 等跟踪端口分析器可以跟踪程序指令执行序列并收集相关信息 在程序编译期间, 跟踪信息可用来对程序代码中的问题进行调试, 或者由 RealView Profiler 用来提高优化性能 对于一些不具备指令跟踪 (ETM) 的 Cortex-M3 微控制器, 仍然可实现基本的跟踪功能 Cortex-M3 处理器支持单线浏览器 (Single-wire Viewer) 输出, 允许通过单个引脚输出少量信息 您可以利用 ULINK2 等低成本的调试硬件来收集跟踪信息 利用单线浏览器提供的跟踪信息, 您可以实现数据跟踪 事件跟踪 ( 如中断 ) P C 采样和仪器跟踪, 其中仪器跟踪是一种新的调试功能, 允许调试器收集软件生成的消息 ( 例如, 可以实现 printf, 而不会对软件执行速度造成太大影响 ) 调试连接在 851 微控制器中, 调试连接通常非常少, 而 ARM 微控制器具有更多的调试连接 JTAG/ 串行线 串行线输出 ( 通常与 TDO 共享, 仅限 Cortex-M3/M4) 请注意,ARM 规定了调试连接的物理连接器标准 进行 PCB 设计时, 使用标准连接器会简单很多 对于新设计, 建议使用新的 Cortex 调试和 ETM 连接器 (.5 2 引脚头 - Samtec FTSH-12) 有关信号协议的详细信息, 请参阅 ETM 架构规范 和 CoreSight 架构规范 VTref KEY Detect /TgtPwr+Cap /TgtPwr+Cap 1 2 TMS/SWIO TCK/SWCLK TDO / SWO / TRACECTL / EXTa TDI / EXTb / NC nreset TRACECLK TRACEDATA TRACEDATA1 TRACEDATA2 TRACEDATA3 19 2 对于没有 ETM 的设备, 您可以使用更小的.5i±1 引脚连接器 VTref KEY Detect 1 2 TMS/SWIO TCK/SWCLK TDO / SWO TDI 9 1 nreset 或者, 您还可以使用旧的 ARM JTAG/ 串行线 2 路 IDC 连接器 1 2 3V3 3V3 ntrst TDI TMS TCK (NC) RTCK TDO (NC) nsrst (NC) DBGRQ (NC) DBGACK nicedetect 19 2 此外, 还有一个旧的基于 38 位 Mictor 连接器的跟踪连接 对于新 设计, 不建议采用 跟踪信号引脚分配情况如下页左图所示 ARM 网站上有一篇有关调试连接器的技术文章, 网址为 : http://infocenter.arm.com/help/topic/com.arm.doc.faqs/ attached/13634/cortex_debug_connectors.pdf 42
Signal NC NC Pin 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 Pin 2 4 6 8 1 12 14 18 2 22 24 26 28 3 32 34 36 38 Signal NC NC TRACECLK Pullup (VRef) Pullup (VSupply) TRACEDATA[3] TRACEDATA[2] TRACEDATA[1] 1 (TRACECTL) TRACEDATA[] 结论由于架构上的差异, 在从 851 迁移到 ARM Cortex 微控制器时, 需要对应用程序代码进行一些修改 修改的原因主要在于数据类型大小上的差异, 以及 851 的一些 C 语言扩展并不适用于 ARM Cortex 微控制器 此外,ARM 微控制器上具有一些新的异常类型和架构特性, 需要修改软件代码才能使用这些新功能 结束 www.realview.com.cn www.arm.com/iqonline 555 1 58 62 ARM Shenzhen Office 755-828 4836 755-828 4839 The Architecture for the Digital World 43