I'm in the process of learning Ada using the GNAT compiler using the AdaCore GPS (GPL) IDE, aimed at ARM "bare board" hardware (STM32F4 using a Ravenscar SFP runtime).
For my ARM based embedded work I've come from a C/C++ background.
Anyway, I've implemented a "last chance handler" that's defined as follows,
procedure Last_Chance_Handler (Msg : System.Address; Line : Integer);
pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler");
Here's the actual procedure (a snippet from the .adb
file),
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;
The Msg
argument is documented as follows,
The Msg parameter is a C null-terminated string representing the source location of the raise statement, as generated by the compiler, or a zero-length string if pragma Suppress_Exception_Locations is used.
I've been trying to figure out how to convert the null
terminated Msg
bytes to an Ada string so that I can display it using a Put_Line()
call (when debugging I can access this type of output via the semihosting mechanism).
I've previously mapped Ada records (representing device registers etc.) to physical memory addresses by setting their 'Address
attribute to a constant value. However, this is the first time I've tried access memory via a System.Address
value held in a variable.
Can anyone suggest how I might go about implementing the Address_To_String()
procedure?
I have experimented with Ada byte arrays and unchecked conversions between them and System.Address
, also with Ada pointers, but so far I've not had any success.
Any help or suggestions would be greatly appreciated!
Many thanks,
...Max
If you come to a last_chance_handler something is probably broken and you shouldnt rely too much on your environment. Ada.Text_IO is a very heavy package. You should try to avoid it generally and especially here.
You could try something like this:
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;