日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

IAP升级

發(fā)布時(shí)間:2023/12/16 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IAP升级 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

相關(guān)資料:https://blog.csdn.net/elikang/article/details/86082960
IAP升級(jí)的原理這里就不介紹了。

1. 修改代碼實(shí)現(xiàn)IAP+Ymodem

基于stm32官方提供的demo工程 STM32F10x_AN2557_FW_V3.3.0

提取出IAP和Ymodem文件,并修改Ymodem代碼,從標(biāo)準(zhǔn)庫到HAL庫。

1.1 首先,從demo中找到執(zhí)行框架,并將其封裝在新建的文件IAP.c中。

#include "main.h" #include "Define.h"/* Flash user program offset */uint32_t BlockNbr = 0; uint32_t UserMemoryMask = 0; //掩碼,用于檢測FLASH是否有寫保護(hù) __IO uint32_t FlashProtection = 0; //讀寫+不被編譯器優(yōu)化pFunction Jump_To_Application; uint32_t JumpAddress;extern uint8_t file_name[FILE_NAME_LENGTH]; extern uint32_t FlashDestination;extern int32_t Ymodem_Receive (uint8_t *); extern uint8_t Ymodem_Transmit (uint8_t *,const uint8_t* , uint32_t ); extern void Int2Str(uint8_t* str, int32_t intnum);uint8_t tab_1024[1024] ={0};/*** @brief Download a file via serial port* @param None* @retval None*/ void SerialDownload(void) {uint8_t Number[10] = " ";int32_t Size = 0;printf("Waiting for the file to be sent ... (press 'a' to abort)\n\r");Size = Ymodem_Receive(&tab_1024[0]);if (Size > 0){printf("\n\n\r Programming Completed Successfully!\n\r--------------------------------\r\n Name: %s",file_name);Int2Str(Number, Size);printf("\n\r Size: %s Bytes\r\n",Number);printf("-------------------\n");}else if (Size == -1){printf("\n\n\rThe image size is higher than the allowed space memory!\n\r");}else if (Size == -2){printf("\n\n\rVerification failed!\n\r");}else if (Size == -3) //收到取消{printf("\r\n\nAborted by user.\n\r");}else{printf("\n\rFailed to receive the file!\n\r");} }/*** @brief Display the Main Menu on to HyperTerminal在超級(jí)終端上顯示主菜單* @param None* @retval None*/ void Main_Menu(void) {uint8_t key = 0;/* Get the number of block (4 or 2 pages) from where the user program will be loaded 獲取塊(4或2頁)的數(shù)目 ,用戶程序?qū)闹屑虞d的(0x8003000-0x8000000)>>12 = 3*/BlockNbr = (FlashDestination - 0x08000000) >> 12;//8/* Compute the mask to test if the Flash memory, where the user program will beloaded, is write protected 計(jì)算掩碼以測試加載用戶程序的閃存是否有寫保護(hù)*/ #if defined (STM32F10X_MD) || defined (STM32F10X_MD_VL)UserMemoryMask = ((uint32_t)~((1 << BlockNbr) - 1)); #else /* USE_STM3210E_EVAL */if (BlockNbr < 62){UserMemoryMask = ((uint32_t)~((1 << BlockNbr) - 1));}else{UserMemoryMask = ((uint32_t)0x80000000);} #endif /* (STM32F10X_MD) || (STM32F10X_MD_VL) *//* Test if any page of Flash memory where program user will be loaded is write protected 測試將加載程序用戶的閃存頁是否有寫保護(hù)*/if (((uint32_t)(READ_REG(FLASH->WRPR)) & UserMemoryMask) != UserMemoryMask){FlashProtection = 1;}else{FlashProtection = 0;}printf("\r\n================== Main Menu ============================\r\n\n");printf(" Download Image To the STM32F10x Internal Flash ------- 1\r\n\n");printf(" Upload Image From the STM32F10x Internal Flash ------- 2\r\n\n");printf(" Execute The New Program ------------------------------ 3\r\n\n");if(FlashProtection != 0){printf(" Disable the write protection ------------------------- 4\r\n\n");}printf("==========================================================\r\n\n");while (1){key = getchar();//功能選項(xiàng)if (key == 0x31){/* Download user application in the Flash */printf("--> Download user application in the Flash\n\r");SerialDownload();}else if (key == 0x32){/* Upload user application from the Flash *///SerialUpload();printf("上傳\n\r");}else if (key == 0x33){printf("跳轉(zhuǎn)\n\r");JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);/* Jump to user application */Jump_To_Application = (pFunction) JumpAddress;/* Initialize user application's Stack Pointer */__set_MSP(*(__IO uint32_t*) ApplicationAddress);Jump_To_Application();}else if ((key == 0x34) && (FlashProtection == 1)){/* Disable the write protection of desired pages */HAL_FLASH_Unlock();printf("解鎖FLASH\n\r");}else{if (FlashProtection == 0){printf("Invalid Number ! ==> The number should be either 1, 2 or 3\r");}else{printf("Invalid Number ! ==> The number should be either 1, 2, 3 or 4\r");} }} }

1.2 其次,提取出Ymodem.c文件,并對其中的一些函數(shù)進(jìn)行修改。

下面是Ymodem.c文件修改前后的對比。最開始是要修改包含的頭文件。main.h文件中包括HAL的Flash函數(shù)。Define.h文件中則是定義了Flash操作相關(guān)的宏定義常量。

下面一段是自己加的注釋,實(shí)則并沒有改變代碼語句。在使用串口終端和設(shè)備進(jìn)行交互時(shí),用戶鍵盤輸入的命令字等會(huì)在這段代碼處被識(shí)別。

下面是傳輸過程中,將數(shù)據(jù)包寫入到Flash的操作。這里將標(biāo)準(zhǔn)庫的函數(shù)用HAL庫函數(shù)來替代。修改前最好理解一下這里的前后文。

下面是注釋信息,Ymodem協(xié)議,等待過程中,一直打印‘C’。

1.3 最后,添加一個(gè)宏定義頭文件,用于放置地址信息等定義。

應(yīng)用程序的起始地址和boot代碼的設(shè)定大小有關(guān)。這里給boot代碼劃分32K的代碼空間。

#define ApplicationAddress 0x8008000 //boot 32K #define FLASH_IMAGE_SIZE (uint32_t) (FLASH_SIZE - (ApplicationAddress - 0x08000000))//這里實(shí)際上是RCT6 256KB的flash#define PAGE_SIZE (0x800) /* 2 Kbytes */#define FLASH_SIZE (0x40000) /* 256K Byte *//* Exported macro ------------------------------------------------------------*/ /* Common routines */ #define IS_AF(c) ((c >= 'A') && (c <= 'F')) #define IS_af(c) ((c >= 'a') && (c <= 'f')) #define IS_09(c) ((c >= '0') && (c <= '9')) #define ISVALIDHEX(c) IS_AF(c) || IS_af(c) || IS_09(c) #define ISVALIDDEC(c) IS_09(c) #define CONVERTDEC(c) (c - '0')#define CONVERTHEX_alpha(c) (IS_AF(c) ? (c - 'A'+10) : (c - 'a'+10)) #define CONVERTHEX(c) (IS_09(c) ? (c - '0') : CONVERTHEX_alpha(c))#define SerialPutString(x) Serial_PutString((uint8_t*)(x))#define FILE_NAME_LENGTH (256) #define FILE_SIZE_LENGTH (16)typedef void (*pFunction)(void);

1.4 在將上述三個(gè)文件準(zhǔn)備好之后,就是如何使用。下面是boot工程的main函數(shù)片段。

(1)初始化外設(shè)。
(2)打印boot信息
(3)判斷是否需要進(jìn)入boot模式,(按鍵被按下,則進(jìn)入boot,未被按下,則直接跳轉(zhuǎn)到app)
(4)如果按鍵被按下,則進(jìn)入IAP升級(jí)框架。(Main_Menu函數(shù))

MX_GPIO_Init();MX_I2C1_Init();MX_IWDG_Init();MX_USART1_UART_Init();printf("\n\r=== 南京某某呵呵啥啥有限公司 ===\n\r");printf("--> BOOT\n\r");printf("--> 編譯時(shí)間:%s %s\n\r",__DATE__,__TIME__);//解鎖FLASHHAL_FLASH_Unlock();//檢測按鍵(后期可以考慮檢測標(biāo)志位)if(HAL_GPIO_ReadPin(USER_KEY_GPIO_Port,USER_KEY_Pin)==0){printf("\r\n======================================================================");printf("\r\n= (C) COPYRIGHT 2010 STMicroelectronics =");printf("\r\n= =");printf("\r\n= In-Application Programming Application (Version 3.3.0) =");printf("\r\n= =");printf("\r\n= By MCD Application Team =");printf("\r\n======================================================================");printf("\r\n\r\n");extern void Main_Menu(void);Main_Menu();}else{uint32_t JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);pFunction Jump_To_Application = (pFunction) JumpAddress;printf("\n\rJump to APP!\n\r");__set_MSP(*(__IO uint32_t*) ApplicationAddress);Jump_To_Application();}while (1){clearIWDG();

2. 代碼框架分析

2.1 IAP框架

略(稍后補(bǔ)充)。

2.2 Ymodem協(xié)議介紹

略(稍后補(bǔ)充)。

3. 關(guān)于使用。

3.1 Bootloader

boot工程配置如下圖所示。

另外,keil編譯生成的是hex文件,需要添加指令才可以生成bin文件。如下圖所示。編譯完成后會(huì)生成Boot.bin文件。

上面用到的Hexbin.bat是一個(gè)腳本文件,內(nèi)容如下。因?yàn)轫?xiàng)目需求,有兩個(gè)版本的代碼同時(shí)存在。該腳本會(huì)判斷兩個(gè)版本代碼的生成目錄是否存在。如果不存在,則創(chuàng)建HexBinE1和HexBinE2文件夾。
通過fromelf.exe工具將hex文件轉(zhuǎn)成bin文件,再移動(dòng)到創(chuàng)建的文件夾中。
用戶可根據(jù)自己的需求修改該腳本。

@echo off if not exist ..\..\HexBinE1 (mkdir ..\..\HexBinE1 )set exePath=%1ARM\ARMCC\bin set outName=%2 set binName=%3%exePath%\fromelf.exe --bin %outName% --output %binName%move /y .\%binName% ..\..\HexBinE1 >nulif not exist ..\..\HexBinE2 (mkdir ..\..\HexBinE2 )%exePath%\fromelf.exe --bin %outName% --output %binName%move /y .\%binName% ..\..\HexBinE2 >nul

3.2 Application

app工程配置如下圖所示。重要注意點(diǎn)是,工程配置的地址以及中斷向量表的地址。這里的配置相當(dāng)于讓出前面32K的空間,給boot使用。

同樣關(guān)于如何生成bin文件,也需要進(jìn)行如下圖所示的操作。以E2版本為例。

這里的HexBin.bat腳本內(nèi)容如下。判斷文件夾是否存在,生成bin文件,移動(dòng)到文件夾中。

@echo off if not exist ..\..\HexBinE2 (mkdir ..\..\HexBinE2 )set exePath=%1ARM\ARMCC\bin set outName=%2 set binName=%3%exePath%\fromelf.exe --bin %outName% --output %binName% move /y .\%binName% ..\..\HexBinE2 >nul

這里的BuildAction.exe是使用Qt編寫的合成工具,用于將Boot.bin和APP_E2.bin合成為一個(gè)bin文件。

其中的配置文件ini內(nèi)容如下。用戶可根據(jù)自己的需求更改。

*以/或者*開頭的行,認(rèn)為整行都是注釋,不解析 *配置文件只可以修改=之后的內(nèi)容。*boot文件的相對位置 boot_path=..\..\..\HexBinE2\Boot *app文件的相對位置 app_path=..\..\..\HexBinE2\APP_E2 *syscfg文件相對位置 syscfg_path=..\..\Inc *產(chǎn)品標(biāo)識(shí)碼 identification=GDCJB2020 *boot_size大小默認(rèn)是以KBytes為單位,例如,實(shí)際boot大小是16K,下面只要寫16就好 boot_size=32 *app區(qū)大小 app_size=96 *整個(gè)flash大小 flash_size=256 *本工具調(diào)試開關(guān) DEBUG=0

還有一個(gè)注意點(diǎn)是BuildAction.exe工具需要一個(gè)頭文件sys_cfg.h,用以定義版本號(hào)。內(nèi)容如下。

#define DEBUG_ENABLE 0 // 調(diào)試使能(停用:0 /啟用:1) // 應(yīng)用層軟件版本號(hào),4個(gè)ASCII字符,臨時(shí)版本0.XX,正式版本E.XX 格式:45 2E 30 31 #define APPVIRSION_BYTE0 0x32 #define APPVIRSION_BYTE1 0x2E #define APPVIRSION_BYTE2 0x30 #define APPVIRSION_BYTE3 0x37

總結(jié)

以上是生活随笔為你收集整理的IAP升级的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。