ESP32 编译和调试步骤

简单介绍利用 OpenOCD+JTAG 来调试一个demo程序的步骤和说明。

2017.01.18 by chenwu

前提条件:

已经理解并完成《ESP32调试环境搭建》。

ESP32 编译和调试步骤

步骤

1. 串口线连接好 ESP-WROVER-KIT 和 PC,并将开关调至 ON.

2. 将本目录下的 hello_world_main.c 覆盖 esp-idf/examples/01_hello_world/main/hello_world_main.c 文件

3. 进入example目录(设当前shell 为 shell A):

$ cd ~/esp/esp-idf/examples/01_hello_world

1

4. 编译程序并烧入ESP32

$ make flash

1

5. 新建一个shell,并进入 openOCD 目录(设当前shell 为 shell B):

$ cd ~/esp/openocd-esp32

1

6. OpenOCD和程序通讯:这步 操作之间必须连贯,不能停顿太多。(否则程序会执行到末尾,无法调试)

6.1 将ESP-WROVER-KIT开关从 ON -> OFF -> ON

6.2 shell B 启动openocd:

$ sudo ./src/openocd -s ./tcl -f ./esp32.cfg

1

or [esp32.cfg 如果更新,则使用下面]

$ cp ../esp-idf/docs/esp32.cfg ./ ; sudo ./src/openocd -s ./tcl -f ./esp32.cfg

1

7. shell A 启动gdb:

$ xtensa-esp32-elf-gdb -ex 'target remote localhost:3333' ./build/hello-world.elf

1

shell A端gdb调试一些说明

ESP32 编译和调试步骤

大概可以仿照如下调试:

b hello_task //设置好断点

display /i $pc //设置好显示下一条汇编

c // 执行到断点处

n // 执行一条源码

n // 执行一条源码

s // 进入函数调用

ni // 执行一条汇编

ni // 执行一条汇编

p i // 输出 i 值

bt // 输出 栈

1

2

3

4

5

6

7

8

9

10

常用调试命令小结:

断点相关:

b hello_task // 设置hello_task函数处断点

b *hello_task+9 // 设置hello_task后 +9 偏移地址处的汇编为断点(不是hello_task后的第九条汇编)

b +10 // 设置当前行 + 10 行处断点(源码+10行)

b a.c:10 // 设置 a.c文件的第十行(源码)处断点

info breakpoints // 显示断点处信息

b 20 // 设置 当前文件第20行 断点,如果设置 b hello_world_main.c:20 则就是设置hello_world_main.c中第20行断点

b 28 if i == 2 // 条件断点,第28行中,如果i==2,则触发断点

d // 删除所有断点

d 1 // 删除1号断点 : 断点按照顺序编号,1号断点就是第一个断点

watch i // 当 当前行的i值发生改变后,会触发断点

1

2

3

4

5

6

7

8

9

10

执行相关:

c // 或continue // 执行程序,直到断点处或者该线程结束

q // 退出 gdb

n // 单步执行一条源码,如果遇到一条函数调用,不进入函数

s // 单步执行一条源码,如果遇到一条函数调用,则进入函数

ni // 单步执行一条汇编,如果遇到一条函数调用,不进入函数

si // 单步执行一条汇编,如果遇到一条函数调用,则进入函数

finish // 跳出当前函数

1

2

3

4

5

6

7

源码相关:

list // 显示当前行前后的源码

list app_main // 显示源码 app_main函数后一段

list 20 // 显示源码的第20行后一段

list 20,40 // 显示 源码的第20-40行

1

2

3

4

显示相关:

display /i $pc // 执行后,每次单步后会显示下一条汇编指令

p i // 或 print i // 输出变量i的值

bt // 或 where // 显示函数调用栈

bt full // 显示函数调用栈的详细信息

x /3uh buf // 表示从内存地址buf读取内容,h表示以双字节为一个单位,3表示三个单位,u表示按十六进制显示

x /s buf // 显示从buf开始的字符串

whatis i // 显示变量i类型

1

2

3

4

5

6

7

布局相关:

layout asm // 显示汇编代码

layout regs // 显示寄存器

layout src // 显示源码 ,结合list使用

layout prev // 切换到上一个布局

layout next // 切换到下一个布局

1

2

3

4

5

线程和进程:

info threads // 查看线程

thread i // 切换到线程号为 i 的线程

info inferiors // 查看进程

inferior i // 切换到进程号为 i 的进程

mon reset // 重置cpu,程序重新执行

1

2

3

4

5

查看其他调试命令:

help all

help

1

2

静态调试-反汇编

我们更加方便的调试,我们可以反汇编二进制文件,这样更加清楚的显示所有汇编代码并查找分析编辑。

生成汇编代码步骤:(前提已经编译完成)

1. 进入hello-world目录:

$ cd ~/esp/esp-idf/examples/01_hello_world

1

2. 拷贝 elf 文件:

$ cp ./build/hello-world.elf ./

1

3. 生成汇编文件:

$ xtensa-esp32-elf-objdump -S hello-world.elf > compile_info.txt

1

[4] 我们在gdb调试时候,可以看到执行位置的地址。在汇编文件compile_info.txt中查找该地址,就可以分析。

注意:

1. 运行 sudo ./src/openocd -s ./tcl -f ./esp32.cfg 中如果不能启动,出现如下错误

Error: couldn’t bind tcl to socket: Address already in use

则证明 刚刚启动的 进程未被终止。

解决办法:

a).查看当前活动进程

netstat为显示网络相关信息 a(all:默认显示所有,如果加了其他选项此项不生效) n(number:以数字形式显示) t(仅仅显示tcp连接),p(process:显示该项是由哪个程序建立起来的)

$ sudo netstat -antp

1

b). 强制杀死它(假设进程号为3560,-9为强制杀死)

$ sudo kill -9 3560

1

2. make flash失败

确保串口连接正常, ll /dev/ttyUSB*

应该可以看到两个设备 ttyUSB0 ttyUSB1.如果不是,则 重置ESP-WROVER-KIT开关:从 ON-> OFF -> ON 或者 重新插拔串口线。

3. gdb启动后出现如下错误:

0x00000000 in ?? ()

或者 openOCD收到如下错误:

Error: Error allocating memory for 1073433568 threads

解决办法:

重新擦写flash (flash由于上次没有擦除干净)

---------------------


分享到:


相關文章: