收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
需要这些体系化资料的朋友,可以加我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行业感兴趣的新人**
**都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**