??首先說一下,我之前的開發(fā)流程是:VSCode 編輯代碼 + Keil 編譯及調(diào)試 。Keil 的調(diào)試功能雖然很強大,但是多數(shù)功能需要配合 ARM 自家的 ULINKpro 才可以用,例如 Performance Analyzer、Event Viewer 等。而我手頭只有Jlink 和 ULINK 非 pro 版的…
??在最近的項目中,隨著代碼量的不斷增加,Keil 的編譯速度瓶頸越來越明顯!有的問題往往是調(diào)試一分鐘,編譯半小時!編譯過慢的問題已經(jīng)嚴(yán)重影響工作效率,于是開始尋找一個替代品!
Ozone 調(diào)試
??起初,在 SEGGER 官網(wǎng)發(fā)現(xiàn)了一個名為 Ozone 的 Jlink 專用的調(diào)試器,非常小巧,調(diào)試也挺好用。不過,它僅僅就是個 Jlink 配套的調(diào)試器,不能編譯代碼。如果使用它,開發(fā)流程就是:VSCode 編輯代碼 + Keil 編譯 + Ozone 調(diào)試 。 調(diào)試的話,需要的功能基本都是全的! ??實際情況是,Keil 本身的調(diào)試功能還是挺好用的,再單獨用 Ozone 調(diào)試似乎也沒啥必要。因此,在試用了一段時間之后,現(xiàn)在基本很少用 Ozone 調(diào)試了。
后文再講如何在 Qzone 中添加華大 MCU
SEGGER Embedded Studio
??放棄 Ozone 調(diào)試之后,無奈繼續(xù)使用 Keil 編譯及調(diào)試,然后繼續(xù)尋找代替方案。同樣在 SEGGER 官網(wǎng)轉(zhuǎn)悠的時候,發(fā)現(xiàn)了 SEGGER Embedded Studio 這個東西,試用了一下還是不錯的!
自帶多套編譯套件:GCC、Clang(LLVM)、SEGGER自家編譯套件(應(yīng)該是基于 LLVM 改的),隨便選擇使用哪個。 可以配置使用 ARM 的編譯器(Keil 自帶的 ARMCC ),這是重點!!! 因為工作環(huán)境不允許使用別的編譯器發(fā)布程序!代碼編輯功能用起來也還行(相比于 Keil 來說),與 VSCode 這一類相比還是有些遜色!比較明顯的就是代碼高亮! 非商用,免費無限制,而 Keil、IAR 均限制代碼量大小!
??在后續(xù)的了解過程中,發(fā)現(xiàn) SEGGER Embedded Studio 就是 SEGGER 買了 CrossWorks 的代碼源代碼,然后自己再加工一下改出來的!CrossWorks 本身是支持多種調(diào)試器的,SEGGER Embedded Studio 則進行了限制,只能支持自家的 Jlink!! 下面是這兩個軟件的對比圖: ??這兩者都使用在線的 Packages 來提供了對于不同廠家的 MCU 的支持。使用者可以直接從軟件的 Packages Manger 在線下載自己對應(yīng)的 MCU 支持包(和 Keil5 中的 Pack Installer 一樣的作用)!下面是 兩者的 Package Manager 的對比圖: ??從支持的 MCU 來看,CrossWorks 要更勝一籌!我覺得,說 SEGGER Embedded Studio 就是 CrossWorks 的閹割版一點都不為過!SEGGER Embedded Studio 也就比 CrossWorks 多了 SEGGER 自家基于 LLVM 的編譯套件而已!
??關(guān)于 CrossWorks 這里不多說,想要進一步了解它的自行去 CrossWorks 的官網(wǎng):https://www.rowley.co.uk/。下面我們重點來說一下 SEGGER Embedded Studio,當(dāng)然,這倆軟件的配置及項目管理方式是一模一樣的!只要搞懂其中一個,另一個肯定不在話下。
項目管理
??SEGGER Embedded Studio 的項目管理使用了 Solution + Project 的方式,相比于 Keil 的單 Project 項目管理(注:Keil 也支持 WorkSpace),不支持文件夾嵌套 不知道強多少。一個 Solution 下可以有多個 Project,Project 下可以有個多個文件或者文件夾,文件夾下又可以有文件夾或文件!但是,SEGGER Embedded Studio 的 Solution + Project 的配置卻是相當(dāng)混亂的,或者說是不容易理解的! ??上圖中,我是經(jīng)過整理之后(手動編輯了.emProject)的項目文件,默認(rèn)的項目文件是有好幾種配置的。導(dǎo)致新手根本不知道該怎么去更改配置。比如,更改 Solution 的各種配置,還是更改 Project 的各種配置。Solution 下的 Public Configuration 及 Private Configuration 下的各種配置與 Project 下的 Public Configuration 及 Private Configuration 下的各種配置有啥區(qū)別?如果在結(jié)合 .emProject 那就更難以理解了。
??根據(jù)目前我的理解,他們的范圍由大到小依次為 Solution > Project > Configuration,后者可以繼承前者的各種配置。Public Configuration 可以繼承 Private Configuration 中的各種配置,我們實際的處理(編譯調(diào)試)的項目,實際就是一個個的 Public Configuration。因此,那些通用配置一般都放在上層,下層直接繼承!
編譯套件選擇
??前面我們說過,SEGGER Embedded Studio 本身就帶了 GCC、Clang(LLVM)、SEGGER自家編譯套件(應(yīng)該是基于 LLVM 改的)這三種編譯套件,在建立項目時,我們可以根據(jù)需要選擇其中一種。但是這里有個前提,必須是 SEGGER Embedded Studio 所支持的 MCU 才可以。因為,MCU 的啟動文件是特定于編譯器的。例如,在 STM32 系列 MCU 中,都會帶有不容編譯器的啟動文件: ??除此之外,其他有些文件也是特定于開發(fā)環(huán)境的,例如,Keil(ARMCC)的分散加載文件(.sct); IAR 的 ILINK Configuration File (.icf)文件等。
SEGGER Embedded Studio 默認(rèn)(SEGGER 自家編譯套件)也是使用 .icf 文件來生成最終的 elf 文件
??很不幸的是,SEGGER Embedded Studio 目前還不支持華大的 MCU。這也就意味著,我們不能在 SEGGER Embedded Studio 中建立華大的 MCU 的項目(華大的官網(wǎng)的開發(fā)環(huán)境支持包也沒有提供對 SEGGER Embedded Studio 的支持)。
??幸運的是,SEGGER Embedded Studio 支持使用外部編譯套件,我么可以直接將 Keil 的項目文件轉(zhuǎn)成 SEGGER Embedded Studio 項目,編譯套件選擇外部的 ARMCC。 其中,選擇 MCU 型號這一步,仍然需要我們自己來處理,SEGGER 的所有工具目前都不支持華大 MCU,下面我們來講解如何處理!
添加華大 MCU 支持
??SEGGER 的所有工具目前都不支持華大 MCU 的,在選擇 MCU 的列表中,是沒有華大 MCU 的。在 SEGGER 的系列工具中(都是使用的 Jlink 的配置文件),都會有個名為 JLinkDevices.xml 的文件,這個文件,就是Jlink 支持的 MCU 的列表。注意:舊版本的 Jlink 沒有這文件! 我們可以直接編輯這個文件,將華大MCU添加進去,如下:
< Device> < ChipInfo Vendor = " O2Micro" Name = " OZ93510F160LN" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " QSPI Flash" BaseAddr = " 0x60000000" MaxSize = " 0x00020000" Loader = " Devices/O2Micro/O2Micro_OZ93510F160LN_QSPI.elf" LoaderType = " FLASH_ALGO_TYPE_OPEN" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32L176" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x2000" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_128K" BaseAddr = " 0x0" MaxSize = " 0x20000" Loader = " Devices/HDSC/FlashHC32L17X_128K.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32L136" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x2000" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_64K" BaseAddr = " 0x0" MaxSize = " 0x10000" Loader = " Devices/HDSC/FlashHC32L13X_64K.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32L130" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x2000" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_64K" BaseAddr = " 0x0" MaxSize = " 0x10000" Loader = " Devices/HDSC/FlashHC32L13X_64K.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32F030" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x2000" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_64K" BaseAddr = " 0x0" MaxSize = " 0x10000" Loader = " Devices/HDSC/FlashHC32F030_64K.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32L110x4" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x800" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_16K" BaseAddr = " 0x0" MaxSize = " 0x4000" Loader = " Devices/HDSC/FlashHC32L110_16K.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32L110x6" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x1000" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_32K" BaseAddr = " 0x0" MaxSize = " 0x8000" Loader = " Devices/HDSC/FlashHC32L110_32K.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32F003" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x800" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_16K" BaseAddr = " 0x0" MaxSize = " 0x4000" Loader = " Devices/HDSC/FlashHC32F003_16K.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32F005" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x1000" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_32K" BaseAddr = " 0x0" MaxSize = " 0x8000" Loader = " Devices/HDSC/FlashHC32F005_32K.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32L15" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x1800" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_128K" BaseAddr = " 0x0" MaxSize = " 0x20000" Loader = " Devices/HDSC/HC32L15.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32F_M14" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x2000" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_128K" BaseAddr = " 0x0" MaxSize = " 0x20000" Loader = " Devices/HDSC/HC32F_M14.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32F46x" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x10000" Core = " JLINK_CORE_CORTEX_M4" /> < FlashBankInfo Name = " Flash_512K" BaseAddr = " 0x0" MaxSize = " 0x80000" Loader = " Devices/HDSC/HC32F46x.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32L19x" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x8000" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_256K" BaseAddr = " 0x0" MaxSize = " 0x40000" Loader = " Devices/HDSC/FlashHC32L19X_256K.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32F19x" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x8000" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_256K" BaseAddr = " 0x0" MaxSize = " 0x40000" Loader = " Devices/HDSC/FlashHC32F19X_256K.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32F17x" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x4000" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_128K" BaseAddr = " 0x0" MaxSize = " 0x20000" Loader = " Devices/HDSC/FlashHC32F17X_128K.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32L17x" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x4000" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_128K" BaseAddr = " 0x0" MaxSize = " 0x20000" Loader = " Devices/HDSC/FlashHC32L17X_128K.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32F072" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x4000" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_128K" BaseAddr = " 0x0" MaxSize = " 0x20000" Loader = " Devices/HDSC/FlashHC32F072_128K.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device> < Device> < ChipInfo Vendor = " HDSC" Name = " HC32L07X" WorkRAMAddr = " 0x20000000" WorkRAMSize = " 0x4000" Core = " JLINK_CORE_CORTEX_M0" /> < FlashBankInfo Name = " Flash_128K" BaseAddr = " 0x0" MaxSize = " 0x20000" Loader = " Devices/HDSC/FlashHC32L07X_128K.FLM" LoaderType = " FLASH_ALGO_TYPE_OPEN" AlwaysPresent = " 1" /> </ Device>
添加文件該文件之后,細(xì)心地就會發(fā)現(xiàn),上面的代碼中的 Loader 指向了一個文件夾中的特定文件,這些文件就是指定的 MCU 的下載算法文件。這些文件我們可以直接從華大官網(wǎng)的 MCU 軟件包中獲得。然后放到上面寫的路徑中 Devices/HDSC 中。 這一步處理完成后,我們就可以在 SEGGER 系列工具中選擇華大的 MCU 了!
錯誤處理
??直接從 Keil 導(dǎo)入項目之后,編譯可能會報錯誤,這些錯誤基本都是因為在自己的項目(Keil)中使用了編譯編譯環(huán)境(Keil)特定的文件導(dǎo)致或者說路徑變化導(dǎo)致的!下面我說一下我遇到的幾個問題
第一個錯誤就是路徑問題。在 Keil 中,默認(rèn)使用 Windows 路徑風(fēng)格:反斜線 ,例如: …\Directory 。而,SEGGER Embedded Studio 使用的是 Linux 路徑風(fēng)格:斜線 ,例如:…/…/Directory。如下,我的項目中有使用的命令,就會導(dǎo)致 SEGGER Embedded Studio 報錯 輸出文件夾變動導(dǎo)致的錯誤。項目在導(dǎo)入到 SEGGER Embedded Studio 后,我編譯生成的文件路徑會被放到 SEGGER Embedded Studio 定義的目錄中(配置項中可更改),同樣是上圖,文件夾變化后(歸根結(jié)底還是文件路徑變化),編譯也會報錯。我們自行做對應(yīng)的更改就可以了。
外設(shè)寄存器
??經(jīng)過上面的處理之后基本編譯 + 調(diào)試應(yīng)該沒有問題了。但是其中一個問題就是,在調(diào)試時,只能看到 CPU 的寄存器(Cortex-M 核定義的寄存器),MCU 外設(shè)寄存器還是沒有的,這里也需要我們自己來處理。
??默認(rèn)情況下,SEGGER Embedded Studio 使用的 xml 格式的外設(shè)寄存器定義文件。但是這個文件只有 SEGGER Embedded Studio 支持的 MCU 才有,我們自己添加的 MCU 是沒有這個文件的。幸運的是,SEGGER Embedded Studio 兼容 ARM 定義的 .svd 的文件,我們可以為 SEGGER Embedded Studio 指定我們 MCU 的 SVD 文件。
MCU 的 SVD 文件可以在華大官網(wǎng)的 MCU 軟件包中獲得!至此,我們應(yīng)該就可以愉快的編譯加調(diào)試了!
遺留問題
目前在調(diào)試時發(fā)現(xiàn), Watch某個變量不能正常工作,無法識別結(jié)構(gòu)體變量。
參考
SEGGER Embedded Studio 手冊
總結(jié)
以上是生活随笔 為你收集整理的华大 MCU 之六 SEGGER Embedded Studio 及 Ozone 使用 Jlink 调试 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。