1、STM32下載方法
單片機的燒錄方式主要可以分為三種,分別為ICP(In Circuit Programing)在電路編程 、ISP(In System Programing)在系統編程 以及IAP(In applicating Programing)在應用編程。
1.1、ICP(In Circuit Programing)在電路編程
ICP是指“在電路編程”,PC上運行的編程工具通過JATAG/SWD協議接口下載器更新晶片內部APROM、LDROM、數據閃存(DataFlash)和目標用戶配置字(Config)芯片。
支持JATAG/SWD協議接口的下載器有JLINK、ULINK、CMSIS-DAP、 STLINK等,這些下載器基本都帶有仿真功能。與之配套的燒錄軟件為J-Flash、NuMicro_ICP_Programming_Tool、st-link utility等。程序編譯器燒寫一般都采用仿真器,既可以燒寫也可以仿真。
(1)JTAG協議接口下載
JTAG(Joint Test Action Group,聯合測試工作組)是一種國際標准測試協議(IEEE 1149.1兼容),主要用於芯片內部測試。
現在多數的高級器件都支持JTAG協議,如DSP、FPGA器件等。標准的JTAG接口是4線:TMS、TCK、TDI、TDO,分別為模式選擇、時鍾、數據輸入和數據輸出線。
需要接線:VCC、GND、TRST---PB4、TDI---PA15、TMS/SWDIO---PA13、TCLK/SWCLK---PA14、TDO/SWO---PB3、RESET---NRST。
(2)SWD協議接口下載
用標准的 JTAG 調試,需要占用 5 個 IO 口,有些時候,可能造成 IO 口不夠用,而用 SWD則只需要 2 個 IO 口,大大節約了 IO 數量,但他們達到的效果是一樣的,所以我們強烈建議仿真器使用 SWD 模式!
SWD 只需要 2 根線(SWCLK 和 SWDIO)就可以下載並調試代碼了,這同我們使用串口下載代碼差不多,而且速度非常快,能調試。所以建議大家在設計產品的時候,可以留出 SWD 來下載調試代碼,而摒棄 JTAG。 STM32 的 SWD 接口與 JTAG 是共用的,只要接上 JTAG,你就可以使用 SWD 模式了(其實並不需要 JTAG 這么多線),當然,你的調試器必須支持 SWD 模式, JLINK V7/V8、ULINK2 和 ST LINK 等都支持 SWD 調試。
特別提醒, JTAG 有幾個信號線用來接其他外設了,但是 SWD 是完全沒有接任何其他外設的,所以在使用的時候, 推薦大家一律使用 SWD 模式!!!
需要接線:VCC、GND、TMS/SWDIO---PA13、TCK/SWCLK---PA14
(3)JTAG/SWD對比
1)SWD模式比JTAG在高速模式下面更加可靠,在大數據量的情況下JTAG下載程序會失敗,但是SWD發生的幾率會小很多,基本使用JTAG的模式下可以直接使用SWD模式的,前提是仿真器支持
2)在GPIO口剛好缺一個的時候,可使用SWD仿真,這種模式支持更少的引腳,使用SW模式PA15,PB3,PB4,都自由了就可以做普通IO口了,只用了stm32的PA13和PA14兩個口
3)在PCB設計體積有限的時候推薦使用SWD模式
1.2、ISP(In System Programing)在系統編程
(1)、 ISP 簡介
ISP,即In-System Programming,在系統編程。目標芯片使用USB/UART/SPI/I²C/RS-485/CAN周邊接口的LDROM引導代碼去更新晶片內部APROM、數據閃存(DataFlash)和用戶配置字(Config)。
ISP(In-System Programming)在系統編程,指電路板上的空白器件可以編程寫入最終用戶代碼,而不需要從電路板上取下器件,已經編程的器件也可以用ISP方式擦除或再編程。ISP技術是未來發展方向。
ISP 的實現相對要簡單一些,一般通用做法是內部的存儲器可以由上位機的軟件通過串口來進行改寫。對於單片機來講可以通過SPI或其它的串行接口接收上位機傳來的數據並寫入存儲器中。
ISP是使用STM32系統存儲器中所帶的引導程序通過USB/UART等接口進行燒錄的,ISP 下載程序的時候需要用到(bootloader)自舉程序,自舉程序存儲在 STM32 器件的內部自舉ROM 存儲器(系統存儲器)中。
其主要任務是通過一種可用的串行外設( USART、 CAN、USB、 I2C 等)將應用程序下載到內部 Flash 中。每種串行接口都定義了相應的通信協議,其中包含兼容的命令集和序列。
與仿真器相比, ISP 只能下載程序,不能在線調試且下載速度慢。 而利用調試工具比如JLINK、ULINK、STLINK 等就可以實時跟蹤程序, 從而找到程序中的bug。
(2)、 ISP 普通下載流程
現在我們針對 USART1 的 ISP 進行分析,通常的 ISP 的步驟如下:
1)、電腦通過 USB 線連接 STM32 的USART、 CAN、USB、 I2C 等,並打開電腦端的上位機;
2)、設置跳線保持 BOOT0 為高電平, BOOT1 為低電平(系統存儲器);
3)、復位單片機使其進入 bootloader 模式,通過上位機下載程序;
4)、下載完畢,設置跳線保持 BOOT0 為低電平, BOOT1 為低電平(內部FLASH);
5)、復位單片機即可啟動用戶代碼,正常運行。
以上步驟有個不好的地方就是下載程序需要跳線及復位操作,很繁瑣。通過對 ISP 的原理認識,一鍵 ISP 就誕生了,它需要做的事情就是用上位機去控制 BOOT0 腳和單片機的復位腳,原理圖如下:
(3)、開始下載
打開 mcuisp 軟件,配置如下:
1)、搜索串口,設置波特率 115200(盡量不要設置的太高)
2)、選擇要下載的 HEX 文件
3)、校驗、編程后執行
4)、DTR 低電平復位, RTS 高電平進入 bootloader
5)、開始編程。如果出現一直連接的情況,按一下開發板的復位鍵
(4) ISP 一鍵下載
USB 轉串口估計大家都很熟悉,一般都是用到 RXD 和 TXD 這兩個口,一鍵 ISP 電路中我們需要用 USB 轉串口的芯片的 DTR 口和 RTS 口來控制單片機的 BOOT0 和 NRST,原理如下:
1)、通過上位機控制 U6(CH340G)的 RTS 腳為低電平, Q1 導通, BOOT0 的電平上拉為高電平。
2)、通過上位機控制 U6(CH340G)的 DTR 腳為高電平,由於 RTS 為低電平, Q2 導通,U8 的 2 腳為低電平, U18 為一個模擬開關,使能端由 4 腳控制,默認高電平, U18的 1 腳和 2 腳導通,所以 NRST 為低電平系統復位。
3)、單片機進入 ISP 模式,此時可以將 DTR 腳設置為低電平, RTS 設置為高電平。 Q1和 Q2 為截至狀態, BOOT0 和 NRST 還原默認電平。
4)、上位機將程序下載到單片機,下載完畢之后,程序自動運行。
5)、至此,很多人還會認為 U18、 Q1、 Q2 是多余的,用 U6 的 RTS 和 DTR 直接控制也可以。正常情況下,這樣理解沒有問題,但是我們忽略了一點,就是單片機上電瞬間如果 USB 轉串口連接了電腦, DTR 和 RTS 的電平是變化的,如果不處理好,單片機會一直進入 ISP 模式,或者系統會復位多次,這種情況是不允許的。
6)、於是,就有了我們全新的一鍵 ISP 電路。我們主要是分析上電瞬間的邏輯關系,單片機上電時我們通過示波器觀察波形得知 DTR 和 RTS 的電平是變化的,但是也有一個規律就是:只要 RTS 為低電平的時候, DTR 的電平也是低,因此一般情況 Q2不會導通,但由於這兩個 IO 口的電平存在“競爭冒險”,會出現 RTS 的下降沿的時候剛好遇到 DTR 的上升沿,這個時候 Q2 導通,導致系統復位,而 BOOT0 此時有可能也為高電平,就會進入 ISP 模式。這個是不受我們控制的,我們不想系統出現這樣的情況。因此加入了模擬開關來切斷這種干擾。
7)、加入模擬開關 U18,通過控制 U18 的 4 腳的開關來達到隔離干擾電平的目的。下面我們分析一下延時開關電路,上電瞬間,電容 C65 通過電阻 R18 來充電,由於電阻 100k 很大,電容的充電電流很小,等電容充電達到 U18 的 4 腳的有效電平 2V時,大概耗時 1S,在這個 1S 時間內 U18 的模擬開關是斷開的,因此 RTS 和 DTR的干擾電平不會影響到系統復位。系統正常運行。
1.3、IAP(In applicating Programing)在應用編程
IAP(In Application Programming)即在應用編程,就是通過軟件實現在線電擦除和編程的方法。 IAP 是用戶自己的程序在運行過程中對User Flash 的部分區域進行燒寫,目的是為了在產品發布后可以方便地通過預留的通信口對產品中的固件程序進行更新升級。
通常實現 IAP 功能時,即用戶程序運行中作自身的更新操作,需要在設計固件程序時編寫兩個項目代碼,第一個項目程序不執行正常的功能操作,而只是通過某種通信方式(如 USB、 USART)接收程序或數據,執行對第二部分代碼的更新;第二個項目代碼才是真正的功能代碼。這兩部分項目代碼都同時燒錄在 User Flash 中,當芯片上電后,首先是第一個項目代碼開始運行,它作如下操作:
1)檢查是否需要對第二部分代碼進行更新
2)如果不需要更新則轉到 4)
3)執行更新操作
4)跳轉到第二部分代碼執行
第一部分代碼必須通過其它手段,如 JTAG 或 ISP 燒入;第二部分代碼可以使用第一部分代碼 IAP 功能燒入,也可以和第一部分代碼一起燒入,以后需要程序更新時再通過第一部分 IAP代碼更新。
我們將第一個項目代碼稱之為 Bootloader 程序,第二個項目代碼稱之為 APP 程序,他們存放在 STM32 FLASH 的不同地址范圍,一般從最低地址區開始存放 Bootloader,緊跟其后的就是 APP 程序(注意,如果 FLASH 容量足夠,是可以設計很多 APP 程序的,本章我們只討論一個 APP 程序的情況)。這樣我們就是要實現 2 個程序: Bootloader 和 APP。
IAP技術是從結構上將Flash存儲器映射為兩個存儲體,當運行一個存儲體上的用戶程序時,可對另一個存儲體重新編程,之后將程序從一個存儲體轉向另一個。
IAP就是通過軟件實現在線電擦除和編程的方法,沒有使用任何工具,僅僅是通過軟件的方法來更新Flash中的數據。
講述一個案例,那就是通過4G模塊來遠程更新程序。將Flash分成兩塊區域,第一塊為Boodload程序,第二塊區域存放的是應用程序APP。4G模塊和目標板通訊,通訊中包含是否更新的位,如果主板接收到需要更新的位,就往Flash中寫入一個標志位,比如'P',之后程序跳到第一段程序Boodload程序中執行,首先判斷Flash中的是否有更新程序的標志位'P',如果有則通過規定的協議進行更新應用程序中的程序,更新完畢后清除Flash中的更新標志位,跳轉到應用程序中去執行。如果沒有更新程序標志位‘P’,跳到應用程序執行。
我們先來看看 STM32 正常的程序運行流程,如下圖所示:
STM32 的內部閃存(FLASH)地址起始於 0x08000000,一般情況下,程序文件就從此地址開始寫入。此外 STM32 是基於 Cortex-M3 內核的微控制器,其內部通過一張“中斷向量表”來響應中斷,程序啟動后,將首先從“中斷向量表”取出復位中斷向量執行復位中斷程序完成啟動,而這張“中斷向量表”的起始地址是 0x08000004,當中斷來臨, STM32 的內部硬件機制亦會自動將 PC 指針定位到“中斷向量表”處,並根據中斷源取出對應的中斷向量執行中斷服務程序。
在上圖 中, STM32 在復位后,先從 0X08000004 地址取出復位中斷向量的地址,並跳轉到復位中斷服務程序,如圖標號①所示;在復位中斷服務程序執行完之后,會跳轉到我們的main 函數,如圖標號②所示;而我們的 main 函數一般都是一個死循環,在 main 函數執行過程中,如果收到中斷請求(發生重中斷),此時 STM32 強制將 PC 指針指回中斷向量表處,如圖標號③所示;然后,根據中斷源進入相應的中斷服務程序,如圖標號④所示;在執行完中斷服務程序以后,程序再次返回 main 函數執行,如圖標號⑤所示。當加入 IAP 程序之后,程序運行流程如下圖所示:
在上圖所示流程中, STM32 復位后, 還是從 0X08000004 地址取出復位中斷向量的地址,並跳轉到復位中斷服務程序,在運行完復位中斷服務程序之后跳轉到 IAP 的 main 函數,如圖標號①所示,此部分同圖 52.1.1 一樣;在執行完 IAP 以后(即將新的 APP 代碼寫入 STM32的 FLASH,灰底部分。新程序的復位中斷向量起始地址為 0X08000004+N+M),跳轉至新寫入程序的復位向量表,取出新程序的復位中斷向量的地址,並跳轉執行新程序的復位中斷服務程序,隨后跳轉至新程序的 main 函數,如圖標號②和③所示,同樣 main 函數為一個死循環,並且注意到此時 STM32 的 FLASH,在不同位置上,共有兩個中斷向量表。
在 main 函數執行過程中,如果 CPU 得到一個中斷請求, PC 指針仍強制跳轉到地址0X08000004 中斷向量表處,而不是新程序的中斷向量表,如圖標號④所示;程序再根據我們設置的中斷向量表偏移量,跳轉到對應中斷源新的中斷服務程序中,如圖標號⑤所示;在執行完中斷服務程序后,程序返回 main 函數繼續運行,如圖標號⑥所示。
通過以上兩個過程的分析,我們知道 IAP 程序必須滿足兩個要求:
1) 新程序必須在 IAP 程序之后的某個偏移量為 x 的地址開始;
2) 必須將新程序的中斷向量表相應的移動,移動的偏移量為 x;
1.3.1、APP 程序起始地址設置方法
默認的條件下,圖中 IROM1 的起始地址(Start)一般為 0X08000000,大小(Size)為 0X80000,即從 0X08000000 開始的 512K FLASH的地址空間為我們的程序存儲(因為我們的 STM32F103ZET6 的 FLASH大小是 512K)。而圖中,我們設置起始地址(Start)為 0X08010000,即偏移量為 0X10000(64K 字節),因而,留給 APP 用的 FLASH 空間(Size)只有 0X80000-0X10000=0X70000(448K 字節)大小了。設置好 Start 和 Szie,就完成 APP 程序的起始地址設置。
這里的 64K 字節,需要大家根據 Bootloader 程序大小進行選擇,比如我們的 Bootloader程序為 22K 左右,理論上我們只需要確保 APP 起始地址在 Bootloader 之后,並且偏移量為 0X200的倍數即可(相關知識,請參考: http://www.openedv.com/posts/list/392.htm)。這里我們選擇 64K(0X10000)字節,留了一些余量,方便 Bootloader 以后的升級修改。
這是針對 FLASH APP 的起始地址設置,如果是 SRAM APP,那么起始地址設置如圖 52.1.4所示:
這里我們將 IROM1 的起始地址(Start)定義為: 0X20001000,大小為 0XC000(48K 字節),即從地址 0X20000000 偏移 0X1000 開始,存放 APP 代碼。因為整個 STM32F103ZET6 的 SRAM大 小 為 64K 字 節 , 所 以 IRAM1 ( SRAM ) 的 起 始 地 址 變 為 0X2000D000( 0x20001000+0xC000=0X2000D000 ) , 大 小 只 有 0X3000 ( 12K 字 節 )。 這 樣 , 整 個STM32F103ZET6 的 SRAM 分配情況為:最開始的 4K 給 Bootloader 程序使用,隨后的 48K 存放 APP 程序,最后 12K,用作 APP 程序的內存。這個分配關系大家可以根據自己的實際情況修改,不一定和我們這里的設置一模一樣,不過也需要注意,保證偏移量為 0X200 的倍數(我們這里為 0X1000)。
1.3.2、中斷向量表的偏移量設置方法
之前我們講解過,在系統啟動的時候,會首先調用 systemInit 函數初始化時鍾系統,同時systemInit 還完成了中斷向量表的設置,我們可以打開 systemInit 函數,看看函數體的結尾處有這樣幾行代碼:
#ifdef VECT_TAB_SRAM SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */ #else SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ #endif
從 代 碼 可 以 理 解 , VTOR 寄 存 器 存 放 的 是 中 斷 向 量 表 的 起 始 地 址 。 默 認 的 情 況VECT_TAB_SRAM 是沒有定義,所以執行 SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;
對於 FLASH APP,我們設置為 FLASH_BASE+偏移量 0x10000,所以我們可以在 FLASH APP 的main 函數最開頭處添加如下代碼實現中斷向量表的起始地址的重設:
SCB->VTOR = FLASH_BASE | 0x10000;
以上是 FLASH APP 的情況,當使用 SRAM APP 的時候, 我們設置起始地址為:SRAM_bASE+0x1000,同樣的方法,我們在 SRAM APP 的 main 函數最開始處,添加下面代碼:
SCB->VTOR = SRAM_BASE | 0x1000;
這樣,我們就完成了中斷向量表偏移量的設置。
通過以上兩個步驟的設置,我們就可以生成 APP 程序了,只要 APP 程序的 FLASH 和 SRAM大小不超過我們的設置即可。不過 MDK 默認生成的文件是.hex 文件,並不方便我們用作 IAP更新,我們希望生成的文件是.bin 文件,這樣可以方便進行 IAP 升級(至於為什么,請大家自行百度 HEX 和 BIN 文件的區別!)。這里我們通過 MDK 自帶的格式轉換工具 fromelf.exe,來實現.axf 文件到.bin 文件的轉換。該工具在 MDK 的安裝目錄\ARM\BIN40 文件夾里面。
fromelf.exe 轉換工具的語法格式為: fromelf [options] input_file。其中 options 有很多選項可以設置,詳細使用請參考光盤《mdk 如何生成 bin 文件.doc》 .
本章,我們通過在 MDK 點擊 Options for Target→User 選項卡,在 After Build/Rebuild 欄,勾選 Run #1,並寫入: D:\tools\mdk5.14\ARM\ARMCC\bin\fromelf.exe --bin -o ..\OBJ\RTC.bin..\OBJ\RTC.axf。如圖 52.1.6 所示:
通過這一步設置,我們就可以在 MDK 編譯成功之后,調用 fromelf.exe(注意,我的 MDK 是安裝在 D:\tools\mdk5.14 文件夾下, 如果你是安裝在其他目錄,請根據你自己的目錄修改fromelf.exe 的路徑),根據當前工程的 RTC.axf(如果是其他的名字,請記住修改,這個文件存放在 OBJ 目錄下面,格式為 xxx.axf),生成一個 RTC.bin 的文件。並存放在 axf 文件相同的目錄下,即工程的 OBJ 文件夾里面。在得到.bin 文件之后,我們只需要將這個 bin 文件傳送給單片機,即可執行 IAP 升級。
最后再來看 APP 程序的生成步驟:
1) 設置 APP 程序的起始地址和存儲空間大小
對於在 FLASH 里面運行的 APP 程序, 我們可以按照圖 52.1.3 的設置。對於 SRAM 里面運行的 APP 程序,我們可以參考圖 52.1.4 的設置。
2) 設置中斷向量表偏移量
這一步按照上面講解,重新設置 SCB->VTOR 的值即可。
3) 設置編譯后運行 fromelf.exe,生成.bin 文件.
通過在 User 選項卡,設置編譯后調用 fromelf.exe,根據.axf 文件生成.bin 文件,用於IAP 更新。
以上 3 個步驟,我們就可以得到一個.bin 的 APP 程序,通過 Bootlader 程序即可實現更新。
1.4、總結
ICP:使用JTAG/SWD接口進行燒錄,如J-Link燒錄器和J-Flash軟件配合使用。
ISP:使用引導程序(Bootload)加上外圍UART/USB等接口進行燒錄。
IAP:軟件自身實現在線電擦除和編程的方法,不使用任何工具。程序通常分成兩塊,分別為引導程序和應用程序。