1. 程式人生 > >stm32串列埠isp

stm32串列埠isp

原文地址:https://blog.csdn.net/nicekwell/article/details/79093780

這裡介紹stm32串列埠isp實現方法,包含st官方協議整理和實現程式碼。

已提交到github https://github.com/nicekwell/stm32ISP。

概述
stm32串列埠ISP程式,基於c語言。
在ubuntu和mac下測試都ok,ubuntu下需要修改/dev/ttyUSB0許可權,mac下不需要修改。
本程式在stm32f103c8t6上ok,根據官方文件,其他型號微控制器下載協議相同,但沒有測試過。

使用方法:
stm32isp /dev/ttyUSB0 stm32_test.bin
mac下的usb串列埠節點是 /dev/tty.usbserial

注:

波特率固定為57600不允許修改。實際上測試了各種波特率,只有57600和38400可以穩定下載(程式寫的還不太穩定吧),所以波特率固定為了57600。
下載的是bin檔案,不是hex檔案。bin檔案是純粹的編碼,hex檔案包含了地址資訊。keil預設不生成bin檔案,生成bin檔案的方法可網上查詢。
廣告
老婆做畢業設計,給我下了死命令,一定要找300個程式設計師研究一下,請各位同行做個調查問卷,可掃描下面二維碼或者直接點選此連結:https://www.wjx.cn/jq/17710478.aspx,多謝!

 移除ad.jpg
下載協議
stm32官方文件已提交到本工程 documents 目錄下。https://github.com/nicekwell/stm32ISP/raw/master/documents/stm32isp%20application%20note.pdf

1、硬體
首先要讓stm32進入bootloader啟動:

引腳電平BOOT0高電平BOOT1低電平

這樣啟動後就會從system分割槽啟動,開始接收串列埠資料。

連線串列埠1:

引腳功能PA9TXD,連線host RXDPA10RXD,連線host TXD

2、sync
以下資料指的是響應host或device端傳送的資料。

hostdevicenote0x7f-傳送0x7f,微控制器收到後會自動匹配波特率。-0x79(ACK)/0x1F(NACK)device返回ACK或NACK,表示對host的反應。

適配波特率這一步是無條件執行的,執行完這一步之後就可以接收各種指令。
下面就介紹各個指令的功能和資料協議。

3、get command
在上面已經適配波特率情況下可以執行此指令。
【指令碼】0x00
【功能】獲取stm32裡bootloader版本號,以及所有支援的指令程式碼。
【資料協議】

hostdevicenote0x00 + 0xff- -0x79(ACK)/0x1F(NACK) -N1位元組,表示下面要接收到的位元組數。bootloaderversion位元組數 + 所有指令位元組數 = N+1-bootloader version1位元組,如0x21代表2.1版本-所有支援的指令多個位元組,每個位元組資料都表示一個支援的指令-0x79(ACK)/0x1F(NACK)指令執行結束後會返回0x79

4、get version & read protection
【指令碼】0x01
【功能】獲取stm32裡bootloader版本號,讀取保護狀態。
【資料協議】

hostdevicenote0x01+0xfe- -0x79(ACK)/0x1F(NACK) -bootloader version -2個位元組這兩個位元組和保護狀態有關-0x79(ACK)/0x1F(NACK) 

5、get ID command
【指令碼】0x02
【功能】獲取stm32 PID(product ID,不是晶片唯一識別碼)。
【資料協議】

hostdevicenote0x02+0xfd- -0x79(ACK)/0x1F(NACK) -N1位元組,表示下面 PID位元組數 - 1-PID多位元組(上一個位元組已指明位元組數),先傳高位後傳低位。我這次用的stm32f103c8t6是2位元組。-0x79(ACK)/0x1F(NACK) 

6、Erase Memory command
【指令碼】0x43
【功能】擦除flash,可以全擦或擦除一部分,這裡只介紹全擦。
【資料協議】

hostdevicenote0x43+0xbc- -0x79(ACK)/0x1F(NACK) 0xff+0x00-這是全擦指令-0x79(ACK)/0x1F(NACK) 

7、Write Memory command
【指令碼】0x31
【功能】
寫儲存器,可以寫任意的RAM、flash,我們寫程式就用這個。
【資料協議】

hostdevicenote0x31+0xCE- -0x79(ACK)/0x1F(NACK) addr-4位元組,下載地址。使用者flash起始地址是0x08000000。

先發高位,後發低位

addr checksum-1位元組,地址的checksum,就是上面4位元組資料的異或。-0x79(ACK)/0x1F(NACK) count-1位元組,表示後面將要傳輸的位元組數,範圍(0, 255]。

位元組數 = 這個值+1

,也就是說最大傳輸256位元組。data-多位元組,位元組數 = count + 1,最大256位元組。

這裡下載進去的是bin檔案,不是hex。。

checksum-1位元組,上面的data資料,以及資料個數count的checksum。注意這裡的checksum包含

資料和個數

。-0x79(ACK)/0x1F(NACK) 

注:

對於寫flash,使用者flash的起始地址是0x08000000。
對於寫flash,這裡最多一次寫256位元組,寫一個bin檔案需要多次使用此協議寫入。
8、Read Memory command
【指令碼】0x11
【功能】
讀取stm32記憶體,可以讀取stm32任意地址的RAM、flash等資料。
我們常在下載完成後把flash內容讀取出來驗證。
【資料協議】

hostdevicenote0x11+0xEE0x79(ACK)/0x1F(NACK) addr-4位元組,下載地址。使用者flash起始地址是0x08000000。

先發高位,後發低位

addr checksum-1位元組,地址的checksum,就是上面4位元組資料的異或。-0x79(ACK)/0x1F(NACK) count-1位元組,將要讀取的資料個數,0~255。count+1就是將要讀取的位元組數,最多讀取256位元組。checksum-1位元組,count的按位取反。-0x79(ACK)/0x1F(NACK) -datacount+1個位元組,這就是要讀取的資料。

注:

對於讀取flash,使用者flash的起始地址是0x08000000。
一次最多讀取256位元組,要讀取大段內容就重複執行這個讀取操作。
9、Go command
略。

程式碼說明
根據上面的下載協議,封裝成了模組,這裡介紹本程式結構和模組的使用,以便移植到其他地方。

程式結構
wiringSerial.c wiringSerial.h
串列埠驅動,在樹莓派wiringPi基礎上修改,增加了資料塊讀寫程式碼,增加了更多設定項。
這部分驅動在mac、桌面ubuntu、樹莓派上都可以使用。

stm32isp.c stm32isp.h
下載邏輯程式碼,基於串列埠驅動,串列埠的開啟、關閉操作也歸於這部分控制。
以上兩個部分,serial完全歸於stm32isp,外部使用stm32isp時不需要再管串列埠了。

main.c
程式互動的實現,呼叫上面stm32isp介面實現下載。

下面著重介紹的是stm32isp部分的介面函式。

stm32isp介面
stm32isp使用前提是串列埠工作正常。

stm32isp_init
int stm32isp_init(const char *device, const int baud, const int databits, const int stopbits, const char parity, const int timeout);

使用前需要先呼叫此函式,主要是完成串列埠初始化(串列埠的開啟和關閉也交給stm32isp模組管理)。

例:

stm32isp_init("/dev/ttyUSB0", 57600, 8, 1, 'N', 30);

注:此驅動測試只有57600和38400兩個波特率可以正常下載。

stm32isp_close
void stm32isp_close(); //成功返回1,失敗返回0

下載結束後呼叫此函式,主要是完成串列埠關閉(串列埠的開啟和關閉也交給stm32isp模組管理)。

stm32isp_sync
int stm32isp_sync();

同步波特率,成功返回1,失敗返回0。 開啟串列埠後第一步就需要sync,和微控制器同步波特率。

stm32isp_get_command
int stm32isp_get_command()

獲取ID和command列表,資訊儲存在驅動內部結構體,不輸出,但會進行列印資訊。成功返回1,失敗返回0。

這一步不是下載必須執行的。

stm32isp_get_ID_command
int stm32isp_get_ID_command();

獲取PID,資訊儲存在驅動內部結構體,不輸出,但會進行列印。成功返回1,失敗返回0。

這一步不是下載必須執行的。

stm32isp_erase_all
int stm32isp_erase_all();

 全擦flash,成功返回1,失敗返回0。

下載之前先擦除flash。

stm32isp_write_bin
int stm32isp_write_bin(char *p);

傳入bin檔案路徑,寫入bin檔案到flash,成功返回1,失敗返回0。

注意寫入的是bin檔案,不是hex檔案。

bin檔案路徑可能由main函式的argv引數傳入。

stm32isp_verify
int stm32isp_verify(char *p);

傳入bin檔案路徑,根據bin檔案大小讀取flash相應大小內容,並把兩個比較,驗證成功返回1,失敗返回0。

這一步可選,為了保險可下載後驗證一下。

--------------------- 
作者:nicekwell 
來源:CSDN 
原文:https://blog.csdn.net/nicekwell/article/details/79093780