日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

IAP之boot实现

發布時間:2023/12/16 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IAP之boot实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

flash基本規劃


為實現IAP升級,一般將flash規劃成如上區域。
bootloader: 系統引導
app: 主程序運行的地方
update: 新的主程序固件存放的地方
這里給bootloader預留16K的空間,所以APP所在地址是0x08004000,編譯APP時,要注意將中斷向量表的偏移地址設置為0x4000

bootloader要完成的功能

根據以上描述,bootloader應有以下功能

  • 跳轉功能,可以跳轉到app區執行主程序
  • 固件搬運功能,因為固件中斷向量偏移是固定的0x4000,所以如果有新固件,需要將新固件轉移到app區再跳轉(APP區地址偏移需和中斷向量偏移對應)
  • bootloader實現

    根據上節分析,實現bootloader要有如下工作:

  • 編寫讀寫內部flash的接口
  • 編寫跳轉到指定地址運行程序的代碼
    • 根據ST官方例程實現的flash操作接口:
      擦除操作
    // flash只能按頁擦除。第一個參數是待擦除的起始頁,第二個參數是要擦除的頁數 uint32_t FLASH_If_Erase(uint32_t start_page, uint8_t pages) {uint32_t PageError = 0;FLASH_EraseInitTypeDef pEraseInit;HAL_StatusTypeDef status = HAL_OK;/* Unlock the Flash to enable the flash control register access *************/ HAL_FLASH_Unlock();pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;pEraseInit.PageAddress = start_page;pEraseInit.Banks = FLASH_BANK_1;pEraseInit.NbPages = pages;status = HAL_FLASHEx_Erase(&pEraseInit, &PageError);/* Lock the Flash to disable the flash control register access (recommendedto protect the FLASH memory against possible unwanted operation) *********/HAL_FLASH_Lock();if (status != HAL_OK){/* Error occurred while page erase */return FLASHIF_ERASEKO;}return FLASHIF_OK; }

    寫flash

    #define UPDATE_APP_ADDRESS (uint32_t)0x0802C000 /* ADDR_FLASH_PAGE_88 */ #define APP_ADDRESS (uint32_t)0x08004000 uint32_t FLASH_If_Write(uint32_t destination, uint32_t *p_source, uint32_t length) {uint32_t i = 0;/* Unlock the Flash to enable the flash control register access *************/HAL_FLASH_Unlock();for (i = 0; (i < length) && (destination <= (USER_FLASH_END_ADDRESS-4)); i++){/* Device voltage range supposed to be [2.7V to 3.6V], the operation willbe done by word */ if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, destination, *(uint32_t*)(p_source+i)) == HAL_OK) {/* Check the written value */if (*(uint32_t*)destination != *(uint32_t*)(p_source+i)){/* Flash content doesn't match SRAM content */return(FLASHIF_WRITINGCTRL_ERROR);}/* Increment FLASH destination address */destination += 4;}else{/* Error occurred while writing data in Flash memory */return (FLASHIF_WRITING_ERROR);}}/* Lock the Flash to disable the flash control register access (recommendedto protect the FLASH memory against possible unwanted operation) *********/HAL_FLASH_Lock();return (FLASHIF_OK); }
    • 固件轉移
    void AppMove(void) {// 新固件區的首個字是存放固件大小的uint32_t file_size = *(uint32_t*)UPDATE_APP_ADDRESS;uint32_t pages_use = 0;uint32_t* data_ptr = NULL;uint32_t file_size_word = 0;if (file_size != 0xffffffff) {printf("move app\n");data_ptr = (uint32_t*)(UPDATE_APP_ADDRESS + 4);// 計算需要擦除的頁數pages_use = file_size / FLASH_PAGE_SIZE + 1;printf("size: %d pages_use: %d\n", file_size, pages_use);file_size_word = file_size / 4;FLASH_If_Erase(APP_ADDRESS, pages_use);// 讀取UPDATA區并寫入APP跳轉區域FLASH_If_Write(APP_ADDRESS, data_ptr, file_size_word);// 擦除UPDATA區FLASH_If_Erase(UPDATE_APP_ADDRESS, pages_use);} else {printf("no new app\n");} }
    • 程序跳轉
    typedef void (*pFunction)(void); void AppJump(void) {printf("jump\n");if (((*(__IO uint32_t*)APP_ADDRESS) & 0x2FFE0000 ) == 0x20000000) {uint32_t jump_addr = *(__IO uint32_t*)(APP_ADDRESS + 4);pFunction jump_to_app = (pFunction)jump_addr;__set_MSP(*(__IO uint32_t*)APP_ADDRESS);__disable_irq();jump_to_app();} }
    • main.c
    int main(void) {/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART3_UART_Init();/* USER CODE BEGIN 2 */AppMove();AppJump();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */ }

    bool就完成了 IAP參考這里

    總結

    以上是生活随笔為你收集整理的IAP之boot实现的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。