国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

STM32G473 固件升級(jí)IAP(BootLoader)CAN/USART。(詳細(xì)步驟)

這篇具有很好參考價(jià)值的文章主要介紹了STM32G473 固件升級(jí)IAP(BootLoader)CAN/USART。(詳細(xì)步驟)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

本例程僅供參考(個(gè)人學(xué)習(xí)總結(jié)_有需要文中有的封裝好的跳轉(zhuǎn)函數(shù)可私信),

例程可舉一反三完成FDCAN通信和USART通信。

目錄

簡介

1.APP程序配置步驟

APP 程序起始地址設(shè)置方法

中斷向量表的偏移量設(shè)置方法

KEIL5生成bin文件步驟

2.IAP(BootLoader 程序)配置(HAL庫,Cubemax)

2.1RCC配置

2.2時(shí)鐘樹配置

2.3CAN配置(版本例程CAN接收數(shù)據(jù)和發(fā)送數(shù)據(jù)為普通模式,配合TIM2定時(shí)器使用)

2.4TIM2定時(shí)器配置

2.5USART配置

3.IAP(BootLoader)代碼程序配置

? ? ? ? 3.1CAN過濾器,發(fā)送,接收函數(shù)配置

3.2CAN發(fā)送配置

3.3CAN.h函數(shù)聲明

3.4CAN測(cè)試函數(shù)

3.5CAN測(cè)試效果

3.6USART接收

3.7Printf重映射函

3.8USART主函數(shù)測(cè)試

3.9USART測(cè)試效果

4.Flash寫入數(shù)據(jù)

5.跳轉(zhuǎn)至APP函數(shù)(即IAP)

6.?Bootloader 程序

7.Main程序代碼

8.升級(jí)效果

8.1CAN升級(jí)效果

8.2USART升級(jí)效果

9.注意事項(xiàng)


簡介

IAP 是用戶自己的程序在運(yùn)行過程中對(duì) User Flash 的部分區(qū)域進(jìn)行燒寫,目的是為了在產(chǎn) 品發(fā)布后可以方便地通過預(yù)留的通信口對(duì)產(chǎn)品中的固件程序進(jìn)行更新升級(jí)。通常實(shí)現(xiàn) IAP 功能時(shí),即用戶程序運(yùn)行中作自身的更新操作,需要在設(shè)計(jì)固件程序時(shí)編寫兩個(gè)項(xiàng)目代碼,

第一個(gè)項(xiàng)目程序不執(zhí)行正常的功能操作,而只是通過某種通信方式(如 USB、USART)接收程序或數(shù)據(jù),執(zhí)行對(duì)第二部分代碼的更新;

第二個(gè)項(xiàng)目代碼才是真正的功能代碼。這兩部分項(xiàng)目代碼都同時(shí)燒錄在 User Flash 中,當(dāng)芯片上電后,首先是第一個(gè)項(xiàng)目代碼開始運(yùn)行,它做如下操作:

1)檢查是否需要對(duì)第二部分代碼進(jìn)行更新

2)如果不需要更新則轉(zhuǎn)到 4)

3)執(zhí)行更新操作

4)跳轉(zhuǎn)到第二部分代碼執(zhí)行

第一部分代碼必須通過其它手段,如 JTAG 或 ISP 燒入;第二部分代碼可以使用第一部分代碼 IAP 功能燒入,也可以和第一部分代碼一起燒入,以后需要程序更新時(shí)再通過第一部分 IAP 代碼更新。

我們將第一個(gè)項(xiàng)目代碼稱之為 Bootloader 程序,第二個(gè)項(xiàng)目代碼稱之為 APP 程序,他們存放在 STM32G4??FLASH 的不同地址范圍,一般從最低地址區(qū)開始存放 Bootloader,緊跟其后的就是 APP 程序(注意,如果 FLASH 容量足夠,是可以設(shè)計(jì)很多 APP 程序的),這樣我們就是要實(shí)現(xiàn) 2 個(gè)程序:Bootloader 程序和 APP程序。

STM32G4 的 APP 程序不僅可以放到 FLASH 里面運(yùn)行,也可以放到 SRAM 里面運(yùn)行,我們選用在 FLASH 運(yùn)行。Flash存儲(chǔ)器是一種非易失性存儲(chǔ)器,可以在掉電之后保存數(shù)據(jù),通常用于存儲(chǔ)程序代碼。Flash存儲(chǔ)器的可寫入次數(shù)有限,且需要執(zhí)行擦除操作才能寫入新的數(shù)據(jù),因此,在使用過程中需要注意擦寫周期和數(shù)據(jù)備份問題。SRAM存儲(chǔ)器則是一種易失性存儲(chǔ)器,具有相對(duì)較快的讀寫速度和無限的讀寫次數(shù),但掉電時(shí)將會(huì)丟失所有內(nèi)容。SRAM存儲(chǔ)器主要用于暫存數(shù)據(jù)和臨時(shí)變量,讀寫操作由CPU直接完成,訪問速度較快。

單片機(jī)的Flash存儲(chǔ)器和SRAM存儲(chǔ)器都嵌入在單片機(jī)芯片內(nèi)部,能夠方便的實(shí)現(xiàn)對(duì)程序和數(shù)據(jù)、變量的讀寫操作。通常,編譯器會(huì)把程序燒錄在Flash存儲(chǔ)器,并使用SRAM存儲(chǔ)器來存儲(chǔ)變量、函數(shù)堆棧以及其他的臨時(shí)數(shù)據(jù)

1.APP程序配置步驟

  1. APP 程序起始地址設(shè)置方法? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    圖中 IROM1 的起始地址(Start)為 0x08000000,大?。⊿ize)為 0x80000,即從 0x08000000 開始的 512K 空間為我們的程序存儲(chǔ)區(qū)。

    APP程序?qū)⒃O(shè)置起始地址(Start)為 0x08010000,即偏移量為 0x10000(64K?字節(jié),即留給 BootLoader 的空間),因而,留給 APP 用的 FLASH 空間(Size)只有 0x80000- 0x10000=0x70000(448K 字節(jié))大小了。設(shè)置好 Start 和 Size,就完成 APP 程序的起始地址設(shè)置。IRAM 是內(nèi)存的地址,APP 可以獨(dú)占這些內(nèi)存,不需要修改。

    注意:需要確保 APP 起始地址在 Bootloader 程序結(jié)束位置之后,并且偏移量為 0x200 的倍數(shù)即可

  2. 中斷向量表的偏移量設(shè)置方法

    VTOR 寄存器存放的是中斷向量表的起始地址。默認(rèn)的情況它由 BOOT 的啟動(dòng)模式?jīng)Q定,對(duì)于 STM32G4 來說就是指向 0x0800 0000 這個(gè)位置,也就是從默認(rèn)的啟動(dòng)位置加載中斷向量等信息,不過 ST 允許重定向這個(gè)位置,這樣就可以從 Flash 區(qū)域的任意位置啟動(dòng)我們的代碼了。我們可以通過調(diào)用 sys.c 里面的 sys_nvic_set_vector_table 函數(shù)實(shí)現(xiàn),該函數(shù)定義如下:
    /** 
    * @brief 設(shè)置中斷向量表偏移地址 
    * @param baseaddr : 基址 
    * @param offset : 偏移量 
    * @retval 無 
    */ 
    void sys_nvic_set_vector_table(uint32_t baseaddr, uint32_t offset) 
    { 
    /* 設(shè)置 NVIC 的向量表偏移寄存器,VTOR 低 9 位保留,即[8:0]保留 */ 
    SCB->VTOR = baseaddr | (offset & (uint32_t)0xFFFFFE00); 
    }

    該函數(shù)用于設(shè)置中斷向量偏移,baseaddr 為基地址(即 APP 程序首地址),Offset 為偏移量,需要根據(jù)自己的實(shí)際情況進(jìn)行設(shè)置。比如 FLASH APP 設(shè)置中斷向量表偏移量為0x10000,調(diào)用情況如下:

    /* 設(shè)置中斷向量表偏移量為 0x10000 */
    sys_nvic_set_vector_table(FLASH_BASE, 0x10000);

    通過以上兩個(gè)步驟的設(shè)置,我們就可以生成 APP 程序了,只要 APP 程序的 FLASH大小不超過我們的設(shè)置即可? ?MDK 默認(rèn)生成的文件是.hex 文件,并不方便我們用作 IAP更新,工程直接生成.bin 文件,可以方便進(jìn)行 IAP 升級(jí)。can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

  3. KEIL5生成bin文件步驟

通過 MDK 自帶的格式轉(zhuǎn)換工具 fromelf.exe 來生成 bin 文件。注意:如果用戶安裝 MDK 在 C 盤的默認(rèn)路徑,那它的位置一般C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe。

其他位置可點(diǎn)擊鼠標(biāo)右鍵 KEIL 軟件 打開文件所在目錄 ,然后跳轉(zhuǎn)到上一級(jí)文件目錄的ARM ->>ARMCC ->>獲得絕對(duì)路徑。

點(diǎn)擊Options for Target→User,在 After Build/Rebuild 一欄中,勾選 Run #1,輸入轉(zhuǎn)換語句

D:\A_A_ProgramFiles\A_Keil5\ARM\ARMCC\bin\fromelf --bin -o ..\..\..\..\..\A_ADesktop\Program\Stm32_00X\Can_IAP_003\Output\@L.bin ..\..\..\..\..\A_ADesktop\Program\Stm32_00X\Can_IAP_003\MDK-ARM\Can_IAP_003\%L

推薦相對(duì)地址,(不同的工程文件地址可能不同,需要根據(jù)自己的工程來定,文件路徑較深推薦用絕對(duì)路徑。)can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

轉(zhuǎn)換語句的組成解釋如下:

首先是MDK 自帶的格式轉(zhuǎn)換工具 fromelf.exe的絕對(duì)路徑 + 命令fromelf --bin -o?路徑(生成bin文件保存路徑)\@L.bin??路徑(生.axf的文件路徑)%L。

D:\A_A_ProgramFiles\A_Keil5\ARM\ARMCC\bin\fromelf --bin -o?..\..\..\..\..\A_ADesktop\Program\Stm32_00X\Can_IAP_003\Output\@L.bin?..\..\..\..\..\A_ADesktop\Program\Stm32_00X\Can_IAP_003\MDK-ARM\Can_IAP_003\%L

總結(jié)APP 程序的生成步驟

  1. 設(shè)置 APP 程序的起始地址和存儲(chǔ)空間大小
  2. 設(shè)置中斷向量表偏移量
  3. 設(shè)置編譯后運(yùn)行 fromelf.exe,生成.bin 文件

以上 3 個(gè)步驟,就可以得到一個(gè).bin 的 APP 程序,通過 Bootlader 程序即可實(shí)現(xiàn)更新

APP程序中加入can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言文件夾中的can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言.c和.h文件在工程中添加包含路徑,并在Main函數(shù)最開始部分添加語句can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

2.IAP(BootLoader 程序)配置(HAL庫,Cubemax)

2.1RCC配置

can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

2.2時(shí)鐘樹配置

can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

2.3CAN配置(版本例程CAN接收數(shù)據(jù)和發(fā)送數(shù)據(jù)為普通模式,配合TIM2定時(shí)器使用)

can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

2.4TIM2定時(shí)器配置

can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

2.5USART配置

can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

生成工程

can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

3.IAP(BootLoader)代碼程序配置

? ? ? ? 3.1CAN過濾器,發(fā)送,接收函數(shù)配置

/* USER CODE BEGIN 0 */
FDCAN_FilterTypeDef   sFilterConfig;	//接收過濾器類型定義結(jié)構(gòu)體
/* USER CODE END 0 */

 /* USER CODE BEGIN FDCAN1_Init 2 *///配置接收過濾	
sFilterConfig.IdType = FDCAN_STANDARD_ID;       
//  配置為過濾標(biāo)準(zhǔn)幀
  sFilterConfig.FilterIndex = 0;                 
  // 過濾器的索引號(hào)  如果有2組標(biāo)準(zhǔn)幀過濾,那么就是通過index區(qū)別,0  1   2這種
  sFilterConfig.FilterType = FDCAN_FILTER_RANGE;  
//  過濾方式為范圍,即從FilterID1~FilterID2之間的值
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
  sFilterConfig.FilterID1 = 0x0000;
  sFilterConfig.FilterID2 = 0x07ff;         		  
//標(biāo)準(zhǔn)幀為11位ID,即0x7ff,本例配置為接收所有幀
/*設(shè)置接收過濾器,根據(jù)FDCAN_FilterTypeDef結(jié)構(gòu)中指定的參數(shù)配置FDCAN接收篩選器。*/
if(HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)	
{
    Error_Handler();
}
  /*配置FDCAN全局過濾器*/
if(HAL_FDCAN_ConfigGlobalFilter(&hfdcan1,FDCAN_REJECT,FDCAN_REJECT,DCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
  {
    Error_Handler();
  }
if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
  {
    Error_Handler();
  }
/* USER CODE END FDCAN1_Init 2 */

3.2CAN發(fā)送配置

/*發(fā)送函數(shù)*/
void CAN_Send_Msg(FDCAN_HandleTypeDef hcan,uint32_t can_id,uint8_t tx_buff[])
{	
	FDCAN_TxHeaderTypeDef TxHeader;	
	TxHeader.Identifier = can_id;                         /* 32位ID */         
TxHeader.IdType = FDCAN_STANDARD_ID;					  /* 標(biāo)準(zhǔn)ID */
  TxHeader.TxFrameType = FDCAN_DATA_FRAME;		     	  /* 數(shù)據(jù)幀 */
  TxHeader.DataLength = FDCAN_DLC_BYTES_8;				 	/* 數(shù)據(jù)長度 */
  TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
  TxHeader.BitRateSwitch = FDCAN_BRS_ON;			   //用于設(shè)置發(fā)送是否波特率可變。
  TxHeader.FDFormat = FDCAN_CLASSIC_CAN;				//普通can還是FDcan
  TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;		
//是用于設(shè)置發(fā)送事件FIFO控制事件是否保存
  TxHeader.MessageMarker = 0;											
//marker++;	//用于設(shè)置復(fù)制到TX EVENT FIFO的消息Maker,來識(shí)別消息狀態(tài),范圍0到0xFF
  HAL_FDCAN_AddMessageToTxFifoQ(&hcan, &TxHeader, tx_buff); //發(fā)送
}	
void CAN_Receive_Msg(void)
{  /*函數(shù)的作用是獲取CAN接收FIFO的填充級(jí)別。*/
  if(HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1,FDCAN_RX_FIFO0) >= 1)
{
			/*從Rx FIFO 收取一個(gè) CAN 幀*/
if(HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &CANRec_msg, CANRec_buff) == HAL_OK )	{
		  CANRecFlag = 1;//接收完成標(biāo)志位
		}				
}					
}
在數(shù)函數(shù)中全局變量
uint8_t CANRecFlag ;     //CAN接收表示,完成 1 
uint8_t CANRec_buff[8];  //CAN接受到的數(shù)據(jù)位
FDCAN_RxHeaderTypeDef CANRec_msg;   
在Main.h中extern
extern uint8_t CANRecFlag ;
extern uint8_t CANRec_buff[8];
extern FDCAN_RxHeaderTypeDef CANRec_msg;   

3.3CAN.h函數(shù)聲明

void CAN_Send_Msg(FDCAN_HandleTypeDef hcan,uint32_t can_id,uint8_t tx_buff[]);
void CAN_Receive_Msg(void);
void Power_ON_Start_TX(void);

3.4CAN測(cè)試函數(shù)

void Power_ON_Start_TX(void)
{
  FDCAN_TxHeaderTypeDef TxHeader;
  uint8_t tx_data[8] = {0x20, 0x23, 0x11, 0x09, 0x12, 0x20, 0x00, 0x00};
  uint32_t can_id = 0x601;  
TxHeader.Identifier = can_id;
TxHeader.IdType = FDCAN_STANDARD_ID;
  TxHeader.TxFrameType = FDCAN_DATA_FRAME;
  TxHeader.DataLength = FDCAN_DLC_BYTES_8;
  TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
  TxHeader.BitRateSwitch = FDCAN_BRS_ON; 				//用于設(shè)置發(fā)送是否波特率可變。
  TxHeader.FDFormat = FDCAN_CLASSIC_CAN;				//普通can還是FDcan
  TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;		
//是用于設(shè)置發(fā)送事件FIFO控制事件是否保存
  TxHeader.MessageMarker = 0;											
//marker++;	//用于設(shè)置復(fù)制到TX EVENT FIFO的消息Maker,來識(shí)別消息狀態(tài),范圍0到0xFF
HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, tx_data);//向 Tx 郵箱中增加一個(gè)消息,并且激活對(duì)應(yīng)的傳輸請(qǐng)求
  }

在#include "stm32g4xx_it.c文件中添加CAN頭文件和TIM2中斷函數(shù)中添加接收函數(shù)

#include "fdcan.h"
int TickMs = 0;
void TIM2_IRQHandler(void)
{
  /* USER CODE BEGIN TIM2_IRQn 0 */
  /* USER CODE END TIM2_IRQn 0 */
  HAL_TIM_IRQHandler(&htim2);
  /* USER CODE BEGIN TIM2_IRQn 1 */
CAN_Receive_Msg();//FDCAN接收函數(shù)
  TickMs++;//定時(shí)器計(jì)數(shù)
  /* USER CODE END TIM2_IRQn 1 */
}

主函數(shù)Main.c中while中添加如下代碼

//while前
HAL_TIM_Base_Start_IT(&htim2);	          //定時(shí)器 中斷
Power_ON_Start_TX();						//上電后發(fā)送一串?dāng)?shù)據(jù)	
//While中
if (CANRecFlag)
{
CANRecFlag = 0;
CAN_Send_Msg(hfdcan1,CANRec_msg.Identifier,CANRec_buff);
//接收到數(shù)據(jù)網(wǎng)CAN上位機(jī)反饋一下
}

3.5CAN測(cè)試效果

上電程序運(yùn)行,會(huì)發(fā)送一組數(shù)據(jù) 20 23 11 09 12 20 00 00,然后上位機(jī)發(fā)送數(shù)據(jù)后會(huì)將發(fā)送的數(shù)據(jù)進(jìn)行反饋給上位機(jī),表示數(shù)據(jù)接收成功。

can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

3.6USART接收

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)             /* 如果是串口1 */
    {
        if ( UART_RX_Cont  < USART1_MAX_REC_LENGTH)
        {
            UART1_Rx_Buff[UART_RX_Cont] = UART1_Rx_Temp[0];
            UART_RX_Cont++;
        }
        /* 接收完成后在開啟寫一次中斷接收 */
        HAL_UART_Receive_IT(&huart1, (uint8_t *)UART1_Rx_Temp, RXBUFF_ERSIZE);
    }
}



串口相關(guān)定義
/* USER CODE BEGIN 0 */
uint16_t UART1_Rx_Sta=0;               					/* 接收狀態(tài) */
uint8_t UART1_Rx_Buff[USART1_MAX_REC_LENGTH];           /* HAL庫使用的串口接收緩沖 */
uint8_t UART1_Rx_Temp[RXBUFF_ERSIZE];         			/* 接收字節(jié) */      
uint32_t UART_RX_Cont = 0;
UART_HandleTypeDef huart1;
/* USER CODE END 0 */



usart.h聲明
#include "stdio.h"
int fputc(int ch, FILE *f);
#define RXBUFF_ERSIZE    1 /* 緩存大小 */
#define USART1_MAX_REC_LENGTH   64*1024          /* 定義最大接收字節(jié)數(shù) 200 */
extern uint8_t  UART1_Rx_Buff[USART1_MAX_REC_LENGTH];  	
/* 接收緩沖,最大USART_REC_LEN個(gè)字節(jié).末字節(jié)為換行符 */
extern uint16_t UART1_Rx_Sta;   							/* 接收狀態(tài)標(biāo)記 */  
extern uint8_t UART1_Rx_Temp[RXBUFF_ERSIZE];    			/* HAL庫USART接收Buffer */
extern uint32_t UART_RX_Cont ;            /* 接收到的app代碼長度 */



Main.c
uint32_t lastcount = 0;                     /* 上一次串口接收數(shù)據(jù)值 */
uint32_t applenth = 0;                      /* 接收到的app代碼長度 */
printf("STM32_CAN_UASRT_IAP_End\n");	  //程序串口運(yùn)行發(fā)送STM32_CAN_UASRT_IAP_End



 在usart.c中MX_USART1_UART_Init函數(shù)中,打開中斷接收
 /* USER CODE BEGIN USART1_Init 2 */
	HAL_UART_Receive_IT(&huart1, (uint8_t *)UART1_Rx_Temp, RXBUFF_ERSIZE);//開啟中斷
  /* USER CODE END USART1_Init 2 */

3.7Printf重映射函

int fputc(int ch, FILE *f)
{
 uint8_t temp[1] = {ch};
 HAL_UART_Transmit(&huart1, temp, 1, 0xffff);
return ch;
}

3.8USART主函數(shù)測(cè)試

/*----------串口接收1--------------------------------------*/		
 if (UART_RX_Cont)
    {
       if (lastcount == UART_RX_Cont)   /* 新周期內(nèi),沒有收到任何數(shù)據(jù),認(rèn)為本次數(shù)據(jù)接收完成 */
         {
            applenth = UART_RX_Cont;
            lastcount = 0;
            UART_RX_Cont = 0;
          for(int i = 0; i<applenth;i++)
			{
printf("UART1_Rx_Buff[%d] == %x \r\n",i,UART1_Rx_Buff[i]);
			}
                printf("用戶程序接收完成!\r\n");
                printf("代碼長度:%dBytes\r\n", applenth);
            }
            else lastcount = UART_RX_Cont;
        }

3.9USART測(cè)試效果

上電發(fā)送STM32_CAN_UASRT_IAP_End,通過上位機(jī)發(fā)送數(shù)據(jù),將數(shù)據(jù)每一位轉(zhuǎn)化成ascll碼后16進(jìn)制進(jìn)行打印,發(fā)送的bin文件的所有數(shù)據(jù)都存放在UART1_Rx_Buff的數(shù)組中can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

4.Flash寫入數(shù)據(jù)

FLASH寫入數(shù)據(jù)是引用封裝后的函數(shù),在文件夾can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言文件中的can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言文件可以直接添加到工程中,并添加頭文件的路徑。使用時(shí)直接引用相關(guān)函數(shù)。

5.跳轉(zhuǎn)至APP函數(shù)(即IAP)

跳轉(zhuǎn)函數(shù)同樣也是引用的封裝好的函數(shù),在跳轉(zhuǎn)函數(shù)中做了一些改進(jìn),可以直接添加工程中直接進(jìn)行使用can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

注意:由于是因引用的封裝后的庫,建議將can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

中的所有源文件(.c)和頭文件(.h)同時(shí)添加到工程文件中。

到此部分Bootloader 程序的CAN通訊和usart通訊已經(jīng)完成(接收升級(jí)固件包數(shù)據(jù))

下面程序的升級(jí)邏輯介紹

6.?Bootloader 程序

升級(jí)程序流程圖如下

can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

7.Main程序代碼

函數(shù)聲明部分
/* USER CODE BEGIN Includes */
#include "sys.h"
#include "delay.h"
#include "iap.h"
uint8_t CANRecFlag ;     //CAN接收表示,完成 1 
uint8_t CANRec_buff[8];  //CAN接受到的數(shù)據(jù)位
FDCAN_RxHeaderTypeDef CANRec_msg;   

#define APP_LEN_MAX 60*1024
uint8_t APP_RX_BUF[APP_LEN_MAX] = {0};  //接收緩沖,最大64kb.
uint32_t APPLength = 0;									//升級(jí)程序數(shù)據(jù)長度
extern int TickMs;
/* USER CODE END Includes */


Bootloader程序升級(jí)或跳轉(zhuǎn)選擇while 
 /* USER CODE BEGIN 2 */
	 //delay_init(170);                //若有報(bào)錯(cuò)打開注釋
	 uint32_t lastcount = 0;                      /* 上一次串口接收數(shù)據(jù)值 */
      uint32_t applenth = 0;                      /* 接收到的app代碼長度 */
	 HAL_TIM_Base_Start_IT(&htim2);	           //定時(shí)器 中斷
	 Power_ON_Start_TX();				      //上電后發(fā)送一串?dāng)?shù)據(jù)	
	 printf("STM32_IAP_02\n");	 
	while(1)
    {    
	  if(TickMs>5000)//5秒后跳轉(zhuǎn)
	  {
		if (((*(volatile uint32_t *)(FLASH_APP1_ADDR + 4)) & 0xFF000000) == 0x08000000)
 /* 判斷FLASH里面是否有APP,有的話執(zhí)行 */
		{
		 printf("開始執(zhí)行FLASH用戶代碼!!\r\n\r\n");
		 printf("RUN addr :%x \r\n",(*(volatile uint32_t *)(FLASH_APP1_ADDR )));
		 iap_load_app(FLASH_APP1_ADDR);       /* 執(zhí)行FLASH APP代碼 */					}else{
			printf("非APP———FLASH應(yīng)用程序,無法執(zhí)行!\r\n");
			printf("進(jìn)入主程序等待升級(jí)!!\r\n");
			break;
			 }
	 }
	if(CANRecFlag)//升級(jí)命令CAN口有接收任意消息
	{
		CANRecFlag = 0;
		printf("進(jìn)入主程序等待升級(jí)!!\r\n");
	break;
	  }
    }
  /* USER CODE END 2 */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
/*-----------串口接收數(shù)據(jù)處理--------------------------------------*/		
if (UART_RX_Cont)
     {
        if (lastcount == UART_RX_Cont)   /* 新周期內(nèi),沒有收到任何數(shù)據(jù),認(rèn)為本次數(shù)據(jù)接收完成 */
        {
                applenth = UART_RX_Cont;
                lastcount = 0;
                UART_RX_Cont = 0;
//		for(int i = 0; i<applenth;i++)
//		{
//		  printf("UART1_Rx_Buff[%d] == %x \r\n",i,UART1_Rx_Buff[i]);
//	     }
          printf("用戶程序接收完成!\r\n");
          printf("代碼長度:%dBytes\r\n", applenth);
        }
            else lastcount = UART_RX_Cont;
     }
/*----------CAN升級(jí)命令------------------------------*/
if (CANRecFlag)
	{
	  CANRecFlag = 0;
//	CAN_Send_Msg(hfdcan1,CANRec_msg.Identifier,CANRec_buff);
//接收到數(shù)據(jù)網(wǎng)CAN上位機(jī)反饋一下
	  if (CANRec_msg.Identifier ==0x123) //升級(jí)指令包
	{
		  if (applenth < APP_LEN_MAX)
			{
		     	for(int i=0 ;i < 8;i++)
				{
			     	APP_RX_BUF[applenth] = CANRec_buff[i];
					applenth++;
				}
			 }else{	
				printf("緩沖區(qū)容量不足...\r\n");
				}
			}
	 if (CANRec_msg.Identifier ==0x111) 
		{
	     	printf("APP_RX_BUF[%d] \n",applenth);//APPLength
//		  for(int i = 0; i<applenth;i++)
//			{
//		     	printf("APP_RX_BUF[%d] = %x\n",i,APP_RX_BUF[i]);
//			}
	 if(applenth)
		{
/*-------------串口升級(jí)----------------------------------------------------------------------*/			  if (((*(volatile uint32_t *)(UART1_Rx_Buff + 4)) & 0xFF000000) == 0x08000000)  
/* 判斷是否為0X08XXXXXX */
		{
		  printf(" \n串口升級(jí)開始更新固件...\r\n");
		printf("updata addr :%x \r\n",(*(volatile uint32_t *)(UART1_Rx_Buff + 4)) & 0xFF000000);		iap_write_appbin(FLASH_APP1_ADDR, UART1_Rx_Buff, applenth);/* 更新FLASH代碼 */		printf("UPdata addr :%x \r\n",(*(volatile uint32_t *)(FLASH_APP1_ADDR )));         			printf("\n?。?!串口升級(jí)固件更新完成!?。r\n");						
		 }
/*---------------CAN升級(jí)-------------------------------------------------------------------*/		
		else if (((*(volatile uint32_t *)(APP_RX_BUF + 4)) & 0xFF000000) == 0x08000000)  
/* 判斷是否為0X08XXXXXX */
		{					
		printf(" \nCAN升級(jí)開始更新固件...\r\n");										
		printf("updata addr :%x \r\n",(*(volatile uint32_t *)(APP_RX_BUF + 4)) & 0xFF000000);		iap_write_appbin(FLASH_APP1_ADDR, APP_RX_BUF, applenth);	/* 更新FLASH代碼 */		printf("UPdata addr :%x \r\n",(*(volatile uint32_t *)(FLASH_APP1_ADDR )));         			printf("\n?。?!固件更新完成!?。r\n");
		}else{		
			printf("\n?。?!非FLASH應(yīng)用程序?。?!\r\n");
	     }
		}else{
            printf("沒有可以更新的固件!\r\n");
            }
		}
	if (CANRec_msg.Identifier == 0x222)   /* KEY1按鍵按下, 運(yùn)行FLASH APP代碼 */
	{
	  printf("flash Run addr :%x \r\n",(*(volatile uint32_t *)(FLASH_APP1_ADDR + 4)) & 0xFF000000);
	   if (((*(volatile uint32_t *)(FLASH_APP1_ADDR + 4)) & 0xFF000000) == 0x08000000) /* 判斷FLASH里面是否有APP,有的話執(zhí)行 */
		{
		  printf("開始執(zhí)行FLASH用戶代碼!!\r\n\r\n");
			printf("RUN addr :%x \r\n",(*(volatile uint32_t *)(FLASH_APP1_ADDR )));
			iap_load_app(FLASH_APP1_ADDR);/* 執(zhí)行FLASH APP代碼 */						}else	{
			printf("沒有可以運(yùn)行的固件!\r\n");
			}
		}
	}
/*-------------------Bootloader LED反饋--------------------------------------------------*/
		HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_1|GPIO_PIN_0);
		HAL_Delay(500);
  }
  /* USER CODE END 3 */

8.升級(jí)效果

8.1CAN升級(jí)效果

can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言

8.2USART升級(jí)效果

通過Ecantools發(fā)送更新,升級(jí)指令實(shí)現(xiàn)升級(jí)跳轉(zhuǎn)程序

can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言文章來源地址http://www.zghlxwxcb.cn/news/detail-777211.html

9.注意事項(xiàng)

  1. CAN接受數(shù)據(jù)時(shí)不可有延時(shí)出現(xiàn),否則會(huì)影響數(shù)據(jù)接收
  2. CAN通過上位機(jī)發(fā)送bin文件數(shù)據(jù)或其他方式發(fā)送文件數(shù)據(jù)時(shí),需要注意發(fā)送每一幀數(shù)據(jù)的時(shí)間間隔的控制,否則會(huì)出現(xiàn)數(shù)據(jù)丟幀,不能接收完整的數(shù)據(jù)包。
  3. 配置APP程序和Bootloader程序時(shí),需要注意起始地址和空間大小,具體看程序的大小從而進(jìn)行配置。本程序的起始控件大小如下can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言can 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言
  4. 程序中有Printf重映射相關(guān)的函數(shù),需要將上圖中的 ??????????use MicroLIBcan 升級(jí) 固件 stm32,stm32,單片機(jī),嵌入式硬件,c語言勾選上

到了這里,關(guān)于STM32G473 固件升級(jí)IAP(BootLoader)CAN/USART。(詳細(xì)步驟)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【STM32】IAP升級(jí)01 bootloader實(shí)現(xiàn)以及APP配置(主要)

    【STM32】IAP升級(jí)01 bootloader實(shí)現(xiàn)以及APP配置(主要)

    通過之前的了解 之前的了解,我們知道實(shí)現(xiàn)IAP升級(jí)需要兩個(gè)條件: 1.APP程序必須在 IAP 程序之后的某個(gè)偏移量為 x 的地址開始; 2.APP程序的中斷向量表相應(yīng)的移動(dòng),移動(dòng)的偏移量為 x; 默認(rèn)條件下的起始地址 默認(rèn)的條件下,圖中 IROM1 的起始地址(Start)一般為 0x08000000,大小

    2024年02月03日
    瀏覽(47)
  • 基于STM32單片機(jī)BOOTLOADER通過串口升級(jí)程序IAP——APP方案

    基于STM32單片機(jī)BOOTLOADER通過串口升級(jí)程序IAP——APP方案

    ????????????????????????此方法前提是你得有一個(gè)EEPROM ? ? ? ? 我用的單片機(jī)是STM32F103ZET6 , 此單片機(jī)FLASH容量為512KB; 在此單片機(jī)里面FLASH的起始地址是0X8000000,BOOT作為引導(dǎo)加載程序一般都是從這個(gè)地址開始,單片機(jī)一上點(diǎn)默認(rèn)會(huì)從這個(gè)地址開始運(yùn)行,所以將自己

    2024年02月04日
    瀏覽(96)
  • STM32F0實(shí)現(xiàn)IAP升級(jí)固件

    STM32F0實(shí)現(xiàn)IAP升級(jí)固件

    好幾年前寫過一篇關(guān)于 STM32 bootloader 升級(jí)固件的博客,但是使用的芯片是 STM32 F4 系列,升級(jí)固件的方式是在外部 flash 的 fat32 文件系統(tǒng)中存入固件文件,reset 后通過特定按鍵進(jìn)入 IAP 程序。 最近需要在 STM32 上實(shí)現(xiàn)同樣的 IAP 功能,但是方式不太一樣,也發(fā)現(xiàn)一些芯片的差別,

    2024年02月14日
    瀏覽(21)
  • STM32單片機(jī)實(shí)現(xiàn)固件在線升級(jí)(IAP)

    單片機(jī)的固件升級(jí)方式有很多種, 1、ICP:In Circuit Programing,簡單說就是在單片機(jī)開發(fā)時(shí)使用燒錄器升級(jí)程序,比如使用J-Link燒錄單片機(jī)程序。 2、ISP:In System Programing,在單片機(jī)內(nèi)部實(shí)現(xiàn)了基于通信接口(如串口、I2C、SPI等等)的FLASH引導(dǎo)程序,配合廠家提供的燒錄軟件工具

    2024年02月13日
    瀏覽(23)
  • bootloader編寫——MCU固件升級(jí)系列2(STM32)

    bootloader編寫——MCU固件升級(jí)系列2(STM32)

    本系列將從升級(jí)流程、boot代碼編寫、APP代碼編寫以及固件打包來介紹,硬件選用STM32F407ZGT6(手里只有),來完成這系列教程。 開發(fā)STM32固件升級(jí)并編寫B(tài)ootloader時(shí),需要注意以下幾個(gè)關(guān)鍵點(diǎn): 熟悉硬件和數(shù)據(jù)手冊(cè):在開發(fā)過程中,確保充分理解STM32微控制器的特性和功能。閱

    2024年02月03日
    瀏覽(29)
  • STM32 IAP應(yīng)用開發(fā)——通過USB實(shí)現(xiàn)固件升級(jí)

    STM32 IAP應(yīng)用開發(fā)——通過USB實(shí)現(xiàn)固件升級(jí)

    什么是IAP? IAP(In-Application Programming) 指MCU可以在系統(tǒng)中獲取新代碼并對(duì)自己重新編程,即可用程序來改變程序。在應(yīng)用編程(IAP)是用戶的應(yīng)用代碼對(duì)片內(nèi)Flash存儲(chǔ)器進(jìn)行擦除/編程的方法。這種方式的典型應(yīng)用就是用一小段代碼來實(shí)現(xiàn)程序的下載,實(shí)際上單片機(jī)的ISP功能就

    2024年02月12日
    瀏覽(19)
  • 調(diào)試筆記-stm32的OTA/IAP 通過485升級(jí)固件

    調(diào)試筆記-stm32的OTA/IAP 通過485升級(jí)固件

    背景:最近需要在stm32上實(shí)現(xiàn)通過rs485升級(jí)固件功能。經(jīng)過幾天搜索和調(diào)試,實(shí)現(xiàn)了功能。 目標(biāo):使用cubeIDE實(shí)現(xiàn)stm32F407VGT6,通過RS485升級(jí)固件 調(diào)試記錄: 步驟1. 在keil環(huán)境下的rs485升級(jí)固件(含源碼):STM32 OTA應(yīng)用開發(fā)——通過串口/RS485實(shí)現(xiàn)OTA升級(jí)(方式2)_stm32串口升級(jí)_柒壹漆

    2024年02月11日
    瀏覽(21)
  • STM32 IAP應(yīng)用開發(fā)——通過串口/RS485實(shí)現(xiàn)固件升級(jí)(方式2)

    STM32 IAP應(yīng)用開發(fā)——通過串口/RS485實(shí)現(xiàn)固件升級(jí)(方式2)

    什么是IAP? IAP(In-Application Programming) 指MCU可以在系統(tǒng)中獲取新代碼并對(duì)自己重新編程,即可用程序來改變程序。在應(yīng)用編程(IAP)是用戶的應(yīng)用代碼對(duì)片內(nèi)Flash存儲(chǔ)器進(jìn)行擦除/編程的方法。這種方式的典型應(yīng)用就是用一小段代碼來實(shí)現(xiàn)程序的下載,實(shí)際上單片機(jī)的ISP功能就

    2024年02月14日
    瀏覽(24)
  • STM32 IAP應(yīng)用開發(fā)——通過串口/RS485實(shí)現(xiàn)固件升級(jí)(方式1)

    STM32 IAP應(yīng)用開發(fā)——通過串口/RS485實(shí)現(xiàn)固件升級(jí)(方式1)

    什么是IAP? IAP(In-Application Programming) 指MCU可以在系統(tǒng)中獲取新代碼并對(duì)自己重新編程,即可用程序來改變程序。在應(yīng)用編程(IAP)是用戶的應(yīng)用代碼對(duì)片內(nèi)Flash存儲(chǔ)器進(jìn)行擦除/編程的方法。這種方式的典型應(yīng)用就是用一小段代碼來實(shí)現(xiàn)程序的下載,實(shí)際上單片機(jī)的ISP功能就

    2024年02月10日
    瀏覽(19)
  • STM32 usart bootloader 源代碼 STM32 usart bootloader 源代碼 STM32 usart bootloader 原代源碼

    STM32 usart bootloader 源代碼 STM32 usart bootloader 源代碼 STM32 usart bootloader 原代源碼

    STM32 usart bootloader 源代碼 ? STM32 usart bootloader 源代碼 ?STM32 usart bootloader 原代源碼,上位機(jī)C#,下位機(jī)c。 簡單修改可以支持stm32全系列芯片。 支持串口升級(jí) 該版本為優(yōu)化過的版本, 1.支持代碼段保護(hù); 2.支持燒寫失敗重置; 3.兼容我公司生產(chǎn)的配套wifi模塊和w5500模塊遠(yuǎn)程更新

    2024年01月23日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包