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由於上次沒有擦除乾淨)

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


分享到:


相關文章: