使用VisualGDB開發Keil MDK-ARM專案
前言
本教程展示瞭如何使用VisualGDB使用Keil MDK-ARM編譯器構建專案,使用VisualGDB智慧感知包括CodeMap,並使用Visual Studio除錯它。
步驟
在開始之前,確保您可以使用uVision IDE構建Keil專案
開啟Visual Studio,開始建立一個新的嵌入式VisualGDB專案:
選擇“匯入專案”和“生成Makefile”選項:
在下一頁選擇ARM工具鏈,然後選擇“手動指定標誌”,現在標誌為空:
指定包含Keil專案的目錄。如果您沒有太多的檔案,您可以選擇“顯示所有原始檔在一起”,以平展Keil目錄結構:
選擇一個除錯方法。在本例中,我們將使用STM32F411RE核子板中集成了ST-Link的OpenOCD:
不要忘記手動選擇裝置型別。當您手動指定標誌時,VisualGDB將無法檢測它。
預設情況下,VisualGDB不會匯入程式集啟動檔案(.s),因此將其複製到新的專案目錄中,並通過上下文選單將其新增到專案中:
現在我們需要從uVision專案匯入編譯器和連結器標誌。開啟uVision中的目標屬性,複製編譯器控制字串:
指定的選項需要分為3類:
- 包括目錄和前處理器巨集。這些選項對於智慧感知很重要。
- Keil-specific選項。這些選項不相容gcc,並且會產生智慧感知錯誤。
- “-c”和“-o”等指定檔名的選項。它們是由Makefile自動新增的。
下表對示例uVision專案的選項進行了分類:
首先,我們將向專案屬性新增與智慧感知相關的選項。在第一頁開啟VisualGDB專案屬性,並指定從uVision標誌中提取的目錄的定義和包含目錄:
注意,您可以指定與專案目錄相關的路徑(例如,RTE表示RTE)。
轉到Makefile Settings頁面,除去uVision flags中除了-g和-O0之外的所有gc特定的標誌(也禁用二進位制檔案生成):
稍後我們將指定特定於keil的標誌。如果您在這裡輸入它們,它將會混淆基於clang的智慧感知引擎。
按下OK。VisualGDB將重新檢查標誌並更新智慧感知。開啟原始檔,確保沒有智慧感知錯誤,語法著色工作正常:
現在,我們將更改Makefile,以使用Keil編譯器而不是GCC,並提供特定於Keil的標誌。開啟mcu.mak檔案:
mcu.mak檔案指定了編譯器工具(CC, CXX, LD和AR)和智慧感知引擎使用的公共標誌。因為我們不想破壞智慧感知,所以我們將在不同的地方指定它們,而不是修改這個檔案。在此之前,開啟Keil目標選項並注意連結器標誌:
現在我們將指定特定於keil的標誌。建立一個名為keil的檔案。mak在專案目錄中,放置剩餘的C/ c++標誌和連結器標誌,以及CC、CXX和其他工具的覆蓋:
以下是keil.mak的樣本內容:
KEIL_ROOT := C:/Keil_v5/ARM/ARMCC
CC := $(KEIL_ROOT)/bin/armcc.exe
CXX := $(CC)
LD := $(KEIL_ROOT)/bin/armlink.exe
AR := $(KEIL_ROOT)/bin/armar.exe
FROMELF := $(KEIL_ROOT)/bin/fromelf.exe
COMMONFLAGS += --cpu Cortex-M4.fp --apcs=interwork
LDFLAGS += --cpu Cortex-M4.fp
--ro-base 0x08000000
--entry 0x08000000
--rw-base 0x20000000
--entry Reset_Handler
--first __Vectors
--strict
--summary_stderr
--info summarysizes
--map
--xref
--callgraph
--symbols
--info sizes
--info totals
--info unused
--info veneers
--list "$(BINARYDIR)/stm32demo.map"
最後,我們需要調整Makefile。首先,指定“ADDITIONAL_MAKE_FILES += keil”。麥鴻崧說:“兩者之間包括以下指示:
include $(CONFIGURATION_FLAGS_FILE) ADDITIONAL_MAKE_FILES += keil.mak include $(ADDITIONAL_MAKE_FILES)
然後用“–depend”替換所有“-MD -MF”
$(BINARYDIR)/%.o : %.cpp $(all_make_files) |$(BINARYDIR) $(CXX) $(CXXFLAGS) -c $< -o [email protected] --depend $(@:.o=.dep)
如果你現在構建你的專案,你將會得到幾個錯誤關於丟失的HAL符號:
要解決這個問題,首先通過uVision找到HAL資料夾:
該資料夾中的原始檔實現了各種HAL功能:
在解決方案資源管理器中右鍵單擊,選擇Add->現有項並向專案新增HAL原始檔。然後構建你的解決方案。雙擊VisualGDB使用Keil編譯器和連結器的構建日誌:
現在按F5開始除錯程式。一旦你驗證了LED是閃爍的,在你的程式迴圈的某處設定一個斷點,並驗證你可以計算變數:
右鍵點選main()函式,開啟CodeMap,選擇“show called functions”來驗證Clang智慧感知:
由Keil連結器生成的ELF檔案有一個基本問題。如果用GDB載入它,全域性變數的值將是-1,而不是正常的初始值:
這是因為GNU和Keil連結器之間的差異。GNU連結器為資料部分計算兩個不同的地址:載入它的地址(VMA)和儲存其內容的快閃記憶體地址(LMA)。然後,GDB將節內容放在LMA地址,啟動程式碼將其複製到VMA。Keil連結器設定了LMA = VMA,因此GDB沒有將資料部分寫入FLASH中,而是直接將其放入RAM中,在RAM中會被Keil statup程式碼覆蓋,該程式碼希望它在FLASH中。為了解決這個問題,我們首先需要找到節名。arm-eabi-objdump執行。exe -x (objdump工具是GCC工具鏈的一部分):
我們將通過兩個步驟來解決這個問題:首先,我們將執行名為fromelf的Keil工具。exe將ELF檔案轉換為.bin檔案,以反映Keil工具所期望的FLASH記憶體內容:
然後,我們將使用objcopy工具編輯.elf檔案,用.bin檔案的內容替換複製到快閃記憶體中的資料。這將確保GDB將初始化資料以Keil期望的方式放入FLASH中:
經過修改的Makefile片段如下所示(片段名稱和地址取決於裝置,應該從原始elf檔案轉儲中取出):
下圖解釋了.axf (KEIL ELF)、.bin和最終.elf檔案之間的依賴關係:
現在構建專案並驗證變數是否正確初始化:
如果它們仍然被破壞,通過檢查arm-eabi-objdump工具生成的轉儲檔案,再次檢查ROM部分是否被放置在正確的地址,其大小是否與bin檔案的大小匹配:
因為我們已經手動建立了這個專案,VisualGDB不會顯示裝置的外圍暫存器。要解決這個問題,請為您的裝置建立一個普通的VisualGDB專案,並搜尋。MCUDefinitionFile元素專案目錄中的xml檔案,例如:
在%LOCALAPPDATA%VisualGDBEmbeddedBSPs中查詢檔案(它將具有.gz副檔名),並將其複製到包含mcu的目錄中。匯入Keil專案的xml檔案。然後修改mcu。xml檔案引用裝置定義檔案:
重新開始除錯您的專案,並驗證硬體暫存器現在顯示:
最後,我們將修復Keil錯誤訊息的解析。由於它們使用的語法與GCC不同,VisualGDB預設不會識別它們。您可以通過新增一個簡單的函式來重現這個問題,該函式將產生警告和錯誤,並嘗試構建您的檔案:
為了支援“, line ”格式,下載BuildMessageRegexes。xml檔案,將其儲存到您的專案目錄(或附近的任何其他目錄),並在.vgdbsettings檔案中指定它的相對路徑,如下所示:
如果您現在構建專案,Visual Studio將正確顯示錯誤和警告:
如果您正在使用VisualGDB和Keil編譯器,請在論壇中告訴我們。一旦我們收集了足夠的反饋,我們將在下一個VisualGDB版本中簡化與Keil工具的整合。