为什么从BootLoader跳转到APP后,在执行f_mount()函数时disk.drv[0] 的指针会跳转到BootLoad 的区域呢

为什么从BootLoader跳转到APP后,在执行f_mount()函数时disk.drv[0] 的指针会跳转到BootLoad 的区域呢?如下图
在BootLoader程序也执行了相同的操作,没出现上述问题。

img

这是正确的地址

img

这是执行到绿色高亮处后,地址发生了跳变。

@小胡同志和小张老师的故事 您好!谢谢您的解答。
这是BootLoader 跳转的程序,里面已经做了栈的切换。


```c
void up_load_app(struct _UPDATE *update)  //0x08020000
{
    if(((*(uint32_t*)update->appxaddr)&0x2FFE0000)==0x20000000)    //检查栈顶地址是否合法.
    {
        jump2app=(iapfun)*(uint32_t*)(update->appxaddr+4);        //用户代码区第二个字为程序开始地址(复位地址)

        __set_PRIMASK(1);

        //初始化用户程序的堆栈指针
        __set_PSP(*(__IO uint32_t*) update->appxaddr);      //重新设置进程PSP堆栈地址
        __set_CONTROL(0);                                       //设置为MSP
        __set_MSP(*(__IO uint32_t*) update->appxaddr);
//        MSR_MSP(*(uint32_t*)update->appxaddr);                             //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
        INTX_DISABLE();
        jump2app();                                                                    //跳转到APP.
    }
}

```

谢谢各位给出的建议,目前问题还未解决。由于项目紧急,选择了其他方案,日后解决我再分享解决办法。
再次感谢各位!!!

这可能是由于在从 BootLoader 跳转到 APP 后,未正确切换栈。在跳转之前和之后,栈指针的值需要被恢复到正确的位置。如果栈指针未被正确切换,那么在调用函数时,函数所使用的栈空间将与预期的不同,也就会出现各种异常情况,例如你提到的disk.drv[0]指针跳转到Bootloader区域的情况。

在 BootLoader 和 APP 中定义的栈指针应该是互相独立的,需要在跳转时另外设置栈指针以供 APP 使用。当 APP 程序入口执行时,它需要将栈指针移动到正确的位置,并将所有寄存器初始化为正确的值。通常情况下,栈指针应该指向 RAM 区域,并且最好在 RAM 区域中已经预留出一段大小足够的空间。此外,为了避免 APP 程序因为栈溢出而崩溃,通常还需要定义一个栈空间大小的全局变量,并在 APP 中使用 __check_stack 函数检查栈空间是否足够。

另外,在从 BootLoader 跳转到 APP 时,需要确保 APP 的代码和数据的地址与 BootLoader 不重复。如果有重复,那么调用同样的名称或变量时,就会出现未定义的行为。

这可能是因为在执行跳转操作时,未正确修改相关指针导致的。建议在跳转时仔细检查和修改相关指针,确保跳转后指向正确的地址。另外,也可以参考 BootLoader 程序的相关代码,查找其中的差异并进行比较。

这种情况可能是由于在从BootLoader跳转到APP时,没有正确地初始化或切换硬件环境导致的。如果在BootLoader和APP之间使用了共享内存或共享硬件资源,可能会导致指针跳转到错误的内存区域。

在执行f_mount()函数时,该函数需要访问磁盘驱动器的数据结构,通常是通过一个指向该数据结构的指针进行访问。如果该指针指向错误的内存区域,可能会导致函数执行错误或崩溃。

为了解决这个问题,您可以尝试以下方法:

确保在从BootLoader跳转到APP时,正确地初始化硬件环境,并正确地切换到APP的运行环境。

确保在BootLoader和APP之间不共享内存或共享硬件资源,或者在共享时确保正确地进行同步和互斥操作。

确保在执行f_mount()函数之前,正确地初始化磁盘驱动器的数据结构,并确保磁盘驱动器的数据结构在APP的内存区域中。

如果问题仍然存在,可以使用调试器或打印调试信息来确定指针跳转到错误的内存区域的原因。检查指针的值以及指针所指向的内存区域是否正确,以便找到问题所在。

可以借鉴下

1.无论在bootloader跳转到app还是在app跳转到bootloader时都不能在中断中跳转,因为这样导致跳转后app程序还是在中断状态,如果app或bootloader中再次使能了该中断的时钟,那么可能就跑硬件中断了

2.如果app使用了ucos系统,在app跳转到bootloader时要使用__set_CONTROL(0);//把psp修改成msp,因为ucos会把msp变成psp,如果跳转的时候不重新置回msp可能就会出现硬件中断,查看当前程序是msp还是psp可以在仿真程序时的左边框框的register面板中打开bank选项看control是0还是2,0为msp,2为psp


在 Android 系统中,启动过程主要分为三个阶段:Bootloader、Kernel、System。其中,Bootloader 是一个位于存储设备(如 SD 卡)的独立程序,用于完成设备的初始化工作,包括检测硬件、加载 Bootloader、执行 Bootloader 中的代码等。

具体来说,当设备上电后,首先会运行 Bootloader。在 Bootloader 中,会读取系统分区的 Image 文件(即内核镜像),并将该 Image 文件写入到 RAM 中。然后,Bootloader 会跳转到 Image 文件所在的地址,并执行其中的 f_mount() 函数,将系统分区挂载到内存中。

在执行 f_mount() 函数时,Bootloader 会使用一个指向磁盘驱动器的指针(disk.drv[0])来访问系统分区。由于这个指针是在 Bootloader 中定义的,因此它指向的是 Bootloader 所在的区域,而不是内核镜像所在的区域。

当内核镜像被加载到 RAM 中后,Kernel 会接管这个指针,并将其指向内核镜像所在的区域。这样,在接下来的启动过程中,操作系统就可以使用这个指针来访问内核镜像了。

可以借鉴下

1、keil烧录Bootloader,烧录APP1,烧录APP2
2、跳转到APP1执行正常,跳转到APP2执行正常
3、执行APP2拷贝到APP1
4、跳转到APP1执行失败
5、重新通过KEIL烧录APP2到APP2区域
6、跳转到APP1执行成功

以上是调试现象,通过调试发现
1、通过调试发现,APP2拷贝到APP1后,两个区域数据是完全一致的,那么拷贝过程错误排除
2、通过现象2发现,跳转到APP1执行正常,跳转到APP2执行正常,跳转功能错误排除
3、通过现象56发现,APP1执行正常的前提是重新通过KEIL烧录APP2到APP2区域,那么问题就出在这了。

问题解析:
我在网上找参考资料时,Bootloader和APP1都是直接通过KEIL烧录到MCU的,区别在于Bootloader的keil的设置中,ROM起始地址是0x08000000,APP1起始地址是0x08010000,那么我在编译APP2时,自然就把APP2的ROM起始地址设为0x08040000了,这样问题就出现了。

APP2拷贝到APP1区域后,通过调试发现memory区域的数据,0x08010000开头的数据都是0x08040000,这导致程序执行首先去0x08040000寻找了,但是0x08040000已经被我擦除了,所以肯定无法执行了,然后当我通过KEIL再次下载到APP2区域后,那么再跳转到APP1后,自然就能执行了

所以解决的方法是调试时,APP2的固件keil编译时依旧rom设置为0x08010000,但是固件通过STM32 ST-LINK Utility下载到0x08040000中,这样整个问题就解决了


  1. 内存映射问题:在内存映射方面,BootLoader和APP通常有不同的内存布局和映射方式,因此在跳转到APP后可能需要重新映射内存。如果没有正确设置内存映射或者切换内存映射失败,就可能会导致在执行f_mount()函数时disk.drv[0]指针跳转到了错误的内存地址。
  2. 系统调用问题:在跳转到APP后,可能需要重新设置系统调用,例如在ARM Cortex-M系列处理器中,App和BootLoader通常有不同的中断向量表和系统调用表。如果没有正确设置系统调用或者切换系统调用失败,就可能会导致在执行f_mount()函数时disk.drv[0]指针跳转到了错误的内存地址。
  3. 程序逻辑问题:在执行f_mount()函数时,可能有一些程序逻辑没有正确处理。例如,如果在跳转到APP后没有正确初始化或者清除一些变量或寄存器,就可能会导致在执行f_mount()函数时disk.drv[0]指针跳转到了错误的内存地址。

针对这些问题,您可以尝试以下方法:

  1. 确保正确设置内存映射和系统调用,特别是在切换从BootLoader到APP时。
  2. 确保在跳转到APP后正确初始化和清除变量和寄存器。
  3. 检查并调试f_mount()函数的实现,特别是与磁盘驱动器相关的部分,以确定其是否存在逻辑错误。
  4. 如果可能的话,尝试使用调试器等工具来跟踪和定位问题的根本原因。

有没有可能是栈溢出了,导致了该问题~

可能是因为在跳转到APP后,某些数据没有被正确初始化或更新,导致指针指向了错误的区域。在BootLoader程序中没有出现此问题可能是因为此时系统还没有跳转到APP,数据初始化和更新的过程还没有发生,因此指针没有被错误地修改。

检查在跳转到APP后的初始化代码,确认数据被正确初始化和更新,特别是和disk.drv[0]有关的数据。