:官方資料體系與實(shí)戰(zhàn)避坑指南)
提到GD32不少人的第一反應(yīng)是“國產(chǎn)STM32”。這句話對也不全對。真正把GD32從選型到畫板再到寫代碼完整走一遍之后你會(huì)發(fā)現(xiàn)它是一套獨(dú)立的MCU產(chǎn)品線——內(nèi)核可能是Cortex-M3/M4甚至RISC-V外設(shè)寄存器和固件庫有自己的命名邏輯和設(shè)計(jì)習(xí)慣官方資料體系也完全是自成一套。從選型手冊到數(shù)據(jù)手冊從用戶手冊到固件庫User Guide再到應(yīng)用筆記和勘誤表文檔量非常驚人。很多新人一上來就在網(wǎng)上亂搜搜到哪個(gè)看哪個(gè)結(jié)果光是引腳復(fù)用表就看得一頭霧水更別提Keil里怎么配調(diào)試器、Linux下怎么編譯鏈接、以及“Code Flash和Flash到底哪里不一樣”這類細(xì)節(jié)問題。這篇文章不打算教你背手冊而是把我自己整理出來的GD32官方資料學(xué)習(xí)體系完整拆開講一遍型號(hào)怎么選、原理圖PCB怎么畫、軟件開發(fā)怎么入門、用戶手冊怎么讀才對路。適合正在接觸GD32的嵌入式工程師也適合想從STM32遷移過來的朋友。我會(huì)把一些實(shí)際工程里踩過的坑一起放進(jìn)來照著走能省不少事。1. 先把GD32的官方資料體系摸清楚1.1 五類文檔各有各的用途GD32官方資料體系和很多MCU廠商一樣是分層的。第一層是選型手冊作用是幫你在幾十個(gè)型號(hào)里圈出候選第二層是數(shù)據(jù)手冊包含引腳定義、電氣特性、封裝尺寸這是畫原理圖時(shí)必須逐頁核對的文件第三層是用戶手冊也就是寄存器級別的外設(shè)說明寫驅(qū)動(dòng)、查寄存器映射都得靠它第四層是固件庫用戶指南對應(yīng)官方固件庫的API說明做應(yīng)用開發(fā)時(shí)反而最先用到第五層是勘誤表和應(yīng)用筆記這個(gè)我建議每個(gè)人都下載別跳過。這五類文檔的分工很容易理解選型階段看選型手冊和數(shù)據(jù)手冊的概述部分硬件設(shè)計(jì)階段盯著數(shù)據(jù)手冊的引腳和電氣特性軟件開發(fā)階段以固件庫指南和用戶手冊為主遇到“為什么芯片行為跟手冊對不上”的問題時(shí)再翻勘誤表。實(shí)際工作中我發(fā)現(xiàn)很多人卡住不是因?yàn)椴欢夹g(shù)而是文檔看錯(cuò)了對象。比如引腳復(fù)用功能數(shù)據(jù)手冊里的復(fù)用表才是最終依據(jù)網(wǎng)上很多博客抄來抄去容易漏掉細(xì)節(jié)還是要以官方文件為準(zhǔn)。1.2 資料去哪下載版本怎么管GD32官方資料主要在官網(wǎng)的“資料下載”板塊通常需要注冊賬號(hào)后下載。這里有個(gè)小建議除了數(shù)據(jù)手冊和用戶手冊固件庫也要一起下載并且留意修訂版本號(hào)。GD32固件庫從最早的V1.0到現(xiàn)在的V2.0甚至更高API變化不小你下載的版本要和芯片型號(hào)對得上。另外提醒一句網(wǎng)絡(luò)上搜“GD32用戶手冊”很容易被各種轉(zhuǎn)載和SEO文章干擾我甚至見過有人搜出來一個(gè)UI設(shè)計(jì)工具的用戶手冊純屬浪費(fèi)時(shí)間。正確做法是直接在官網(wǎng)按型號(hào)分類下載保存到本地建一個(gè)固定目錄。我的習(xí)慣是這樣每個(gè)項(xiàng)目建一個(gè)“doc”文件夾里面按“01_選型”“02_數(shù)據(jù)手冊”“03_用戶手冊”“04_固件庫”“05_勘誤表”分類這樣無論做到哪個(gè)階段都能快速定位。版本號(hào)一定要記錄在項(xiàng)目文檔里否則固件庫升級后代碼編譯報(bào)錯(cuò)你都不知道是哪里變了。還有一點(diǎn)容易被忽略勘誤表。芯片廠商會(huì)在勘誤表里列出已經(jīng)發(fā)現(xiàn)但尚未修復(fù)的硬件問題比如某個(gè)定時(shí)器在特定條件下會(huì)產(chǎn)生額外中斷、某個(gè)外設(shè)的寄存器在復(fù)位后有異常值等。我見過不止一個(gè)工程師排查了好幾天最后發(fā)現(xiàn)是勘誤表里早就寫明的問題。所以拿到一個(gè)新型號(hào)第一件事就是下載勘誤表通讀一遍。2. MCU選型別等畫完板子再回來改芯片2.1 GD32產(chǎn)品家族速覽GD32的產(chǎn)品線比很多人想象中豐富。以常見系列來說GD32F1x0是Cortex-M3內(nèi)核的入門款主頻從72MHz到108MHzFlash從16KB到128KB適合簡單控制類應(yīng)用GD32F10x是經(jīng)典的STM32F103兼容系列也是市面上資料最多的型號(hào)GD32F3x0是Cortex-M4內(nèi)核主頻能到120MHz性價(jià)比很高我用過幾次性能和價(jià)格平衡得不錯(cuò)GD32F30x是增強(qiáng)型Cortex-M3主頻可以到120MHz外設(shè)資源更豐富GD32F4xx是Cortex-M4F帶硬件浮點(diǎn)和更高主頻部分型號(hào)還帶以太網(wǎng)MAC適合做需要聯(lián)網(wǎng)的復(fù)雜應(yīng)用另外還有低功耗的GD32E系列和RISC-V內(nèi)核的GD32VF103系列。選型時(shí)最忌諱只看主頻和Flash大小。我的做法是先列一個(gè)外設(shè)需求清單比如需要幾個(gè)串口、幾個(gè)SPI、是否需要CAN、是否需要USB或以太網(wǎng)然后拿著選型手冊逐項(xiàng)比對。選型手冊里通常有每個(gè)系列的外設(shè)配置表一眼就能看出哪些型號(hào)帶你想要的功能塊。2.2 選型要素與接口兼容性具體選型時(shí)這幾點(diǎn)要重點(diǎn)看。第一是Flash和RAM這兩個(gè)決定了代碼復(fù)雜度和內(nèi)存開銷第二是封裝GD32從QFN20到BGA144都有小封裝適合空間受限的產(chǎn)品但對PCB工藝要求更高第三是溫度等級工業(yè)級和商業(yè)級的差價(jià)不大但環(huán)境惡劣時(shí)一定要選工業(yè)級第四是外設(shè)資源比如定時(shí)器有幾個(gè)、ADC通道數(shù)夠不夠、DMA通道數(shù)是否充足第五是供貨和價(jià)格這個(gè)我就不展開了但做過量產(chǎn)的人都知道有時(shí)候選型選得再好供應(yīng)鏈不支持也是白搭。還有一個(gè)非常實(shí)際的考量和STM32的兼容性。GD32早期很多型號(hào)在引腳上兼容STM32這意味著如果你的產(chǎn)品原來用的是STM32遷移到GD32時(shí)PCB改動(dòng)的成本很低。但要注意兼容不等于完全一樣。外設(shè)寄存器地址可能相同但某些寄存器位的行為、復(fù)位值、甚至?xí)r鐘樹結(jié)構(gòu)會(huì)有差異。別想當(dāng)然地以為“兼容就是替代”實(shí)際遷移時(shí)一定要對照GD32的用戶手冊重新檢查外設(shè)初始化代碼。我以前做過一個(gè)項(xiàng)目原方案是STM32F103想遷移到GD32F103系列。一開始代碼直接燒進(jìn)去大部分功能能跑但ADC的采樣結(jié)果一直不對后來發(fā)現(xiàn)GD32的ADC校準(zhǔn)方式和STM32不一樣。這種事情很常見。所以選型時(shí)就要有心理預(yù)期兼容只是降低遷移成本不是零成本遷移。3. 原理圖與PCB設(shè)計(jì)數(shù)據(jù)手冊里藏著答案3.1 最小系統(tǒng)設(shè)計(jì)要點(diǎn)GD32的最小系統(tǒng)設(shè)計(jì)說簡單也簡單說容易踩坑也容易踩坑。先看電源部分。數(shù)字電源引腳DVDD和模擬電源引腳AVDD都需要去耦電容一般每個(gè)電源引腳放一個(gè)100nF電容靠近引腳放置另外再放一個(gè)10uF的鉭電容或者陶瓷電容做儲(chǔ)能。AVDD建議通過磁珠或小電感從DVDD隔離出來這樣可以降低數(shù)字噪聲對模擬電路的影響。如果系統(tǒng)里還有ADC、DAC這類模擬外設(shè)電源的潔凈度直接決定采樣精度。復(fù)位電路NRST引腳接一個(gè)10kΩ上拉電阻到VDD再加一個(gè)100nF電容到地這是最常見的配置。如果系統(tǒng)對復(fù)位可靠性要求高可以加一個(gè)復(fù)位監(jiān)控芯片但大多數(shù)情況下RC復(fù)位就夠了。調(diào)試接口建議把SWD的SWDIO、SWCLK加上拉電阻并引出SWDIO上拉10kΩ、SWCLK下拉10kΩ也行這樣調(diào)試器連接更穩(wěn)定。有些設(shè)計(jì)還會(huì)在SWDIO和SWCLK上串聯(lián)33Ω電阻對信號(hào)質(zhì)量有幫助。晶振電路要重點(diǎn)說。GD32大多數(shù)型號(hào)的HSE支持4MHz到32MHz官方典型配置是8MHz或25MHz。晶振兩端的匹配電容需要根據(jù)晶振的負(fù)載電容計(jì)算CL (C1 * C2) / (C1 C2) 寄生電容。如果C1和C2相等都取18pF負(fù)載電容大約就是9pF加上3~5pF寄生電容約12~14pF。具體值以晶振手冊為準(zhǔn)。我不想在這里給出唯一答案因?yàn)椴煌д竦钠ヅ潆娙菘赡懿詈芏唷.婸CB時(shí)晶振要靠近MCU走線盡量短并且周圍用地包起來避免干擾。BOOT引腳的處理也很重要。GD32有BOOT0和BOOT1引腳決定啟動(dòng)模式。量產(chǎn)設(shè)計(jì)中通常將BOOT0通過10kΩ下拉到地BOOT1不用特別處理內(nèi)部下拉即可。但如果你的產(chǎn)品需要ISP下載BOOT0引腳的跳線或者焊盤就得保留方便后續(xù)維護(hù)。3.2 PCB布局布線經(jīng)驗(yàn)PCB部分核心原則是模擬地和數(shù)字地要有完整的參考平面但不要切割得支離破碎。經(jīng)常會(huì)看到新手工程師把地平面劃成好幾塊結(jié)果回流路徑斷裂EMI反而更差。我自己的習(xí)慣是整塊地平面盡量保持完整必要時(shí)在模擬區(qū)域外圍保留一個(gè)縫隙然后單點(diǎn)連接但只在確有噪聲問題時(shí)才這么做。晶振底下不要走信號(hào)線這是鐵律。電源走線要足夠?qū)捀鶕?jù)電流大小計(jì)算1mm寬走線大約能過1A電流但最好留兩倍余量。去耦電容一定要靠近MCU電源引腳否則高頻噪聲濾不掉。如果有以太網(wǎng)PHYMII/RMII接口的信號(hào)線要對等長控制特別是TX_CLK、RX_CLK這類時(shí)鐘信號(hào)。官方提供的參考設(shè)計(jì)PCB文件非常值得參考。不要自己悶頭畫先下載官方評估板的原理圖和PCB按照它的布局思路來然后再根據(jù)產(chǎn)品需求調(diào)整。我用過的GD32F303評估板設(shè)計(jì)就很規(guī)范直接抄它的電源和晶振部分省了很多試錯(cuò)時(shí)間。這里補(bǔ)充一個(gè)細(xì)節(jié)GD32F4xx系列的部分型號(hào)帶以太網(wǎng)MAC但PHY需要外接。選PHY的時(shí)候要留意RMII接口的時(shí)鐘是從哪來的——有的PHY用自己的50MHz晶振有的需要MCU提供50MHz參考時(shí)鐘。這個(gè)在原理圖設(shè)計(jì)階段就要定清楚不然后期調(diào)試網(wǎng)絡(luò)功能會(huì)非常痛苦。4. 軟件開發(fā)入門工具鏈怎么選固件庫怎么用4.1 開發(fā)工具選型Embedded Builder、Keil還是別的GD32的軟件開發(fā)方式主要有三種官方IDE、Keil MDK、命令行GCC工具鏈。先說官方IDE也就是GD32 Embedded Builder它基于Eclipse和GCC工具鏈內(nèi)置了工程向?qū)Э梢园葱酒吞?hào)生成帶固件庫的標(biāo)準(zhǔn)工程。它的好處是免費(fèi)而且官方更新很勤新器件支持快適合不想折騰授權(quán)的新手。不足之處是界面熟悉度不如Keil插件偶爾會(huì)有小問題但不影響使用。Keil MDK是絕大多數(shù)嵌入式工程師最熟悉的工具。要在Keil里開發(fā)GD32需要安裝GD32的設(shè)備支持包Pack這個(gè)可以從Keil官網(wǎng)或GD32官網(wǎng)下載安裝包。裝好后新建工程時(shí)芯片列表里就能找到GD32的型號(hào)。Keil的優(yōu)點(diǎn)是調(diào)試體驗(yàn)成熟、資料多、網(wǎng)上能搜到大量工程模板比較適合從STM32遷移過來的開發(fā)者。缺點(diǎn)是商業(yè)版需要授權(quán)而且對GCC工具鏈支持不如Eclipse系方便。關(guān)于“GD32在Keil里怎么配置”其實(shí)核心就兩步第一步裝Device Pack第二步在工程選項(xiàng)里選對芯片型號(hào)并確認(rèn)調(diào)試器識(shí)別到的是Cortex-M內(nèi)核。如果Keil里編譯宏定義不對比如芯片型號(hào)選錯(cuò)導(dǎo)致啟動(dòng)文件不匹配燒錄后大概率跑不起來。我個(gè)人對工具選型的建議是新項(xiàng)目用GD32 Embedded Builder圖個(gè)省心團(tuán)隊(duì)協(xié)作或遷移項(xiàng)目用Keil圖一個(gè)熟悉度Linux環(huán)境下開發(fā)就直接走GCC命令行后面會(huì)詳細(xì)說。IAR也能用但我用得少這里不展開。4.2 Code Flash和Flash有什么區(qū)別“GD32 Code Flash和Flash有什么區(qū)別”這個(gè)問題幾乎每個(gè)接觸GD32F3x0系列的工程師都會(huì)問。簡單說GD32F3x0系列芯片內(nèi)部有兩種獨(dú)立的Flash區(qū)域Code Flash是主存儲(chǔ)區(qū)用來放程序代碼容量較大比如64KB、128KBData Flash是獨(dú)立的數(shù)據(jù)存儲(chǔ)區(qū)容量較小通常只有1KB到4KB用來存放用戶參數(shù)、校準(zhǔn)數(shù)據(jù)等可以像EEPROM一樣使用。這兩種Flash在物理上是分開的操作方式也不同。Code Flash通過FMC控制器進(jìn)行擦寫編程時(shí)需要先設(shè)置頁地址再寫入數(shù)據(jù)Data Flash也有自己的一套寄存器操作流程有些型號(hào)甚至可以直接用字編程和頁擦除。最關(guān)鍵的差異是擦寫壽命Data Flash的擦寫次數(shù)通常遠(yuǎn)高于Code Flash比如Code Flash標(biāo)稱1萬次擦寫Data Flash可能標(biāo)稱10萬次。所以不要拿Code Flash當(dāng)EEPROM頻繁擦寫否則芯片很快就報(bào)廢了。實(shí)際工程中踩過的坑有人為了省事把配置參數(shù)直接寫到Code Flash的末尾地址程序每次啟動(dòng)時(shí)讀取。這個(gè)過程本身沒問題但如果參數(shù)更新頻率高Code Flash的壽命很快就會(huì)被耗盡而且萬一寫入過程中掉電主程序區(qū)可能被破壞芯片直接變磚。更穩(wěn)妥的做法是優(yōu)先使用Data Flash或者外掛EEPROM只有當(dāng)Data Flash容量不夠時(shí)才考慮Code Flash并且要做好磨損均衡和掉電保護(hù)。另外要注意地址映射。我在GD32F330上做過的項(xiàng)目里Code Flash的起始地址是0x08000000Data Flash的地址則在0x1FFFF000附近具體型號(hào)有差異以用戶手冊為準(zhǔn)。初始化代碼里如果錯(cuò)誤地把Data Flash地址當(dāng)成了普通Flash讀取讀回來的數(shù)據(jù)是亂的這個(gè)問題排查起來相當(dāng)費(fèi)勁。4.3 Linux下編譯GD32項(xiàng)目很多開發(fā)和服務(wù)器環(huán)境是Linux這時(shí)候就不能用Keil了需要走GCC工具鏈。Linux下編譯GD32項(xiàng)目的基本思路是安裝arm-none-eabi-gcc工具鏈準(zhǔn)備啟動(dòng)文件、鏈接腳本、固件庫源碼和應(yīng)用程序代碼然后寫一個(gè)Makefile或者CMakeLists完成編譯鏈接。先說工具鏈Ubuntu或Debian系統(tǒng)直接安裝gcc-arm-none-eabi包即可。GD32F4xx這類帶硬件浮點(diǎn)的型號(hào)編譯選項(xiàng)里要加上-mfloat-abihard和-mfpufpv4-sp-d16少了這兩個(gè)選項(xiàng)一旦代碼里用了浮點(diǎn)運(yùn)算程序直接進(jìn)HardFault連調(diào)試器都很難抓到原因。工程結(jié)構(gòu)上官方固件庫提供了標(biāo)準(zhǔn)外設(shè)庫源碼放在Firmware目錄下一般包含Core內(nèi)核相關(guān)、Peripheral外設(shè)驅(qū)動(dòng)和Device芯片啟動(dòng)文件及系統(tǒng)初始化。啟動(dòng)文件startup_gd32fxxx.s和鏈接腳本gd32fxxx_flash.ld是必須配好的。Makefile里有幾個(gè)關(guān)鍵點(diǎn)編譯標(biāo)志中的-mcpu要對應(yīng)內(nèi)核型號(hào)比如Cortex-M4就寫-mcpucortex-m4 -mthumb鏈接腳本里的FLASH和RAM起始地址、大小必須與數(shù)據(jù)手冊一致堆棧大小也要根據(jù)應(yīng)用需求設(shè)置。簡單列一個(gè)Makefile片段方便大家參考CROSS_COMPILE arm-none-eabi- CC $(CROSS_COMPILE)gcc OBJCOPY $(CROSS_COMPILE)objcopy CPU_FLAGS -mcpucortex-m4 -mthumb -mfloat-abihard -mfpufpv4-sp-d16 CFLAGS $(CPU_FLAGS) -Os -Wall -I./Firmware -I./User LDFLAGS -T ./Device/gd32f4xx_flash.ld $(CPU_FLAGS) --specsnano.specs OBJS $(SRCS:.c.o) $(TARGET).elf: $(OBJS) $(CC) $(LDFLAGS) -o $ $^ $(TARGET).bin: $(TARGET).elf $(OBJCOPY) -O binary $ $編譯命令就是make燒錄命令可以用OpenOCD連接J-Link或ST-Link也可以用官方命令行工具。OpenOCD對GD32的支持已經(jīng)比較完善配置好interface和target后燒錄和調(diào)試都能在終端里完成。Linux下編譯遇到最多的問題是啟動(dòng)文件和鏈接腳本版本對不上。有一次我從老項(xiàng)目里復(fù)制鏈接腳本芯片卻是新型號(hào)RAM起始地址偏移了結(jié)果程序能編譯通過但一運(yùn)行就崩潰。后來仔細(xì)核對才發(fā)現(xiàn)是RAM地址不對。所以每次換芯片型號(hào)啟動(dòng)文件和鏈接腳本一定要從官方固件庫對應(yīng)版本重新拿不要復(fù)用舊文件。5. 用戶手冊這樣讀才高效5.1 文檔閱讀順序與方法GD32用戶手冊動(dòng)輒上千頁不可能也不應(yīng)該從頭到尾一遍一遍啃。我的閱讀順序是先看數(shù)據(jù)手冊的第一章產(chǎn)品概述了解這芯片有什么外設(shè)、主頻多少、Flash和RAM多大然后直接跳到引腳定義章節(jié)對照原理圖逐個(gè)確認(rèn)引腳功能。畫原理圖和PCB階段我會(huì)反復(fù)翻數(shù)據(jù)手冊的電氣特性章節(jié)確認(rèn)電源電壓范圍、IO的電平特性和驅(qū)動(dòng)能力。到了寫代碼階段才開始看用戶手冊。但也不是通讀而是按外設(shè)模塊來查。比如要配置DMA就只看DMA這一章關(guān)注寄存器描述、傳輸模式、通道映射然后對照固件庫里的dma.c代碼看看初始化函數(shù)具體操作了哪些寄存器。這樣把手冊“翻譯”成代碼的效率高得多。固件庫用戶指南是連接手冊和代碼的橋梁。里面會(huì)告訴你每個(gè)API的作用、參數(shù)含義、返回值以及使用注意事項(xiàng)。我建議寫代碼前先快速翻一遍固件庫指南的目錄知道有哪些API可用用到時(shí)再查細(xì)節(jié)比對著手冊從寄存器開始寫要快得多。再說一次勘誤表。每次新接觸一個(gè)型號(hào)先把勘誤表過一遍把和自己項(xiàng)目相關(guān)的部分標(biāo)注出來。比如某個(gè)定時(shí)器的輸入捕獲模式下存在可能少采一個(gè)脈沖的問題你的項(xiàng)目恰好用到捕獲就要提前想好規(guī)避方案而不是等測試時(shí)才發(fā)現(xiàn)。還有個(gè)小技巧遇到“手冊上說功能應(yīng)該正常但實(shí)際表現(xiàn)不正常”的情況不要急著懷疑硬件先把勘誤表翻完再動(dòng)手。有一次我調(diào)網(wǎng)絡(luò)功能調(diào)了兩天最后發(fā)現(xiàn)是MAC的DMA描述符對齊要求勘誤表里寫得明明白白之前沒仔細(xì)看白白浪費(fèi)了時(shí)間。5.2 以太網(wǎng)接收描述符怎么理解“GD32 網(wǎng)絡(luò)接收描述符”這個(gè)關(guān)鍵詞說明有不少人在做帶以太網(wǎng)的項(xiàng)目。GD32F4xx系列內(nèi)置的以太網(wǎng)MAC通過DMA收發(fā)數(shù)據(jù)DMA描述符是整個(gè)傳輸機(jī)制的核心。簡單理解描述符就是一塊內(nèi)存區(qū)域里面記錄了一幀數(shù)據(jù)的緩沖區(qū)地址、數(shù)據(jù)長度、狀態(tài)等信息。發(fā)送和接收各有一組描述符形成環(huán)形隊(duì)列。接收描述符里最重要的字段是OWN位它由DMA和軟件輪流控制。初始化時(shí)軟件把描述符準(zhǔn)備好置OWN位為1表示DMA可以使用該描述符當(dāng)DMA收到網(wǎng)絡(luò)數(shù)據(jù)會(huì)自動(dòng)把數(shù)據(jù)寫入描述符指向的緩沖區(qū)然后清掉OWN位軟件輪詢或中斷里發(fā)現(xiàn)OWN位為0就知道有一幀數(shù)據(jù)到了可以處理了。處理完畢重新置OWN位為1把描述符還給DMA。理解這個(gè)機(jī)制后網(wǎng)絡(luò)驅(qū)動(dòng)的問題就好排查了。網(wǎng)上有人問“為什么接收不到數(shù)據(jù)”90%的情況要么是描述符沒有正確初始化要么是描述符的環(huán)形隊(duì)列長度不匹配要么是OWN位狀態(tài)混亂了。實(shí)際調(diào)試時(shí)可以先查看描述符的狀態(tài)位確認(rèn)DMA是否真的收到了幀如果描述符狀態(tài)是0x80000000說明OWN位還屬于DMA數(shù)據(jù)可能還在接收過程中。我還遇到過一個(gè)情況開啟DMA中斷后網(wǎng)絡(luò)收包很卡。排查發(fā)現(xiàn)是中斷服務(wù)函數(shù)里處理時(shí)間太長導(dǎo)致下一個(gè)包覆蓋了緩沖區(qū)。解決方案是使用雙緩沖區(qū)機(jī)制或者描述符數(shù)量設(shè)置多一些確保DMA有足夠的緩沖可用。這些細(xì)節(jié)在用戶手冊的以太網(wǎng)章節(jié)都有說明只是需要靜下心來看。6. 實(shí)戰(zhàn)問題排查與個(gè)人經(jīng)驗(yàn)6.1 STLink連接報(bào)Internal Command Error“GD32連接STLink報(bào)internal command error”是論壇上出現(xiàn)頻率很高的問題。首先明確一點(diǎn)STLink是STMicroelectronics的調(diào)試器目標(biāo)芯片是STM32GD32雖然是兼容設(shè)計(jì)但畢竟不是ST產(chǎn)品所以STLink對GD32的官方支持有限。Internal Command Error這個(gè)錯(cuò)誤本質(zhì)是調(diào)試器與目標(biāo)芯片之間通信失敗。最常見的原因是接線或供電問題。檢查SWDIO、SWCLK、NRST、GND這幾根線是否連接牢固SWDIO和SWCLK有沒有加上拉電阻目標(biāo)板是否獨(dú)立供電JTAG/SWD接口電壓和調(diào)試器是否匹配。這些基礎(chǔ)問題排查完之后再考慮軟件層面。在Keil里用STLink調(diào)試GD32時(shí)可以嘗試把SWD時(shí)鐘頻率調(diào)低默認(rèn)4MHz在長線上容易不穩(wěn)定降到1MHz或500kHz一般都有效。另外確認(rèn)Keil的Debug頁面里選擇的調(diào)試器型號(hào)和接口模式正確STLink要選SWD模式而不是JTAG模式。如果這些都不行還有一個(gè)辦法先按住目標(biāo)板上的復(fù)位鍵點(diǎn)Keil的運(yùn)行按鈕在運(yùn)行指令發(fā)出的瞬間松開復(fù)位鍵。這種做法能讓芯片在復(fù)位后立刻被調(diào)試器接管很多“internal command error”都是因?yàn)樾酒呀?jīng)跑飛了調(diào)試器才連上所以失敗。還有一種情況是芯片進(jìn)入了低功耗模式調(diào)試接口被關(guān)閉這時(shí)候可以嘗試給目標(biāo)板斷電再上電然后立刻連接。實(shí)測下來最穩(wěn)定的組合還是用J-Link或者GD官方調(diào)試器兼容性遠(yuǎn)好于STLink。STLink不是不能用只是需要更多耐心和運(yùn)氣。如果手頭沒有別的調(diào)試器按上面的順序逐步排查解決問題的概率還是挺高的。 這幾種情況都試過之后還不行就檢查一下Keil的“Utilities”設(shè)置確保“Reset and Run”選項(xiàng)沒有勾選或者勾選之后再取消一次。我遇到過某次固件升級后調(diào)試器始終報(bào)錯(cuò)最后發(fā)現(xiàn)是Keil工程里誤選了“Erase Full Chip”導(dǎo)致啟動(dòng)區(qū)被擦掉重新全片擦除后再燒錄就好了。6.2 新手常踩的坑速查做個(gè)速查表把實(shí)際項(xiàng)目中遇到的典型問題整理一下方便大家對照排查?,F(xiàn)象可能原因排查方法芯片不定時(shí)復(fù)位看門狗溢出、電源紋波太大先關(guān)看門狗測試再量VDD波形串口數(shù)據(jù)亂碼時(shí)鐘頻率配置錯(cuò)誤波特率分頻不準(zhǔn)核對時(shí)鐘樹確認(rèn)HSE頻率和分頻系數(shù)ADC采樣值跳動(dòng)AVDD噪聲大參考電壓不穩(wěn)檢查電源去耦A(yù)VDD加磁珠隔離程序能跑但I(xiàn)O控制無效引腳復(fù)用被其他外設(shè)占用查數(shù)據(jù)手冊引腳復(fù)用表檢查GPIO配置Keil燒錄后無法運(yùn)行啟動(dòng)文件與芯片型號(hào)不匹配更換對應(yīng)型號(hào)的啟動(dòng)文件確認(rèn)宏定義以太網(wǎng)收不到數(shù)據(jù)描述符OWN位異?;騊HY時(shí)鐘錯(cuò)誤調(diào)試DMA描述符狀態(tài)檢查PHY配置這里面最想提醒的就是引腳復(fù)用問題。GD32大部分IO引腳都有多種復(fù)用功能一個(gè)引腳可以是USART的TX也可以是SPI的SCK或者是定時(shí)器的PWM輸出。配置外設(shè)時(shí)必須先確認(rèn)這個(gè)引腳在目標(biāo)復(fù)用模式下是否可用。很多人程序?qū)懲瓴虐l(fā)現(xiàn)某個(gè)功能怎么都使能不了查來查去發(fā)現(xiàn)是引腳被另一個(gè)外設(shè)占用了。固件庫版本不一致也是常見問題。GD32不同版本的固件庫API名稱和參數(shù)可能不同。比如早期版本的庫函數(shù)和V2.0版本的庫函數(shù)在初始化外設(shè)時(shí)參數(shù)結(jié)構(gòu)體的成員名稱就不一樣。從網(wǎng)上抄一段代碼編譯報(bào)錯(cuò)不要懷疑編譯器有問題先檢查庫版本。我的建議是以官網(wǎng)最新固件庫為準(zhǔn)網(wǎng)上資料只做參考不要直接復(fù)制。最后說一下調(diào)試經(jīng)驗(yàn)的積累。我個(gè)人的習(xí)慣是每個(gè)項(xiàng)目都建一個(gè)“問題筆記”記錄遇到的現(xiàn)象、排查過程、最終原因和解決方案。比如“Internal Command Error”這個(gè)問題解決一次之后把步驟記下來下次遇到直接照著做。嵌入式開發(fā)的知識(shí)很大一部分就是這種經(jīng)驗(yàn)堆起來的多記錄、多復(fù)盤比多看幾遍手冊更有用。