程序员开发实例大全宝库

网站首页 > 编程文章 正文

嵌入式项目实战:单片机STM32 Bootloader 快速实现(超详细)

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


前言

嵌入式的设备,或多或少都需要对设备进行更新已适配更多的需求,如果未出货的设备还可以使用下载线去下载,但是如果出货之后到了客户那里,客户没有下载线而且不是专业人员,无法对设备进行升级,这时候,bootLoader 的重要性就凸显出来了,bootLoader 的设计就是为了设备能够进行远程升级或者只用指令升级,极大简便了升级需要的步骤,做到傻瓜式升级,极大增强了产品的后续维护性。

下面我来介绍写如何快速实现 STM32 BootLoader 的引导,帮助正在读文章的您更快将此技术运用起来!

一、Bootloader 是什么?

Bootloader是在应用程序开始前运行的一个小程序,里面可以进行一些初始化操作,升级引用程序等,在嵌入式设备中很常见。

二、BootLoader 的实现

我这里做了一个简单的 BootLoader 程序,只能进行引导,还没有对升级进行编写,升级是对约定好的应用程序Flash 进行擦+写,比较常用的升级方式是通过 TFTP 的方式进行升级,您可以在 STM32官方的这个例程找到答案: 基于LwIP TCP/IP栈通过以太网进行STM32F4x7应用内编程(IAP)(AN3968)

2.1 生成 bin 文件

  • 使用 Cube 生成出来后,打开工程的设置选项,填入如下命令
fromelf --bin -o ".\bin_file\@L.bin" "#L"


编译之后,可以看到 bin_file 文件夹里面生成了 bin 文件,并可以知道其大小,我们根据其大小约定应用程序Flash 的起始位置


2.2 确认应用程序的起始位置

  • 升级的过程被称为 IAP(In Application Programming) ,每个芯片的 Flash 的扇区不同,我这里使用的是 STM32F767,上官网查看有关资料:STM32F76xxx and STM32F77xxx advanced Arm?-based 32-bit MCUs.pdf 里面有关于 Flash 扇区的地址信息:
  • 步骤2.1已经知道 BootLoaderbin文件大小是22 KB,我们可以根据上面的 Flash 扇区进行分配,我将应用程序的起始位置定在 扇区1,起始地址为 0x0800 8000

2.3 编写引导程序

#include "stm32f7xx.h"

typedef  void (*pFunction)(void);

/*!
* @brief 跳转到应用程序段
*        执行条件:无
* @param[in1] : 用户代码起始地址.
*
* @retval: 无
*/
void jump_to_app(uint32_t app_addr)
{ 
    
    pFunction jump_to_application;
    uint32_t jump_address;
    
    /* Check if valid stack address (RAM address) then jump to user application */
    if (((*(__IO uint32_t*)app_addr) & 0x2FFE0000 ) == 0x20000000)
    {
      /* Jump to user application */
      jump_address = *(__IO uint32_t*) (app_addr + 4);
      jump_to_application = (pFunction) jump_address;
      /* Initialize user application's Stack Pointer */
      __set_MSP(*(__IO uint32_t*) jump_address);
      jump_to_application();
    }    
    
}

#define FLASH_JUMP_ADDR							(0x08008000)

int main(void)
{
	/* 
		初始化程序省略.....  
	*/
	
	if(((FLASH_JUMP_ADDR+4)&0xFF000000)==0x08000000) //Judge if start at 0X08XXXXXX.
	{
		jump_to_app(FLASH_JUMP_ADDR); // Jump to  APP
	}
	
	while(1)
	{
	
	}
}


三、App 的实现

3.1 修改 IROM1 的位置

根据约定好的 Flash 起始位置进行更改,上面步骤 2.2 已经确定好是 0x08008000


3.2 修改向量表

搜索宏定义 VECT_TAB_OFFSET,将 0x00 改为距离 0x08000000 的偏移量

/*!< Uncomment the following line if you need to relocate your vector Table in    Internal SRAM. */
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET  0x8000 /*!< Vector Table base offset field.
                                  This value must be a multiple of 0x200. */

3.3 加入 App 循环打印提示

void StartDefaultTask(void const * argument)
{
	/* USER CODE BEGIN StartDefaultTask */
	segger_rtt_init("APP enter!");
	/* Infinite loop */
	for(;;)
	{
		print_log("You are in App now !!\n");
		osDelay(1000);
	}
	/* USER CODE END StartDefaultTask */
}

四、演示效果

  • 确认烧录过程是 Erase Sectors


  • 打开 RTT 窗口,连接 RTTSTM32 ,依次烧录 BootLoaderApp 的程序;
    如何使用 JLink 实现 Segger log 可以按参考我之前的文章: 【嵌入式小技巧】stm32 实现 Segger RTT 打印(超详细)
  • 烧录完 App 程序之后,可以在 RTT窗口 看到正确引导到 App成功!!!


总结

以上是使用 快速搭建 STM32 Bootloader 的引导程序,希望能够帮助正在读文章的您更快将此技术运用起来!

完整代码可进群免费领取!!!

嵌入式物联网的学习之路非常漫长,不少人因为学习路线不对或者学习内容不够专业而错失高薪offer。不过别担心,我为大家整理了一份150多G的学习资源,基本上涵盖了嵌入式物联网学习的所有内容。点击下方链接,0元领取学习资源,让你的学习之路更加顺畅!记得点赞、关注、收藏、转发哦!

点击这里找小助理0元领取:扫码进群领资料

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

欢迎 发表评论:

最近发表
标签列表