STM32IAP固件升级

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ZhonKai_Ren/article/details/50716498

前段时间在弄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擦除,两个工程都要设置。

今天写到这里,如果有错的请帮我指出来。

没有更多推荐了,返回首页