STM32 板上的多个项目(或图像)

问题描述 投票:0回答:1

我来这里是想问一些有关我的项目的问题。

现在我正在实现一个精简版虚拟机管理程序。

所以我做了三个独立的项目(monitor.bin,OS1.bin,OS2.bin),并划分了内存。

MEMORY
{
  CCMRAM    (xrw)    : ORIGIN = 0x10000000,   LENGTH = 64K
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 32K
  FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH = 128K
  RAM1    (xrw)    : ORIGIN = 0x20008000,   LENGTH = 32K
  FLASH1    (rx)    : ORIGIN = 0x8020000,   LENGTH = 128K
  RAM2    (xrw)    : ORIGIN = 0x20010000,   LENGTH = 32K
  FLASH2    (rx)    : ORIGIN = 0x8040000,   LENGTH = 128K
}
// the part I revised in linker script file for monitor.bin, STM32F407VGTX_RAM.ld, STM32F407VGTX_FLASH.ld
MEMORY
{
  CCMRAM    (xrw)    : ORIGIN = 0x10000000,   LENGTH = 64K
  RAM    (xrw)    : ORIGIN = 0x20008000,   LENGTH = 32K
  FLASH    (rx)    : ORIGIN = 0x8020000,   LENGTH = 128K
}
// the part I revised in linker script file for OS1.bin, STM32F407VGTX_RAM.ld, STM32F407VGTX_FLASH.ld.
// In case of OS2.bin, RAM ORIGIN = 0x20010000, FLASH ORIGIN = 0x08040000

并且我修改了每个项目中中断的矢量偏移部分。

#define USER_VECT_TAB_ADDRESS

#if defined(USER_VECT_TAB_ADDRESS)
/*!< Uncomment the following line if you need to relocate your vector Table
     in Sram else user remap will be done in Flash. */
/*#define VECT_TAB_SRAM*/
#if defined(VECT_TAB_SRAM)
#define VECT_TAB_BASE_ADDRESS   SRAM_BASE       /*!< Vector Table base address field.
                                                     This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET         0x00000000U     /*!< Vector Table base offset field.
                                                     This value must be a multiple of 0x200. */
#else
#define VECT_TAB_BASE_ADDRESS   FLASH_BASE      /*!< Vector Table base address field.
                                                     This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET         0x00020000U     /*!< Vector Table base offset field.
                                                     This value must be a multiple of 0x200. */
#endif /* VECT_TAB_SRAM */
#endif /* USER_VECT_TAB_ADDRESS */

// this is for OS1.bin
// In case for OS2.bin, OFFSET WAS 0x00040000U

经过修改至此,每个项目都被确认运行良好。

但我想做的是实现从监视器跳转到OS1和OS2。

所以我修改了一些代码,但是当我将程序计数器设置为OS1、OS2时,它不起作用。

int main (void) {

    clk();

    RCC->CFGR |= 0x04600000;
    while(1) {
        if(os1 == 0){
            if(os1_first == 1){
                os1 = 1;
                os1_first = 0;
                SCB->VTOR = (uint32_t) 0x8020000;
                __set_MSP(0x20010000);
                __set_PSP(0x20010000);
                asm("BX %0" ::"r"(0x8020000));
            }
            else{
                SCB->VTOR = (uint32_t) 0x8020000;
                __set_MSP(0x20010000);
                __set_PSP(0x20010000);
            }
        }
        else{
            if(os2_first == 1){
                os1 = 0;
                os2_first = 0;
                SCB->VTOR = (uint32_t) 0x8040000;
                __set_MSP(0x20018000);
                __set_PSP(0x20018000);
                asm("BX %0" ::"r"(0x8040000));
            }
            else{

            }
        }
    }
}
// main.c for monitor
int main (void) {

    clk();
        //GPIO, Timer Interrupt init part omitted
    while(1) {
        if(jump_monitor == 1){
            jump_monitor = 0;
            __set_MSP(0x20000000);
            __set_PSP(0x20000000);
            asm("BX %0" ::"r"(0x8000000));
        }
    }
}

void TIM2_IRQHandler() {
    TIM2->SR = 0;
    GPIOD->ODR ^= (1<<13);
    if(first == 1){
        first = 0;
    }
    else{
        jump_monitor = 1;
    }
}

main.c for OS1.bin

我想要的代码流程如下。

监控 -> OS1(2秒左右) -> 监控 -> OS2(2秒左右) -> 监控....

但是每次我尝试使用 asm("BX") 更改程序计数器时,都会陷入硬故障。

我认为我想要的行为与bootloader的行为类似,所以我对bootloader做了一些参考。

我思考了问题的可能性。

  1. 在内存中加载项目时出现问题

:在STM32CUBEIDE中,我在“运行配置”-“启动”选项卡中使用了加载图像和符号,但不起作用。

:所以我使用了STM32CubeProgrammer,并在下载选项卡中选中了“编程前跳过闪存擦除”选项。 并加载三个二进制文件(monitor.bin、OS1.bin、OS2.bin),并修改起始地址。

  1. 设置程序计数器之前的问题

:我在设置程序计数器值之前设置了SCB->VTOR、MSP、PSP。 但是在设置程序计数器之前还需要设置什么吗?

:我检查了引导加载程序代码,发现它们在跳转到应用程序之前设置了 VTOR、MSP、PSP 值。

:我认为跳转到应用程序的起始地址可以使执行工作,从启动代码到 main.c 。

我写的时候问题有点长,有人能回答吗?

我想从monitor.bin跳转到OS1.bin和OS2.bin

监视器.bin RAM 起始地址:0x20000000 闪存起始地址:0x08000000

OS1.bin 内存起始地址:0x20008000 闪存起始地址:0x08020000

OS1.bin 内存起始地址:0x20010000 闪存起始地址:0x08040000

arm stm32 bootloader hypervisor
1个回答
0
投票

我解决了。但我不太明白这个机制。

我没有使用BX(通过内联汇编跳转到应用程序),而是使用函数指针到达地址,然后发生跳转。

使用函数指针和使用内联汇编到达地址有什么区别?

© www.soinside.com 2019 - 2024. All rights reserved.