2017-11-14 13 views
2

私はAdaCore GPS(GPL)IDEを使用して、ARM "ベアボード"ハードウェア(Ravenscar SFPランタイムを使用するSTM32F4)を対象としたGNATコンパイラを使用してAdaを学習中です。Ada Last_Chance_Handlerに例外メッセージを出力する

私のARMベースの埋め込み作業では、私はC/C++バックグラウンドから来ています。

とにかく、私は次のように定義されています "最後のチャンスハンドラ"、ここで

procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); 
pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); 

は、実際の手順( .adbファイルから抜粋)だ、

procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is 
begin 
    LEDs_All_On; 
    -- Put_Line("Detail :" & Address_To_String(Msg)); 
    Put_Line("Line :" & Line'Image); 

    loop 
     null; 
    end loop; 
end Last_Chance_Handler; 

Msgを実装しました引数は次のように文書化されています。

MsgパラメータはCのNULLで終了する文字列ですプラグインSuppress_Exception_Locationsが である場合は、 のraise文のソース位置をコンパイラによって生成された または長さゼロの文字列で表します。

私は私がセミホスティングを介して出力のこのタイプにアクセスすることができますデバッグするとき、それは(Put_Line()コールを使用して表示できるようにエイダ列にnull終了Msgバイトを変換する方法を把握しようとしてきました機構)。

私は以前に、'Address属性を一定値に設定することによって、デバイス・レジスタを表すAdaレコードを物理メモリー・アドレスにマップしました。しかし、変数に保持されているSystem.Addressの値を使ってアクセスメモリを試したのは初めてです。

Address_To_String()手順の実装方法については、誰でもお勧めできますか?

私はAdaバイト配列とそれらととの間のチェックされていないコンバージョンを実験しましたが、Adaポインタもありましたが、これまでのところ成功しませんでした。

ご意見やご提案は大変ありがとうございます。

多くのおかげで、

...マックス

答えて

2

あなたがlast_chance_handlerに来たら、おそらく何かが壊れていて、あなたの環境にあまり依存しすぎてはいけません。 Ada.Text_IOは非常に重いパッケージです。一般的に、特にここでは避けてください。

あなたはこのような何かを試みることができる:返信用

with GNAT.IO; 
with System.Storage_Elements; 
procedure Last_Chance_Handler 
    (Msg : System.Address; Line : Integer) 
is 
    use System.Storage_Elements; -- make "+" visible for System.Address 

    function Peek (Addr : System.Address) return Character 
    is 
     C : Character with Address => Addr; 
    begin 
     return C; 
    end Peek; 
    A : System.Address := Msg; 
begin 
    GNAT.IO.Put ("line :"); 
    GNAT.IO.Put (line); -- avoid the secondary stack for Line'Image 
    GNAT.IO.New_Line; 
    while Peek(A) /= ASCII.NUL loop 
     GNAT.IO.Put (Peek(A)); 
     A := A + 1; 
    end loop; 
    GNAT.IO.New_Line; 
end; 
+0

ニース!私は同様のアプローチを思いついたので、 'System.Address'を' Integer_Address'にキャストするために 'To_Integer()'を使い、 'Unchecked_Conversion'を使ってこれを' Character'ポインタなどに変換しました。コードははるかにクリーンです!私はオンボードUARTの1つを使用する独自のバージョンのPut()とPut_Line()を書きました(私はSTM32F407ベアボードターゲットで開発中です)。私は最終的に私自身の「ゼロフットプリント」ランタイムを使いたいので、とにかくこれらが必要でした。私は多くの面白いことを学んでいます。 –

+0

MaxはAdaCoreのベアボードランタイムの1つを使用していますが、Ada.Text_IOは非常に単純化されています(GNAT.IOと同じ場所で終了します)。そして、これはPut_Lineを呼び出すよりもどのように優れていますか?この方法で、文字化けしたテキストでMaxの問題が取り除かれた場合、非常に奇妙なことが起こっています。 –

+0

Ravenscar RTSは、どのようなRTS Maxを使用しているのか分かりませんでした。 GNAT.IOは整数の印刷を直接サポートしています。彼は、私がここで避けたい、セカンダリスタックを必要とするImage属性を使用します。私のバージョンでは、0の終了文字列のC知識を直接使用しています。 Put_Lineを使用する場合は、最初にゼロ終了文字列をAda文字列に変換し、最後にC形式で印刷する必要があります。 – RREE

2

あなたが探している操作は、おそらくInterfaces.C.Strings.Valueです。それはタイプInterfaces.C.Strings.chars_ptr(Cではchar *に相当)の引数をとり、Stringを返します。

+0

感謝を。 –

+0

ほぼ完璧に動作しましたが、出力が文字化けして、恐らくエンコードの問題であると、私は調査を続けます。また、 'Interfaces.C.Strings'パッケージはRavenscarの「完全な」実行時にのみ利用可能です。私は「sfp」を使用したいと考えていました。私はおそらくどこかでコードをつかむことができます。 –

2

は、念のために、それはあなたが

with Interfaces.C.Strings; 
procedure Last_Chance_Handler 
    (Msg : Interfaces.C.Strings.chars_ptr; Line : Integer); 

を念頭に置いてMsgの文書の記述をもつ宣言するために自由に完璧だ、Jacob’s answerから明確ではなかったです。

+0

それは役に立ちました、私に起こっていなかった、それを試みます。ありがとう。 –

+0

そのタイプ定義を使用するとコードが単純化されましたが、コンソールで文字化けした文字列が残っています。私はそれがRavenscarのランタイムに関係しているのだろうかと思っています。 –