#include 'gd32f4xx.h'

#define BOOTLOADER_SIZE 0x4000 // Bootloader的大小为16KB #define APPLICATION_ADDRESS 0x08010000 // 应用程序的起始地址为64KB

#define PAGE_SIZE 0x400 // Flash的页大小为1KB

typedef void (*pFunction)(void);

void jump_to_application(void) { pFunction app_entry = (pFunction)(*(uint32_t )(APPLICATION_ADDRESS + 4)); __set_MSP((uint32_t *)APPLICATION_ADDRESS); app_entry(); }

void flash_erase(uint32_t address) { FLASH_Unlock(); FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);

FLASH_ErasePage(address);

FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
FLASH_Lock();

}

void flash_write(uint32_t address, uint32_t *data, uint32_t size) { FLASH_Unlock(); FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);

for (uint32_t i = 0; i < size; i += 4) {
    FLASH_ProgramWord(address + i, data[i / 4]);
    while (FLASH_GetFlagStatus(FLASH_FLAG_BSY | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR) != RESET);
}

FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
FLASH_Lock();

}

int main(void) { uint32_t *application_data = (uint32_t *)APPLICATION_ADDRESS; uint32_t *bootloader_data = (uint32_t *)0x20000000; // 从外部存储器读取的数据

// 检查是否需要更新
if (bootloader_data[0] != application_data[0]) {
    // 擦除应用程序区域
    for (uint32_t address = APPLICATION_ADDRESS; address < APPLICATION_ADDRESS + BOOTLOADER_SIZE; address += PAGE_SIZE) {
        flash_erase(address);
    }

    // 写入新的应用程序
    for (uint32_t address = APPLICATION_ADDRESS; address < APPLICATION_ADDRESS + BOOTLOADER_SIZE; address += 4) {
        flash_write(address, &bootloader_data[(address - APPLICATION_ADDRESS) / 4], 4);
    }
    
    // 更新标志位,表示已经更新
    application_data[0] = bootloader_data[0];
    
    // 跳转到应用程序
    jump_to_application();
}

while (1) {
    // 程序主循环
}

}

这段代码首先定义了Bootloader的大小为16KB,应用程序的起始地址为64KB,Flash的页大小为1KB。

'jump_to_application'函数用于跳转到应用程序的入口地址,首先获取应用程序的起始地址和栈指针,然后执行应用程序的入口函数。

'flash_erase'函数用于擦除指定地址的Flash页,首先解锁Flash,然后擦除指定地址的页,最后锁定Flash。

'flash_write'函数用于向指定地址的Flash写入数据,首先解锁Flash,然后逐个写入数据,写入完成后等待Flash操作完成,最后锁定Flash。

'main'函数中首先定义了应用程序数据和Bootloader数据的指针,然后检查是否需要更新。如果需要更新,则先擦除应用程序区域,然后逐个写入新的应用程序数据,最后更新标志位,并跳转到应用程序。

如果不需要更新,程序将进入一个无限循环,执行其他任务。

GD32F450VI系列单片机IAP实现远程升级代码解析

原文地址: https://www.cveoy.top/t/topic/p0wv 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录