iOS开发启动图上加倒计时 iapp倒计时启动 您所在的位置:网站首页 iapp倒计时后自动进入 iOS开发启动图上加倒计时 iapp倒计时启动

iOS开发启动图上加倒计时 iapp倒计时启动

2024-04-12 11:31| 来源: 网络整理| 查看: 265

这两天忙里偷闲,自己编程打通了Bootloader/IAP的通道。仅仅是打通了一个通道,能实现上电进入bootloader,通过串口下载APP程序的功能。还有很多细枝末节的东西没有完善,但最主要的通道打开了,以后的升级完善就全看个人发挥啦。 先大致概括一下Bootloader和APP的程序功能1.BootLoader: 开机后倒计时十秒,若无数据从串口导入,则跳入APP程序,若有数据传入,则将传入数据烧到APP起始地址,然后跳入APP运行;主要包括定时器中断、串口收发、Flash等操作,不算复杂。2.APP: APP程序就我之前瞎编的一个小程序,主要用来监测IAP是否成功。 下面详细说一下BootLoader程序

一.主循环int count = 0; while (1) { if(Bootloader_Str.Code_size_rev == 0) { printf("Run APP %d seconds later\n",10-count); HAL_Delay(1000); HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_7); count++; if(count >= 10) jump2app(0x8008000); } if(Global_Flag.Rev_Completed) { Function_IAP(); Global_Flag.Rev_Completed = 0; jump2app(0x8008000); } }

其中两个if语句中的判断条件来源于两个结构体,定义如下

struct BOOTLOADER_STR{ volatile uint32_t Code_size_rev; volatile uint32_t Code_size_rev_befor; uint8_t CODE_CACHE[CODE_MAX_SIZE]; }; struct GLOBAL_FLAG{ uint8_t Rev_Completed; };

其中BOOTLOADER_STR中包含了串口接收size和上一次定时器检查接收长度时检测到的size_rev_before,还有串口数据接收缓存区CODE_CACHE[CODE_MAX_SIZE]; 何为定时器检查接收长度呢?就是开启一个定时器中断,每次中断服务时检查Code_size_rev和Code_size_rev_befor是否相等,若相等则认为接收完了,则将GLOBAL_FLAG结构体中的 Rev_Completed位置1,在主循环里进行代码烧录的工作。大致意思就是,我设置定时器中断间隔为x毫秒,若x毫秒内接收到的数据size没变,那么我就认为完成了这一次的接收。这个方法比较粗暴且实用,但难免在有些情况下不太稳定,主要是我偷懒,否则完全可以写一个上位机,制定一套协议,从而使得数据传输更加稳定。 继续讲主循环,工作很简单,就是每隔1秒改变一下led灯的亮灭,同时打印一句“程序将在x秒后启动”,然后就是判断Rev_Completed标志位,若Rev_Completed为1,则表示数据接收完毕,接下来去进行烧录工作;再就是10秒之后未收到数据,则跳入APP运行。和有些电脑开机时的倒计时有点像,其实电脑的倒计时也算是个BootLoader。 再简单讲一下串口接收,就是在串口接收中断中,每来一字节数据,我就将它放入CODE_CACHE缓存区中,并且让Code_size_rev加一。当定时器检测到规定时间内Code_size_rev不变了,则进入烧录程序。

二.烧录程序

其实解决了数据接收并保存到缓存区的问题,剩下的烧录程序就是简单的Flash操作了。可以看到主循环中检测到Global_Flag.Rev_Completed标志位置1时,会如下运行

if(Global_Flag.Rev_Completed) { Function_IAP(); Global_Flag.Rev_Completed = 0; jump2app(0x8008000); }

其中Function_IAP()就是烧录程序的过程,这个函数运行完后就清除标志位,并跳转,看一下Function_IAP()代码

void Function_IAP() { TIM3->CR1 &= ~(0x01); HAL_TIM_Base_Stop_IT(&htim3); printf("Get BIN -> Recevie Size = %d ->\n",Bootloader_Str.Code_size_rev); Flash_Erase(); Flash_Program(); BOOTLOADER_STR_CLEAR(); printf("Jump to APP ->\n"); }

首先禁用定时器和定时器中断,防止烧录过程中再次进入Function_IAP();然后打印接收的数据长度,以作为参考看看收没收对,当然,我也是为了偷懒,并没有加入数据收发校验。之后便开始Flash擦除和烧录过程,代码如下

void Flash_Erase(void) { uint32_t sector_error; FLASH_EraseInitTypeDef Flash_erase; Flash_erase.TypeErase = FLASH_TYPEERASE_SECTORS; Flash_erase.Sector = FLASH_SECTOR_2; Flash_erase.NbSectors = 1; Flash_erase.VoltageRange = FLASH_VOLTAGE_RANGE_3; printf("Erasing. . . . . .\n"); HAL_FLASH_Unlock(); HAL_FLASHEx_Erase(&Flash_erase,NULL); HAL_FLASH_Lock(); } void Flash_Program(void) { uint32_t addr_base = 0x8008000; HAL_Delay(1); printf("Programing. . . . . .\n"); HAL_FLASH_Unlock(); for(int i =0;i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有