程序升級bootloader

文章目錄

      • 概述
      • 什么是bootloader?為什么用?
      • bootloader啟動流程圖
        • 步驟
      • 下載過程
      • 代碼
        • 獲取本地配置信息
        • 獲取主機傳過來的配置信息
        • bootloader發送2給上位機,上位機發送文件給bootloader
        • 根據網站復制CRC
      • 燒寫flash
        • erase
        • 啟動
        • 編譯問題

概述

用keil編寫app,來用bootloader更新app,完成燈閃爍指令,升級app的新版本就是燈閃爍的更快了;
通過usb直接傳輸更新的配置給開發板,然他自己啟動bootloder,擦除原來的app和配置信息,燒錄新的app和配置信息;
image.png
image.png

什么是bootloader?為什么用?

運行時,bootloader會先啟動,如果有程序升級,bootloader從RAM里面下數據燒錄到flash的一塊空間上面,就是app;
其中突然斷電沒燒錄完也沒事,bootloader等下次啟動又會重新燒錄,如果沒有bootloader,app不是完整的也不能直接啟動,就不能用了;
原本沒有bootloader怎么運行的:
RAM如果很小,里面不會去在復制一個app進去,問題就是此時上點時是flash的app程序在從RAM下載燒錄數據到flash的app,這直接把自己覆蓋了呀,那會出錯的;
image.png
RAM如果很大,那RAM存一個APP,運行是就用RAM的APP,然后把升級的app數據下載燒錄到flash上把他覆蓋,這樣就不會出現上面的問題了,但是斷電就會導致flash上的APP沒燒錄完整,下次通電先打開flash就打不開了;
通電先執行flash;
image.png
image.png

bootloader啟動流程圖

STM32H563RIV
image.png
image.png

cpu是ARM公司生產的,他們設定只能從0開始讀,因此要設置映射關系,讓cpu一開始在flash的地址0x0800 0000;
1、cpu從0開始讀4個字節存入sp寄存器;
2、cpu從4這個地址讀到4個字節存入pc寄存器
image.pngimage.png

發生中斷時:
硬件會做的事:在異常向量表里面找到函數,執行
我們需要操作的是:告訴cpu異常向量表的基地址
image.png
下圖為有無bootloader的異常向量表的首地址
image.png
要把這個//,因為這個是異常向量表,是flash開頭的異常向量表
image.png
把flash開始燒錄的地址移到0804000,前面的給bootloader;
image.png

步驟

image.png
傳進來的參數是存在寄存器R0里面的;
把R0的數據寫入寄存器VTOR
把R0的數值存入R1所指向的位置;
VTOR保存的是異常向量表的基地址;
image.png
從R0這里讀取R1;
把R1的數值寫給棧SP寄存器;
image.png
跳轉到R0+4的位置

下載過程

1、bootloader發送“1”字符給上位機,請求固件信息;
2、上位機給bootloader發送固件信息:先發同步字符;
image.png
上位機發送的固件信息
a、長度信息
b、加載地址
c、校驗碼
d、文件名
e、版本號
image.png
3、bootloader決定升級
發送0x02給上位機;
4、上位機發送bin文件給bootloader
收到后bootloader會(1)計算CRC校驗碼,(2)與之前收到的固件信息比較;
5、bootloader開始燒寫,同時可以發送燒寫進度給上位機

生成設備信息
用這個create_firemware_info來生成腳本
image.png

代碼

獲取本地配置信息

#define CFG_OFFSET 0x081FE000//設備地址

file_len是判斷配置信息有沒有寫
image.png

獲取主機傳過來的配置信息

image.png
先是usb傳輸發送1;
接收上機回應信號5個0x5a;
接收上機設備配置信息32個寄存器;
image.png

bootloader發送2給上位機,上位機發送文件給bootloader

上位機發送文件時就會發送一系列的數據,超時時間*10,給上位機充分時間發送
image.png

根據網站復制CRC

image.png

bootloaderTask
這里任務要等待一會
因為usb插到電腦上,要等電腦識別出來usb,才能進行傳輸,
image.png

獲取固件失敗的原因?
數據丟失,上位機發送數據給bootloader,是不是數據沒有接收全,數據覆蓋了,數據丟失了;
先看是不是數據接收不全,怎么看呢,我們是創建隊列來接收的,隊列初始化時的大小看一下,能不能裝得下;
找到usb傳輸的隊列只有200bit,但是傳輸的數據有5kb ,5x1024bit,把隊列改成10kb=10240bit
image.png
image.png
BootTask整體流程:
無標題.png

#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os2.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "draw.h"
#include "stdio.h"
#include "draw.h"
#include "ux_api.h"
#include "modbus.h"
#include "errno.h"
#include "uart_device.h"
#include "semphr.h"#include "bootloader.h"#define UPDATE_TIMEOUT 1000//超時時間#define CFG_OFFSET 0x081FE000static struct UART_Device *g_pUpdateUART;static uint32_t BE32toLE32(uint8_t *buf)
{return ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | ((uint32_t)buf[3] << 0);
}static int GetLocalFirmwareInfo(PFirmwareInfo ptFirmwareInfo)
{PFirmwareInfo ptFlashInfo = (PFirmwareInfo)CFG_OFFSET;if (ptFlashInfo->file_len == 0xFFFFFFFF)return -1;*ptFirmwareInfo = *ptFlashInfo;return 0;
}static int GetServerFirmwareInfo(PFirmwareInfo ptFirmwareInfo)
{uint8_t data = '1';uint8_t buf[sizeof(PFirmwareInfo)];/*send 0x01 cmd to pc*/if(0 != g_pUpdateUART->Send(g_pUpdateUART, &data, 1, UPDATE_TIMEOUT))return -1;/*wait for response*/while(1){if(0 != g_pUpdateUART->RecvByte(g_pUpdateUART, &data, UPDATE_TIMEOUT*10))return -1;if(data != 0x5a){buf[0] = data;break;}}for(int i = 1; i < sizeof(PFirmwareInfo); i++){if(0 != g_pUpdateUART->RecvByte(g_pUpdateUART, &buf[i], UPDATE_TIMEOUT))return -1;}ptFirmwareInfo->version = BE32toLE32(&buf[0]);ptFirmwareInfo->file_len = BE32toLE32(&buf[4]);ptFirmwareInfo->load_addr = BE32toLE32(&buf[8]);ptFirmwareInfo->crc32 = BE32toLE32(&buf[12]);strncpy((char *)ptFirmwareInfo->file_name, (char *)&buf[16], 16);return 0;}static int GetServerFirmware(uint8_t *buf, uint32_t len)
{uint8_t data = '2';/*send 0x01 cmd to pc*/if(0 != g_pUpdateUART->Send(g_pUpdateUART, &data, 1, UPDATE_TIMEOUT))return -1;/*上位機發送文件給bootloader*/for(int i = 0; i < len; i++){if(0 != g_pUpdateUART->RecvByte(g_pUpdateUART, &buf[i], UPDATE_TIMEOUT*10))return -1;}return 0;
}/* https://lxp32.github.io/docs/a-simple-example-crc32-calculation/ */
static int GetCRC32(const char *s,size_t n)
{uint32_t crc=0xFFFFFFFF;for(size_t i=0;i<n;i++) {char ch=s[i];for(size_t j=0;j<8;j++) {uint32_t b=(ch^crc)&1;crc>>=1;if(b) crc=crc^0xEDB88320;ch>>=1;}}return ~crc;
}void BootLoaderTask( void *pvParameters )	
{struct UART_Device *pUSBUART = GetUARTDevice("usb");FirmwareInfo tLocalInfo;FirmwareInfo tServerInfo;int err;int need_update = 0;uint8_t *firmware_buf;vTaskDelay(10000); /* wait for pc ready */pUSBUART->Init(pUSBUART, 115200, 'N', 8, 1);g_pUpdateUART = pUSBUART;while (1){/* read cfg info, to detect app's version */err = GetLocalFirmwareInfo(&tLocalInfo);if (err){/* update */need_update = 1;}else{pUSBUART->Send(pUSBUART, (uint8_t *)"GetLocalFirmwareInfo Failed\r\n", strlen("GetLocalFirmwareInfo Failed\r\n"), UPDATE_TIMEOUT);}err = GetServerFirmwareInfo(&tServerInfo);if (!err){/* compate version */if (tServerInfo.version > tLocalInfo.version){/* update */need_update = 1;}}else{need_update = 0;pUSBUART->Send(pUSBUART, (uint8_t *)"GetServerFirmwareInfo Failed\r\n", strlen("GetServerFirmwareInfo Failed\r\n"), UPDATE_TIMEOUT);}if (need_update){firmware_buf = pvPortMalloc(tServerInfo.file_len);if (!firmware_buf){/* error */pUSBUART->Send(pUSBUART, (uint8_t *)"Malloc Failed\r\n", strlen("Malloc Failed\r\n"), UPDATE_TIMEOUT);}err = GetServerFirmware(firmware_buf, tServerInfo.file_len);if (!err){/* calc CRC */                uint32_t crc = GetCRC32((const char *)firmware_buf, tServerInfo.file_len);if (crc == tServerInfo.crc32){/* OK *//* burn */pUSBUART->Send(pUSBUART, (uint8_t *)"Download OK\r\n", 13, UPDATE_TIMEOUT);}else{pUSBUART->Send(pUSBUART, (uint8_t *)"GetCRC32 Failed\r\n", strlen("GetCRC32 Failed\r\n"), UPDATE_TIMEOUT);}}else{pUSBUART->Send(pUSBUART, (uint8_t *)"GetServerFirmware Failed\r\n", strlen("GetServerFirmware Failed\r\n"), UPDATE_TIMEOUT);}}else{/* start app */}}
}

燒寫flash

對比flash上面的版本比主機發過來的版本小,或者flash上面的配置信息壞了,就啟動升級:
1、erase 擦除flash
2、燒寫

flash有兩個棧區,bank1和bank2 128個棧區x 每個棧區8k
把中間藍色圈APP擦除再燒錄,只是更新APP,以及把配置文件的信息改成對應的最新的;
image.png

erase

image.png
1、擦除app并燒錄
擦除bank1和bank2的APP的,APP的長度可能延伸到了bank2有if進行判斷,傳入的地址是bootloader后的,也就是APP開頭地址
3.png
2、擦除配置文件并燒錄
image.png
3、bootloadertask
下載完成主機發送過來的配置文件就用1、2這兩個函數進行擦除燒錄;
image.png

啟動

觸發軟件復位
1.png
復位最終會調用main
image.png
如果是復位的話就會得到flash上面這個應用程序的基地址,然后調用這個匯編函數start_app來啟動程序
2.png
注意:
image.png

編譯問題

non-ASCLL表示引入了中文字符
image.png

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

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

相關文章

聲明隊列和交換機 + 消息轉換器

目錄 1、聲明隊列和交換機 方法一&#xff1a;基于Bean的方式聲明 方法二&#xff1a;基于Spring注解的方式聲明 2、消息轉換器 1、聲明隊列和交換機 方法一&#xff1a;基于Bean的方式聲明 注&#xff1a;隊列和交換機的聲明是放在消費者這邊的&#xff0c;這位發送的人他…

Dynamic Web Module facet version問題

The default superclass, "javax.servlet.http.HttpServlet", according to the projects Dynamic Web Module facet version (3.1), was not found on the Java Build Path. 1.右鍵項目 2.點擊Properties 3.點擊Java Build Path&#xff0c;右邊找到Libraries&…

大模型在營銷領域的探索及創新

1 AIGA介紹 2 AIGA在營銷領域的 應用和探索 3 總結與展望

java 如何暴露header給前端

在Java中&#xff0c;將HTTP響應的Header暴露給前端通常涉及在Web應用程序的服務器端代碼中設置這些Header。這可以通過不同的Java Web框架來實現&#xff0c;比如Spring MVC、JAX-RS&#xff08;Jersey&#xff09;、Servlet等。這里&#xff0c;我將提供一個使用Spring MVC框…

學習筆記——交通安全分析13

目錄 前言 當天學習筆記整理 5城市主干道交通安全分析 結束語 前言 #隨著上一輪SPSS學習完成之后&#xff0c;本人又開始了新教材《交通安全分析》的學習 #整理過程不易&#xff0c;喜歡UP就點個免費的關注趴 #本期內容接上一期12筆記 當天學習筆記整理 5城市主干道交…

docker-compose Install gitlab 17.1.1

gitlab 前言 GitLab 是一個非常流行的開源 DevOps 平臺,用于軟件開發項目的整個生命周期管理。它提供了從版本控制、持續集成/持續部署(CI/CD)、項目規劃到監控和安全的一系列工具。 前提要求 Linux安裝 docker docker-compose 參考Windows 10 ,11 2022 docker docker-c…

多線程爬蟲技術詳解

&#x1f380;引言?? 在當今信息爆炸的時代&#xff0c;網絡爬蟲&#xff08;Web Crawler&#xff09;作為一種自動獲取網頁內容的程序&#xff0c;已經成為數據挖掘和信息檢索不可或缺的工具。多線程爬蟲作為提高爬蟲效率的重要手段&#xff0c;通過并行處理技術大幅度提升…

開發個人Go-ChatGPT--4 用戶管理

開發個人Go-ChatGPT–4 用戶管理 先看下我的目錄結構&#xff0c;可以根據個人愛好&#xff0c;進行重構 |-- Dockerfile |-- LICENSE |-- common | |-- callmodel | | |-- gemma.go | | -- models.go | |-- consts | | |-- code.go | | |-- common.go |…

k8s 部署RuoYi-Vue-Plus之nginx部署

1.掛載存儲 可參考 之前文章設置 https://blog.csdn.net/weimeibuqieryu/article/details/140183843 2.部署yaml 先創建命名空間ruoyi, 有就不用創建了 kubectl create namespace ruoyi我暫不需要使用xxjob和Monitor模塊, 所以去除了. 有需要再自行添加 需要先啟動后端服務…

(ECCV,2022)Mask-CLIP:從CLIP中提取自由密集標簽

文章目錄 Extract Free Dense Labels from CLIP相關資料摘要引言方法Mask-CLIPMask-CLIP 實驗 Extract Free Dense Labels from CLIP 相關資料 代碼&#xff1a;https://github.com/chongzhou96/MaskCLIP 論文&#xff1a;https://arxiv.org/abs/2112.01071 摘要 對比語言-…

SprongBoot及其基礎應用全套部署腳本和配置

POM.xml配置 </dependencies> <!--skywalking日志監控依賴--><dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-logback-1.x</artifactId><version>8.5.0</version></dependency&g…

修改編譯依賴openssl的libcrypto.so

由于centos7默認使用openssl1.0.2k的libcrypto.so.10共享庫。即使openssl升級為3.0.11后&#xff0c;編譯使用ldd命令查看共享庫依舊會引用libcrypto.so.10。 現希望引用libcrypto.so.3&#xff0c;需要在生成動態鏈接庫的CMakeLists.txt中增加如下配置&#xff0c;明確指定ope…

《警世賢文》摘抄:守法篇、惜時篇、修性篇、修身篇、待人篇、防人篇(建議多讀書、多看報、少吃零食多睡覺)

若該文為原創文章&#xff0c;轉載請注明原文出處 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/140243440 長沙紅胖子Qt&#xff08;長沙創微智科&#xff09;博文大全&#xff1a;開發技術集合&#xff08;包含Qt實用技術、樹莓派、三維、OpenCV…

mysql 連接出現 Public Key Retrieval is not allowed

在MySQL連接中出現“Public Key Retrieval is not allowed”錯誤&#xff0c;通常是因為在使用安全套接字層&#xff08;SSL&#xff09;連接時遇到了問題。這是因為MySQL 8.0及以上版本對安全性要求更高&#xff0c;特別是在使用密碼插件如caching_sha2_password時&#xff0c…

【周末閑談】AI“搶飯碗”?絕對不是危言聳聽

AI是在幫助開發者還是取代他們? 在軟件開發領域,生成式人工智能(AIGC)正在改變開發者的工作方式。無論是代碼生成、錯誤檢測還是自動化測試,AI工具正在成為開發者的得力助手。然而,這也引發了對開發者職業前景和技能需求變化的討論。AI究竟是在幫助開發者還是取代他們?…

2024組裝一臺能跑AI大模型的電腦

title: 2024組裝一臺能跑AI大模型的電腦 tags: [組裝電腦, AI大模型] categories: [其他, 電腦, windows] 這里不寫組裝步驟&#xff0c;哪里接線&#xff0c;購買什么品牌網上一大堆。 這里只寫如何根據你自己的需求&#xff0c;選擇合適的、兼容的配件。 概述 需求&#xff…

本地多卡(3090)部署通義千問Qwen2-72B大模型提速實踐:從龜速到夠用

最近在做文本風格轉化&#xff0c;涉及千萬token級別的文本。想用大模型轉寫&#xff0c;在線的模型一來涉及數據隱私&#xff0c;二來又不想先墊錢再找報銷。本地的7-9B小模型又感覺效果有限&#xff0c;正好實驗室給俺配了4卡3090的機子&#xff0c;反正也就是做個推理&#…

運維系列.Nginx配置中的高級指令和流程控制

運維專題 Nginx配置中的高級指令和流程控制 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/…

ssrf結合redis未授權getshell

目錄 漏洞介紹 SSRF Redis未授權 利用原理 環境搭建 利用過程 rockylinux cron計劃任務反彈shell 寫公鑰免密登錄 ubuntu 寫公鑰免密登錄 漏洞介紹 SSRF SSRF&#xff08;server side request forgrey&#xff09;服務端請求偽造&#xff0c;因后端未過濾用戶輸入&…

桂花網藍牙網關X1000:引領物聯網新時代的智能連接

在物聯網技術飛速發展的今天&#xff0c;藍牙網關作為連接藍牙設備與互聯網的關鍵設備&#xff0c;其性能與穩定性直接影響到物聯網系統的整體運行效果。桂花網藍牙網關X1000憑借其卓越的性能和廣泛的應用場景&#xff0c;成為了物聯網領域的佼佼者。 一、產品概述 桂花網藍牙…