本帖最后由 MCU@Baize 于 2024-1-12 17:39 编辑
#申请原创# #技术资源#
时间过得真快,不知不觉就进入到2024年了。近期抽空写了一个HC32F460 I2C 的bootloader和上位机程序,分享出来。欢迎拍砖,^_^
首先在进入main,代码封装好了,看起来比较清爽。分别是初始化和boot任务。 int32_t main(void) { bootloader_init();//初始化 while(1) { bootloader_thread();//boot任务 } } 初始化里,会初始化GPIO,时钟和I2C,然后检测一下boot参数,有需要的话可以直接跳转到app区。 void bootloader_init(void) { LL_PERIPH_WE(LL_PERIPH_ALL); gpio_init();//GPIO初始化 BSP_CLK_Init();//时钟初始化 i2c_init();//I2C模块实始化 LL_PERIPH_WP(LL_PERIPH_ALL); check_boot();//检查boot参数,做跳转 m_boot.checksum = 0; m_boot.Status = Status_Idle; } 然后就是boot任务,任务里做了分支,处理不同的指令 void bootloader_thread(void) { if(UserBuf.lenth != 0) { switch(UserBuf.data[0]) { case CMD_CFG://配置参数 bootconfig(); break; case CMD_WRITE://写入数据 bootwrite(); break; case CMD_VERIFY://校验(未实现) bootverify(); break; case CMD_VERSION://读取版本号 bootversion(); break; case CMD_JUMP://跳转 bootjump(); break; case CMD_RESET://复位 bootreset(); case CMD_ERASE://擦除 booterase(); break; case CMD_READ8://8位访问MCU内部资源 bootread8(); break; case CMD_READ16://16位访问MCU内部资源 bootread16(); break; case CMD_READ32://32位访问MCU内部资源 bootread32(); break; } UserBuf.lenth = 0; } } 这里会有m_boot结构体来控制状态机。由m_boot.Status控制状态。 先来看一下配置参数命令服务函数。这里会将目标地址,bin文件长度等参数传进来。把状态设置为Status_Linkup; static void bootconfig(void) { m_boot.targetaddress = *(unsigned int *)&UserBuf.data[1]; m_boot.lenth = *(unsigned int *)&UserBuf.data[5]; m_boot.targetaddress_end = m_boot.targetaddress + m_boot.lenth; m_boot.version = *(unsigned int *)&UserBuf.data[9]; m_boot.Status = Status_Linkup; GPIO_SetPins(GPIO_PORT_D,GPIO_PIN_05); u8TxBuf[0] = 'a'; u8TxBuf[1] = 'c'; u8TxBuf[2] = 'k'; u8TxBuf[3] = '.'; } 然后就是擦除指令。这里会将app用到的空间全部擦除一次。把状态设置为Status_Erase。 static void booterase(void) { if(m_boot.Status == Status_Linkup) { for(int i = m_boot.targetaddress; i <m_boot.targetaddress+m_boot.lenth; ) { FlashErasePage(i); i += 0x2000; } m_boot.Status = Status_Erase; } u8TxBuf[0] = 'a'; u8TxBuf[1] = 'c'; u8TxBuf[2] = 'k'; u8TxBuf[3] = '.'; } 接着是写flash数据。Flash必须先擦后写,因此在擦除指令执行前,不允许写数据。 static void bootwrite(void) { if(m_boot.Status == Status_Erase) { unsigned int address, lenth; address = *(unsigned int *)&UserBuf.data[1]; lenth = *(unsigned int*)&UserBuf.data[5]; FlashWritePage(address,&UserBuf.data[9],lenth); } u8TxBuf[0] = 'a'; u8TxBuf[1] = 'c'; u8TxBuf[2] = 'k'; u8TxBuf[3] = '.'; } 最后就是跳转指令,重要的时跳转前把外设反初始化,设置中断向量表偏移地址。 static void bootjump(void) { IAP_JumpToApp(m_boot.targetaddress); } static int32_t IAP_JumpToApp(uint32_tu32Addr) { uint32_t JumpAddress;
/* Check if user code is programmed starting from address"u32Addr" */ /* Check stack top pointer. */ system_deInit(); /* Jump to user application */ JumpAddress = *(__IO uint32_t *)(u32Addr + 4); JumpToApplication = (func_ptr_t)JumpAddress; /* Initialize user application's Stack Pointer */ __set_MSP(*(__IO uint32_t *)u32Addr); /* Rebase the vector table base address */ SCB->VTOR = ((uint32_t) u32Addr & SCB_VTOR_TBLOFF_Msk);//设置中断向量表偏移地址 /* Jump to application Reset Handler in the application */ JumpToApplication();
return 0; } 最终效果
本次所使用的工具如下: 白泽USB转I2C工具 https://m.tb.cn/h.5m2udJO?tk=10MSWUUnOvW
HC32F460PETB 核心板 https://m.tb.cn/h.5NPZFJZ?tk=BViYWUUmKkB
上位机软件也有相关链接,感谢支持。 在此附上MCU工程代码和上位机源代码(上位机工程文件太大,上传失败,若有需要,可以进QQ群:961899436 或者加QQ:3140430649获取,备注需要BootLoader工程文件),供二次开发。
最后提示一下连接方式:例程SCL接PE15,SDA接PB5 #define I2C_SCL_PORT (GPIO_PORT_E) #define I2C_SCL_PIN (GPIO_PIN_15) #define I2C_SDA_PORT (GPIO_PORT_B) #define I2C_SDA_PIN (GPIO_PIN_05)
就到这里了,大家有疑问回帖交流啦,<(* ̄▽ ̄*)/
淘宝店铺:打开淘宝,搜索“白泽开发板”
各类国产品牌MCU评估板(小华、GD,持续更新中。。。。。。),以及USB转UART_I2C_SPI串行口调试模块:
【淘宝】https://m.tb.cn/h.5aGeMF8?tk=Okj0ds6cghX CZ0001 「华大开发板,HC32F4A0SITB,核心板,国产,研发调试」
点击链接直接打开 或者 淘宝搜索直接打开
【淘宝】https://m.tb.cn/h.5NPZFJZ?tk=BViYWUUmKkB CZ3457 「华大开发板 HC32F460PETB 核心板 调试研发」
点击链接直接打开 或者 淘宝搜索直接打开
【淘宝】https://m.tb.cn/h.5aCN4a4?tk=sF14dsQXD6p CZ0001 「小华 HC32F448MCTI 核心板 开发板 工程板」
点击链接直接打开 或者 淘宝搜索直接打开
【淘宝】https://m.tb.cn/h.5m2udJO?tk=10MSWUUnOvW CZ3457 「USB转UART_I2C_SPI串行口模块」
点击链接直接打开 或者 淘宝搜索直接打开
|