U-Boot 之二 详解使用 eclipse + J-Link 进行编译及在线调试
??在上一篇博文 U-Boot 之一 零基礎編譯 U-Boot 過程詳解 及 編譯后的使用說明 中,最后使用階段遇到了一些錯誤,然后發現不能調試(靠打印信息)實在是難受,就開始摸索如何調試 U-Boot,于是就有了這篇博文。
??找了一下網上現有的資料,直接使用 GDB 命令行調試是一個選擇,但是明顯效率不高。于是開始探索直接使用 eclipse 對 U-Boot 進行編譯及調試。發現網上有不少說明文章,但大多數都太老舊了,因此我決定重新整理一篇,使用的當前最新的工具環境如下:
下載安裝 eclipse
??首先從官網下載最新的針對嵌入式 C/C++ 的 tar 包(現在 eclipse 針對不同開發環境提供了不同的包,我記得之前并沒有分開):Eclipse IDE for Embedded C/C++ Developers,地址:https://www.eclipse.org/downloads/packages/release/2021-12/r/eclipse-ide-embedded-cc-developers,然后進行安裝(解壓):
解壓之后,我們在 /opt/eclipse/eclipse 目錄(我這里先建立了 eclipse 文件夾導致多了一級,大家可以直接解壓到 /opt)下直接雙擊運行 eclipse 程序即可。這里我們直接下載嵌入式專用的版本,主要是出于以下幾點:
進一步,我們可以選擇建立一個 eclipse 的快捷方式,方便后續啟動:
附 tar 命令:
# 壓縮tar -czvf ***.tar.gztar -cjvf ***.tar.bz2# 解壓縮tar -xzvf ***.tar.gztar -xjvf ***.tar.bz2# 參數 -c :建立一個壓縮檔案的參數指令(create 的意思); -x :解開一個壓縮檔案的參數指令! -t :查看 tarfile 里面的檔案!特別注意,在參數的下達中, c/x/t 僅能存在一個!不可同時存在!因為不可能同時壓縮與解壓縮。 -z :是否同時具有 gzip 的屬性,亦即是否需要用 gzip 壓縮 -j :是否同時具有 bzip2 的屬性,亦即是否需要用 bzip2 壓縮 -v :壓縮的過程中顯示檔案!這個常用,但不建議用在背景執行過程! -f :使用檔名。注意,在 f 之后要立即接檔名,不要再加參數!例如使用『 tar -zcvfP tfile sfile 』就是錯誤的寫法,要寫成『 tar -zcvPf tfile sfile 』才對! -p :使用原檔案的原來屬性(屬性不會依據使用者而變) -P :可以使用絕對路徑來壓縮! -N :比后面接的日期(yyyy/mm/dd)還要新的才會被打包進新建的檔案中!下載安裝 J-Link 驅動
??這個就相當簡單了,SEGGER 提供了安裝包,直接從 https://www.segger.com/downloads/J-Link/ 下載對應的的 linux 的安裝包(例如我的 Ubuntu 對應 64-bit DEB Installer),然后雙擊安裝就可以了。安裝之后默認位置是 ./opt/SEGGER 目錄下。
里面的可執行程序都沒有對應的桌面圖標,運行后在左側的工具欄上也是黑乎乎的。使用時直接使用命令行或者到目錄下雙擊對應的可執行程序即可。
配置 eclipse
??eclipse 的配置分為全局、工作區、項目,優先級前者最低后者最高(后者會覆蓋前者)。對于一些通用的配置(例如我們安裝的 J-Link 驅動,無論工作區還是項目,應該都用一個),eclipse 推薦直接在全局或者工作區中配置,項目直接繼承使用全局或工作區的配置就可以了。 啟動 eclipse 會提示選擇工作區,默認可以選擇不再提示。
啟動之后,直接 菜單 --> Window --> Preferences 打開配置界面,我們主要是配置更改 MCU 這個目錄(這個好像是由于我們用的嵌入式版 eclipse 自帶了 CDT 插件才有這個)下的內容,其他的配置項則根據自己的需要自行修改即可。具體如下:
我這里僅僅配置了編譯工具鏈和 J-Link 的安裝位置。之所以這里選擇對全局配置項進行配置,主要還是方便在后續建立項目之后,項目自動繼承這些配置,方便減少很多操作。
??這里再次說明,由于我們選擇的是嵌入式專用的 eclipse(Eclipse IDE for Embedded C/C++ Developers ),因此,我們不需要安裝 CDT 插件等操作。否則光是配置 eclipse 內容就挺多!
安裝 CMSIS-Packs
??CMSIS Pack 是 ARM 為 Cortex-M 核定義的一個規范,是一種有效的封裝技術,目前支持近 9000 種不同的微控制器。它們為軟件組件、設備參數和評估板支持提供了一種交付機制。軟件包(文件集合)包括:
- 源代碼、頭文件和軟件庫
- 文檔和源代碼模板
- 設備參數以及啟動代碼和編程算法
- 示例工程
??用過 MDK-ARM(Keil)的應該很熟悉,這個東西不僅可以在 MDK-ARM(Keil)中使用,現在 eclipse、IAR 都集成了 CMSIS Pack,通過 CMSIS Pack 我們可以在線安裝一些芯片的包。
?? 這里我們之所以安裝 CMSIS Pack(確切的說是安裝 CMSIS Pack 中提供的芯片的包),是因為從中我們可以獲取到芯片的 SVD 文件,而 SVD 文件中記錄了芯片中各種外設的寄存器,在調試時非常有用!如果不使用 SVD 文件,調試器將無法獲取芯片中外設的寄存器,只能顯示 ARM 核中的幾個寄存器。
?? eclipse 中安裝非常簡單,但是由于訪問的是國外的服務器,速度相當慢(那些包都挺大的),而且經常出現某些芯片下載不下來報錯。如果出現報錯直接選擇忽略即可。具體操作如下圖所示:
??CMSIS Pack 的安裝位置可以在 菜單--> Window-->Preferences --> C/C++ --> MCU Packages 下找到及更改。查看其中的內容,其實就是 Keil 中的那一套東西,因此一種變通的方法是將下載好的內容直接放到上面的目錄中即可。SVD 文件就位于 CMSIS-Packs\Keil\STM32F7xx_DFP\2.14.1\CMSIS\SVD 目錄下。
注意,上面的這個目錄應該是個隱藏文件夾!
編譯 U-Boot
新建項目
??準備好以上環境及工具之后,就可以直接建立項目了,對于 U-Boot ,我們選擇 Makefile Project with Existing Code。我這里把步驟盡量把步驟合并到一張圖,以節約篇幅。具體步驟如下圖所示:
??其中,我們選擇的編譯工具鏈是 Arm Cross GCC。這里的選擇主要是讓 eclipse 能夠主動使用適合我們的一些配置。如果選擇其他的,后續也可以再次進行更改(步驟會多一些)。
注意,如果選擇在配置章節說的已經在配置了全局或者工作區,下面有些配置其實可以不用更改。我這里就以沒有配置來進行演示(覆蓋全局配置),對于全局配置有影響的地方單獨說明一下。
??點擊 Finish 之后,默認在選擇的源代碼目錄下新建兩個(隱藏)文件:.cproject 和 .project,這兩個就是 eclipse 記錄的項目配置信息文件(我之前以為會和 Windows 上的一些軟件(例如 vs)似得放到選擇的工作區目錄下,要不然我選擇工作區干啥!)。
項目配置
??點擊右鍵菜單最下面的 Properties (也可以通過 菜單 --> Project --> Properties)之后,就打開了項目的配置頁面,接下來就是更改一些項目專用的配置了。下面我們一步步說明需要做哪些更改:
新增環境變量。具體操作如下圖所示:
環境變量下原有的兩個 CMD、PWD 我們不用管它(PATH 變量默認也應該有,不知為何我這里沒有)。我們最終需要新增三個環境變量 ARCH、CROSS_COMPILE、PATH(如果沒有的話),其中, ARCH 和 CROSS_COMPILE 就是我們使用命令行編譯時指定的。PATH 主要是告訴 eclipse 我們是用的工具的位置。
??這里需要特殊注意 PATH 的值。我們需要先通過上面的 Variables 找到系統 PATH 變量,然后點擊 OK,此時,eclipse 就會導入系統環境變量的值。我們需要編輯它,在其中添加我們自己的編譯工具鏈位置(我這里是 /usr/share/gcc-arm-none-eabi-10.3.2021.10/bin,注意,bin 目錄不止一個),否則在編譯時會提示找不到相關工具。注意,如果在上面說的全局設置中已經添加了編譯器的路徑,這里不用再次添加。 最終添加后如下所示:
我們添加的編譯器路徑用于讓 eclipse 找到編譯器,其他原有的系統環境變量可以讓 eclipse 找到 make 程序。此外,最下面的 Append xxx 這句不要去掉。
更改我們使用的編譯工具鏈以及選擇使用的芯片。
如果沒有配置全局編譯器路徑,這里必須單獨配置;如果設置了這里就會自動讀取全局設置的編譯工具鏈,查看一下是否正確即可。如果這里選擇了芯片,在調試的時候會省略一些配置。
[可選] 不使用 CDT 內建的編譯工具鏈的相關設置(因為我們更換了編譯工具鏈),注意,這里不更換也沒啥問題!
新增我們自己的編譯工具鏈的頭文件路徑。每一個編譯工具鏈下都會有 include 文件夾用來存放編譯器使用的各種頭文件。需要注意的是, include 可能會有好幾個,最好都添加上。如果在全局中配置了編譯器路徑,eclipse 就會自動識別指定的編譯工具的相關頭文件,這里就可以不用設置。
[可選] 開啟并行編譯。就是指定 make -jn 參數(n 根據處理器來定) 。eclipse 配置如下:
[可選] 增加 make stm32f769-disco_defconfig步驟。完整的構建 U-Boot 的步驟中,第一步是生成 .config 文件,而后是 make menuconfig,最后才是 make。如果不添加到 eclipse ,則需要先用命令行執行以上步驟,否則 eclipse 會提示錯誤。
具體添加如下:
之后,我們就可以在 菜單 --> Project --> Build Targets --> Build 中直接點擊上面的配置,執行這一步了。
[可選] 修改 make clean。默認情況下,我們執行 Clean 時,使用是 make clean,而我們編譯 U-Boot 一般使用 make distclean。這個是 eclipse 默認的設置,我們可以通過如下位置進行修改:
此外,還可以參考第 6 步中新建一個 Build Targets,只是使用起來沒有上面這個方式簡單。我第 6 步的圖示中已經建立好了!
編譯
經過以上步驟,完整的 U-Boot 編譯環境就搭建好了,接下來就可以在 eclipse 中構建 U-Boot 了。
調試 U-Boot
J-Link 連接開發板
??調試之前肯定是先把 J-Link 連接到開發板(開發板上有個 20 針腳的 JTAG/SWD 調試接口),確保連接正確。測試連接具體可以使用我們安裝的 J-Link 驅動里相應的工具:JFlashExe,新建一個 STM32F769 芯片的項目,然后連接一下:
提示 Connected successfully 即可。
eclipse 調試相關配置
??連接沒有問題之后,接下來就是配置 eclipse 了:菜單 --> Run --> Debug Configuration...,總的來說配置并不麻煩,我這里使用是 J-Link,因此,選擇 GDB SEGGER J-link Debugging,然后點擊上面的新建圖標(或者直接雙擊 GDB SEGGER J-link Debugging)就會出現一個新的配置,具體步驟如下圖所示:
??需要注意的就是選擇 C/C++ Application 這一項,我們需要從眾多執行程序中選擇出我們最終需要 u-boot(這個是最終編譯出的帶調試信息的,不是 u-boot.bin。具體見博文U-Boot 之三 U-Boot 源碼文件解析及移植過程詳解)。接下來就是配置界面中剩下的Debugger、Startup、Source、Common、SVD Path 這 5 個 Tab 頁面內容,下面我直接上圖來說明每個頁面需要的配置:
如果已經在全局配置中設置了J-Link 的路徑,這里默認是會自動讀取全局的配置的 J-Link,不用更改也可以。當然這里再選擇一下肯定沒有問題。芯片類型如果在構建時選擇了芯片,這里也會自動填上選擇的芯片。還有就是 Startup --> Setbreakpoint at: 這個默認是 mian,但是 U-Boot 默認沒有 main,這里根據實際情況選擇。直接 reset,簡單粗暴!還有可以使用 _main。
如果按照前面說的安裝了 CMSIS-Packs,那么這里就可以找到對應芯片的 SVD 文件,選擇 SVD 文件之后,我們在調試時就可以查看外設寄存器的值,否則將無法查看!如下圖所示:
??注意,eclipse 寄存器分為兩部分:Registers 窗口中是 ARM Cortex 核的寄存器(例如,R0、PC),Peripherals 下面就是我們的 SVD 文件中描述的外設寄存器。
U-Boot 調試修改
開啟調試選項
??默認情況下,U-Boot 的編譯已經進行了優化,且默認并不開啟調試的,因此我們需要更改一下 U-Boot 的配置。第一個是需要取消 General Setup --> Optimise for size,在一個就是開啟 General Setup --> Configure standard U-Boot features (expert users) -> enable debug information for tools,具體如下圖所示:
??這里需要注意,如果使用 make distclean 會清理所有文件,這就會導致以上的配置被清理!所以除非必要,否則還是使用 make clean 好一些。目前來看 make menuconfig 這一步還是需要在終端中執行。
??警告:目前我在測試中發現,去掉 General Setup --> Optimise for size 可能導致程序無法運行,暫時沒找到解決方法!我目前是在僅開啟了 General Setup --> Configure standard U-Boot features (expert users) -> enable debug information for tools 的情況進行調試的。就是偶爾會出現斷點位置不正確,不影響正常調試!
??這里有個比較嚴重的問題,去掉 General Setup --> Optimise for size 之后,會導致程序變大,從而原來默認的 SPL 的大小(0x8000)不能容納實際 SPL 大小,進一步導致了 U-Boot 無法啟動。因此,這里我們必須要修改 U-Boot 的基地址。目前,有如下地方需要修改(圖里面的 stm32f769-eval 是我移植的,上文暫時還沒有更換):
修改設備樹配置
??接下來還有個問題:在啟動調試之后,調試的程序在調試時只能執行一部分代碼,此后就會失敗,而且如果不調試想要直接運行是無法直接啟動!具體現象如下圖所示:
根本原因是由于調試的程序有沒有設備樹!默認情況下,U-Boot 的可執行程序是 bin 后拼接上 dtb 組成的,而我們調試的程序只有 bin,沒有 dtb!解決方法如下有如下兩種:
- 將設備樹直接編譯進 U-Boot 的 bin 文件中,而不是將 設備樹單獨出來!U-Boot 本身就有這方面的配置,具體如下:
如果執行過 make distclean 那么每次都需要重新配置上面的選項。 - 在 eclipse 中指定設備樹地址。如果使用的是 U-Boot 默認的分離設備樹模式,那么在編譯成功之后,會在源碼的根目錄下生成 u-boot.dtb ,這個就是設備數編譯之后的文件,而我們可執行程序的結束地址可以從源碼的根目錄下的 u-boot.map 文件中的 __end 符號找到。
有了 u-boot.dtb 和 __end 之后,我們就可以在 eclipse 中通過命令來解決:
如果 U-Boot 的可執行程序大小有變化,每次都需要更改這里!而且在剛開始啟動調試時,eclipse 會報一個錯誤,稍等一會即可正常進入調試。
??經過以上兩種方法的任意一種,再次啟動調試時,就可以正常執行 board_inti_f 這個函數了!注意,由于這個函數里包含很多接口,執行速度可能有些慢!
重定位配置
??接下來的問題就是內存重定位,U-Boot 中存在一段內存重定位的代碼,重定位之后將導致調試失敗!這主要是因為,在重定位之后,eclipse 正確加載符號表中的各符號。
??目前,我還沒有找到比較好的解決方法,官網推薦的方法是 使用 gdb 命令行來手動加載符號表 。命令非常簡單:add-symbol-file u-boot 重定位后的地址。重定位后的地址就位于 gd 中的成員變量 unsigned long relocaddr; 中。
調試
??經過上面的配置之后,我們就可以使用 eclipse 對 U-Boot 進行調試了。這里需要注意的是,我們調試的如果是 U-Boot 本身,需要現將 SPL 燒寫好,當然我們也可以調試 SPL。啟動調試如下圖所示:
參考
總結
以上是生活随笔為你收集整理的U-Boot 之二 详解使用 eclipse + J-Link 进行编译及在线调试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: U-Boot 之一 零基础编译 U-Bo
- 下一篇: U-Boot 之三 U-Boot 源码文