完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
IAP是In Application Programming的首字母缩写,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。
以上是IAP的官方解释,通俗一点来说,iap就是一个专门用来升级应用程序的程序。 首先,为什么存在IAP? 在产品不能进行直接烧写时,例如已经包装好了外壳,或已经发到了客户手里等不能接触,只能通过iap来更新应用程序的功能。 其次,IAP是怎么工作的,它和APP有什么关联,共用的外设怎么分配? 我们知道单片机的执行位置是PC指针所指的地方,如下图所示,它指向IAP时,则运行IAP的代码,此时所有的外设自然都服务于IAP,指向APP时同理。 上图的每个方框代表flash上的一块区域,可以是一个或多个扇区,IAP工程生成的bin文件最后就烧写在我们指定给它的flash区域中,APP的bin文件同理。 当执行IAP中的各个函数时,PC指针就会在这个区域中跳来跳去(其实各个函数的地址在map文件中也能看到), 当执行IAP中的跳转到APP的指令时,PC就指向了APP的区域,继续在那一块区域跳来跳去。 下面我用cubemx + stm32f4 来举个栗子,详细说明iap具体怎么实现跳转 IAP实例 使用cubemx ,配置好串口1和时钟,生成iap和app两个工程,app工程需要更改执行起始地址,本例中app改为了0x8010000,具体如何更改也很简单,可以参考我的另一篇文章, 先做好串口重定向,跳转函数,跳转地址宏,代码如下: /* USER CODE BEGIN Includes */ #include "stdio.h" /* USER CODE END Includes */ /* USER CODE BEGIN 0 */ int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF); return ch; } #define APP_FLASH_ADDR 0x8010000 typedef unsigned int u32; typedef void (*iapfun)(void); //定义一个函数类型的参数. iapfun jump2app; void iap_load_app(u32 appxaddr) { printf("iap jump to app,addr:%08xrn",appxaddr); jump2app=(iapfun)*(u32*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址) __set_MSP(*(u32*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) jump2app(); } /* USER CODE END 0 */ main函数中改动代码如下 /* USER CODE BEGIN 2 */ printf("iap demorn"); iap_load_app(APP_FLASH_ADDR); printf("iap demo endrn");//正常情况下,永远不会执行这行以及下面的代码。 /* USER CODE END 2 */ tips1:关于jump指令 定义函数指针类型的参数,方便阅读,如果想紧凑一点可以参考下方代码一样可以跳转,不论哪种写法,流程是一样的, 1,*(u32*) >> 取0x8010000处的第二字的内容,也就是tips2中的08012ccd 2, ((void(*)()) >> 将08012ccd强转为无返回无入参的函数指针, 3,执行函数指针,也就是执行地址为08012ccd的函数 void iap_load_app(u32 appxaddr) { printf("iap jump to app,addr:%08xrn",appxaddr); //jump2app=(iapfun)*(u32*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址) __set_MSP(*(u32*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) //jump2app(); ((void(*)())(*(u32*)(appxaddr+4)))(); } tip2:为什么不是跳转到0x8010000,set_msp又是什么鬼? 我们先来看看app烧写成功之后,0x8010000处是什么样子的,如下图 可以看到第一个字是20000570其实是栈顶地址,那其他的又是什么,我们再来看两张图 一张是APP的启动文件中的中断向量表,另一张是APP编译后的map文件所打印出来的各函数的地址,时间关系没有框全,但我们将几张图的序号对应起来看,不难发现,其实用户代码开始几个字,是按顺序对应的栈顶地址,Reset_Handler地址等。 当我们从IAP跳转到第二个字也就是Reset_Handler之后,会执行SystemInit来初始化时钟,后面的__iar_program_start是iar的一条内部指令,对C的运行,以及全局变量等做初始化操作,一系列准备工作就绪之后再进入main.c函数,执行APP代码,至此,跳转成功完成。 结果展示 先附上APP的代码 /* USER CODE BEGIN 2 */ printf("diy8 demorn"); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { HAL_Delay(1000); printf("uart testrn"); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ 再看来自串口的打印信息 由图可知,跳转成功,IAP中的iap demo end也确实没有执行打印,end。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1602 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1536 浏览 1 评论
967 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
680 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1579 浏览 2 评论
1860浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
640浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
513浏览 3评论
527浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
500浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-19 13:27 , Processed in 3.496394 second(s), Total 79, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号