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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

STM32f103C8T6 bootloader设计

發布時間:2025/3/21 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STM32f103C8T6 bootloader设计 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

STM32 bootloader設計

?

???????使用的是STM32f103C8T6:64Kflash,在應用程序中通過CAN把接受到的bin寫到外置 flash的指定地址處。在bootloader中判斷一個單獨的標志位看程序是否需要升級,如果需要升級,則復制外置flash處的內容到STM32的內置flash的指定地址處。

如:

bootloader地址:0x08000000UL?? 大小:10K——0x2800——STM32的內置flash

應用程序地址:0x08002800UL?? 大小:45K——0xB400——STM32的內置flash

升級信息表:0x720000UL?? 大小:8K——0x2000——外置flash

升級的bin文件地址:0x08012400? 大小:45K——0xB400——外置flash

?

升級信息表主要有:更新標志,程序大小等;

bootloader設計思想:(bootloader是一個引導程序,復雜的CAN接收升級文件部分在應用程序中實現, 它只起一個拷貝和跳轉的功能)

1、判斷“升級信息表”中的標志位是否更新,是更新,則復制“升級的bin文件地址”的內容到“應用程序地址”處;

2、跳轉到應用程序處。

?

bootloader:BootLoader 就是在操作系統內核運行之前運行的一段小程序。通過這段小程序,我們可以初始化硬件設備、建立內存空間映射圖,從而將系統的軟硬件環境帶到一個合適狀態,以便為最終調用操作系統內核準備好正確的環境。這里我們所說的Bootloader也是系統開機前的一段小程序,其主要任務是用來初始化串口和IAP 端口(網口CAN 接口等)的,通過判斷狀態是否需要從IAP 端口進行更新應用程序,若需要更新則從端口接收應用程序,并存放到指定的Flash 里面,更新完成后則跳入到指定的Flash 里面執行應用程序。

應用程序:即我們需要開發板實現功能的程序,其中應用程序主要分為兩種:hex 文件和bin 文件。在我們經常使用的KEIL 中默認編譯生成的可執行文件(應用程序)為hex 格式的,若需要編譯生成bin 格式需要做如下修改,加入 “D:\Keil\ARM\ARMCC\bin\fromelf.exe--bin--output ./Obj/Can_Updata.bin ./Obj/test.axf” ,重新編譯生成的 Can_Updata.bin文件存放在 Obj 文件夾下。

?

有幾點需要注意的:

1、中斷向量的重映射(應用程序中要設置,否則無法使用中斷)

?

  • NVIC_VectTab_FLASH —— 0x8002800

  • NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x2800);

  • ?

    2、跳轉到指定地址處;

    ?

  • static voidjump_to_app(void)

  • {

  • app_cb app_start = (app_cb)(*(uint32_t*)(APP_START_ADDR + 4));

  • ?
  • all_nvic_disabled();

  • //all_gpio_disabled();

  • ?
  • delay_ms(100);

  • __set_PSP(*(u32 *)(APP_START_ADDR));

  • __set_CONTROL(0);

  • ?
  • __set_MSP(*(uint32_t *)(APP_START_ADDR));

  • NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x2800);

  • ?
  • app_start();

  • }


  • 部分代碼:

    ?

    ?

  • #include <stdio.h>

  • #include "usart.h"

  • #include "delay.h"

  • #include "iap.h"

  • #include "misc.h"

  • ?
  • typedef void (*app_cb)(void);

  • ?
  • static void all_nvic_disabled(void)

  • {

  • int i = 0;

  • for(i = 19; i < 59; i++)

  • {

  • NVIC->ICER[i >> 0x05] = (unsigned int )0x01 << (i & (unsigned char)0x1F);

  • }

  • ?
  • }

  • ?
  • static void all_gpio_disabled(void)

  • {

  • GPIO_InitTypeDef gpio_init;

  • gpio_init.GPIO_Pin = 0xffff;

  • gpio_init.GPIO_Speed = GPIO_Speed_50MHz;

  • gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  • GPIO_Init(GPIOA, &gpio_init);

  • GPIO_Init(GPIOB, &gpio_init);

  • GPIO_Init(GPIOC, &gpio_init);

  • GPIO_Init(GPIOD, &gpio_init);

  • }

  • ?
  • static void jump_to_app(void)

  • {

  • app_cb app_start = (app_cb)(*(uint32_t *)(APP_START_ADDR + 4));

  • ?
  • all_nvic_disabled();

  • //all_gpio_disabled();

  • ?
  • delay_ms(100);

  • __set_PSP(*(u32 *)(APP_START_ADDR));

  • __set_CONTROL(0);

  • ?
  • __set_MSP(*(uint32_t *)(APP_START_ADDR));

  • NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x2800);

  • ?
  • app_start();

  • }

  • ?
  • int main(void)

  • {

  • iap_t iap;

  • uint8_t flag; // 0:未升級 1:已升級

  • ?
  • DelayInit();

  • UARTInit(9600);

  • GD25Q32BConfig();

  • printf("uart ok...\r\n");

  • delay_ms(100);

  • ?
  • flag = FlashIAPReadFlag(&iap);

  • ?
  • printf("flag: %d\n", flag);

  • printf("iap.version: %d\n", iap.version);

  • printf("iap.size: %d\n", iap.size);

  • ?
  • if(0 == flag)

  • {

  • FlashCopy(APP_START_ADDR, IAP_APP_START, &iap);

  • printf("copy ok!\n");

  • }

  • ?
  • jump_to_app();

  • ?
  • return 0;

  • }

  • #include <string.h>

  • #include "app_flash_manager.h"

  • #include "iap.h"

  • #include "debug.h"

  • ?
  • // 讀取升級狀態,0: 未升級; 1: 已經升級

  • uint8_t FlashIAPReadFlag(iap_t *update)

  • {

  • uint8_t flag;

  • ?
  • spiFlashRead(IAP_INFO_START, sizeof(iap_t), (uint8_t *)update);

  • ?
  • flag = update->flag;

  • ?
  • return flag;

  • }

  • ?
  • // 從backup_addr拷貝info->size的大小到app_addr地址處

  • boolean FlashCopy(uint32_t app_addr, uint32_t backup_addr, iap_t *info)

  • {

  • uint8_t upgrade_buffer[FLASH_SECTOR_SIZE];

  • uint16_t pageremain = FLASH_SECTOR_SIZE - backup_addr % FLASH_SECTOR_SIZE; // 單頁剩余字節

  • ?
  • if(((app_addr + info->size - 1) > APP_END_ADDR) || (app_addr < APP_START_ADDR))

  • {

  • return COPY_FALSE;

  • }

  • ?
  • if(info->size <= pageremain) // 程序總大小小于等于單頁大小

  • {

  • pageremain = info->size;

  • }

  • FlashErase(app_addr, APP_BLOCK);

  • ?
  • while(1)

  • {

  • // 分頁寫入

  • memset(upgrade_buffer, 0, sizeof(upgrade_buffer));

  • spiFlashRead(backup_addr, pageremain, upgrade_buffer); // 從備份區讀出pageremain字節數

  • FlashWrite(app_addr, upgrade_buffer, pageremain); // 寫到程序運行的地址處

  • ?
  • if(info->size == pageremain)

  • {

  • break; // 寫入結束

  • }

  • else

  • {

  • backup_addr += pageremain;

  • app_addr += pageremain;

  • info->size -= pageremain; // 減去已經寫入了的字節數,地址都往后面偏移

  • ?
  • if(info->size > FLASH_SECTOR_SIZE)

  • {

  • pageremain = FLASH_SECTOR_SIZE; // 超過1頁數據,一頁一頁寫入

  • }

  • else

  • {

  • pageremain = info->size; // 不夠1頁數據

  • }

  • }

  • }

  • ?
  • return COPY_OK;

  • }

  • #include "mcu_flash.h"

  • #include <string.h>

  • #include "stm32f10x_flash.h"

  • // STM32f103內置flash的讀寫擦除

  • // addr:地址 count:塊數量

  • flash_status_t FlashErase(uint32_t addr, uint8_t count)

  • {

  • uint8_t i;

  • ?
  • for(i = 0; i < count; ++i)

  • {

  • if(FLASH_ErasePage(addr + i * FLASH_SECTOR_SIZE) != FLASH_COMPLETE)

  • {

  • return FLASH_FAILURE;

  • }

  • }

  • ?
  • return FLASH_SUCCESS;

  • }

  • ?
  • uint32_t FlashWrite(uint32_t addr, uint8_t *buffer, uint32_t length)

  • {

  • uint16_t i, data = 0;

  • ?
  • FLASH_Unlock();

  • ?
  • for(i = 0; i < length; i += 2)

  • {

  • data = (*(buffer + i + 1) << 8) + (*(buffer + i));

  • if(FLASH_ProgramHalfWord((uint32_t)(addr + i), data) != FLASH_COMPLETE)

  • {

  • return i;

  • }

  • }

  • ?
  • FLASH_Lock();

  • ?
  • return length;

  • }

  • ?
  • uint32_t FlashRead(uint32_t addr, uint8_t *buffer, uint32_t length)

  • {

  • memcpy(buffer, (void *)addr, length);

  • ?
  • return length;

  • }

  • 總結

    以上是生活随笔為你收集整理的STM32f103C8T6 bootloader设计的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 色婷婷综合激情 | 国产一区 在线播放 | 9i在线看片成人免费 | 亚洲国产精品毛片 | 精品视频免费在线观看 | 美乳人妻一区二区三区 | 亚洲男人天堂2023 | 欧美日韩在线观看一区二区三区 | 91激情视频在线观看 | 成人性生交大片免费看vrv66 | 怡红院av亚洲一区二区三区h | 视频在线观看一区二区 | 欧美成人播放 | 久草手机在线视频 | 欧美疯狂做受 | 黄色网页在线播放 | 青青超碰| 亚洲高清视频一区 | 青青草视频免费看 | 91精品国产一区二区 | 国产综合亚洲精品一区二 | av直播在线观看 | 日韩成人免费视频 | 色站av | 人妻丰满熟妇av无码区 | 色综合色综合网色综合 | 91热久久 | 国产视频精品自拍 | 日韩精品――色哟哟 | 婷婷成人在线 | 简单av网 | 精品国产av无码一区二区三区 | 在线免费观看成年人视频 | 国产乱子一区二区 | 在线日韩| 秋霞欧美一区二区三区视频免费 | 制服.丝袜.亚洲.中文.综合懂 | 波多在线播放 | 黄色一级视频在线观看 | 在线啪| 黑人番号| 亚洲图片小说视频 | 成人免费毛片糖心 | 国语粗话呻吟对白对白 | 亚欧洲精品视频在线观看 | 最新在线视频 | 丁香婷婷激情 | av网站有哪些 | 97中文字幕 | 中文字幕日韩欧美一区二区三区 | 欧美一区二区日韩一区二区 | 在线aa | ,午夜性刺激免费看视频 | 日韩国产毛片 | 国产福利视频一区 | 91视频免费| 国产精品污视频 | 一区二区免费在线观看视频 | 国产精品456 | 亚洲美免无码中文字幕在线 | 国产欧美日韩精品区一区二污污污 | 亚洲啊啊啊啊啊 | 神马午夜在线观看 | 手机在线看片你懂的 | 婷婷五综合| 三级黄色片免费观看 | 亚洲伦理中文字幕 | 亚洲人成电影在线播放 | 日韩精品三区 | 亚洲免费av一区 | 国产成人无码精品久久二区三 | 超碰老司机 | 黑人玩弄人妻一区二区绿帽子 | 国产a视频精品免费观看 | 婷婷综合在线观看 | 无码乱人伦一区二区亚洲 | 高潮一区二区三区乱码 | 黑白配av | 久久久国产免费 | 亚洲av无码乱码国产精品fc2 | 欧美专区综合 | 国产精品无码一区二区三区 | 日本公妇乱淫免费视频一区三区 | 中日韩免费毛片 | 日韩在线导航 | 性爱免费视频 | 久草影视在线观看 | 久久大胆视频 | 国产精选视频在线观看 | 日本中文字幕不卡 | 国产精品久久福利 | 久久精品视频一区 | 天堂网av2014| 日韩欧美激情视频 | 国产a网站 | 亚洲精品456 | 加勒比视频在线观看 | 大尺度做爰呻吟舌吻网站 | 午夜av免费在线观看 |