程序员开发实例大全宝库

网站首页 > 编程文章 正文

STM32F103系列(基于HAL库)——Bootloader实现1

zazugpt 2024-08-22 04:41:20 编程文章 15 ℃ 0 评论

需求:对STM32F103进行Firmware升级。可能有人会问,STM官网会提供DFU接口并且有专门的ST LINK可以给芯片下载Firwmare。

事实上,真实的需求是,我需要做一个Debug工具,下位机是STM32F103,上位机会用C#实现。这个Debug工具会进行更新,比如这次的测试需求满足,过了一段时间,另外的测试需求出现了,那么我的下位机需要具备Firmware在线更新的能力。这个Debug工具的使用者是多种多样的人甚至包括我这边的客户。所以,这个在线升级Firmware的工具最好和上位机是做到一起的,并且要简单易用,不需要复杂的配置。

因此,Bootloader将是必不可少的。

基本的设计思路:下位机分为两个区域,一个为Bootloader区域,另一个为Application区域,Bootloader区域不需要升级,每次对Application进行升级。另外,Bootloader里面的代码需要对Application区域的Firmware进行CRC校验,如果Application里面的CRC值与STM32 Bootloader算出来的CRC值不一致,那么Firmware将停留在Bootloader区域,保证芯片处在已知的工作范围,如果校验一致,那么Firmware将跳转至Application区域。

STM32F103的Firmware默认执行地址为0x8000000,Bootloader的Main函数需要放在初始默认位置,需要对Application区域的Code进行重新定位。Bootloader预留32K的Flash。剩下的Application区域,然后需要预留1K Bytes保存配置信息,如Application的CRC值,Applicaion Firmware 版本信息等等。因此Application代码的地址为0x8008400(32K(bootloader)+1K(configuration Code)),如下所示:

#define APP_RUN_BASEADDR   0x8008400    //32K for Bootloader, and another space for APP

那么,Bootloader里面的主要代码如下:

SysTick->CTRL =0;//关闭滴答定时器
HAL_DeInit();//关闭滴答定时器
HAL_NVIC_DisableIRQ(SysTick_IRQn);//关闭滴答定时器中断
HAL_NVIC_ClearPendingIRQ(SysTick_IRQn);//清除滴答定时器中断标志位,
//这几步的目的是避免滴答定时器产生的中断影响Firmware的跳转
__disable_irq();//关闭其他中断。
//上述步骤为关闭中断,防止中断影响Firmware跳转,之所以对滴答定时器操作很多,是因为我Firmware中滴答定时器是默认开启的。因此,对滴答定时器特殊照顾
JumpAddress =*(__IO uint32_t*)(APP_RUN_BASEADDR+4);
JumpToApplication = (pFunction)JumpAddress; //Firmware 复位地址,为初始地址+4
__set_MSP(*(__IO uint32_t*)APP_RUN_BASEADDR);//设置堆栈指针
JumpToApplication();//跳转到Application

Application区域的代码需要对中断向量表重新定位。如下所示,将HAL库中的VECT_TAB_OFFSET宏定义改掉为0x00008400.

#define FLASH_BASE            0x08000000UL /*!< FLASH base address in the alias region */
#define VECT_TAB_OFFSET  0x00008400U /*!< Vector Table base offset field.
                                  This value must be a multiple of 0x200. */
#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif

然后Application的代码就可以正常写了,代码编译的时候会自动从0x8008400开始放。注意:有一些库可能会在代码中对中断向量表重新定位,我目前使用的库中只有上面一处对中断向量地址进行了定义。

另外需要说明的一点,就是要在链接文件STM32F103XX_Flash.ld文件修改为:

/* Memories definition */
MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 64K//RAM的空间分配
  FLASH    (rx)    : ORIGIN = 0x8008400,   LENGTH = 470K//Flash的空间分配
}

代码的烧录:初次代码烧录使用ST-LINK,以及官网上提供的STM32CubeProgrammer,利用SWD进行烧录,注意选择文件的时候,需要选择HEX文件,HEX文件才会有地址信息,不要选择BIN文件,不要选择BIN文件,不要选择BIN文件。

另外在烧录之前,可以判断一下,Application初始地址是否设置成功,可以用STM32CubeProgrammer打开Application的HEX文件,将会显示,0x8008400上的值一定是0x2001000,否则就是设置失败。设置成功之后,将Bootloader的HEX和Application的HEX分别下载进入STM32,就实现了一个基本的Bootloader功能。

我上面写的关于对Application代码检测的CRC检验,将在后面的文章介绍。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表