OpenOCD-JTAG调试

目录

  • Todo
  • 概述
  • 断点
  • 快速使用
    • 测试led的断点
    • NAND调试(进阶)
  • OpenOCD
    • 启动OpenOCD
    • OpenOCD命令
    • OpenOCD烧录程序
  • GDB
    • GDB命令
    • 使用条件
    • 使用步骤
  • Eclipes
    • 使用条件
    • 简单工程
    • 注意
    • u-boot工程
  • STM32烧写程序


title: OpenOCD-JTAG调试

tags: ARM

date: 2018-10-13 23:36:28

---

Todo

  • [ ] JTAG 调试linux内核
  • [ ] linux下使用OpenOCD调试
  • [x] win下使用OpenOCD调试

概述

  • 学习文档 韦东山 Eclipse,OpenOCD,OpenJTAGv3.1嵌入式开发教程版本5.pdf

  • 硬件连接: PC>JTAG调试器>CPU
  • 软件控制:IDE(KEIL/ADS/)> GDB(指令)> OpenOCD(实际命令)> JTAG调试器> 单板
  • JTAG控制CPU功能:
    1. 当CPU的地址信号ADDR=xxx,停止CPU-硬件断点
    2. 当CPU的数据信号DATA=xxx,停止CPU--软件断点
    3. 重新运行CPU
    4. 读取R0,..寄存器
    5. 控制外设,内存
  • 百问网的OpenJTAG.exe这个GUI实际是封装了openocd.exe命令行
    1. 设置Workdir到程序代码目录
    2. 点击telnet,或者直接cmd输入telnet 127.0.0.1 4444
    3. 使用help查看帮助或者查看`Eclipse,OpenOCD,OpenJTAGv3.1嵌入式开发教程版本5.pdf

断点

  • 硬件断点:一个程序只能打两个断点(ARM7),可以调试ROM,NOR

    设置CPU里面的JTAG比较器,使硬件断点 Addr=A,当CPU发出A地址时停止

    CPU是如何运行?CPU需要取指令,也就是需要发出地址信号去取得指令,JTAG就检测到这个地址

  • 软件断点,可以有无数个软件断点.前提是断点的地址可写,所以无法调试NOR,或者ROM上的程序,具体可以看下面的led.c的示例
    1. 设置CPU里面的JTAG比较强,使其值=一个特殊值
    2. 替换掉希望断点位置(A)的值=这个特殊值,做好备份
    3. 当CPU读取到这个特殊值,程序断点
    4. 重新运行时,恢复这个(A)位置的指令

快速使用

常用命令

halt 停止cpu
reg 查看寄存器
mdw 0 //memory display word 查看内存
mww 0 0x12345678 //memory write word
load_image leds.bin 0 //下载程序到0地址,然后可以使用mdw读取0,看看是不是程序的bin
resume 0 //指定地址运行,如果不指定地址,则恢复运行
reset 复位目标板子
reset halt

step 0 //执行第一句话,并halt
step  //单步执行

bp设置断点
bp 0x6c 4 hw  在0x6c的地址位置设置断点,硬件断点
rpb 0x6c 取消断点

测试led的断点

//led.c
void  wait(volatile unsigned long dly)
{
    for(; dly > 0; dly--);
}

int main(void)
{
    unsigned long i = 0;

    GPFCON = GPF4_out|GPF5_out|GPF6_out;

    while(1){
        wait(30000);-------------------尝试在这里断点,就能观察灯的变化
        GPFDAT = (~(i<<4));
        if(++i == 8)
            i = 0;
    }

    return 0;
}

//反汇编摘要
00000044 <main>:
  44:   e52de004    str lr, [sp, #-4]!
  48:   e24dd004    sub sp, sp, #4  ; 0x4
  4c:   e3a03000    mov r3, #0  ; 0x0
  50:   e58d3000    str r3, [sp]
  54:   e3a03456    mov r3, #1442840576 ; 0x56000000
  58:   e2833050    add r3, r3, #80 ; 0x50
  5c:   e3a02c15    mov r2, #5376   ; 0x1500
  60:   e5832000    str r2, [r3]
  64:   e3a00c75    mov r0, #29952  ; 0x7500
  68:   e2800030    add r0, r0, #48 ; 0x30
  6c:   ebffffe9    bl  18 <wait>---------------------------尝试在这里断点
  70:   e3a02456    mov r2, #1442840576 ; 0x56000000
  74:   e2822054    add r2, r2, #84 ; 0x54
  78:   e59d3000    ldr r3, [sp]
  7c:   e1a03203    mov r3, r3, lsl #4
  80:   e1e03003    mvn r3, r3
  84:   e5823000    str r3, [r2]
  88:   e59d3000    ldr r3, [sp]
  8c:   e2833001    add r3, r3, #1  ; 0x1
  90:   e58d3000    str r3, [sp]
  94:   e3530008    cmp r3, #8  ; 0x8
  98:   1afffff1    bne 64 <main+0x20>
  9c:   e3a03000    mov r3, #0  ; 0x0
  a0:   e58d3000    str r3, [sp]
  a4:   eaffffee    b   64 <main+0x20>
Disassembly of section .debug_line:

使用openocd命令来调试断点

halt
load_image leds.bin 0   //下载程序
resume 0                //指定地址运行,如果不指定地址,则恢复运行
halt
bp 0x6c 4 hw            //在0x6c的地址位置设置断点,硬件断点

resume                  //反复这个断点,就能观察灯的变化了

测试软件断点是否改变ram值

//读取原来的值
> mdw 0x6c
0x0000006c: ebffffe9
//设置软件断点
> bp 0x6c 4
breakpoint set at 0x0000006c
//读回这个ram值,发现改变了
> mdw 0x6c
0x0000006c: deeedeee
//删除这个断点
> rbp 0x6c
//读回来
> mdw 0x6c
0x0000006c: ebffffe9

NAND调试(进阶)

程序概述:

  1. 链接地址在0x30000,0000,运行的时候应该位于0x3000,0000
  2. 直接烧写程序到内存中,也就是程序运行在0地址.并没有在加载地址
  3. 程序功能:main中点灯,但是直接烧录到内部ram,跑飞了
  4. 程序的bug在于,所有的代码都应该是位置无关的否则需要搬运代码
.text
.global _start
_start:
            @函数disable_watch_dog, memsetup, init_nand, nand_read_ll在init.c中定义
            ldr     sp, =4096               @设置堆栈
            bl      disable_watch_dog       @关WATCH DOG
            bl      memsetup                @初始化SDRAM
            bl      nand_init               @初始化NAND Flash

            @将NAND Flash中地址4096开始的1024字节代码(main.c编译得到)复制到SDRAM中
                                            @nand_read_ll函数需要3个参数:
            ldr     r0,     =0x30000000     @1. 目标地址=0x30000000,这是SDRAM的起始地址
            mov     r1,     #0              @2.  源地址   = 0
            mov     r2,     #4096           @3.  复制长度= 2048(bytes),
            bl      nand_read               @调用C函数nand_read

            ldr     sp, =0x34000000         @设置栈
            ldr     lr, =halt_loop          @设置返回地址
            ldr     pc, =main               @b指令和bl指令只能前后跳转32M的范围
                                            @,所以这里使用向pc赋值的方法进行跳转
halt_loop:
            b       halt_loop

bug原因:mem_cfg_val是在栈,是位置无关的,但是他的初始值是去在链接地址取的,也就是0x3000000后面

void memsetup()
{
    unsigned long  const    mem_cfg_val[]={ 0x22011110,     //BWSCON
                                            0x00000700,     //BANKCON0
                                            0x00000700,     //BANKCON1
                                            0x00000700,     //BANKCON2
                                            0x00000700,     //BANKCON3
                                            0x00000700,     //BANKCON4
                                            0x00000700,     //BANKCON5
                                            0x00018005,     //BANKCON6
                                            0x00018005,     //BANKCON7
                                            0x008C07A3,     //REFRESH
                                            0x000000B1,     //BANKSIZE
                                            0x00000030,     //MRSRB6
                                            0x00000030,     //MRSRB7
                                    };

}

调试开始

>reset halt
> load_image nand.bin 0
1520 bytes written at address 0x00000000
downloaded 1520 bytes in 0.063003s (23.560 KiB/s)

执行第一句话step 0也就是执行mov sp, #4096 ; 0x1000,可以使用reg看到sp=0x1000

step执行跳转,可以发现pc=0x38,对应汇编

30000000 <_start>:
30000000:   e3a0da01    mov sp, #4096   ; 0x1000
30000004:   eb00000b    bl  30000038 <disable_watch_dog>

然后一步一步step,并使用poll查看当前pc值等,使用mdw查看该设置的内存

跳转到memsetup,pc=0x08,反汇编先入栈,可以发现sp=4096-5*4=4076=0xFEC

可以使用 step 0,然后设置 bp 0x50 4 hw 断点 直接跳到想到的位置

然后在汇编代码,发现问题了

// ip=300005bc
30000050:   e1a0400c    mov r4, ip
30000054:   e8b4000f    ldmia   r4!, {r0, r1, r2, r3}
//从r4中指向的内存给r0~r3

//也就是说从 300005bc读取一些数据,但是这个时候300005bc(sdram)并没有被初始化且进行代码搬运,所以这里的数据肯定有问题

//这里的其实就是那个局部数组的值 mem_cfg_val
300005bc <.rodata>:
300005bc:   22011110    andcs   r1, r1, #4  ; 0x4
300005c0:   00000700    andeq   r0, r0, r0, lsl #14
300005c4:   00000700    andeq   r0, r0, r0, lsl #14
300005c8:   00000700    andeq   r0, r0, r0, lsl #14
300005cc:   00000700    andeq   r0, r0, r0, lsl #14
300005d0:   00000700    andeq   r0, r0, r0, lsl #14
300005d4:   00000700    andeq   r0, r0, r0, lsl #14
300005d8:   00018005    andeq   r8, r1, r5
300005dc:   00018005    andeq   r8, r1, r5
300005e0:   008c07a3    addeq   r0, ip, r3, lsr #15
300005e4:   000000b1    streqh  r0, [r0], -r1
300005e8:   00000030    andeq   r0, r0, r0, lsr r0
300005ec:   00000030    andeq   r0, r0, r0, lsr r0
Disassembly of section .comment:

OpenOCD

全称是(Open On-Chip Debugger)

使用前都需要打开OpenOCD,连接上开发板,然后打开telent,或者使用命令telnet 127.0.0.1 4444

启动OpenOCD

专家模式:对应比较自由高级的配置,我们一般直接用普通模式即可

  • Interface对应 OpenOCD\0.4.0\interface`中的选项
  • Target对应OpenOCD\0.4.0\ targetOpenOCD\0.4.0\board

启用telnet

Win7默认没有打开这个功能,需要在程序和功能>打开或关闭 windows 功能> TelentClient打开

OpenOCD命令

这些命令都在telnet中运行,官方命令索引在这里,PDF文档OpenOCD User‘s Guide.pdf

  • 记住的命令

    reset halt
    resume
    step
    load_image
  • 目标板状态处理命令(Target state handling)
    poll 查询目标板当前状态
    halt 中断目标板的运行
    resume [address] 恢复目标板的运行,如果指定了 address,则从 address 处开始运行
    step [address] 单步执行,如果指定了 address,则从 address 处开始执行一条指令
    reset 复位目标板
  • 断点命令
    bp <addr> <length> [hw] 在地址 addr 处设置断点,指令长度为 length, hw 表示硬件断点
    rbp <addr> 删除地址 addr 处的断点 内存访问指令(Memory access commands)
  • 内存访问指令(Memory access commands)
    mdw [‘phys‘] <addr> [count] 显示从(物理)地址 addr 开始的 count(缺省是 1)个字(4 字节)
    mdh [‘phys‘] <addr> [count] 显示从(物理)地址 addr 开始的 count(缺省是 1)个半字(2 字节)
    mdb [‘phys‘] <addr> [count] 显示从(物理)地址 addr 开始的 count(缺省是 1)个字节
    mww [‘phys‘] <addr> <value> 向(物理)地址 addr 写入一个字,值为 value
    mwh [‘phys‘] <addr> <value> 向(物理)地址 addr 写入一个半字,值为 value
    mwb [‘phys‘] <addr> <value> 向(物理)地址 addr 写入一个字节,值为 value
  • 内存装载命令,注意:下载程序之前先使用“ halt” 命令暂停单板,才能下载代码;如果使用“ poll” 命令发现单板的 MMU 或 D-cache 已经使能,则需要使用“ arm920t cp15 2 0” 、“ step”两条命令禁止 MMU 和 D-cache。
    load_image <file> <address> [‘bin’|‘ihex’|‘elf’]
    ======将文件<file>载入地址为 address 的内存,格式有‘bin’、 ‘ihex’、 ‘elf’
    dump_image <file> <address> <size>
    ======将内存从地址 address 开始的 size 字节数据读出,保存到文件<file>中
    verify_image <file> <address> [‘bin’|‘ihex’|‘elf’]
    ======将文件<file>与内存 address 开始的数据进行比较,格式有‘bin’、 ‘ihex’、 ‘elf’
  • CPU 架构相关命令(Architecture Specific Commands)
    reg 打印寄存器的值
    arm7_9 fast_memory_access [‘enable‘|‘disable‘]
    =======使能或禁止“快速的内存访问”
    arm mcr cpnum op1 CRn op2 CRm value 修改协处理器的寄存器
    =======比如: arm mcr 15 0 1 0 0 0 关闭 MMU
    arm mrc cpnum op1 CRn op2 CRm 读出协处理器的寄存器
    =======比如: arm mcr 15 0 1 0 0 读出 cp15 协处理器的寄存器 1
    arm920t cp15 regnum [value] 修改或读取 cp15 协处理器的寄存器
    =======比如 arm920t cp15 2 0 关闭 MMU
  • 其他命令
    script <file> 执行 file 文件中的命令

OpenOCD烧录程序

load_image <file> <address> [‘bin’|‘ihex’|‘elf’]
======将文件<file>载入地址为 address 的内存,格式有‘bin’、 ‘ihex’、 ‘elf’
====load_image led.bin 0

SDRAM初始化

OpenOCD可以快速读写SDRAM,前提是需要程序先初始化好SDRAM,这样之后可以烧录u-boot到sdram,然后通过u-boot烧录其他大程序.这里需要一段初始化sdram的位置无关的代码init.bin

//从 Nand Flash 启动
load_image init/init.bin 0x0
resume 0x0
//NOR 启动
load_image init/init.bin 0x40000000
resume 0x40000000

烧录u-boot,之后打开串口,就能看到跑起来了

halt
load_image u-boot/u-boot.bin 0x33f80000
resume 0x33f80000

uboot烧录其他程序(led/uboot)

  • u-boot 的命令把所有的数字当作 16 进制,所以不管是否在数字前加前缀“ 0x”,这个数

    字都是 16 进制的。

  • 擦除 Flash 的长度、烧写的数据长度,这些数值都是根据要烧写的

    文件的长度确定的。 u-boot.bin 的长度是 178704 字节,即 0x2BA10 字节,使用的长

    度都是 0x30000,一是为了与 Flash 的可擦除长度相配(16K 的整数倍),二是方便。

GDB

  • linux下 arm-linux-gdb,win下arm-elf-gdb
arm-elf-gdb nand_elf
target remote 127.0.0.1:3333
load

GDB命令

启动/退出
gdb [FILE] arm-elf-gdb [FILE] arm-linux-gdb [FILE] 启动 gdb,调试 FILE(也可以先不指定文件)
quit 退出 gdb
target remote ip:port 远程连接
文件操作
file 载入文件 FILE,注意:不会下载到单板上
load [FILE] 把文件下载到单板上,如果不指定 FILE,则下载之前指定 过的(比如 file 命令指定的,或是 gdb 运行时指定的文件)
查看源程序
list 列出某个函数
list 以当前源文件的某行为中间显示一段源程序
list 接着前一次继续显示
break *

在某个地址上设置断点,比如 break *0x84
list - 显示前一次之前的源程序
list 显示指定文件的一段程序
info source 查看当前源程序
info stack 查看堆栈信息
info args 查看当前的参数
断点操作
break 在函数入口设置断点
break 在当前源文件的某一行上设置断点
break 在指定源文件的某一行上设置断点
info br 查看断点
delete 删除断点
diable 禁止断点
enable 使能断点
监视点(watch)操作
watch 当指定变量被写时,程序被停止
rwatch 当指定变量被读时,程序被停止
数据操作
print < EXPRESSION > 查看数据
set varible=value 设置变量
x /NFU ADDR 检查内存值 ① N 代表重复数 ② F 代表输出格式 x : 16 进制整数格式 d : 有符号十进制整数格式 u : 无符号十进制整数格式 f : 浮点数格式 ③ U 代表输出格式: b :字节(byte) h :双字节数值 w :四字节数值 g :八字节数值 比如“ x /4ub 0x0”将会显示 0 地址开始到 4 个字节
执行程序
step next nexti 都是单步执行: step 会跟踪进入一个函数, next 指令则不会进入函数 nexti 执行一条汇编指令
continue 继续执行程序,加载程序后也可以用来启动程序
帮助
help [command] 列出帮助信息,或是列出某个命令的帮助信
其他命令
monitor <command …> 调用 gdb 服务器软件的命令,比如:“ monitor mdw 0x0” 就是调用 openocd 本身的命令“ mdw 0x0”

使用条件

  1. 代码已经重定位,处于它的链接地址.为什么?【在源文件设置断点,其实是在链接地址设置断点,是根据链接地址去修改内存(软断点)】
  2. 链接脚本必须是按照固定格式text,data,bss分开
  3. 被调试的程序中含有debug信息,也就是编译elf时有-g选项
    %.o:%.c
     arm-linux-gcc -Wall -c -g -O2 -o [email protected] $<
    
    %.o:%.S
     arm-linux-gcc -Wall -c -g -O2 -o [email protected] $<
  4. FAQ: 无法调试重定位的代码,那么代码搬运与sdram初始化怎么办? 使用opencod来执行,也就是再弄一个程序初始化sdram,使用openocd烧录

使用步骤

  1. 打开openocd,打开telent
  2. 如果是需要使用sdram的程序,则先在OpenOCD中先下载初始化sdram的程序
    > load_image init/init.bin 0
    > resume 0
    > halt
    target state: halted
    target halted in ARM state due to debug-request, current mode: Supervisor
    cpsr: 0x200000d3 pc: 0x000000b8
    MMU: disabled, D-Cache: disabled, I-Cache: enabled
    
    // 测试一下 sdram可用
    > mdw 0x30000000
    0x30000000: ea000017
    > mww 0x30000000 0x12345678
    > mdw 0x30000000
    0x30000000: 12345678
  3. 打开cmd,输入arn-elf-gdb leds_elf启动gdb,指定程序
  4. 连接到OpenOCDtarget remote 127.0.0.1:3333
  5. 下载程序load

直接使用命令脚本 gdb.init : arm-elf-gdb -x gdb.init leds_elf

target remote localhost:3333
monitor halt
monitor arm920t cp15 2 0
monitor step
load
break main
continue

注意 gdb运行之后没有断点之后停不了了,需要在telnet使用halt,然后GDB界面才能继续输入

常用命令

si 执行一条指令
braek main.c:21 //在main.c的21行打断点
c 或者 continue 继续运行

print i  //查看变量值

Eclipes

Eclipse 是 gdb(包括 arm-elf-gdb, arm-linux-gdb)的图形化前台,使用 Eclipse 进行调试实质

上是使用 gdb 进行调试。

使用 gdb 进行调试时, gdb 会用到程序的链接地址。比如在 main 函数打断点, gdb 会根

据 main 函数的链接地址找到内存上对应的指令,修改这条指令为一条特殊的指令。当程序执

行到这条特殊的指令时,就会停止下来。[也就是软件断点]

使用条件

  1. 程序应该位于它的链接地址上
  2. 如果用到SDRAM,先初始化SDRAM,然后下载程序到链接地址

简单工程

  1. 点击图标Workbench
  2. 新建一个C工程File -> New -> C Project,选择“ Makefile project->Empty Projects”、“ Other Toolchain”
  3. 导入文件在File -> Import中的General>File System
  4. 工程设置
    • 在“ Project” 菜单里,点击去掉“ Build Automatically”前面的标

      记,表示不自动编译工程

    • 在“ Project” 菜单里,点击clean,去除Start a build immediately
  5. 编译,其实在目录下直接make也是可以的了,已经安装后工具链了
    • 使用Project中的build allbuild project都可以了
    • 使用clean也行了
    • 注意,make是不一样的,一个是arm-linux,另一个是arm-elf
  6. 调试配置
    • 参考下面uboot的图配,非uboot不需要配置source选项,命令行也不需要第一个路径配置
    • 去除debug中的stop on  startup at main
    • project> debug config选择Zylin Native,new或者双击都可以,出现配置
    • Main> C/C++ Application选择调试的elfleds.elf
    • Debugger> Debugger选择EmbeddedGDB,下面的main选择arm-elf-gdb或者是C:\Program Files\yagarto\bin\arm-elf-gdb.exe
    • GDB command file 可以选择,也可以不选,其实就是提前运行的命令
      target remote localhost:3333
      monitor halt
      monitor arm mcr 15 0 1 0 0 0
      monitor step 0
      load
      break main
      continue

      但是虽然这里设置了断点,貌似有点问题,依然需要在command输入

      load
      break main
      continue

注意

如果有时候没有看到debug窗口,右上角点一下debug视图,然后F5试试

有时候使用clean,需要看下是不是有debug存在着,需要关掉

u-boot工程

调试网上下载的 u-boot 时,需要定义 CONFIG_SKIP_LOWLEVEL_INIT,它表示

“跳过底层的初始始化”,就是不要初始化存储控制器,不要再次复制 u-boot 本身到 SDRAM

中。对于韦东山的的 u-boot,已经增加的自动识别代码,无需定义这个宏。

  1. import相关文件
  2. 设置命令如下,这个是为了建立路径对应
    set substitute-path /work/eclipse_projects/u-boot/u-boot-1.1.6_OpenJTAG E:/Eeclipse_projects/u-boot/u-boot-1.1.6_OpenJTAG
    load
    break start_armboot
    c

    然后再source中删除原来的default,添加如下(这个实际是上面的命令在生效)

    \work\projects\OpenPDA\u-boot-1.1.6_OpenJTAG
    E:\Eeclipse_projects\u-boot\u-boot-1.1.6_OpenJTAG\

STM32烧写程序

halt
flash probe 0
flash write_image erase STM3210B.bin 0x08000000
verify_image STM3210B.bin 0x08000000

原文地址:https://www.cnblogs.com/zongzi10010/p/9784797.html

时间: 2024-08-30 12:08:46

OpenOCD-JTAG调试的相关文章

ARM JTAG 调试原理

OPEN-JTAG 开发小组 1 前言 这篇文章主要介绍 ARM JTAG 调试的基本原理. 基本的内容包括了 TAP (TEST ACCESS PORT) 和 BOUNDARY-SCAN ARCHITECTURE 的介绍, 在此基础上,结合 ARM7TDMI 详细 介绍了的 JTAG 调试原理. 这篇文章主要是总结了前段时间的一些心得体会,希望对想了解 ARM JTAG 调试的网友们 有所帮助. 我个人对 ARM JTAG 的理解还不是很透彻,在文章中,难免会有偏失和不准确的地 方, 希望精通

使用JTAG调试器和Freemaster 2.0 进行powerpc架构的mpc5XXX系列的调试

使用JTAG调试器和Freemaster 2.0 进行powerpc架构的mpc5XXX系列的调试. 该功能可以方便实现实时监控程序中的变量的变化.非常方便.使用环境: 1.类PE的JTAG接口的调试器. 2.安装了Freemaster 2.0 的PC机 3.编译过程中产生的elf文件或者map文件 只需要上述条件,就可以对目标硬件板进行调试.成本低.实时性好.使用过程中健壮性比较强.唯一的缺点就是freemaster这个上位的一些操作比较模糊,有时候让人感到费解,但是功能都有,均正常.这个需要

openocd 怎样能支持FreeRTOS 8.1.2

沉寂了几年了,觉得应该分享些什么了.前段时间用FreeRTOS做了些东西,陆续拿出来给大家拍砖. 应该说本人是Linux的粉丝吧,所以我业余时间分享的经验也多半是应用Linux作为桌面开发平台的.闲话少说,进入正题. 选用FreeRTOS绝对不是应为他的代码是如何的优秀,而是因为他在自由软件社区展现出的很强的生命力.要知道,如果一个自由软件社区足够的活跃,就意味着有更多的爱好者不停的解决和修正他运行的过程中遇到的诸多问题. 由于本人的工作中会采用STM32的CortexM的MCU,所以后续的调试

ARM体系结构调试系统

预计会有几篇较大篇幅的文章大体描述下ARM体系结构调试系统方面的软硬件接口设计. 简述 经历过软件开发基本上都知道调试的重要性,能一次写好,并且没有BUG的软件毕竟少之又少. ARM体系结构从ARMv4开始硬件支持各种调试特性,随着系统的复杂度提升,到现今的ARMv7,甚至ARMv8,ARM从硬件层面也提供了更多的调试方式. 本文从大方向上概述ARM调试系统的组成,包括其中的debug,trace,profiling等方面 ,又着重在调试系统的软硬件接口配合. 调试分类 从大方向上看,我们基本可

Altera 的 FPGA 的 AS、PS 和 JTAG 配置模式

FPGA 器件有三种配置下载方式:主动配置方式(AS)和被动配置方式(PS)和最常用的(JTAG)配置方式. AS 模式(Active Serial Configuration Mode): FPGA 器件每次上电时作为控制器,由 FPGA 器件引导配置操作过程,它控制着外部存储器和初始化过程,从配置器件 EPCS 主动发出读取数据信号,从而把 EPCS 的数据读入 FPGA 中,实现对 FPGA 的编程配置数据通过 DATA0 引脚送入 FPGA,配置数据被同步在 DCLK 输入上,1 个时钟

调试器不能连接到STM32的问题与解决办法

很多人都碰到过调试器不能连接到STM32的问题,不管是IAR的J-Link还是Keil的ULink,或者是ST的ST-Link.出现这个问题时,调试软件会提示不能建立与Cortex-M3的连接,或提示不能下载程序,或提示找不到要调试的设备等.       这样的问题都是发生在调试那些可以在CPU不干预的时候自动运行的模块.或在调试低功耗模式的程序的时候.所谓“可以在CPU不干预的时候自动运行的模块”包括:DMA.定时器.连续转换模式下的ADC.看门狗等模块. ------------------

《FPGA全程进阶---实战演练》第二章之焊接板子及调试注意事项

1.若是读者第一次做板子,强烈建议画完PCB板后将PCB图打印出来,然后对照你买的芯片将芯片放置对 应的位置,然后查看所有的封装格式适不适合,否则等你做出板子来后再试,为时晚矣.笔者虽然知道要这么 做,但是笔者第一次发给工厂做回来的PCB发现有一个芯片封装画大了,而且那个芯片还是贴片封装的,这让 笔者心痛不已,300多大洋就这么要毁于一旦了. 2.在参考别人的电路时一定要注意,你想用的芯片型号的电路适不适合你参考的电路图,若是完全一致,那么可以直接照抄照搬,若是不一样,这时候要非常注意电路的设计

大杀招之使用QEMU调试Linux内核代码

Linux内核代码的调试非常麻烦,一般都是加printk, 或者用JTAG调试. 这里的方法是用QEMU来调试Linux内核.因为QEMU自己实现了一个gdb server, 所以可以非常方便的使用gdb来调内核. 这对内核的学习也非常有帮助. 为了尽量不多花时间在QEMU设置上,这里直接使用以下的内核image: http://free-electrons.com/community/demos/qemu-arm-directfb/ 1. QEMU的安装 这个可以自己去QEMU的官网下载编译,

使用QEMU调试Linux内核代码

Linux内核代码的调试非常麻烦,一般都是加printk, 或者用JTAG调试.这里的方法是用QEMU来调试Linux内核.因为QEMU自己实现了一个gdb server, 所以可以非常方便的使用gdb来调内核. 这对内核的学习也非常有帮助. 为了尽量不多花时间在QEMU设置上,这里直接使用以下的内核image: http://free-electrons.com/community/demos/qemu-arm-directfb/ 1,QEMU的安装 这个可以自己去QEMU的官网下载编译,如果