STM32F1xx HAL RTThread移值支持Bootloader

为什么需要bootloader

当设备需要OTA在线升级,或者通过串口升级固件的时候,为了设计的方便,可对片内flash进行分区,做成bootloader加app的方式,bootloader在一个分区,app在一个分区,bootloader只做app引导以及升级app的。app镜像的下载,不论是通过wifi,lan,2g,4g,蓝牙模块,还是通过串口等通信接口,可以在app里面实现,最后更新到片内flash上,通过bootloader来实现。

 

环境

1. 开发板,正点原子ALIENTEK MiniSTM32 V3.4

2. RTThread for stm32f1xx hal源码,下载地址

https://gitee.com/login?url_to=/rtthread/rt-thread/repository/archive/master.zip

这里试验的BSP为stm32f10x-HAL

3. 试验源码

bootloader:

app:https://download.csdn.net/download/mooney_yuan/10717025

 

bootloader实现原理

将片内flash划分为两个区域,前面为bootloader,后面为app,系统默认复位跳到bootloader执行,在bootloader中跳到app地址。bootloader在编译链接的时候,用默认值就可以了。app在编译链接的时候,需要修改配置rom的起始地址。

在跳转到app的时候,采取的是通过固定地址(中断向量表),读出reset中断服务程序的地址,然后跳转到app的reset中断服务程序,从而完成app启动。

在这个例子中,我们将bootloader的大小为16k,其flash起始地址为 0x08000000。剩余区域为app,flash起始地址为 0x08004000。

跳转的代码如下:

#define ApplicationAddress    0x8004000 //应用程序起始地址

typedef  void (*pFunction)(void);
pFunction JumpToApplication;
uint32_t m_JumpAddress;

static void JumpToApp(void)
{
  if (((*(uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
  {
    DBG("\r\nJump to Application !\r\n");
    /* Jump to user application */
    m_JumpAddress = *(uint32_t*) (ApplicationAddress + 4); //应用程序起始地址偏移4,为reset中断服务程序地址
    JumpToApplication = (pFunction) m_JumpAddress; //将reset中断服务程序地址转换为函数指针

    /* Initialize user application's Stack Pointer */
    __set_MSP(*(uint32_t*) ApplicationAddress);
    JumpToApplication();
  }else{
    DBG("not find APPlication...");
  }
}

 

修改配置rtthread

scons编译方式:

1. 修改bsp目录下的stm32_rom.ld文件,将ROM起始地址改成0x08004000

/* Program Entry, set to mark it as "used" and avoid gc */
MEMORY
{
    CODE (rx) : ORIGIN = 0x08004000, LENGTH = 240k /* 512KB flash */
    DATA (rw) : ORIGIN = 0x20000000, LENGTH =  64k /* 64K sram */
}

2. 修改bsp\stm32f10x-HAL\Libraries\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c,将Vector Table Relocation 偏移设置为0x00004000

#define VECT_TAB_OFFSET  0x00004000U /*!< Vector Table base offset field. 
                                  This value must be a multiple of 0x200. */

keil mdk5编译方式:

1. 打开 “option for target”,将IROM1起始地址设置为0x08004000

STM32F1xx HAL RTThread移值支持Bootloader_第1张图片

2. bsp\stm32f10x-HAL\Libraries\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c文件同上

 

调试过程及问题

刚开始只设置了链接选项(stm32_rom.ld),结果从bootloader跳转到app后,发现rtthread只打印版本信息就死机了。将rthtread的所有调试日志都打开,见如下日志

 \ | /
- RT -     Thread Operating System
 / | \     3.1.1 build Oct 12 2018
 2006 - 2018 Copyright by rt-thread team
start scheduler: max priority 0x20
malloc size 128
thread (NULL) take sem:heap, which value is: 1
thread (NULL) releases sem:heap, which value is: 0
allocate memory at 0x200022dc, size: 140
malloc size 2048
thread (NULL) take sem:heap, which value is: 1
thread (NULL) releases sem:heap, which value is: 0
allocate memory at 0x20002368, size: 2060
startup a thread:main with priority:10
thread resume:  main
insert thread[main], the priority: 10
startup a thread:tidle with priority:31
thread resume:  tidle
insert thread[tidle], the priority: 31

经追踪,在调用 rt_system_scheduler_start 后死住了,推断应该是中断响应是死机了,因此应该是中断向量表地址错误
经查找发现startup之后,在reset中断服务,进行了 SystemInit,在这里进行了中断向量表的初始化。也就是上述 system_stm32f1xx.c 文件,将中断向量表设置为默认地址了。改了这个地方之后就正常了。

以下文章提到的也是这个问题:

https://www.rt-thread.org/qa/forum.php?mod=viewthread&tid=6958&page=1#pid33996

 

你可能感兴趣的:(RTThread)