網(wǎng)站一般怎么推廣百度互聯(lián)網(wǎng)營銷是什么
目錄
- 1.STM32的升級方式
- 2.IAP升級
- 3.代碼邏輯展示
- 3.1 劃分存儲區(qū)域
- 3.2 IAP的狀態(tài)
- 4.源碼分析
- 4.1 記錄IAP的狀態(tài)
- 4.2 APP代碼異常判斷
- 4.3 IAP狀態(tài)的切換以及異常的處理邏輯
- 4.4 完整的邏輯代碼
1.STM32的升級方式
1、ICP:In Circuit Programing,簡單說就是在單片機(jī)開發(fā)時使用燒錄器升級程序,比如使用J-Link燒錄單片機(jī)程序。
2、ISP:In System Programing,在單片機(jī)內(nèi)部實(shí)現(xiàn)了基于通信接口(如串口、I2C、SPI等等)的FLASH引導(dǎo)程序,配合廠家提供的燒錄軟件工具或自行開發(fā)的軟件實(shí)現(xiàn)程序燒錄。
3、IAP:In applicating Programing,是指單片機(jī)程序開發(fā)好之后在運(yùn)行過程中由外部用戶發(fā)起的在線升級,這種升級方式一般由用戶自行設(shè)計升級方案,方案靈活性和自由度較高,在智能家居、汽車電子、物聯(lián)網(wǎng)設(shè)備中常用的OTA(Over The Air)即空中下載技術(shù)原理也與之類似。
2.IAP升級
ICP和ISP需要連接才能更新固件,實(shí)際的交付客戶的產(chǎn)品肯定不行,需要用到IAP,STM32的IAP升級,需要用到Bootloader,需要兩段代碼一段boot,一段app,boot區(qū)域負(fù)責(zé)更新app區(qū)域的代碼,而app區(qū)域是項目的邏輯實(shí)現(xiàn)和功能實(shí)現(xiàn)。
STM32 IAP (In-Application Programming) 介紹STM32 IAP(In-Application Programming)是一種允許應(yīng)用程序在運(yùn)行時更新或編程內(nèi)部Flash存儲器的技術(shù)。通過IAP,您可以在不使用外部編程器的情況下,直接從應(yīng)用程序代碼中對STM32的內(nèi)部Flash進(jìn)行讀取、寫入和擦除操作。這對于實(shí)現(xiàn)固件升級、數(shù)據(jù)存儲等功能非常有用。
- IAP 的應(yīng)用場景
?固件升級:通過IAP,您可以實(shí)現(xiàn)OTA(Over-The-Air)固件升級,允許設(shè)備在運(yùn)行時從網(wǎng)絡(luò)或其他來源下載并安裝新的固件版本。
?數(shù)據(jù)存儲:IAP可以用于將用戶數(shù)據(jù)、配置參數(shù)等存儲到Flash中,確保數(shù)據(jù)在斷電后不會丟失。
?多應(yīng)用管理:某些應(yīng)用可能需要在同一片F(xiàn)lash中存儲多個應(yīng)用程序,并根據(jù)需要切換運(yùn)行不同的應(yīng)用程序。 - IAP 的工作原理IAP的核心是通過調(diào)用STM32 HAL庫或標(biāo)準(zhǔn)外設(shè)庫中的Flash編程函數(shù)來操作Flash存儲器。STM32的Flash存儲器分為多個扇區(qū)(Sector),每個扇區(qū)可以獨(dú)立進(jìn)行擦除和寫入操作。IAP通常包括以下幾個步驟:
?解鎖Flash:在對Flash進(jìn)行任何操作之前,必須先解鎖Flash以允許編程操作。
?擦除Flash:在寫入新數(shù)據(jù)之前,必須先擦除目標(biāo)扇區(qū)。注意,擦除操作是以扇區(qū)為單位的,不能只擦除單個字節(jié)或字。
?寫入數(shù)據(jù):將新數(shù)據(jù)寫入指定的Flash地址。寫入操作是以半字(16位)或字(32位)為單位進(jìn)行的。
?鎖定Flash:完成所有操作后,重新鎖定Flash以防止意外修改。 - IAP 的實(shí)現(xiàn)方式IAP可以通過以下幾種方式實(shí)現(xiàn):3.1 Bootloader + Application 結(jié)構(gòu)這是最常見的IAP實(shí)現(xiàn)方式。系統(tǒng)啟動時,首先運(yùn)行Bootloader程序,Bootloader負(fù)責(zé)檢查是否有新的固件需要更新。如果有,則將新固件寫入應(yīng)用程序區(qū)域,然后跳轉(zhuǎn)到應(yīng)用程序執(zhí)行。如果沒有新固件,則直接跳轉(zhuǎn)到應(yīng)用程序。
?優(yōu)點(diǎn)?
?Bootloader和應(yīng)用程序分離,互不影響。
?可以實(shí)現(xiàn)安全的固件升級,避免損壞整個系統(tǒng)。
?支持多種升級方式(如UART、USB、SPI、Ethernet等)。
?缺點(diǎn)?
?需要額外的空間來存儲Bootloader。
?Bootloader和應(yīng)用程序之間的通信需要設(shè)計良好的協(xié)議。
3.代碼邏輯展示
3.1 劃分存儲區(qū)域
把下載的固件存儲到一個固定位置,另外還需要把原先APP區(qū)的代碼進(jìn)行備份,避免升級過程中出現(xiàn)異常導(dǎo)致生成磚
//1M start
#define USER_FLASH_FIRST_PAGE_ADDRESS 0x000000 //
#define USER_FLASH_LAST_PAGE_ADDRESS 0x0FFFFF //
#define USER_FLASH_END_ADDRESS 0x0FFFFF
//1M end//3M start
#define APP_FLASH_BACKUP_FIRST_PAGE_ADDRESS 0x200000 //
#define APP_FLASH_BACKUP_LAST_PAGE_ADDRESS 0x27FFFF //
#define APP_FLASH_BACKUP_END_ADDRESS 0x27FFFF//3M end
3.2 IAP的狀態(tài)
//IAP STATUS
typedef enum iap_status_code{IAP_NO = 0,IAP_START = 1,IAP_COPY_APP_TO_BACKUP, //拷貝APP區(qū)域代碼到備份區(qū)域IAP_COPY_APP_TO_BACKUP_SUCCESS_STATUS, //拷貝APP區(qū)域代碼 成功IAP_COPY_APP_TO_BACKUP_FAIL_STATUS, //拷貝APP區(qū)域代碼 失敗IAP_COPY_APP_TO_BACKUP_CHECK_MD5_FAIL_STATUS, //拷貝APP區(qū)域代碼 MD5校驗(yàn)失敗IAP_COPY_NEWBIN_TO_APP, //拷貝新的固件到APP區(qū)IAP_COPY_NEWBIN_TO_APP_NO_DATA_STATUS,//新固件存儲區(qū)域沒有數(shù)據(jù)IAP_COPY_NEWBIN_TO_APP_SUCCESS_STATUS,//成功IAP_COPY_NEWBIN_TO_APP_FAIL_STATUS,//失敗IAP_COPY_NEWBIN_TO_APP_CHECK_MD5_FAIL_STATUS,//MD5校驗(yàn)失敗 IAP_BACK_TO_BACKUP_OLDBIN, //備份區(qū)域的舊固件恢復(fù)到APP區(qū)域IAP_BACK_TO_BACKUP_OLDBIN_NO_DATA_STATUS,//備份區(qū)域沒有數(shù)據(jù)IAP_BACK_TO_BACKUP_OLDBIN_SUCCESS_STATUS,//成功IAP_BACK_TO_BACKUP_OLDBIN_FAIL_STATUS,//失敗 IAP_BACK_TO_BACKUP_OLDBIN_CHECK_MD5_FAIL_STATUS,//MD5校驗(yàn)失敗 IAP_ERROR_TO_APP, //IAP 升級失敗 跳轉(zhuǎn)到APP區(qū)運(yùn)行IAP_END_TO_APP, //IAP 升級成功 跳轉(zhuǎn)到APP區(qū)運(yùn)行}IAP_STATUS;#define IAP_COPY_APP_SIZE 409600 //(400*1024) (448*1024)
為了避免升級過程中出現(xiàn)異常,需要對下載的文件進(jìn)行MD5校驗(yàn),此外未預(yù)防OTA文件有問題,添加多少次沒有進(jìn)入APP區(qū)域,代碼自動回滾到上一個版本
4.源碼分析
4.1 記錄IAP的狀態(tài)
記錄上一次IAP的狀態(tài),避免中途斷電,斷網(wǎng)等異常導(dǎo)致OTA流程被打斷后無法正常OTA
//讀取OTA過程中上一次的iap狀態(tài)BSP_W25Qx_Read(&last_iap_status_flag,IAP_STATUS_FLAG_ADDRESS,1);if(last_iap_status_flag == 0xFF || last_iap_status_flag > 20){last_iap_status_flag = 0;BSP_GD25QXX_Write(&last_iap_status_flag,IAP_STATUS_FLAG_ADDRESS,1);}
4.2 APP代碼異常判斷
Boot區(qū)和APP區(qū)進(jìn)入次數(shù)進(jìn)行比較,差異超過設(shè)定的次數(shù),表示APP區(qū)域代碼有問題,需要回滾到上一版本的代碼
in_boot_times_count();get_in_app_times();if(boot_app_times_compare() != 0){iap_status = IAP_BACK_TO_BACKUP_OLDBIN; last_iap_status_flag = IAP_BACK_TO_BACKUP_OLDBIN; LOG_INFO("in_boot_times.value - in_app_times.value >30 iap_status = IAP_BACK_TO_BACKUP_OLDBIN...\r\n"); }
4.3 IAP狀態(tài)的切換以及異常的處理邏輯
switch(iap_status){//不需要IAPcase IAP_NO:LOG_INFO("IAP_NO...jump to app --->\r\n"); HAL_Delay(1000);load_jump_to_app();break;//開始IAP的升級流程case IAP_START:LOG_INFO("IAP_START 1 : last_iap_status_flag = %d iap_status = %d\r\n",last_iap_status_flag,iap_status);if(last_iap_status_flag > IAP_START && last_iap_status_flag < IAP_ERROR_TO_APP){iap_status = last_iap_status_flag;}else{iap_status = IAP_COPY_APP_TO_BACKUP; }LOG_INFO("IAP_START 2 : last_iap_status_flag = %d iap_status = %d\r\n",last_iap_status_flag,iap_status);break;//拷貝app區(qū)域的內(nèi)容到外部flash的備份區(qū)域case IAP_COPY_APP_TO_BACKUP:{//把外部flash的備份區(qū)域的內(nèi)容清空if(Erase_back_flash_Sector_to_backup_app_area() != 0){LOG_INFO("IAP_COPY_APP_TO_BACKUP Erase_back_flash_Sector_to_backup_app_area fail......\r\n");iap_status = IAP_COPY_APP_TO_BACKUP_FAIL_STATUS;}else{LOG_INFO("IAP_COPY_APP_TO_BACKUP Erase_back_flash_Sector_to_backup_app_area success......\r\n");error_code = copy_app_to_back_area(IAP_COPY_APP_SIZE);//LOG_INFO("copy_app_to_back_area error_code = %d\r\n",error_code);if(error_code == 0){calculate_app_area_md5(now_app_md5_value,IAP_COPY_APP_SIZE);LOG_INFO("IAP_COPY_APP_TO_BACKUP now_app_md5_value MD5: ");for(uint16_t i =0;i<16;i++){LOG_INFO("%02x",now_app_md5_value[i]);}LOG_INFO("\r\n");calculate_back_area_md5(back_md5_value,IAP_COPY_APP_SIZE); LOG_INFO("IAP_COPY_APP_TO_BACKUP back_md5_value MD5: ");for(uint16_t i =0;i<16;i++){LOG_INFO("%02x",back_md5_value[i]);}LOG_INFO("\r\n");if(!compare_md5_2buff(now_app_md5_value,back_md5_value,16)){LOG_INFO("IAP_COPY_APP_TO_BACKUP_SUCCESS_STATUS......\r\n");BSP_GD25QXX_Write(back_md5_value,APP_FLASH_BACKUP_MD5_VALUE_ADDRESS,16); iap_status = IAP_COPY_APP_TO_BACKUP_SUCCESS_STATUS;//BSP_GD25QXX_Write(&iap_status,IAP_STATUS_FLAG_ADDRESS,1); }else{LOG_INFO("IAP_COPY_APP_TO_BACKUP copy_app_to_back_area check is fail ---> BSP_Reset_system\r\n");HAL_Delay(100);iap_status = IAP_COPY_APP_TO_BACKUP_CHECK_MD5_FAIL_STATUS; }}else{LOG_INFO("IAP_COPY_APP_TO_BACKUP copy_app_to_back_area copy is fail ---> BSP_Reset_system\r\n");HAL_Delay(100);iap_status = IAP_COPY_APP_TO_BACKUP_FAIL_STATUS;}} }break;case IAP_COPY_APP_TO_BACKUP_SUCCESS_STATUS:{iap_status = IAP_COPY_APP_TO_BACKUP_SUCCESS_STATUS;BSP_GD25QXX_Write(&iap_status,IAP_STATUS_FLAG_ADDRESS,1); iap_status = IAP_COPY_NEWBIN_TO_APP;} break; case IAP_COPY_APP_TO_BACKUP_FAIL_STATUS:iap_copy_app_to_backup_error_cnt++;if(iap_copy_app_to_backup_error_cnt >= 10){iap_status = IAP_COPY_APP_TO_BACKUP_FAIL_STATUS; BSP_GD25QXX_Write(&iap_status,IAP_STATUS_FLAG_ADDRESS,1); iap_status = IAP_ERROR_TO_APP; }else{iap_status = IAP_COPY_APP_TO_BACKUP; }break;case IAP_COPY_APP_TO_BACKUP_CHECK_MD5_FAIL_STATUS:iap_copy_app_to_backup_error_cnt++;if(iap_copy_app_to_backup_error_cnt >= 10){iap_status = IAP_COPY_APP_TO_BACKUP_CHECK_MD5_FAIL_STATUS; BSP_GD25QXX_Write(&iap_status,IAP_STATUS_FLAG_ADDRESS,1); iap_status = IAP_ERROR_TO_APP; <