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)位置的指令

快速使用

常用命令

  1. halt 停止cpu
  2. reg 查看寄存器
  3. mdw 0 //memory display word 查看内存
  4. mww 0 0x12345678 //memory write word
  5. load_image leds.bin 0 //下载程序到0地址,然后可以使用mdw读取0,看看是不是程序的bin
  6. resume 0 //指定地址运行,如果不指定地址,则恢复运行
  7. reset 复位目标板子
  8. reset halt
  9. step 0 //执行第一句话,并halt
  10. step //单步执行
  11. bp设置断点
  12. bp 0x6c 4 hw 0x6c的地址位置设置断点,硬件断点
  13. rpb 0x6c 取消断点

测试led的断点

  1. //led.c
  2. void wait(volatile unsigned long dly)
  3. {
  4. for(; dly > 0; dly--);
  5. }
  6. int main(void)
  7. {
  8. unsigned long i = 0;
  9. GPFCON = GPF4_out|GPF5_out|GPF6_out;
  10. while(1){
  11. wait(30000);-------------------尝试在这里断点,就能观察灯的变化
  12. GPFDAT = (~(i<<4));
  13. if(++i == 8)
  14. i = 0;
  15. }
  16. return 0;
  17. }
  18. //反汇编摘要
  19. 00000044 <main>:
  20. 44: e52de004 str lr, [sp, #-4]!
  21. 48: e24dd004 sub sp, sp, #4 ; 0x4
  22. 4c: e3a03000 mov r3, #0 ; 0x0
  23. 50: e58d3000 str r3, [sp]
  24. 54: e3a03456 mov r3, #1442840576 ; 0x56000000
  25. 58: e2833050 add r3, r3, #80 ; 0x50
  26. 5c: e3a02c15 mov r2, #5376 ; 0x1500
  27. 60: e5832000 str r2, [r3]
  28. 64: e3a00c75 mov r0, #29952 ; 0x7500
  29. 68: e2800030 add r0, r0, #48 ; 0x30
  30. 6c: ebffffe9 bl 18 <wait>---------------------------尝试在这里断点
  31. 70: e3a02456 mov r2, #1442840576 ; 0x56000000
  32. 74: e2822054 add r2, r2, #84 ; 0x54
  33. 78: e59d3000 ldr r3, [sp]
  34. 7c: e1a03203 mov r3, r3, lsl #4
  35. 80: e1e03003 mvn r3, r3
  36. 84: e5823000 str r3, [r2]
  37. 88: e59d3000 ldr r3, [sp]
  38. 8c: e2833001 add r3, r3, #1 ; 0x1
  39. 90: e58d3000 str r3, [sp]
  40. 94: e3530008 cmp r3, #8 ; 0x8
  41. 98: 1afffff1 bne 64 <main+0x20>
  42. 9c: e3a03000 mov r3, #0 ; 0x0
  43. a0: e58d3000 str r3, [sp]
  44. a4: eaffffee b 64 <main+0x20>
  45. Disassembly of section .debug_line:

使用openocd命令来调试断点

  1. halt
  2. load_image leds.bin 0 //下载程序
  3. resume 0 //指定地址运行,如果不指定地址,则恢复运行
  4. halt
  5. bp 0x6c 4 hw //在0x6c的地址位置设置断点,硬件断点
  6. resume //反复这个断点,就能观察灯的变化了

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

  1. //读取原来的值
  2. > mdw 0x6c
  3. 0x0000006c: ebffffe9
  4. //设置软件断点
  5. > bp 0x6c 4
  6. breakpoint set at 0x0000006c
  7. //读回这个ram值,发现改变了
  8. > mdw 0x6c
  9. 0x0000006c: deeedeee
  10. //删除这个断点
  11. > rbp 0x6c
  12. //读回来
  13. > mdw 0x6c
  14. 0x0000006c: ebffffe9

NAND调试(进阶)

程序概述:

  1. 链接地址在0x30000,0000,运行的时候应该位于0x3000,0000
  2. 直接烧写程序到内存中,也就是程序运行在0地址.并没有在加载地址
  3. 程序功能:main中点灯,但是直接烧录到内部ram,跑飞了
  4. 程序的bug在于,所有的代码都应该是位置无关的否则需要搬运代码
  1. .text
  2. .global _start
  3. _start:
  4. @函数disable_watch_dog, memsetup, init_nand, nand_read_llinit.c中定义
  5. ldr sp, =4096 @设置堆栈
  6. bl disable_watch_dog @关WATCH DOG
  7. bl memsetup @初始化SDRAM
  8. bl nand_init @初始化NAND Flash
  9. @将NAND Flash中地址4096开始的1024字节代码(main.c编译得到)复制到SDRAM
  10. @nand_read_ll函数需要3个参数:
  11. ldr r0, =0x30000000 @1. 目标地址=0x30000000,这是SDRAM的起始地址
  12. mov r1, #0 @2. 源地址 = 0
  13. mov r2, #4096 @3. 复制长度= 2048(bytes),
  14. bl nand_read @调用C函数nand_read
  15. ldr sp, =0x34000000 @设置栈
  16. ldr lr, =halt_loop @设置返回地址
  17. ldr pc, =main @b指令和bl指令只能前后跳转32M的范围
  18. @,所以这里使用向pc赋值的方法进行跳转
  19. halt_loop:
  20. b halt_loop

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

  1. void memsetup()
  2. {
  3. unsigned long const mem_cfg_val[]={ 0x22011110, //BWSCON
  4. 0x00000700, //BANKCON0
  5. 0x00000700, //BANKCON1
  6. 0x00000700, //BANKCON2
  7. 0x00000700, //BANKCON3
  8. 0x00000700, //BANKCON4
  9. 0x00000700, //BANKCON5
  10. 0x00018005, //BANKCON6
  11. 0x00018005, //BANKCON7
  12. 0x008C07A3, //REFRESH
  13. 0x000000B1, //BANKSIZE
  14. 0x00000030, //MRSRB6
  15. 0x00000030, //MRSRB7
  16. };
  17. }

调试开始

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

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

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

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

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

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

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

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

  1. // ip=300005bc
  2. 30000050: e1a0400c mov r4, ip
  3. 30000054: e8b4000f ldmia r4!, {r0, r1, r2, r3}
  4. //从r4中指向的内存给r0~r3
  5. //也就是说从 300005bc读取一些数据,但是这个时候300005bc(sdram)并没有被初始化且进行代码搬运,所以这里的数据肯定有问题
  6. //这里的其实就是那个局部数组的值 mem_cfg_val
  7. 300005bc <.rodata>:
  8. 300005bc: 22011110 andcs r1, r1, #4 ; 0x4
  9. 300005c0: 00000700 andeq r0, r0, r0, lsl #14
  10. 300005c4: 00000700 andeq r0, r0, r0, lsl #14
  11. 300005c8: 00000700 andeq r0, r0, r0, lsl #14
  12. 300005cc: 00000700 andeq r0, r0, r0, lsl #14
  13. 300005d0: 00000700 andeq r0, r0, r0, lsl #14
  14. 300005d4: 00000700 andeq r0, r0, r0, lsl #14
  15. 300005d8: 00018005 andeq r8, r1, r5
  16. 300005dc: 00018005 andeq r8, r1, r5
  17. 300005e0: 008c07a3 addeq r0, ip, r3, lsr #15
  18. 300005e4: 000000b1 streqh r0, [r0], -r1
  19. 300005e8: 00000030 andeq r0, r0, r0, lsr r0
  20. 300005ec: 00000030 andeq r0, r0, r0, lsr r0
  21. 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

  • 记住的命令

    1. reset halt
    2. resume
    3. step
    4. load_image
  • 目标板状态处理命令(Target state handling)

    1. poll 查询目标板当前状态
    2. halt 中断目标板的运行
    3. resume [address] 恢复目标板的运行,如果指定了 address,则从 address 处开始运行
    4. step [address] 单步执行,如果指定了 address,则从 address 处开始执行一条指令
    5. reset 复位目标板
  • 断点命令

    1. bp <addr> <length> [hw] 在地址 addr 处设置断点,指令长度为 length hw 表示硬件断点
    2. rbp <addr> 删除地址 addr 处的断点 内存访问指令(Memory access commands)
  • 内存访问指令(Memory access commands)

    1. mdw ['phys'] <addr> [count] 显示从(物理)地址 addr 开始的 count(缺省是 1)个字(4 字节)
    2. mdh ['phys'] <addr> [count] 显示从(物理)地址 addr 开始的 count(缺省是 1)个半字(2 字节)
    3. mdb ['phys'] <addr> [count] 显示从(物理)地址 addr 开始的 count(缺省是 1)个字节
    4. mww ['phys'] <addr> <value> 向(物理)地址 addr 写入一个字,值为 value
    5. mwh ['phys'] <addr> <value> 向(物理)地址 addr 写入一个半字,值为 value
    6. mwb ['phys'] <addr> <value> 向(物理)地址 addr 写入一个字节,值为 value
  • 内存装载命令,注意:下载程序之前先使用“ halt” 命令暂停单板,才能下载代码;如果使用“ poll” 命令发现单板的 MMU 或 D-cache 已经使能,则需要使用“ arm920t cp15 2 0” 、“ step”两条命令禁止 MMU 和 D-cache。

    1. load_image <file> <address> [‘bin’|‘ihex’|‘elf’]
    2. ======将文件<file>载入地址为 address 的内存,格式有‘bin’、 ihex’、 elf
    3. dump_image <file> <address> <size>
    4. ======将内存从地址 address 开始的 size 字节数据读出,保存到文件<file>中
    5. verify_image <file> <address> [‘bin’|‘ihex’|‘elf’]
    6. ======将文件<file>与内存 address 开始的数据进行比较,格式有‘bin’、 ihex’、 elf
  • CPU 架构相关命令(Architecture Specific Commands)

    1. reg 打印寄存器的值
    2. arm7_9 fast_memory_access ['enable'|'disable']
    3. =======使能或禁止“快速的内存访问”
    4. arm mcr cpnum op1 CRn op2 CRm value 修改协处理器的寄存器
    5. =======比如: arm mcr 15 0 1 0 0 0 关闭 MMU
    6. arm mrc cpnum op1 CRn op2 CRm 读出协处理器的寄存器
    7. =======比如: arm mcr 15 0 1 0 0 读出 cp15 协处理器的寄存器 1
    8. arm920t cp15 regnum [value] 修改或读取 cp15 协处理器的寄存器
    9. =======比如 arm920t cp15 2 0 关闭 MMU
  • 其他命令

    1. script <file> 执行 file 文件中的命令

OpenOCD烧录程序

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

SDRAM初始化

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

  1. //从 Nand Flash 启动
  2. load_image init/init.bin 0x0
  3. resume 0x0
  4. //NOR 启动
  5. load_image init/init.bin 0x40000000
  6. resume 0x40000000

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

  1. halt
  2. load_image u-boot/u-boot.bin 0x33f80000
  3. 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
  1. arm-elf-gdb nand_elf
  2. target remote 127.0.0.1:3333
  3. 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 FILENAME:FUNCTION list FILENAME:LINENUM 显示指定文件的一段程序
info source 查看当前源程序
info stack 查看堆栈信息
info args 查看当前的参数
断点操作
break 在函数入口设置断点
break 在当前源文件的某一行上设置断点
break FILENAME:LINENUM 在指定源文件的某一行上设置断点
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选项

    1. %.o:%.c
    2. arm-linux-gcc -Wall -c -g -O2 -o $@ $<
    3. %.o:%.S
    4. arm-linux-gcc -Wall -c -g -O2 -o $@ $<
  4. FAQ: 无法调试重定位的代码,那么代码搬运与sdram初始化怎么办? 使用opencod来执行,也就是再弄一个程序初始化sdram,使用openocd烧录

使用步骤

  1. 打开openocd,打开telent

  2. 如果是需要使用sdram的程序,则先在OpenOCD中先下载初始化sdram的程序

    1. > load_image init/init.bin 0
    2. > resume 0
    3. > halt
    4. target state: halted
    5. target halted in ARM state due to debug-request, current mode: Supervisor
    6. cpsr: 0x200000d3 pc: 0x000000b8
    7. MMU: disabled, D-Cache: disabled, I-Cache: enabled
    8. // 测试一下 sdram可用
    9. > mdw 0x30000000
    10. 0x30000000: ea000017
    11. > mww 0x30000000 0x12345678
    12. > mdw 0x30000000
    13. 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

  1. target remote localhost:3333
  2. monitor halt
  3. monitor arm920t cp15 2 0
  4. monitor step
  5. load
  6. break main
  7. continue

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

常用命令

  1. si 执行一条指令
  2. braek main.c:21 //在main.c的21行打断点
  3. c 或者 continue 继续运行
  4. 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 可以选择,也可以不选,其实就是提前运行的命令

      1. target remote localhost:3333
      2. monitor halt
      3. monitor arm mcr 15 0 1 0 0 0
      4. monitor step 0
      5. load
      6. break main
      7. continue

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

      1. load
      2. break main
      3. continue

注意

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

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

u-boot工程

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

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

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

  1. import相关文件

  2. 设置命令如下,这个是为了建立路径对应

    1. 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
    2. load
    3. break start_armboot
    4. c

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

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

STM32烧写程序

  1. halt
  2. flash probe 0
  3. flash write_image erase STM3210B.bin 0x08000000
  4. verify_image STM3210B.bin 0x08000000

OpenOCD-JTAG调试的更多相关文章

  1. OpenOCD安装与使用(JTAG调试)

    本文介绍openocd开源软件的安装以及搭配JTAG对Xilinx u500VC707devkit的调试 PC OS: Ubuntu20.04 LTS Target ARCH: riscv64 JTA ...

  2. ARM JTAG 调试原理

    ARM JTAG 调试原理 JTAG的接口是一种特殊的4/5个接脚接口连到芯片上 ,所以在电路版上的很多芯片可以将他们的JTAG接脚 通过Daisy Chain的方式连在一起,并且Probe只需连接到 ...

  3. jz2440使用openjtag+openocd+eclipse调试【学习笔记】

    平台:jz2440 作者:庄泽彬(欢迎转载,请注明作者) 说明:韦东山二期视频学习笔记 交叉编译工具:arm-linux-gcc (GCC) 3.4.5 eclipse版本:eclipse-cpp-l ...

  4. OpenOCD SWD调试stm32f0

    参考:http://www.stmcu.org.cn/module/forum/thread-610998-1-2.html

  5. 使用VisualGDB和OpenOCD调试STM32L0开发板

    本教程主要介绍如何配置VisualGDB和OpenOCD来调试STM32L0开发板的固件,使微控制器进入睡眠模式. 我们将创建一个NUCLEO-L031K6开发板的基本工程,并介绍当CPU进入休眠模式 ...

  6. openocd 如何支持FreeRTOS 8.1.2

    沉寂了数年,认为我们应该分享一下.前段时间通过FreeRTOS做点什么,大家纷纷拿出来拍砖. 我应该说,Linux现在粉丝.所以,我的业余时间来分享它通常应用的经验Linux作为桌面开发平台.无需再费 ...

  7. ARM裸板调试思路总结、笔记

    1. 点灯 2. 串口打印 3. JTAG调试器3.1 命令行调试 3.2 源码级别的调试前提a. 程序必须已经重定位好,位于它的链接地址a.1 如果程序的链接地址是SDRAM, 使用openocd初 ...

  8. 裸板驱动总结(makefile+lds链接脚本+裸板调试)

    在裸板2440中,当我们使用nand启动时,2440会自动将前4k字节复制到内部sram中,如下图所示: 然而此时的SDRAM.nandflash的控制时序等都还没初始化,所以我们就只能使用前0~40 ...

  9. arm裸板驱动总结(makefile+lds链接脚本+裸板调试)

    在裸板2440中,当我们使用nand启动时,2440会自动将前4k字节复制到内部sram中,如下图所示: 然而此时的SDRAM.nandflash的控制时序等都还没初始化,所以我们就只能使用前0~40 ...

随机推荐

  1. Nginx geoip模块

    需要编译进 --with-http_geoip_module 首先要安装maxMind里的geoip的c开发库 https://dev.maxmind.com/geoip/legacy/downloa ...

  2. Codeforces 719A 月亮

    参考自:https://www.cnblogs.com/ECJTUACM-873284962/p/6395221.html A. Vitya in the Countryside time limit ...

  3. 洛谷P1038神经网络题解

    题目 这个题不得不说是一道大坑题,为什么这么说呢,这题目不仅难懂,还非常适合那种被生物奥赛刷下来而来到信息奥赛的学生. 因此我们先分析一下题目的坑点. 1: 题目的图分为输入层,输出层,以及中间层. ...

  4. python中lambda的使用

    为什么我们需要lambda? 既然有了def可以用来定义函数,我们为什么还需要lambda来定义.根据我的使用情况我认为lambda的优点在于: 非常适合用来构造只使用一次的函数,可以是匿名函数 有利 ...

  5. Chemical table CFR500 div2D(并查集)

    给定的一个n*m的区域内,给出一些点的坐标,这些点上有一个元素,如果在矩形的子矩形的三个点都有元素,那么第四个点的元素可以自己产生,其他的元素需要购买,问最少需要购买多少中元素才可以把这个区域给填满. ...

  6. 【linux】linux查找功能

    linux系统中我们经常会需要查找某些文件,当有时候我们不确定一个文件的位置,比如某服务配置文件具体路径,自己没有头绪去寻找的话会很难找,也会耽误时间.linux就提供了很多命令,find,locat ...

  7. 【Linux】linux正则表达式及通配符

    正则表达式就是用于匹配每行输入的一种模式,模式是指一串字符序列.拥有强大的字符搜索功能.也非常方便的搜索过滤出我们想要的内容. linux正则表达式分为基本正则表达式(Basic Regexp)和扩展 ...

  8. 小电阻之大作用——CAN终端电阻

    CAN总线终端电阻,顾名思义就是加在总线末端的电阻.此电阻虽小,但在CAN总线通信中却有十分重要的作用. 终端电阻的作用 CAN总线终端电阻的作用有两个: 1.提高抗干扰能力,确保总线快速进入隐性状态 ...

  9. A/D和D/A的学习

    从我们学到的知识了解到,我们的单片机是一个典型的数字系统.数字系统只能对输入的数字信号进行处理,其输出信号也是数字信号.但是在工业检测系统和日常生活中的许多物理量都是模拟量,比如温度.长度.压力.速度 ...

  10. 牛客寒假算法基础集训营3B 处女座的比赛资格(用拓扑排序解决DAG中的最短路)

    链接:https://ac.nowcoder.com/acm/contest/329/B 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...