跳转程序计数器到新位置

时间:2017-03-28 18:10:16

标签: c arm keil

我使用标准代码使用keil uvision将其他程序闪存到我的stm32f4板的闪存中。我需要在我的电路板上都有这两个代码。但是,如何将我的程序计数器从一个位置转移到另一个位置,以便在需要时执行这两个程序 下面是我正在使用的代码片段,但PC没有跳跃。我认为跳转到应用程序存在问题

#include "usbh_core.h"
#include "usbh_usr.h"
#include "usbh_msc_core.h"
#include "flash_if.h"

USB_OTG_CORE_HANDLE          USB_OTG_Core;
USBH_HOST                    USB_Host;

pFunction Jump_To_Application;
uint32_t JumpAddress;


int main(void)
{

BSP_Init();


FLASH_If_FlashUnlock();



if (STM_EVAL_PBGetState(BUTTON_USER) == Bit_RESET)
{
/* Check Vector Table: Test if user code is programmed starting from address 
   "APPLICATION_ADDRESS" */
 if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
  /* Jump to user application */
  JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
  Jump_To_Application = (pFunction) JumpAddress;
  /* Initialize user application's Stack Pointer */
 __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
         __set_PSP(*(__IO uint32_t*) APPLICATION_ADDRESS);

  Jump_To_Application();
}
}

  /* Init Host Library */
 USBH_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USB_Host, &USBH_MSC_cb, &USR_Callbacks);

while (1)
 {
   /* Host Task handler */
    USBH_Process(&USB_OTG_Core, &USB_Host);
 }
}


 #ifdef USE_FULL_ASSERT
    void assert_failed(uint8_t* file, uint32_t line)
   {

    /* Infinite loop */
    while (1)
     {}
    }
     #endif

1 个答案:

答案 0 :(得分:0)

.global BRANCHTO
BRANCHTO:
   bx r0

修改

几秒钟谷歌搜索发现函数指针基础知识(在StackOverflow不低于)

void (*funadd) ( void );
void fun ( void )
{
    funadd=(void *)0x12345678;
    (*funadd)();
}

00000000 <fun>:
   0:   e59f2008    ldr r2, [pc, #8]    ; 10 <fun+0x10>
   4:   e59f1008    ldr r1, [pc, #8]    ; 14 <fun+0x14>
   8:   e5821000    str r1, [r2]
   c:   e12fff11    bx  r1
  10:   00000000    andeq   r0, r0, r0
  14:   12345678    eorsne  r5, r4, #120, 12    ; 0x7800000

作为我的汇编函数显示同样的事情(基本上是尾部优化)

但是如果你想看到它设置一个返回地址,那么你必须强制

unsigned int (*funadd) ( void );
unsigned int fun ( void )
{
    funadd=(unsigned int *)0x12345678;
    return((*funadd)()+1);
}

00000000 <fun>:
   0:   e59f201c    ldr r2, [pc, #28]   ; 24 <fun+0x24>
   4:   e59f101c    ldr r1, [pc, #28]   ; 28 <fun+0x28>
   8:   e92d4010    push    {r4, lr}
   c:   e5821000    str r1, [r2]
  10:   e1a0e00f    mov lr, pc
  14:   e12fff11    bx  r1
  18:   e8bd4010    pop {r4, lr}
  1c:   e2800001    add r0, r0, #1
  20:   e12fff1e    bx  lr
  24:   00000000    andeq   r0, r0, r0
  28:   12345678    eorsne  r5, r4, #120, 12    ; 0x7800000

EDIT2:

void BRANCHTO ( unsigned int );
void fun ( void )
{
    BRANCHTO(0x12345678);
}

00000000 <fun>:
   0:   e92d4010    push    {r4, lr}
   4:   e59f0008    ldr r0, [pc, #8]    ; 14 <fun+0x14>
   8:   ebfffffe    bl  0 <BRANCHTO>
   c:   e8bd4010    pop {r4, lr}
  10:   e12fff1e    bx  lr
  14:   12345678    eorsne  r5, r4, #120, 12    ; 0x7800000

LR由BLANCHTO处理,分支机构只是一个尾部优化传递,只是浪费推动lr那里和分支链接然后返回然后弹出然后返回。

可以将分支实现为内联汇编,但内联汇编通常非常难看,不是可移植的,只是乱七八糟,真正的汇编更加优越,还有一些工具链可以让你直接将它提供给编译器是一个你不知道如何调用汇编程序的情况。我几乎从不运行Windows,所以没有像我想的那样安装Kiel(它们曾经包含一个减少的RVCT编译器,这将很有趣)。

相关问题