stm32f103 iap的IAP,2个APP的问题

STM32 MCU IAP例程跳转到APP代码简要分析
有客户在初次使用 STM32 MCU IAP 的例程的,可能会对跳转到 APP 部分的函数的实现产生疑问。
STM32 MCU IAP例程跳转到APP代码简要分析下载
下载资料需要,并消耗一定积分。
下载此资料的人还喜欢:
技术交流、我要发言! 发表评论可获取积分! 请遵守相关规定。
本周热点资料
电子资料热门词
上传者其它资料
通信网络下载排行查看: 6080|回复: 50
STM32通过USB实现Bootloader/IAP功能
帖子主题金币
本帖最后由 飞鸿踏雪 于
11:40 编辑
最近在做STM32的USB Bootlader/IAP功能,也就是通过USB实现固件升级,本文介绍下实现的基本思路,希望对实现IAP的同学一个参考,改方法已经在产品中得到实际应用并验证是比较合理,稳定可靠的。
程序空间划分:
在单片机的程序Flash中分两个区,分别存储Bootloader代码和App代码,Bootloader放到代码起始地址,也就是0x,App放到0x8020000地址,中间预留了很多的地址空间,主要是为了用来存储一些需要掉电保存的数据,比如我在0x地址就存放了App程序运行后写入该地址的标志数据。
启动流程:
上电后自然是运行Bootloader程序,Bootloader运行后,做的第一件事情如下所示
[C] 纯文本查看 复制代码
if((*((uint32_t *)EXE_FLAG_ADDR))==0x){
JumpToApplication(APP_START_ADDR);
也就是判断App运行标志是否有效,这个标志是存放到EXE_FLAG_ADDR地址的,若有效就直接跳转到App程序运行,这个时间很短,所以用户看不到有Bootloader执行的效果,感觉就是直接运行的App程序,进入App程序后,App程序第一件事情如下
[C] 纯文本查看 复制代码
if((*((uint32_t *)EXE_FLAG_ADDR))==0xFFFFFFFF){
uint32_t ExeFlag = 0x;
__set_PRIMASK(1);//禁止全局中断
FLASH_Unlock();
ProgramDatatoFlash(EXE_FLAG_ADDR,(uint8_t*)(&ExeFlag),4);
FLASH_Lock();
也就是判断App标志是否有效,若有效则直接执行后面的程序,若无效则需要在EXE_FLAG_ADDR地址写入执行标志。
Bootloader程序判断App标志若无效,那么Bootloader就不会直接跳转到App,因为这个时候是需要进行升级App的操作,所以程序就进入Bootloader的正常工作流程,也就是等待升级App的各种命令,比如擦出固件,烧写固件,校验固件等。当固件成功写入并校验通过之后,PC端就可以发送一个程序跳转命令跳转到App执行。
PC端操作流程:
PC端和单片机是通过USB进行数据交换的,当然用其他方式也可以,基本流程都是差不多的。
PC程序首先当然是扫描设备,打开设备,然后调用获取固件信息的函数,调用该函数后可以得知当前固件的名称,版本号,固件类型(Bootloader还是App),若发现当前固件不是Bootloader,那么就得通过USB给固件发送一个程序跳转命令,也就是跳转到Bootloader代码执行,当然App在跳转到Bootloader的时候必须把EXE_FLAG_ADDR地址的标志数据擦出掉,这样Bootloader才能进入正常的升级流程。
控制固件程序进入Bootloader之后,PC端程序将打开App固件程序文件,然后根据文件大小,发送擦出App代码存储区域Flash的数据,然后再分包将固件发送给单片机,单片机端Bootlader程序接收到数据后将数据写入App的Flash区域,数据写完之后再进行校验,我是通过计算CRC16的方式进行校验的,校验通过之后就可以发送跳转命令控制程序跳转到App运行了,到此升级流程完毕。
PC端程序代码:
[C] 纯文本查看 复制代码// USB2XXXTest.cpp : Defines the entry point for the console application.
#include &stdafx.h&
#include &stdlib.h&
#include &../../USB2XXX/source/bootloader.h&
int _tmain(int argc, _TCHAR* argv[])
int PackSize = 1024*10;
int TimeOut = 0;
int ApplicationAddress = 0x;
int BootAddress = 0x;
FW_INFO FwI
//扫描查找设备
ret = BT_ScanDevice(true);
if(ret &= 0){
printf(&No device connected!\n&);
//打开设备
state = BT_OpenDevice(0);
if(!state){
printf(&Open device error!\n&);
//获取固件信息
BT_GetFirmwareInfo(0,&FwInfo);
printf(&Firmware Name:%s\n&,FwInfo.FirmwareName);
printf(&Firmware Functions:%08X\n&,FwInfo.Functions);
//判断当前固件是否为Bootloader固件
while(!(FwInfo.Functions&FUNCTION_BOOTLOADER)){
//控制程序跳转到Bootloader
state = BT_ExcuteFirmware(0,BootAddress);
printf(&BT_ExcuteFirmware state = %d\n&,state);
BT_CloseDevice(0);
Sleep(100);
ret = BT_ScanDevice(true);//扫描查找设备
if((ret &= 0)&&(TimeOut & 50)){
printf(&No device connected!\n&);
}else if(ret & 0){
TimeOut++;
}while(ret&=0);
TimeOut = 0;
Sleep(100);
state = BT_OpenDevice(0);//打开设备
if((!state)&&(TimeOut & 50)){
printf(&Open device error!\n&);
}else if(state){
TimeOut++;
}while(!state);
//获取固件信息
BT_GetFirmwareInfo(0,&FwInfo);
printf(&Firmware Name:%s\n&,FwInfo.FirmwareName);
printf(&Firmware Functions:%08X\n&,FwInfo.Functions);
//打开固件文件
FILE *pFile=fopen(&Project.bin&,&rb&); //获取文件的指针
fseek(pFile,0,SEEK_END); //把指针移动到文件的结尾 ,获取文件长度
int FileLen=ftell(pFile); //获取文件长度
static char *pBuf = (char *)malloc(FileLen);
//定义文件指针
if(pBuf == NULL){
printf(&malloc error\n&);
rewind(pFile); //把指针移动到文件开头 因为我们一开始把指针移动到结尾,如果不移动回来 会出错
fread(pBuf,1,FileLen,pFile); //读文件
fclose(pFile); // 关闭文件
//擦除之前的固件
state = BT_EraseSectors(0,ApplicationAddress,ApplicationAddress+FileLen);
if(!state){
printf(&BT_EraseSectors error!\n&);
printf(&BT_EraseSectors success\n&);
//循环写入固件数据到芯片Flash
int PackIndex = 0;
for(PackIndex=0;PackIndex&FileLen/PackSPackIndex++){
state = BT_WriteData(0,ApplicationAddress+PackIndex*PackSize,(unsigned char *)(&pBuf[PackIndex*PackSize]),PackSize,0);
if(!state){
printf(&BT_WriteData Error\n&);
if(FileLen%PackSize){
state = BT_WriteData(0,ApplicationAddress+PackIndex*PackSize,(unsigned char *)(&pBuf[PackIndex*PackSize]),FileLen%PackSize,0);
if(!state){
printf(&BT_WriteData Error\n&);
printf(&BT_WriteData Success\n&);
//循环校验数据是否写成功
for(PackIndex=0;PackIndex&FileLen/PackSPackIndex++){
state = BT_VerifyData(0,ApplicationAddress+PackIndex*PackSize,(unsigned char *)(&pBuf[PackIndex*PackSize]),PackSize);
if(!state){
printf(&BT_VerifyData Error\n&);
if(FileLen%PackSize){
state = BT_VerifyData(0,ApplicationAddress+PackIndex*PackSize,(unsigned char *)(&pBuf[PackIndex*PackSize]),FileLen%PackSize);
if(!state){
printf(&BT_VerifyData Error\n&);
printf(&BT_VerifyData Success\n&);
//执行固件
state = BT_ExcuteFirmware(0,ApplicationAddress);
printf(&BT_ExcuteFirmware state = %d\n&,state);
//关闭设备
BT_CloseDevice(0);
PC端程序运行效果如下所示:
1.png (21.21 KB, 下载次数: 6)
10:24 上传
我是用STM32F4+USB3300高速USB实现IAP功能的,12K的App代码几乎瞬间下载完毕,整个程序测试了很多次,没一次出问题...
人生到处知何似,应似飞鸿踏雪泥。
帖子主题金币
新手上路, 积分 9, 距离下一级还需 41 积分
新手上路, 积分 9, 距离下一级还需 41 积分
感觉好厉害
帖子主题金币
注册会员, 积分 161, 距离下一级还需 39 积分
注册会员, 积分 161, 距离下一级还需 39 积分
不知道USB和网口法师IAP程序,哪个更快点;
帖子主题金币
不知道USB和网口法师IAP程序,哪个更快点;
高速USB应该会快一点,如果是全速USB,网口可能会快点
人生到处知何似,应似飞鸿踏雪泥。
帖子主题金币
注册会员, 积分 73, 距离下一级还需 127 积分
注册会员, 积分 73, 距离下一级还需 127 积分
我只能说,楼主厉害
帖子主题金币
注册会员, 积分 57, 距离下一级还需 143 积分
注册会员, 积分 57, 距离下一级还需 143 积分
如果是串口升级,怎么调到BOOT中呢?
帖子主题金币
注册会员, 积分 161, 距离下一级还需 39 积分
注册会员, 积分 161, 距离下一级还需 39 积分
高速USB应该会快一点,如果是全速USB,网口可能会快点
版主研究过官网STM32F407/STM32F207的LwIP+SSL范例吗?
帖子主题金币
注册会员, 积分 161, 距离下一级还需 39 积分
注册会员, 积分 161, 距离下一级还需 39 积分
如果是串口升级,怎么调到BOOT中呢?
这个还不简单,串口接收到指令在EEPROM内设个标志位置1,然后看门狗方式复位,读取EEPROM标志位是否为1,来判断是否运行BOOT程序还是直接跳到APP程序区;
帖子主题金币
版主研究过官网STM32F407/STM32F207的LwIP+SSL范例吗?
人生到处知何似,应似飞鸿踏雪泥。
帖子主题金币
注册会员, 积分 57, 距离下一级还需 143 积分
注册会员, 积分 57, 距离下一级还需 143 积分
把你的源码公开撒
帖子主题金币
注册会员, 积分 57, 距离下一级还需 143 积分
注册会员, 积分 57, 距离下一级还需 143 积分
你好!& &你的APP程序带系统吗??& && & 我的程序带UCOS,boot调到APP后就死了,没有UCOS的没有问题
帖子主题金币
你好!& &你的APP程序带系统吗??& && & 我的程序带UCOS,boot调到APP后就死了,没有UCOS的没有问题
没用过带系统的,估计是启动文件或者其他什么地方需要修改吧
人生到处知何似,应似飞鸿踏雪泥。
帖子主题金币
注册会员, 积分 63, 距离下一级还需 137 积分
注册会员, 积分 63, 距离下一级还需 137 积分
感觉好厉害
帖子主题金币
注册会员, 积分 57, 距离下一级还需 143 积分
注册会员, 积分 57, 距离下一级还需 143 积分
升级软件用什么啊?
帖子主题金币
升级软件用什么啊?
就是用我帖子里面的程序噻
人生到处知何似,应似飞鸿踏雪泥。
帖子主题金币
注册会员, 积分 57, 距离下一级还需 143 积分
注册会员, 积分 57, 距离下一级还需 143 积分
PC软件也是自己写的?& & 你的USB升级也是DFU协议??
帖子主题金币
自己写的程序,自己定的协议,不是dfu
帖子主题金币
自己写的程序,自己定的协议,不是dfu
帖子主题金币
注册会员, 积分 57, 距离下一级还需 143 积分
注册会员, 积分 57, 距离下一级还需 143 积分
把一下公开下撒,让我们也学习下
帖子主题金币
把一下公开下撒,让我们也学习下
学习的话可以按照我这个思路自己折腾,这个是产品里面用到的代码,不是很方便,若有需求可以私聊我
人生到处知何似,应似飞鸿踏雪泥。
帖子主题金币
注册会员, 积分 76, 距离下一级还需 124 积分
注册会员, 积分 76, 距离下一级还需 124 积分
过于强大啊
帖子主题金币
新手上路, 积分 37, 距离下一级还需 13 积分
新手上路, 积分 37, 距离下一级还需 13 积分
感谢共享!!!!!!!!!!
帖子主题金币
中级会员, 积分 285, 距离下一级还需 215 积分
中级会员, 积分 285, 距离下一级还需 215 积分
这个貌似蛮复杂的啊,真是牛人
帖子主题金币
新手上路, 积分 38, 距离下一级还需 12 积分
新手上路, 积分 38, 距离下一级还需 12 积分
感谢共享!!!!!!!!!!
帖子主题金币
新手上路, 积分 49, 距离下一级还需 1 积分
新手上路, 积分 49, 距离下一级还需 1 积分
不错不错,真是牛人
帖子主题金币
新手上路, 积分 21, 距离下一级还需 29 积分
新手上路, 积分 21, 距离下一级还需 29 积分
好厉害,谢谢
帖子主题金币
新手上路, 积分 21, 距离下一级还需 29 积分
新手上路, 积分 21, 距离下一级还需 29 积分
回复不了?& &
帖子主题金币
中级会员, 积分 211, 距离下一级还需 289 积分
中级会员, 积分 211, 距离下一级还需 289 积分
不错不错,真是牛人
帖子主题金币
新手上路, 积分 34, 距离下一级还需 16 积分
新手上路, 积分 34, 距离下一级还需 16 积分
感觉好厉害
帖子主题金币
中级会员, 积分 366, 距离下一级还需 134 积分
中级会员, 积分 366, 距离下一级还需 134 积分
楼主,STM32F bootloader最近想学学,能否提供源码,谢谢!
帖子主题金币
中级会员, 积分 238, 距离下一级还需 262 积分
中级会员, 积分 238, 距离下一级还需 262 积分
帖子主题金币
中级会员, 积分 238, 距离下一级还需 262 积分
中级会员, 积分 238, 距离下一级还需 262 积分
挣个金币,顺便感谢一下楼主
帖子主题金币
中级会员, 积分 238, 距离下一级还需 262 积分
中级会员, 积分 238, 距离下一级还需 262 积分
挣个金币,顺便感谢一下楼主!!!!!!!!!!!!
帖子主题金币
新手上路, 积分 27, 距离下一级还需 23 积分
新手上路, 积分 27, 距离下一级还需 23 积分
楼主威武,我也是类似这么做的
帖子主题金币
注册会员, 积分 51, 距离下一级还需 149 积分
注册会员, 积分 51, 距离下一级还需 149 积分
xue xi xue xi
帖子主题金币
注册会员, 积分 61, 距离下一级还需 139 积分
注册会员, 积分 61, 距离下一级还需 139 积分
这个思路可以借鉴,敬佩。
帖子主题金币
中级会员, 积分 324, 距离下一级还需 176 积分
中级会员, 积分 324, 距离下一级还需 176 积分
版主的帖子好有技术含量。
帖子主题金币
新手上路, 积分 23, 距离下一级还需 27 积分
新手上路, 积分 23, 距离下一级还需 27 积分
值得学习!
帖子主题金币
新手上路, 积分 23, 距离下一级还需 27 积分
新手上路, 积分 23, 距离下一级还需 27 积分
不错的分享
帖子主题金币
新手上路, 积分 32, 距离下一级还需 18 积分
新手上路, 积分 32, 距离下一级还需 18 积分
输必须由主机发起是什么意思?
帖子主题金币
新手上路, 积分 12, 距离下一级还需 38 积分
新手上路, 积分 12, 距离下一级还需 38 积分
通过物联网平台实现对大量固件的远程OTA,不知道楼主有没有什么好的方案呢?使用MQTT传输可以么。
帖子主题金币
通过物联网平台实现对大量固件的远程OTA,不知道楼主有没有什么好的方案呢?使用MQTT传输可以么。
MQTT速度是问题,可以使用TFTP协议
人生到处知何似,应似飞鸿踏雪泥。
帖子主题金币
新手上路, 积分 35, 距离下一级还需 15 积分
新手上路, 积分 35, 距离下一级还需 15 积分
很强大,学习了,感谢分享
帖子主题金币
注册会员, 积分 134, 距离下一级还需 66 积分
注册会员, 积分 134, 距离下一级还需 66 积分
版主好厉害,必须赞,源码能公开让大家学一下最好了
帖子主题金币
注册会员, 积分 134, 距离下一级还需 66 积分
注册会员, 积分 134, 距离下一级还需 66 积分
版主好厉害,必须赞,源码能公开让大家学一下最好了
帖子主题金币
新手上路, 积分 11, 距离下一级还需 39 积分
新手上路, 积分 11, 距离下一级还需 39 积分
楼主好厉害!
帖子主题金币
新手上路, 积分 35, 距离下一级还需 15 积分
新手上路, 积分 35, 距离下一级还需 15 积分
谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢
帖子主题金币
注册会员, 积分 64, 距离下一级还需 136 积分
注册会员, 积分 64, 距离下一级还需 136 积分
资料真心不错,非常有用。
帖子主题金币
中级会员, 积分 378, 距离下一级还需 122 积分
中级会员, 积分 378, 距离下一级还需 122 积分
过于强大,值得学习!
帖子主题金币
注册会员, 积分 73, 距离下一级还需 127 积分
注册会员, 积分 73, 距离下一级还需 127 积分
很好,准备自己也加上这功能
帖子主题金币
新手上路, 积分 30, 距离下一级还需 20 积分
新手上路, 积分 30, 距离下一级还需 20 积分
赞,打点酱油,换个金币
Powered by21ic官方微信-->
后使用快捷导航没有帐号?
查看: 3286|回复: 7
iap和和app跳转问题
&&未结帖(20)
主题帖子积分
实习生, 积分 18, 距离下一级还需 32 积分
实习生, 积分 18, 距离下一级还需 32 积分
主题帖子积分
专家等级:结帖率:0%
主题帖子积分
实习生, 积分 18, 距离下一级还需 32 积分
实习生, 积分 18, 距离下一级还需 32 积分
& & & & & & & && &/* Test if user code is programmed starting from address &APPLICATION_ADDRESS& */
& & & & & & & & & & & & if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x)
& & & & & & & & & & & & {
& & & & & & & & & & & & & & & & /* Jump to user application */
& & & & & & & & & & & & & & & & JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
& & & & & & & & & & & & & & & & Jump_To_Application = (pFunction) JumpA
& & & & & & & & & & & & & & & &
& & & & & & & & & & & & & & & & /* Initialize user application's Stack Pointer */
& & & & & & & & & & & & & & & & __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
& & & & & & & & & & & & & & & &
& & & & & & & & & & & & & & & & /* Jump to application */
& & & & & & & & & & & & & & & & Jump_To_Application();
& & & & & & & & & & & & }
上面是iap跳转到app的代码,经过验证APPLICATION_ADDRES 是iap或app的首地址的话 比如(iap 程序首地址是0x8000000,app首地址是0x8003000),都可以相互跳转到复位地址执行,但是我改成JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS );APPLICATION_ADDRESS&&是我固定的一个函数的地址,这样执行总是失败,失败就进入中断的错误函数里void HardFault_Handler(void),
请问大侠们 怎么能跳转到函数的地址呀,实现直接绝对跳转到函数地址执行函数, 是不是我的堆栈的设置有问题?
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
中级工程师, 积分 4890, 距离下一级还需 110 积分
中级工程师, 积分 4890, 距离下一级还需 110 积分
主题帖子积分
专家等级:结帖率:100%
主题帖子积分
中级工程师, 积分 4890, 距离下一级还需 110 积分
中级工程师, 积分 4890, 距离下一级还需 110 积分
JumpAddress = APPLICATION_ADDRESS;
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
实习生, 积分 18, 距离下一级还需 32 积分
实习生, 积分 18, 距离下一级还需 32 积分
主题帖子积分
专家等级:结帖率:0%
主题帖子积分
实习生, 积分 18, 距离下一级还需 32 积分
实习生, 积分 18, 距离下一级还需 32 积分
STARM 发表于
JumpAddress = APPLICATION_ADDRESS;
试了,也不行呀。我把一个函数的地址固定成0x8001000,
#define APPLICATION_ADDRESS (u32)0x
不知道为什么不能跳转到函数执行,但是跳转到 0x复位地址却可以,
这个跟堆栈的设置__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);有关系吗?这句话是不是只是定义了堆栈指针的位置,是不是还需要清空堆栈??但是我没找到情况堆栈的指令
要不就是地址对齐问题??
最后进去void HardFault_Handler(void)&&
不知道是啥问题呀!!求助
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
中级工程师, 积分 4890, 距离下一级还需 110 积分
中级工程师, 积分 4890, 距离下一级还需 110 积分
主题帖子积分
专家等级:结帖率:100%
主题帖子积分
中级工程师, 积分 4890, 距离下一级还需 110 积分
中级工程师, 积分 4890, 距离下一级还需 110 积分
#define APPLICATION_ADDRESS (u32)(0x)
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
实习生, 积分 18, 距离下一级还需 32 积分
实习生, 积分 18, 距离下一级还需 32 积分
主题帖子积分
专家等级:结帖率:0%
主题帖子积分
实习生, 积分 18, 距离下一级还需 32 积分
实习生, 积分 18, 距离下一级还需 32 积分
STARM 发表于
#define APPLICATION_ADDRESS (u32)(0x)
大神,前两天休息,
按照你指点的两条确实可以跳转到函数并且往下执行了,
有一点没弄明白,如果不+1,可以跳到函数处,但是无法向下进行,+1后可以跳到函数处,并且往下执行,这是为什么呢?+1是什么道理??
iap调了好几天了,我从app 跳到iap的某一函数处后,就会莫名其妙的出现很多问题,不知道跳转到函数地址后还要不要进行什么操作,以避免莫名其妙的问题?如果直接运行iap都是正常,就是跳转到iap的某函数开始运行就出现莫名其妙的问题
跳回后我再初始化一次串口,就会出现idle无法置位的问题,这样,串口发送就只能发一次,就无法工作了
然后我干脆不初始化串口了,串口可以工作,但是 程序运行到写flash的时候就会崩溃,大神帮分析一下,这是咋回事,这程序调了好久 我都要疯了,!!
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
中级工程师, 积分 4890, 距离下一级还需 110 积分
中级工程师, 积分 4890, 距离下一级还需 110 积分
主题帖子积分
专家等级:结帖率:100%
主题帖子积分
中级工程师, 积分 4890, 距离下一级还需 110 积分
中级工程师, 积分 4890, 距离下一级还需 110 积分
&& +1是什么道理??
STM32F0 使用 Thumb2 指令集,&&要用 Thumb 模式跳转
define APPLICATION_ADDRESS (u32)(0x)
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
Jump_To_Application = (pFunction) JumpA // APPLICATION_ADDRESS
& && && && && && && && && && &&&
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
& && && && && && && && && && &&&
/* Jump to application */
Jump_To_Application(); -- 这里生成类似 BLX R0 形式的指令
其中 R0 的Bit[0] 将复制到 CPSR 的标志位 T
如果R0 中的第0 位为1,处理器将执行Thumb 指令
如果R0 中的第0 位为0,执行ARM 指令。
因为STM32一直使用 Thumb 指令, 所以必须是跳转地址的最低位为 1, 从而执行Thumb 指令
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
实习生, 积分 18, 距离下一级还需 32 积分
实习生, 积分 18, 距离下一级还需 32 积分
主题帖子积分
专家等级:结帖率:0%
主题帖子积分
实习生, 积分 18, 距离下一级还需 32 积分
实习生, 积分 18, 距离下一级还需 32 积分
STARM 发表于
&& +1是什么道理??
STM32F0 使用 Thumb2 指令集,&&要用 Thumb 模式跳转
多谢指点!
是不是就是 r0 的bit[0] 一直存放的是ARM指令或 Thumb 指令的标志位,所以是从bit[1].开始执行。
要不是你告诉我 怎么我也想不+1 估计我就永远卡死在这里了。太感谢了
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
初级技术员, 积分 66, 距离下一级还需 34 积分
初级技术员, 积分 66, 距离下一级还需 34 积分
主题帖子积分
专家等级:结帖率:0%
主题帖子积分
初级技术员, 积分 66, 距离下一级还需 34 积分
初级技术员, 积分 66, 距离下一级还需 34 积分
多谢指点!
是不是就是 r0 的bit[0] 一直存放的是ARM指令或 Thumb 指令的标志位,所以是从bit[1].开始执 ...
您好 ,请问您这个函数,跳到APP后 ,通过什么方式跳回到 主函数的?
appEntry = (void (*)(void)) (0x);
(*appEntry)( );//在此跳入到APP
jump_back();怎么跳回到主函数 ,这个位置呢?
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
技术新星奖章
人才类勋章
突出贡献奖章
等级类勋章
湍急之河流
发帖类勋章
技术奇才奖章
人才类勋章
时间类勋章

我要回帖

更多关于 stm32 iap 的文章

 

随机推荐