當(dāng)前位置:首頁 > 公眾號精選 > 嵌入式云IOT技術(shù)圈
[導(dǎo)讀]本程序編寫基于秉火霸道STM32F103ZET6運(yùn)行環(huán)境。 最近疫情期間,特地將自己大部分硬件資源全部用熱膠搶焊到了一起,以便以后自己復(fù)習(xí)和學(xué)習(xí),當(dāng)然還有很多,弄不上來了,只能等以后有機(jī)會再重新搞一塊!我還是非常舍得花錢買設(shè)備的!哈哈!這是一個STM32+Linu














本程序編寫基于秉火霸道STM32F103ZET6運(yùn)行環(huán)境。

最近疫情期間,特地將自己大部分硬件資源全部用熱膠搶焊到了一起,以便以后自己復(fù)習(xí)和學(xué)習(xí),當(dāng)然還有很多,弄不上來了,只能等以后有機(jī)會再重新搞一塊!我還是非常舍得花錢買設(shè)備的!哈哈!這是一個STM32+Linux+51的大雜燴開發(fā)平臺!

1、產(chǎn)生問題

公司的產(chǎn)品,每次生產(chǎn)燒寫程序都得把機(jī)器拆開,然后插上串行線或者ST-Link進(jìn)行燒寫,產(chǎn)品量產(chǎn)的情況下數(shù)量很多,所以生產(chǎn)每次都需要花費很長去時間去給機(jī)器燒程序(這里我們用野火的開發(fā)板來模擬)。

2、現(xiàn)有的硬件接口

現(xiàn)在的產(chǎn)品(野火的STM32F103ZET6開發(fā)板)有一個USB接口,硬件連接圖如下:

如上圖所示,當(dāng)PD3為低電平的時候,USB接口供電,即可用,這一點在上一篇文章已經(jīng)講解了,我們在STM32CubeMX把這個管腳默認(rèn)拉低即可。

3、分析問題

STM32CubeMX支持了與USB相關(guān)的諸多配置功能,請看如下:

于我們需要使用USB接口來更新程序,所以我們需要在配置USB設(shè)備模式的時候給它選擇Download Firmware Update Class(DFU)。

1、USB燒寫原理及流程分析

1.1 燒寫原理

這點與IAP升級是大同小異的,只不過這里我們使用了USB來燒寫,之前寫過類似的一篇文章:帶串口屏顯示的BootLoader程序開發(fā) 在這篇文章里面也介紹了相應(yīng)的原理,這里就不再重復(fù)描述,我們負(fù)責(zé)把這篇文章里提到的幾點實現(xiàn)就可以了。

1.2 程序存儲分區(qū)

STM32F103ZET6的FLASH容量一共有512KB。所以,我給BootLoader的大小是64K,也就是0x10000,具體是怎么算的呢?

0x10000轉(zhuǎn)十進(jìn)制為65536,65536/1024 = 64K

把剩下的空間全部分配給APP,也就是0x70000,具體是怎么算的呢?

0x70000轉(zhuǎn)十進(jìn)制為458752,458752/1024 = 448K

4、解決問題

4.1 配置編寫B(tài)ootLoader程序的CubeMX工程

4.1.1 配置RCC時鐘

4.1.2 配置串行調(diào)試接口

4.1.3 配置按鍵、調(diào)試燈、調(diào)試串口、USB使能管腳

調(diào)試燈選擇的是PB1,低電平點亮,具體可以看原理圖:

USB使能管腳默認(rèn)為低電平。

選用USART2作為調(diào)試打印輸出。

4.1.4 配置USB相關(guān)的選項

配置的基本參數(shù)默認(rèn)即可,不需要改變。

在中斷設(shè)置這里,將USB優(yōu)先級調(diào)低,可以避免一些默認(rèn)其妙不穩(wěn)定的現(xiàn)象。接下來配置USB設(shè)備相關(guān)的選項。

類參數(shù)有一個字段比較重要:

@Internal Flash   /0x08000000/03*016Ka,01*016Kg,01*064Kg,07*128Kg,04*016Kg,01*064Kg,07*128Kg

這個參數(shù)的具體含義描述如下:

  • @:檢測到這是一個特殊的映射描述符(避免解碼標(biāo)準(zhǔn)描述符)

  • /:用于區(qū)域之間的分隔符

  • 每個地址以“ 0x”開頭的最大8位數(shù)字

  • /:用于區(qū)域之間的分隔符

  • 扇區(qū)數(shù)的最大2位數(shù)字

  • *:用于扇區(qū)數(shù)和扇區(qū)大小之間的分隔符

  • 扇區(qū)大小在0到999之間的最大3位

  • 扇區(qū)大小乘數(shù)的1位數(shù)字。有效條目為:B(字節(jié)),K(千),M(兆)

  • 扇區(qū)類型的1位數(shù)字,如下所示:

– a(0x41):可讀
– b(0x42):可擦除
– c(0x43):可讀和可擦除
(0x44):可寫
– e(0x45):可讀寫
–f(0x46):可擦除和可寫
–g(0x47):可讀寫,可寫

4.1.5 生成工程

這里默認(rèn)不讓它自動生成main函數(shù),main函數(shù)我們自己寫。在配置USB設(shè)備參數(shù)里,USBD_DFU_XFER_SIZE參數(shù):USB數(shù)據(jù)pack大小,越大配置速度越快。默認(rèn)配置1024Bytes. 1024Bytes使用的是堆空間,故堆空間要大于1024Bytes. 原因:代碼如下。

#define USBD_malloc         malloc
/* Allocate Audio structure */
pdev->pClassData = USBD_malloc(sizeof (USBD_DFU_HandleTypeDef));

所以這里的堆我把它配置成0x1000。(個人習(xí)慣)

4.2 編寫B(tài)ootLoader程序

4.2.1 實現(xiàn)usbd_dfu_if.c中相關(guān)的接口

宏定義一些參數(shù)

//FLASH的擦寫實現(xiàn)
#define FLASH_ERASE_TIME (uint16_t)50
#define FLASH_PROGRAM_TIME (uint16_t)50
//APP存放的結(jié)束地址
#define USBD_DFU_APP_END_ADD 0x08080000
//FLASH頁大小
#define FLASH_PAGE_SIZE 0x800U //2K

實現(xiàn)如下接口:

MEM_If_Init_FS,       閃存初始化,解鎖內(nèi)部flash。
MEM_If_DeInit_FS, 閃存反(取消)初始化,上鎖內(nèi)部flash。
MEM_If_Erase_FS, 閃存擦除。
MEM_If_Write_FS, 閃存寫入。
MEM_If_Read_FS, 閃存讀取。
MEM_If_GetStatus_FS 獲取閃存狀態(tài),返回寫入或擦除操作所需的時間。

閃存初始化,解鎖內(nèi)部flash。

uint16_t MEM_If_Init_FS(void)
{
/* USER CODE BEGIN 0 */
//解鎖內(nèi)部FLASH
HAL_FLASH_Unlock();
//清除FLASH的一些標(biāo)志,可以避免一些莫名其妙的問題
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR);
return (USBD_OK);
/* USER CODE END 0 */
}

閃存反(取消)初始化,上鎖內(nèi)部flash。

uint16_t MEM_If_DeInit_FS(void)
{
/* USER CODE BEGIN 1 */
//給FLASH上鎖
HAL_FLASH_Lock();
return (USBD_OK);
/* USER CODE END 1 */
}

閃存擦除。

uint16_t MEM_If_Erase_FS(uint32_t Add)
{
/* USER CODE BEGIN 2 */
/*擦除整個APP程序存放的空間,即是0x08080000-0x08010000*/
/*
因為起始地址是0x8000000,而Size是0x80000,所以MCU存放代碼的最后一個區(qū)域的地址為0x8080000。
而DFU占了其中的0x10000的空間。
*/
uint32_t NbOfPages = 0 ;
uint32_t PageError = 0 ;
FLASH_EraseInitTypeDef pEraseInit ;
NbOfPages = (USBD_DFU_APP_END_ADD - USBD_DFU_APP_DEFAULT_ADD)/FLASH_PAGE_SIZE ;
pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
pEraseInit.PageAddress = USBD_DFU_APP_DEFAULT_ADD;
pEraseInit.NbPages = NbOfPages; //erase all pages of APP
if(HAL_FLASHEx_Erase(&pEraseInit,&PageError)!= HAL_OK)
return USBD_FAIL ;
return (USBD_OK);
/* USER CODE END 2 */
}

閃存寫入。

uint16_t MEM_If_Write_FS(uint8_t *src, uint8_t *dest, uint32_t Len)
{
/* USER CODE BEGIN 3 */
uint32_t i =0;

for(i=0;i<Len;i+=4)
{
if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,(uint32_t)(dest+i),*(uint32_t*)(src+i))== HAL_OK)
{
if(*(uint32_t*)(src+i) != *(uint32_t*)(dest+i))
return USBD_FAIL;
}
else
{
return USBD_FAIL;
}
}
return (USBD_OK);
/* USER CODE END 3 */
}

閃存讀取

uint8_t *MEM_If_Read_FS(uint8_t *src, uint8_t *dest, uint32_t Len)
{
/* Return a valid address to avoid HardFault */
/* USER CODE BEGIN 4 */
uint32_t i = 0;
uint8_t *psrc = src;

for (i = 0; i < Len; i++)
{
dest[i] = *psrc++;
}

return (uint8_t*) (dest);
/* USER CODE END 4 */
}

獲取閃存狀態(tài),返回寫入或擦除操作所需的時間。

uint16_t MEM_If_GetStatus_FS(uint32_t Add, uint8_t Cmd, uint8_t *buffer)
{
/* USER CODE BEGIN 5 */
switch (Cmd)
{
case DFU_MEDIA_PROGRAM:
buffer[1] = (uint8_t)FLASH_PROGRAM_TIME;
buffer[2] = (uint8_t)(FLASH_PROGRAM_TIME << 8);
buffer[3] = 0;
break;

case DFU_MEDIA_ERASE:
buffer[1] = (uint8_t)FLASH_ERASE_TIME;
buffer[2] = (uint8_t)(FLASH_ERASE_TIME << 8);
buffer[3] = 0;
break ;
default:

break;
}

return (USBD_OK);
/* USER CODE END 5 */
}

4.2.1 實現(xiàn)main.c

定義調(diào)試打印接口,這里我用的是USART2

int fputc(int ch, FILE* FILE)
{
HAL_UART_Transmit(&huart2, (uint8_t*)&ch, 1, HAL_MAX_DELAY);
return ch;
}

跳轉(zhuǎn)到APP的代碼實現(xiàn):

static void JumpToApp(void)
{
typedef void (*pFunction)(void);
static pFunction JumpToApplication;
static uint32_t JumpAddress;

/* Test if user code is programmed starting from USBD_DFU_APP_DEFAULT_ADD * address */
if (((*(__IO uint32_t *) USBD_DFU_APP_DEFAULT_ADD) & 0x2FFE0000) == 0x20000000)
{
/* Jump to user application */
JumpAddress = *(__IO uint32_t *) (USBD_DFU_APP_DEFAULT_ADD + 4);
JumpToApplication = (pFunction) JumpAddress;

/* Initialize user application's Stack Pointer */
__set_MSP((*(__IO uint32_t *) USBD_DFU_APP_DEFAULT_ADD));
JumpToApplication();
}
}

在正常啟動過程中,如果APP區(qū)域存放有數(shù)據(jù),我們不希望去啟動USB,在剛開始的時候我們可以把USB的功能給失能掉,如果檢測到APP區(qū)域沒有數(shù)據(jù),則再初始化USB功能,所以在這里編寫一個USB的失能函數(shù)。

static void USB_GPIO_DeInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11 | GPIO_PIN_12, GPIO_PIN_RESET);

/*Configure GPIO pin*/
GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_Delay(500);
}

main函數(shù)實現(xiàn)

int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
USB_GPIO_DeInit();
MX_USART2_UART_Init();
/*如果沒有按下按鍵,則自動跳轉(zhuǎn)到APP區(qū),如果跳轉(zhuǎn)不過去,則代表區(qū)域無APP*/
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) != GPIO_PIN_SET)
{
JumpToApp();
printf("跳轉(zhuǎn)失敗,開始進(jìn)入DFU模式\r\n");
}
//進(jìn)入DFU模式
MX_USB_DEVICE_Init();
printf("Bruce.Yang DFU\n");
//調(diào)試燈常亮,代表此時在DFU模式
HAL_GPIO_WritePin(LED_BLUE_GPIO_Port, LED_BLUE_Pin,GPIO_PIN_RESET);
while(1)
{
HAL_Delay(1000);
}
}

實現(xiàn)完畢,接下來可以編譯程序,下載到開發(fā)板,由于沒有APP,所以開發(fā)板上PB1的燈常亮。

4.2.2 編寫APP程序

APP程序很簡單,就讓PB1燈以500ms的頻率進(jìn)行翻轉(zhuǎn)吧。

配置過程(略)太簡單了,應(yīng)用APP的核心代碼如下:

 while (1)
{
/* USER CODE END WHILE */
HAL_GPIO_TogglePin(BLUE_LED_GPIO_Port,BLUE_LED_Pin);
HAL_Delay(500);
/* USER CODE BEGIN 3 */
}

接下來主要是在工程里做一些設(shè)置。

1、點擊魔術(shù)棒設(shè)置APP啟動的地址

2、更改中斷向量表偏移

接下來編譯生成APP_TEST.hex文件,我們用一個工具來將它燒寫到板子上。

安裝DFU燒錄軟件:DfuSe_Demo

官網(wǎng)下載鏈接:

https://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-programmers/stsw-stm32080.html#resource

默認(rèn)安裝即可。

安裝成功后得到兩個軟件。


Dfu file manager是把bin文件或者h(yuǎn)ex文件生成 .dfu后綴的文件, .dfu后綴的文件就是我們的固件。DfuSe_Demo是燒錄 文件后綴 .dfu 軟件。

燒錄步驟:

1、將.hex文件轉(zhuǎn)化成.dfu后綴的文件

生成后可以看到效果:

2、連接USB到開發(fā)板的設(shè)備端口到PC

看到?jīng)]有識別DFU

我們需要手動給它更新下驅(qū)動程序,直接就是剛剛下載的DfuSe安裝的目錄下找對應(yīng)系統(tǒng)版本的驅(qū)動就好了。

最后可以看到該模式被識別了:

接下來打開DfuSeDemo這個軟件,可以看到開發(fā)板現(xiàn)在已經(jīng)被識別了。

接下來將剛剛生成的APP_TEST1.dfu加載進(jìn)來。

點擊Upgrade進(jìn)行升級。

升級成功!接下來點擊Leave DFU mode,程序則會自動開始執(zhí)行。


這時候APP已經(jīng)跑起來了,燈在以500ms的頻率不斷閃爍。

至此USB DFU固件成功!

Bootloader代碼以及APP代碼在這里下載:

鏈接:https://pan.baidu.com/s/1zRv7j4E8SXgCV5F6RbSo1Q
提取碼:5539

如果有興趣的話,還可以把我之前寫的串口屏BootLoader那個程序繼續(xù)升級一下!

帶串口屏顯示的Bootloader

往期精彩


帶串口屏顯示的Bootloader

為Linux應(yīng)用構(gòu)造有限狀態(tài)機(jī)

編程修養(yǎng)(精品文,建議認(rèn)真品讀并實踐)

嵌入式C語言代碼優(yōu)化方案(深度好文,建議花時間研讀并收藏)

若覺得本次分享的文章對您有幫助,隨手點[在看]并轉(zhuǎn)發(fā)分享,也是對我的支持。

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉