2012-01-26 7 views
2

私はAdaに埋め込みコードを書いています。私はアドレス0x0E00にあるブートローダコードにジャンプしたい。Adaでブートローダにジャンプするには?

with Interfaces; use Interfaces; 
with System; 

package AVR.bootloader is 

    procedure Call; 
    pragma No_Return(Call); 
    pragma Import (Assembler,Call); 
    for Call'Address use System'To_Address (16#0E00#); 

end AVR.bootloader; 

問題は、これが動作しないです:私は、次のコードを使用しようとしています。

編集:私は、次のC相当をしたい:

void (*boot)(void)=0x0E00; 
+1

永遠の質問:**どのように "機能しません"?** –

+0

1.それを行うには? 2.それはどのように機能しませんか? 3.私はそれについて考えなかった可能性がありますか?プラグマに問題があると思います。インポートには何もリンクされていません。 –

+0

「どうしてうまくいかないの?」という意味は:試してみたときに何が起こったのですか? –

答えて

2

私はこのMacBook Proで小さな実験を行いました。あなたのコードは、あなたがそれを意味するように思えます。私は

with System; 

procedure Bootloader is 

    procedure Call; 
    pragma No_Return (Call); 
    pragma Import (Assembler, Call); 
    for Call'Address use System'To_Address (16#0E00#); 

begin 
    Call; 
end Bootloader; 

を読み取るために、コードを変更し、私はgnatmake -c -u -f -S bootloader.adbでコンパイルするときに保存アセンブラは、私が知っているASMで十分慣れていないんですけれども、有望に見える

 .text 
     .globl __ada_bootloader 
__ada_bootloader: 
LFB1: 
     pushq %rbp 
LCFI0: 
     movq %rsp, %rbp 
LCFI1: 
     subq $16, %rsp 
LCFI2: 
     movq $3584, -8(%rbp) 
     movq -8(%rbp), %rax 
     call *%rax 
     leave 
LCFI3: 
     ret 
[...] 

です。私が手GDBの下でそれを実行

(後のおしゃべりのロット)、より希望に満ち見えます

(gdb) run 
Starting program: /Users/simon/tmp/bootloader 
Reading symbols for shared libraries ++........................ done 

Program received signal EXC_BAD_ACCESS, Could not access memory. 
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000e00 
0x0000000000000e00 in ??() 
(gdb) bt 
#0 0x0000000000000e00 in ??() 
Cannot access memory at address 0xe00 
#1 0x0000000100000d93 in main (argc=1, argv=140734799805048, envp=140734799805064) at /Users/simon/tmp/b~bootloader.adb:121 
#2 0x0000000100000bf4 in start() 

おそらくあなたのAVRコンパイラはコード生成が適切ではありませんか?

+0

されました: LDS \t R30、0000 LDS \t R31、0000 icall 私はクリーンな環境(仮想システム、のみGNAT)をインストールし、今で動作するようです!奇妙ですが、問題は解決しました。本当に助けてくれた実験に感謝します。 –

+0

これらの '0x0000'のうちの1つが' 0x0e00'である必要があると思います!今はOKです。 –

2

通常、ブートローダーはリセット時に実行されるため、最も簡単な方法は、プロセッサのリセットを強制することです。ブートローダは、リセット状態で初期化されていないシステムで実行されていると想定し、すでに初期化されているシステムでは無効な初期化を実行する可能性があるため、リセットを強制するのが最も安全です。

お使いのプロセッサには、これを直接実行できるリセット命令またはリセットコントローラがある場合があります。ウォッチドッグタイマがリセットを生成する可能性があります。適切に短いタイムアウトでウォッチドッグタイマーを開始し、ウォッチドッグタイマーを処理せずに実行させます。

+0

私は現在ウォッチドッグを使用していますが、この解決策は私を満足させません。私はリセット時にブートローダを無効にして、メインプログラム内から呼び出す必要があります。ブートローダーは、正しく動作するためには特定のアドレスに配置する必要があります。私はインラインアセンブリを書くことを避け、清潔なソリューションに固執したいと思います。 –

+0

私はちょっと無知なのに申し訳ありませんが、ブートローダーを最初に実行しなくてもメインプログラムにどうやって行くつもりですか?ブートローダ*はリセット時に実行されません。そうしないと、システムはロードされません。あなたの質問にあなたが達成しようとしていたことを説明できますか?私はあなたが答えを受け入れたことを知っている、私はちょうどそれをよりよく理解したいと思います。 – Anthony

+0

多くのシステムでは、ブートローダがシステムメモリを何らかの外部メモリからオペレーティングメモリにロードしています。私の場合、私は単純な組み込みシステムを持っています。このシステムでは、ブートローダを使って不揮発性のプログラムメモリ(同じ名前で少し異なる機能)をプログラムします。メインループに入るのに時間がかかるので、私はリセットごとにブートローダーを実行したくありません。デバイスがハングアップしても、デバイスは中断されるべきプロセスを駆動します。このような状況では、ウォッチドッグはリセットを引き起こします。それでも私は物理的なアクセスなしでそれをプログラムしたい。 –

関連する問題