bootloader 编译为 Debug 无法引导 MS-RTOS 问题_scm402fb

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

一、问题描述

在智芯 SCM402F 芯片上,bootloader 如果按照 Debug 模式编译则无法成功引导 MS-RTOS,反之按照 Release 模式编译则可以正常引导。引导代码如下所示:

static void ms_boot_os(ms_addr_t *addr)
{
    ms_func_t func = (ms_func_t)addr[1U];

    ms_printk(MS_PK_NOTICE, "Start MS-RTOS...\n");
    
    SysTick->CTRL = 0U;
    __asm__ __volatile__ (
            "MOV  R13, %[sp]\n"
            :
            : [sp] "r" (addr[0])
            : "cc");

    func();
}

ms_boot_os() 函数传入 MS-RTOS 镜像基址 addr,基址指向向量表,向量表第一位是栈顶地址,第二位为复位入口。代码中首先保存 addr[1] 即复位入口到变量 func 中,再使用一段嵌入汇编将 R13(SP) 赋值为 addr[0]。最后调用 func(),即跳转到 MS-RTOS 的复位入口处。

二、问题分析

上述在逻辑上有一个很大的问题,我们先看一下 Debug 模式下的反汇编代码:

static void ms_boot_os(ms_addr_t *addr)
{
 8007100:	b500      	push	{lr}
 8007102:	b085      	sub	sp, #20
 8007104:	9001      	str	r0, [sp, #4]
    ms_func_t func = (ms_func_t)addr[1U];
 8007106:	9b01      	ldr	r3, [sp, #4]
 8007108:	3304      	adds	r3, #4
 800710a:	681b      	ldr	r3, [r3, #0]
 800710c:	9303      	str	r3, [sp, #12]

    ms_printk(MS_PK_NOTICE, "Start SW-RTOS...\n");
 800710e:	4908      	ldr	r1, [pc, #32]	; (8007130 <ms_boot_os+0x30>)
 8007110:	2005      	movs	r0, #5
 8007112:	f000 fc6d 	bl	80079f0 <ms_printk>

    /*
     * Disable system tick
     */
    SysTick->CTRL = 0U;
 8007116:	4b07      	ldr	r3, [pc, #28]	; (8007134 <ms_boot_os+0x34>)
 8007118:	2200      	movs	r2, #0
 800711a:	601a      	str	r2, [r3, #0]

    __asm__ __volatile__ (
            "MOV  R13, %[sp]\n"
            :
            : [sp] "r" (addr[0])
 800711c:	9b01      	ldr	r3, [sp, #4]
 800711e:	681b      	ldr	r3, [r3, #0]
    __asm__ __volatile__ (
 8007120:	469d      	mov	sp, r3
            : "cc");

    func();
 8007122:	9b03      	ldr	r3, [sp, #12]
 8007124:	4798      	blx	r3
}

在这段代码的最后,首先读取变量 func 的值到 r3,然后使用 blx 跳转到 r3 中保存的地址。这里因为 func 是局部变量,使用 SP 指针加偏移的方式获取 func 的值,但是在上一步中已经改变了 SP 的值,因此这里无法正确获取 func 变量的值。所以无法成功引导 MS-RTOS,如下图所示。

分析了 Debug 版本下无法引导的原因后又引出了另一个问题,为什么 Release 可以成功引导呢?同样我们先看一下 Release 模式下的反汇编:

   ms_func_t func = (ms_func_t)addr[1U];
 800445e:	4c1b      	ldr	r4, [pc, #108]	; (80044cc <main+0x3a4>)
    ms_printk(MS_PK_NOTICE, "Start SW-RTOS...\n");
 8004460:	4f1b      	ldr	r7, [pc, #108]	; (80044d0 <main+0x3a8>)
    SysTick->CTRL = 0U;
 8004462:	4e1c      	ldr	r6, [pc, #112]	; (80044d4 <main+0x3ac>)
    ms_func_t func = (ms_func_t)addr[1U];
 8004464:	6865      	ldr	r5, [r4, #4]
    ms_printk(MS_PK_NOTICE, "Start SW-RTOS...\n");
 8004466:	4639      	mov	r1, r7


**收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。**
![img](https://img-blog.csdnimg.cn/img_convert/e4ef5b05ec06805b4ef6d50a04cdf1ca.png)
![img](https://img-blog.csdnimg.cn/img_convert/85b546226d07f872528cfc281445ab7e.png)

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人**

**都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

1024c (备注嵌入式)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人**

**都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值