2017-03-28 15 views
0

私はstil32f4ボードのフラッシュメモリにkeil uvisionを使用して他のプログラムをフラッシュする標準コードを使用しています。私は私のボードに両方のコードを持っている必要があります。しかし、プログラムカウンターをある場所から別の場所に移して、必要に応じて両方のプログラムを実行するにはどうしたらいいですか?
以下は私が使用しているコードですが、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 
+0

通常、割り込みベクタを使用して通信します。多くのコントローラは、一時的なベクタテーブルをRAMにマッピングして、ブート/フラッシュローダを容易にします。 – ThingyWotsit

+0

http://stackoverflow.com/questions/26891432/jump-to-bootloader-in-stm32-through-appliction-ie-using-boot-0-and-boot-1-pinsの可能な複製 –

答えて

0
.global BRANCHTO 
BRANCHTO: 
    bx r0 

EDIT

(劣らず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:LRがBRANCHTOにBLによって処理され

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 

、branchtoはちょうど尾の最適化ですそれだけでそこにlrを押してブランチリンクを押してからポップしてから戻ることは無駄になります。

インラインアセンブリーとしてブランチを実装できますが、インラインアセンブリーは一般的に非常に醜いですが、ポータブルではなく、実際のアセンブリーははるかに優れていますし、コンパイラーに直接フィードすることもできますそれはあなたがアセンブラを呼び出す方法を知らない場合です。私はWindowsをほとんど実行していないので、キールを私が好きかもしれないほどインストールしてはいけません(彼らは遊びに面白いRVCTコンパイラを使用していました)。

+1

このコードスニペット[説明を含む](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers)の質問は、あなたの投稿の質を向上させるのに本当に役立ちます。将来読者の質問に答えていることを覚えておいてください。そうした人々はあなたのコード提案の理由を知らないかもしれません。 –

+0

これはうまくいくが、問題はCとアセンブラではなく関数ポインタを使うことである。動作は少し異なります。関数ポインタを呼び出すとブランチとリンクが作成されますが、あなたのバージョンは 'LR'を更新しません。 –

+0

CからBRANCHTOを呼び出すと、LRを設定して戻りますが、問題はありません。 C言語でアセンブリ言語にコンパイルした後、オブジェクトにアセンブルされます。必要なものを正確に取得する最もクリーンな方法は、ステップをスキップしてアセンブラに直接移動することです。 Cでこれを行うには、ダミーvoid関数を作成し、アドレスを変更してから呼び出します。 –

関連する問題