QT上位機給STM32設備串口IAP升級固件

QT上位機給STM32設備串口IAP升級固件

目錄

QT上位機給STM32設備串口IAP升級固件

1,實現原理

2,程序流程

3,關鍵代碼解析

4,相關工具及代碼


廢話不多說看看效果先


 

1,實現原理

應用編程IAP(In-Application-Programming)是應用在Flash程序存儲器的一種編程模式,它可以在應用程序正常運行的情況下,通過調用特定的IAP程序對另外一段程序Flash空間進行讀/寫操作,甚至可以控制對某段、某頁甚至某個字節的讀/寫操作。主要用於數據存儲和固件升級。對於IAP應用,通常會有兩個程序,第一個程序Bootloader程序不執行正常功能,只是通過某種方式(串口,usb,SD卡)接收第二個程序,並進行更新。第二個程序APP程序是執行的主體,用於實現應用功能。
       對於stm32閃存模塊,主要由主存儲器、信息塊和閃存存儲器接口寄存器三部分構成。
                         
       主存儲器,該部分用來存放代碼和數據常數(如 const 類型的數據)。對於大容量產品,其被劃分爲 256 頁,每頁 2K 字節。注意, 小容量和中容量產品則每頁只有 1K 字節。看出主存儲器的起始地址就是 0X08000000, B0、 B1 都接GND 的時候,就是從 0X08000000開始運行代碼的。

       信息塊,該部分分爲 2 個小部分,其中啓動程序代碼,是用來存儲 ST 自帶的啓動程序,用於串口下載代碼,當 B0 接 V3.3, B1 接 GND的時候,運行的就是這部分代碼。用戶選擇字節,則一般用於配置寫保護、讀保護等功能,本章不作介紹。

       閃存存儲器接口寄存器,該部分用於控制閃存讀寫等,是整個閃存模塊的控制機構。

       對主存儲器和信息塊的寫入由內嵌的閃存編程/擦除控制器(FPEC)管理;編程與擦除的高電壓由內部產生。

 

    對於flash的讀寫的流程

    這裏要特別留意一個閃存等待時間,因爲 CPU 運行速度比 FLASH 快得多, STM32F103的 FLASH 最快訪問速度≤24Mhz,如果 CPU 頻率超過這個速度,那麼必須加入等待時間,比如我們一般使用72Mhz的主頻,那麼FLASH等待週期就必須設置爲 2,該設置通過 FLASH_ACR寄存器設置。

2,程序流程

編程流程

1、檢查 FLASH_CR 的 LOCK 是否解鎖,如果沒有則先解鎖,(向KEYR寄存器中寫入特定序列KEY1和KEY2)

   (實際中需要查看當前要寫入的扇區是否有數據,如果有數據,則需要進行擦除操作,然後再進行下面的步驟)

2、檢查 FLASH_SR 寄存器的 BSY 位,以確認沒有其他正在進行的編程操作
3、設置 FLASH_CR 寄存器的 PG 位爲’1’,用於表示接下來進行寫操作
4、在指定的地址寫入要編程的半字
5、等待 BSY 位變爲’0’,表示編程完成
6、讀出寫入的地址並驗證數據

 

我們在 STM32 的 FLASH 編程的時候,要先判斷縮寫地址是否被擦除了

 

下面介紹頁擦除過程

 


讀出被擦除的頁並做驗證
1、檢查 FLASH_CR 的 LOCK 是否解鎖,如果沒有則先解鎖(向KEYR寄存器中寫入特定序列KEY1和KEY2)
2、檢查 FLASH_SR 寄存器的 BSY 位,以確認沒有其他正在進行的閃存操作
3、設置 FLASH_CR 寄存器的 PER 位爲’1’,用於表示進行頁擦除操作
4、用 FLASH_AR 寄存器選擇要擦除的頁
5、置 FLASH_CR 寄存器的 STRT 位爲‘1’表示開始一次擦除操作
6、等待 BSY 位變爲’ 0’
讀出被擦除的頁並做驗證
 

我們來了解下stm32的程序運行流程,如下圖所示

程序運行的地址從0x08000000(FLASH)開始運行

1程序開始運行後,從中斷向量表中取出復位中斷向量,並執行服務程序。

2執行完中斷向量程序會跳轉至主main函數入口執行,並在死循環中一直執行。

3當在主函數中發生中斷時間時,系統強制PC指針指向對應中斷向量表對應位置。

4PC指針在中斷向量表處取出中斷服務程序入口地址,並跳轉至對應位置執行。

5中斷服務程序執行完成後,PC指針跳回發生中斷時系統在main函數中的位置,繼續往下執行。

 

當加入IAP應用後stm32的程序流程變爲下圖所示

程序運行的地址從0x08000000(FLASH)開始運行

 

1程序開始運行後,從中斷向量表中取出復位中斷向量,並執行服務程序。執行完中斷向量程序會跳轉至Bootloader程序main函數入口執行。

2在main中系統檢查是否需要對第二部分代碼進行更新,如果需要則執行更新操作,如果不需要則跳過更新操作,跳轉至APP程序的入口

3在APP程序入口首先進入重新映射的中斷向量口,根據新的中斷復位向量,執行復位中斷程序,然後跳轉至APP程序main入口。

4當在主函數中發生中斷時間時,系統強制PC指針指向對應中斷向量表對應位置(這裏還是強制跳轉到地址0x0800004中斷向量表位置,而不是APP程序的中斷向量表)。

兩個注意點:

1) 新程序必須在 IAP 程序之後的某個偏移量爲 x 的地址開始;

2) 必須將新程序的中斷向量表相應的移動,移動的偏移量爲 x;

 

 

對於程序的設置

IAP程序

通過串口設置程序的接收

根據要求設置存儲APP程序的地址

 

APP程序

設置程序存儲區,與數據存儲區 在Target->Read/Only Memory Areas-> IROM與IRAM處設置,這裏APP程序的存儲首地址設爲0x08010000,大小爲0x70000(即前0x10000爲存放IAP程序)

設置中斷向量表偏移地址SCB->VTOR = FLASH_BASE | 0x10000; 

生成BIN文件

 

3,關鍵代碼解析

STM32F103的IAP關鍵代碼:

int main(void)
{      
	uint32_t tick1;
	tick1 = SysTick_GetCurrent();
        MCU_Init();	
	AreaFlagFirstLoadInit();
	NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x8000000);  //iap初始都從0x8000000開始運行
	printf("init success\r\n");	   
	__enable_irq();	
	while(1)		
	{
		iapLoop();
		if((remainSend  == 0x00) && (upgradeDoneFlag == 0xaa55aa55)) 
		{			
	
			(currentAreaNum==areaA) ? (FlashDestination=ApplicationAddress_A) : (FlashDestination=ApplicationAddress_B);
			if(((*(__IO uint32_t*)FlashDestination) & 0x2FFE0000 ) == 0x20000000)				//binÎļþÉý¼¶
			{											 
				printf("Execute user APP1 Program upgradeDoneFlag=%x\r\n",upgradeDoneFlag);
				USART_Cmd(USART1, DISABLE);
				__disable_irq();	
				JumpAddress = *(__IO uint32_t*) (FlashDestination + 4);
				Jump_To_Application = (pFunction) JumpAddress;						
				MSR_MSP(*(vu32*)FlashDestination);
				Jump_To_Application();								
			}
			else 
			{			
				if(SysTick_GetLapse(tick1)>1000)
				{
					printf("ÎÞFLASHÓ¦ÓóÌÐò,ÎÞ·¨Ö´ÐÐ!\r\n");	
					tick1 = SysTick_GetCurrent();
				}
				
			}
		}
	}
}


uint8_t AreaFlagFirstLoadInit(void)
{
	uint8_t ret = 0;
	STMFLASH_Read(ADDR_FLASH_LAST_PAGE,&upgradeDoneFlag,1);  
	FLASH_Unlock();
	if(upgradeDoneFlag==0xffffffff || upgradeDoneFlag==0x00000000)
	{
		upgradeDoneFlag = 0xaa55aa55;
		FLASH_ProgramWord(ADDR_FLASH_LAST_PAGE,0xaa55aa55);
	}
	

	STMFLASH_Read(AREA_NUM_ADDR,&currentAreaNum,1);
	
	if(currentAreaNum == 0xffffffff || currentAreaNum==0x00000000)   
	{	
		printf("ÇøÓò±ê־λ³õʼ»¯");
		currentAreaNum = areaA;			
		if(FLASH_COMPLETE!=FLASH_ProgramWord(AREA_NUM_ADDR,areaA))
		{
			printf("ÇøÓòA±ê־λÉϵç³õʼ»¯Ê§°Ü");
			ret = 1;
		}
	}	
	FLASH_Lock();
	
	switch(currentAreaNum)
	{
		case areaA:
			addrCur = ApplicationAddress_B;
			break;
		
		case areaB:
			addrCur = ApplicationAddress_A;
			break;	
			
		default:
			break;
	}

	printf("addrCur=%x currentAreaNum=%x upgradeDoneFlag=%x\n",addrCur,currentAreaNum,upgradeDoneFlag);
	
	return ret;
}

IAP程序中

4,相關工具及代碼

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章