2017-11-14 1 views
2

Ich lerne gerade Ada mit dem GNAT-Compiler unter Verwendung der AdaCore GPS (GPL) IDE, gerichtet auf ARM "bare board" Hardware (STM32F4 mit einer Ravenscar SFP Runtime).Drucken der Ausnahmebedingungsnachricht in einem Ada Last_Chance_Handler

Für meine ARM-basierte eingebettete Arbeit komme ich aus einem C/C++ - Hintergrund.

Auf jeden Fall habe ich eine "letzte Chance Handler" implementiert, die wie folgt definiert ist,

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

Hier ist das eigentliche Verfahren (ein Ausschnitt aus der .adb-Datei),

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; 

Die Msg Das Argument wird wie folgt dokumentiert:

Der Parameter Msg ist eine C-Null-terminierte Zeichenfolge Darstellung des Quellorts der Raise-Anweisung, wie vom Compiler generiert, oder einer Nulllänge, wenn pragma Suppress_Exception_Locations verwendet wird.

Ich habe versucht, herauszufinden, wie man das null beenden Msg Bytes zu einem Ada-String zu konvertieren, so dass ich es anzeigen kann einen Put_Line() Anruf mit (beim Debuggen ich diese Art von Ausgabe über das semihosting zugreifen Mechanismus).

Ich habe zuvor Ada-Datensätze (die Geräteregister usw. darstellen) physikalischen Speicheradressen zugeordnet, indem Sie ihr 'Address-Attribut auf einen konstanten Wert setzen. Dies ist jedoch das erste Mal, dass ich über einen System.Address Wert, der in einer Variablen gespeichert ist, auf den Arbeitsspeicher zugegriffen habe.

Kann jemand vorschlagen, wie ich über die Implementierung der Address_To_String() Prozedur gehen könnte?

Ich habe mit Ada-Byte-Arrays und ungeprüften Konvertierungen zwischen ihnen und System.Address, auch mit Ada-Zeigern, experimentiert, aber bisher hatte ich keinen Erfolg.

Jede Hilfe oder Vorschläge würden sehr geschätzt werden!

Vielen Dank,

... Max

Antwort

2

Wenn Sie zu einem last_chance_handler kommen, ist wahrscheinlich etwas kaputt und Sie sollten sich nicht zu sehr auf Ihre Umgebung verlassen. Ada.Text_IO ist ein sehr schweres Paket. Sie sollten versuchen, es generell und besonders hier zu vermeiden.

Man könnte so etwas wie dies versuchen:

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

Schön! Ich hatte eine ähnliche Herangehensweise, ich benutzte 'To_Integer()', um die 'System.Address' zu einer' Integer_Address' zu transformieren und benutzte dann eine 'Unchecked_Conversion', um diese in einen' Character' Zeiger usw. umzuwandeln Code ist viel sauberer! Ich habe auch meine eigenen Versionen von 'Put()' und 'Put_Line()' geschrieben, die einen der integrierten UARTs verwenden (ich entwickle auf einem STM32F407-Board-Target). Ich brauchte diese sowieso, schließlich möchte ich meine eigene "Null-Fußabdruck" -Laufzeit verwenden. Ich habe viel Spaß beim Lernen von Ada, vielen Dank für die Antwort! –

+0

Max verwendet eine von AdaCores Bare-Board-Laufzeiten, in der Ada.Text_IO sehr vereinfacht ist (und an derselben Stelle endet wie GNAT.IO). Und, wie ist das besser als Put_Line? Wenn dieser Ansatz Max 'Problem mit verstümmelten Texten beseitigt, passiert etwas sehr Seltsames. –

+0

Ich wusste nicht, welche Art von RTS Max verwendet wird, ein Ravenscar RTS ist ein fast voller RTS mit nur eingeschränkter Tasking-Unterstützung AFAIK (nie mit einem gearbeitet). GNAT.IO unterstützt direkt Integer zu drucken. Er verwendet das Bild-Attribut, das den sekundären Stapel benötigt, den ich hier vermeiden möchte. Meine Version verwendet direkt das C-Wissen einer 0-terminierten Zeichenfolge. Wenn Sie Put_Line verwenden möchten, müssen Sie zuerst die Null-End-Zeichenfolge in eine Ada-Zeichenkette konvertieren, um sie am Ende in C-Form zu drucken. – RREE

2

Der Betrieb Sie suchen, ist wahrscheinlich Interfaces.C.Strings.Value. Es benötigt ein Argument des Typs Interfaces.C.Strings.chars_ptr (entspricht char * in C) und gibt eine String zurück.

+0

Vielen Dank für die Antwort. –

+0

Fast hat es funktioniert, aber ärgerlicherweise die Ausgabe ist verstümmelt, möglicherweise ein Codierproblem, werde ich weiter untersuchen. Auch das 'Interfaces.C.Strings' Paket ist nur in der" vollen "Ravenscar Laufzeit verfügbar, ich hatte gehofft" sfp "zu verwenden. Ich kann wahrscheinlich den Code von irgendwo greifen, sobald ich alles funktioniert habe. –

2

Gerade falls es nicht klar von Jacob’s answer war, bist du vollkommen frei

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

unter Berücksichtigung der dokumentierten Beschreibung von Msg zu erklären.

+0

Das ist nützlich, war mir nicht eingefallen, werde es versuchen. Vielen Dank. –

+0

Die Verwendung dieser Typdefinition vereinfachte den Code, aber ich erhalte immer noch unlesbare Zeichenfolgen in der Konsole. Ich frage mich, ob es mit der Laufzeit von Ravenscar zu tun hat. –

Verwandte Themen