STM32 CubeMX (uart_IAP串口)簡單示例

STM32 CubeMX


STM32 CubeMX (串口IAP)

  • STM32 CubeMX
    • IAP有什么用?
    • 整體思路
  • 一、STM32 CubeMX 設置
    • 時鐘樹
    • UART使能
    • UART初始化設置
  • 二、代碼部分
    • 文件移植![在這里插入圖片描述](https://img-blog.csdnimg.cn/0c4841d8328b4169a8833f15fe3d670c.png)
    • 實驗效果
    • APP程序返回IAP程序


IAP有什么用?

Iap,全名為in applacation programming,即在應用編程,與之相對應的叫做isp,in system programming,在系統編程,兩者的不同是isp需要依靠燒寫器在單片機復位離線的情況下編程,需要人工的干預,而iap則是用戶自己的程序在運行過程中對User Flash 的部分區域進行燒寫,目的是為了在產品發布后可以方便地通過預留的通信口對產品中的固件程序進行更新升級。在工程應用中經常會出現我們的產品被安裝在某個特定的機械結構中,更新程序的時候拆機很不方便,使用iap技術能很好地降低工作量.

整體思路

實現iap有兩個很重要的前提,首先,單片機程序能對自身的內部flash進行擦寫,第二,單片機要有能夠和外部進行通訊的方式,無論是網絡還是別的方式,只要能傳輸數據就行

要做iap首先我們要知道stm32的啟動流程,流程如下

  1. 單片機從0x80000000位置啟動,并將該地址當成系統棧頂地址
  2. 運行到中斷向量表中,默認的中斷向量表為0x80000004,該位置存放復位中斷
  3. 跳轉到復位中斷處理函數當中,進行系統初始化,然后運行main函數

兩種實現方式:

  1. 將IAP和APP程序放在一個程序中,會增加代碼的耦合性和難度;
  2. 要將單片機flash分為兩部份 IAP程序 APP程序 ;IAP是燒錄工具燒錄的(如 JTAG 或 ISP 燒入),App是通過串口傳遞bin文件(也可以是其他方式:如藍牙,網卡,CAN等等)然后芯片自己燒錄的

一定要劃分清楚IAP程序和APP程序的flash地址,不要重合了
#1.IAP程序設置,程序地址
在這里插入圖片描述
#2.APP程序設置,程序地址
在這里插入圖片描述
生成bin文件

fromelf.exe --bin -o "$L@L.bin" "#L

在這里插入圖片描述

一、STM32 CubeMX 設置

時鐘樹

在這里插入圖片描述

UART使能

在這里插入圖片描述

UART初始化設置

在這里插入圖片描述

二、代碼部分

移植正點原子的兩部分代碼,IAP和Fashl,也可以移植官方的代碼,有能實現的Dome都可以

文件移植在這里插入圖片描述

在這里插入圖片描述

移植至CubeMX生成的文件夾
在這里插入圖片描述
添加文件和路徑
在這里插入圖片描述

修改IAP.C

#define FLASH_APP1_ADDR		0x8005000  	//第一個應用程序起始地址(存放在FLASH)
iapfun jump2app;
u16 iapbuf[512];//**緩存區大小,因為stm32f103c8t6的flash一頁是1K的,所以要改小為512**

添加函數


//設置棧頂地址
//addr:棧頂地址
__asm void MSR_MSP(u32 addr) 
{MSR MSP, r0 			//set Main Stack valueBX r14
}

修改"stmflash.h"

//用戶根據自己的需要設置
#define STM32_FLASH_SIZE 	64	 		//所選STM32的FLASH容量大小(單位為K)
#define STM32_FLASH_WREN 	1              	//使能FLASH寫入(0,不是能;1,使能)
#define FLASH_WAITETIME  	50000          	//FLASH等待超時時間//FLASH起始地址
#define STM32_FLASH_BASE 0x08000000 		//STM32 FLASH的起始地址

修改UART

#include "usart.h"
#include "stdio.h"
int fputc(int ch, FILE *f) {HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);return ch;
}/* USER CODE BEGIN 0 */
#define USART_REC_LEN  			15*1024 //定義最大接收字節數 55K
#define EN_USART1_RX 			1		//使能(1)/禁止(0)串口1接收
#define RXBUFFERSIZE   1 					//緩存大小	  	
uint8_t USART_RX_BUF[USART_REC_LEN] __attribute__ ( ( at ( 0X20001000 ) ) ); //接收緩沖,最大USART_REC_LEN個字節,起始地址為0X20001000.
//接收狀態
//bit15,	接收完成標志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字節數目
uint16_t USART_RX_STA = 0;       	//接收狀態標記
uint16_t USART_RX_CNT = 0;			//接收的字節數
/* USER CODE END 0 */
u8 aRxBuffer[RXBUFFERSIZE];//HAL庫使用的串口接收緩沖UART_HandleTypeDef 	huart1;/* USART1 init function *///初始化IO 串口1 
//bound:波特率
void uart_init(u32 bound)
{	//UART 初始化設置huart1.Instance=USART1;					    //USART1huart1.Init.BaudRate=bound;				    //波特率huart1.Init.WordLength=UART_WORDLENGTH_8B;   //字長為8位數據格式huart1.Init.StopBits=UART_STOPBITS_1;	    //一個停止位huart1.Init.Parity=UART_PARITY_NONE;		    //無奇偶校驗位huart1.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //無硬件流控huart1.Init.Mode=UART_MODE_TX_RX;		    //收發模式HAL_UART_Init(&huart1);					    //HAL_UART_Init()會使能UART1HAL_UART_Receive_IT(&huart1, (u8 *)aRxBuffer, RXBUFFERSIZE);//該函數會開啟接收中斷:標志位UART_IT_RXNE,并且設置接收緩沖以及接收緩沖接收最大數據量}//UART底層初始化,時鐘使能,引腳配置,中斷配置
//此函數會被HAL_UART_Init()調用
//huart:串口句柄void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{//GPIO端口設置GPIO_InitTypeDef GPIO_Initure;if(huart->Instance==USART1)//如果是串口1,進行串口1 MSP初始化{__HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA時鐘__HAL_RCC_USART1_CLK_ENABLE();			//使能USART1時鐘__HAL_RCC_AFIO_CLK_ENABLE();GPIO_Initure.Pin=GPIO_PIN_9;			//PA9GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//復用推挽輸出GPIO_Initure.Pull=GPIO_PULLUP;			//上拉GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9GPIO_Initure.Pin=GPIO_PIN_10;			//PA10GPIO_Initure.Mode=GPIO_MODE_AF_INPUT;	//模式要設置為復用輸入模式!	HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA10#if EN_USART1_RXHAL_NVIC_EnableIRQ(USART1_IRQn);				//使能USART1中斷通道HAL_NVIC_SetPriority(USART1_IRQn,3,3);			//搶占優先級3,子優先級3
#endif	}
}
extern u8 flag_1;//串口1中斷服務程序
void USART1_IRQHandler(void)                	
{ u8 Res;if((__HAL_UART_GET_FLAG(&	huart1,UART_FLAG_RXNE)!=RESET))  //接收中斷(接收到的數據必須是0x0d 0x0a結尾){Res=USART1->DR; if(USART_RX_CNT<USART_REC_LEN){USART_RX_BUF[USART_RX_CNT]=Res;USART_RX_CNT++;			 									     }}flag_1=1;HAL_UART_IRQHandler(&	huart1);	
} 

main.c

int main(void)
{/* USER CODE BEGIN 1 */u16 oldcount = 0;				//老的串口接收數據值u16 applenth = 0;				//接收到的app代碼長度u16 app_bin = 0;u16 app_enter = 0;HAL_Init();SystemClock_Config();MX_GPIO_Init();uart_init(115200);while ( 1 ){//	 首先判斷app代碼的首地址是否為0x0800 000,是則進入app,否的話進行引導區。if ( ( ( * ( vu32* ) ( FLASH_APP1_ADDR + 4 ) ) & 0xFF000000 ) == 0x08000000 ) //判斷是否為0X08XXXXXX.{iap_load_app ( FLASH_APP1_ADDR ); //執行FLASH APP代碼}//   判斷app代碼棧頂是否為0x2000 000,不是則進入升級模式,代碼如下,其中 FLASH_APP1_ADDR=0x8005000;if ( ( ( ( * ( vu32* ) FLASH_APP1_ADDR ) & 0x2FFE0000 ) != 0x20000000 ) ){printf ( "/***** No APP! *****/ \r\n" );printf ( "stm32f103c8t6在線升級  \r\n" );printf ( "選擇對應的app bin文件 \r\n" );printf ( "輸入 A 發送bin文件 \r\n" );printf ( "輸入 E 進入app \r\n" );while ( 1 ){printf ( "滴答!\r\n" );if( flag_1==1){flag_1=0;printf ( "holle wored!\r\n" );}if ( USART_RX_CNT ){if ( oldcount == USART_RX_CNT ) //新周期內,沒有收到任何數據,認為本次數據接收完成.{applenth = USART_RX_CNT;oldcount = 0;USART_RX_CNT = 0;if ( applenth > 100 ){printf ( "用戶程序接收完成!\r\n" );printf ( "代碼長度:%dBytes\r\n", applenth );}}else oldcount = USART_RX_CNT;}HAL_Delay(1000);if ( USART_RX_BUF[0] == 'A' ){if ( applenth )printf ( "\r\n 請發送bin文件 \r\n" );app_bin = 1;applenth = 0;}else if ( app_bin ){if ( applenth ){printf ( "開始更新固件...\r\n" );printf ( "Copying APP2FLASH..." );//此處 0X20001000 地址為串口緩沖區開始接收數據地址if ( ( ( * ( vu32* ) ( 0X20001000 + 4 ) ) & 0xFF000000 ) == 0x08000000 ) //判斷是否為0X08XXXXXX. 串口是否接收到數據{iap_write_appbin ( FLASH_APP1_ADDR, USART_RX_BUF, applenth ); //更新FLASH代碼 printf ( "Copy APP Successed!!" );printf ( "固件更新完成!\r\n" );applenth = 0;app_bin = 0;}}}if ( USART_RX_BUF[0] == 'E' ){if ( applenth )printf ( "\r\n 將要執行APP \r\n" );app_enter = 1;applenth = 0;} if ( app_enter ){printf ( "開始執行FLASH用戶代碼!!\r\n" );if ( ( ( * ( vu32* ) ( FLASH_APP1_ADDR + 4 ) ) & 0xFF000000 ) == 0x08000000 ) //判斷是否為0X08XXXXXX.{iap_load_app ( FLASH_APP1_ADDR ); //執行FLASH APP代碼}else {printf ( "非FLASH應用程序,無法執行!\r\n" );printf ( "Illegal FLASH APP!" );}}}}}/* USER CODE END 3 */
}

實驗效果

請添加圖片描述

APP程序返回IAP程序

執行下面代碼可以重回函數

 			  SCB->VTOR = FLASH_BASE | 0x0000;HAL_NVIC_SystemReset();

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/39546.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/39546.shtml
英文地址,請注明出處:http://en.pswp.cn/news/39546.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PHP Smarty中的緩存如何實現?

歡迎來到PHP Smarty的緩存世界&#xff01;這里是一個簡單的指南&#xff0c;幫助你理解如何在這個強大的模板引擎中啟用和配置緩存。 首先&#xff0c;讓我們先了解一下什么是緩存。簡單來說&#xff0c;緩存就是將需要花費大量時間處理的數據或資源存儲起來&#xff0c;以便…

2023/8/16總結

這幾天完成了私信的功能點&#xff0c;用websocket做的。 這是大概的界面&#xff0c;參考的是微信 用戶可以搜索好友&#xff1a; 如果不存在是下面這樣&#xff0c;存在就會在左邊的聊天里面顯示有這個人選項 發送消息 接下來需要把推薦算法給做了

文件IO編程 1 2

頭文件包含路徑 linux 操作系統分為兩大空間&#xff1a;用戶空間和內核空間 這樣劃分&#xff0c;是為了保護內核的核心組件&#xff0c;不被輕易訪問和修改 系統調用&#xff1a;安全的訪問內核空間 其核心是&#xff1a;函數API&#xff08;API&#xff1a;用戶編程接口&…

svn文章五:問題排查與修復 - 出了問題怎么辦?SVN故障排除與修復指南

文章五&#xff1a;問題排查與修復 - “出了問題怎么辦&#xff1f;SVN故障排除與修復指南” 概述&#xff1a;在使用SVN時&#xff0c;難免會遇到一些問題和錯誤。在這篇文章中&#xff0c;我們將教您如何進行故障排查和修復&#xff0c;保護您的SVN倉庫和數據安全。 1. 引言…

K8S系列文章之 Docker安裝使用Kafka

通過Docker拉取鏡像的方式進行安裝 照例先去DockerHub找一下鏡像源&#xff0c;看下官方提供的基本操作&#xff08;大部分時候官方教程比網上的要清晰一些&#xff0c;并且大部分教程可能也是翻譯的官方的操作步驟&#xff0c;所以直接看官方的就行&#xff09; 老實說Kafka…

“深入剖析JVM內部原理:解密Java虛擬機的奧秘“

標題&#xff1a;深入剖析JVM內部原理&#xff1a;解密Java虛擬機的奧秘 摘要&#xff1a;本文將深入探討Java虛擬機&#xff08;JVM&#xff09;的內部原理&#xff0c;包括其架構、內存管理、垃圾回收機制、即時編譯器等關鍵組成部分。通過解密JVM的奧秘&#xff0c;我們將更…

【Vue3】Vue3 UI 框架 | Element Plus —— 創建并優化表單

安裝 # NPM $ npm install element-plus --save // 或者&#xff08;下載慢切換國內鏡像&#xff09; $ npm install element-plus -S// 可以選擇性安裝 less npm install less less-loader -D // 可以選擇性配置 自動聯想src目錄Element Plus 的引入和注入 main.ts import…

解決VSCode CPU高占問題的方法

如果你也遇到VSCode的CPU占用過高的問題&#xff0c;可以嘗試使用官方自帶的插件Bisect&#xff08;擴展二分查找&#xff09;功能來查找具體是哪個擴展出了問題。 找到“糟糕”的擴展可能很容易&#xff0c;也可能很困難。 打開擴展視圖 ( CtrlShiftX )&#xff0c;禁用擴展&…

網絡:雜記

1. 完成鏈路認證后&#xff0c;STA會繼續發起鏈路服務協商&#xff0c;具體的協商是通過Association報文實現。 2. RSTP可以提高收斂速度的原因&#xff1a; RSTP的拓撲變化機制 Proposal/Agreement機制 根端口快速切換機制 邊緣端口的引入

git cherry-pick

cherry-pick命令的基本用法 對于多分支的代碼庫&#xff0c;將代碼從一個分支轉移到另一個分支是常見需求。這時分兩種情況。一種情況是&#xff0c;你需要另一個分支的所有代碼變動&#xff0c;那么就采用合并&#xff08; git merge &#xff09;。另一種情況是&#xff0c;…

總結 TCP 協議的相關特性

TCP協議段格式: 如圖, 端口號: 是其中一個重要的部分,知道端口號才能確認數據交給哪個應用程序(端口號屬于傳輸層的概念). 4位首部長度:4bit表示的范圍是0->15,在此處,單位是"4字節",因此,將這里的數值 * 4&#xff0c;才是真正的報頭長度,即TCP 報頭最大長度,60…

Cenos7 搭建Minio最新版集群部署服務器(一)

------> 道 | 法 | 術 | 器 | 勢 <------ 多臺服務器間免密登錄|免密拷貝 Cenos7 搭建Minio集群部署服務器(一) Cenos7 搭建Minio集群Nginx統一訪問入口|反向動態代理(二) Spring Boot 與Minio整合實現文件上傳與下載(三) CentOS7的journalctl日志查看方法 …

已知四個坐標點,怎樣求出四邊形的四個內角

1&#xff0c;理論 最簡單的方式利用向量進行求解 如圖可得&#xff1a; cosθa*b/&#xff08;|a|*|b|&#xff09; 已知三點坐標&#xff0c;很容易可以得到兩向量之積a*b&#xff0c;以及每個的模值 2&#xff0c;四個角度求解過程 首先&#xff0c;我們定義了四個坐標點…

在數字游民天堂,Polkadot Hubs 探索建設更緊密的全球社區

分布式辦公是 Web3 行業的協作常態&#xff0c;當數字游民們享受著線上遠程工作的自由和便捷時&#xff0c;也在懷念著一種面對面與他人交流與共創的經歷。共享空間隨之興起&#xff0c;為許多初創項目公司提供開放舒適的環境&#xff0c;卻難以在不同的人群之間搭起一張巨大的…

系統架構設計師考試大綱(2017年)

1.考試目標 考試合格人員應能夠根據系統需求規格說明書,結合應用領域和技術發展的實際情況,考慮有關約束條件,設計正確、合理的軟件架構,確保系統架構具有良好的特性;能夠對項目系統架構進行描述、分析、設計與評估;能夠按照相關標準編寫相應的設計文檔;能夠與系統分析師…

完美解決Github提交PR后報錯:File is not gofumpt-ed (gofumpt)

問題闡述 最近在Github上提交PR后&#xff0c;遇到了這么一個問題&#xff1a;golangci-lint運行失敗&#xff0c;具體原因是File is not gofumpt-ed (gofumpt)。 名詞解釋 golangci-lint&#xff1a; golangci-lint 是Go語言社區中常用的代碼質量檢查工具&#xff0c;它可以…

react中使用shouldComponentUpdate生命周期函數調用setState引起的無限循環的錯誤

場景&#xff1a; 在 React 組件中&#xff0c;當在 componentWillUpdate 或 componentDidUpdate 生命周期方法中調用 setState 時&#xff0c;會觸發無限循環&#xff0c;導致超過最大更新深度。 錯誤原因 在React組件中 &#xff0c;我們使用componentWillUpdate 或 componen…

Windows 2016安裝Jenkins

Jenkins 下載&#xff0c;安裝 下載OpenJDK 11 for Wndows 兩種方式 choco install openjdk11 https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.20%2B8/OpenJDK11U-jdk_x64_windows_hotspot_11.0.20_8.msi how to enable administrator user to …

[自學記錄06|*百人計劃]Gamma矯正與線性工作流

一、前言 Gamma矯正其實也屬于我前面落下的一塊內容&#xff0c;打算把它補上&#xff0c;其它的沒補是因為我之前寫的GAMES101筆記里已經涵蓋了&#xff0c;而Gamma矯正在101里面確實沒提到&#xff0c;于是打算把它補上&#xff0c;這塊內容并不難&#xff0c;但是想通透的理…

我的創作紀念日(256天)

前言 結緣 我與csdn的結緣&#xff0c;之前在創作紀念日&#xff08;128天&#xff09;便已提到&#xff0c;今在此便不再多言 收獲 很慚愧&#xff0c;自六月底至八月中旬&#xff0c;因為忙于找工作&#xff0c;奔赴面試求職之際&#xff0c;寫博客沒有像之前那么勤&#x…