STM32IAP固件升级
来源:互联网 发布:手机改淘宝评价怎么改 编辑:程序博客网 时间:2024/04/28 20:21
前段时间在弄stm32基于GMS的固件升级,在网上查了很多资料,知道个大概。现在把我遇到的一些问题记录下来,和大家一起分享。
第一次写技术博客,高手勿喷!!!!
stm32IAP可以说分为两部分:bootloader+APP(我们平时烧录进单片机的程序)。启动过程大概是这样:1stm32上电,进入bootloader程序。2检测是否需要固件升级,如果需要,则通过USART,CAN,网络等收到hex或者bin流,用flash编程写进后面的flash中。3如果不需要升级则跳到APP程序。
在这里先说说关于stm32统一编址,stm32的寻址范围是2的32次方,也就是4G。我的用户flash的起始地址为0x0800 0000,SRAM的起始地址为0x2000 0000。那么0x0000 0000-0x07FF FFFF这段空间其实是根据我们boot1和boot0的选择确定是从flash启动还是从SRAM启动的,换句话说也就是将flash或者SRAm的地址映射过来的。
bootloader:首先我们要知道自己所用的cpu的flash和SRAM空间,我的是stm32F103,256Kflash,48KSRAM,弄清楚这个可以合理的分配bootloader和APP的空间。我在我的项目中分给bootloader的空间是0x8000,也就是32Kflash来存放bootloader。剩余的0x0380 0000的空间我用来存放APP(起始地址为0x0800 8000)。
关键代码:
#define ApplicationAddress1 0x08008000 //应用程序起始地址
typedef void (*pFunction)(void);
uint32_t JumpAddress;
pFunction Jump_To_Application; //应用程序地址指针
void jump(void) //这个是跳转函数,是bootloader中跳转到APP的函数
{
u32 ApplicationAddress=0;
if(0x01==flg)
{
ApplicationAddress = ApplicationAddress1;//ApplicationAddress1=0x0800 8000
//UART_printf("Execute user Program1\r\n");
}
else
{
return ;
}
if (((*(volatile uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
//这句话即通过判断栈顶地址值是否正确(是否在0x2000 0000 - 0x 2000 C000之间)来判断是否应用程序已经下载了,防止程序跑飞
{
JumpAddress = *(volatile uint32_t*)(ApplicationAddress + 4);
JumpAddress = *(volatile uint32_t*)JumpAddress;
Jump_To_Application = (pFunction)JumpAddress;
__set_MSP(*(volatile uint32_t*)ApplicationAddress); //初始化用户程序的堆栈指针
Jump_To_Application();
}
}
bootloader的中断向量表是不用偏移的,但是APP程序要把中断向量表偏移(具体偏移大于等于bootloader分配空间大小)
下面这段代码是APP程序中的:
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
// Set the Vector Table base location at 0x20000000
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else /* VECT_TAB_FLASH */
// Set the Vector Table base location at 0x08000000
//NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x08000);
// SCB->VTOR = FLASH_BASE | 0x08000;//等价于NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x08000);
#endif
同样在APP中也一样可以跳回bootloader程序 :
#ifdef ApplicationAddress0
if(0x01==BootloaderFlg)
{
ApplicationAddress = ApplicationAddress0;//ApplicationAddress0=0x0800 0000
UART_PutStr(USART1,"Execute user Program0\0");
}
else
{
return ;
}
if (((*(volatile uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
{
JumpAddress = *(volatile uint32_t*)(ApplicationAddress + 4);
Jump_To_Application = (pFunction)JumpAddress;
__set_MSP(*(volatile uint32_t*)ApplicationAddress); //初始化用户程序的堆栈指针
Jump_To_Application();
}
#endif
注意:
用Keil打开bootloader工程,点击魔术棒,打开目标选项设置,选择Target选项卡,IROM1改为from0x0800 0000,size为0x8000
用Keil打开APP工程,点击魔术棒,打开目标选项设置,选择Target选项卡,IROM1改为from0x0800 8000,size为0x0380 0000
其实在这里我最想说的事情并不是这个,这些可以在网上找到很多,下面的步骤是困扰我两天的MKD配置问题,导致我的一度怀疑自己写的程序配置有问题。
点击魔术棒,Utilitiles选项卡,点击setting按钮,弹出Flash download卡,Erase sectors打上勾,不然每次写入都会把整块flash擦除,两个工程都要设置。
今天写到这里,如果有错的请帮我指出来。
- STM32IAP固件升级
- stm32IAP代码升级小结
- STM32IAP升级-----编写IAP升级遇到的问题总结
- STM32IAP升级-----编写IAP升级遇到的问题总结
- STM32IAP升级-----编写IAP升级遇到的问题总结
- STM32IAP升级-----编写IAP升级遇到的问题总结
- iphone升级固件
- WEB固件升级
- WEB固件升级
- BM78 固件升级
- 固件升级思路
- pyboard固件升级
- ESP8266固件升级
- OpenMV固件升级
- 嵌入式Linux固件升级
- 宏基A500 固件升级
- jtagice3固件升级方法
- 部分内容7---升级固件
- kbhit() 检查当前是否有键盘输入,若有则返回一个非0值,否则返回0
- 公有继承或者公有多继承是可以用::符号
- C++学习笔记:数组的操作符重载(包括[]和=运算符)
- Android入门文档
- 堆排序
- STM32IAP固件升级
- javascript的5种基本数据类型
- Shell脚本中的for,while用法
- ubuntu软件安装二 oh-my-zsh
- RecyclerView 中setSpanSizeLookup 解释
- xilinx 的 HDMI输出的 IP CORE 调试
- golang语法总结(十八):处理异常
- Spring自定义接口,不定期更新。。。
- Android学习之路