在Ada Last_Chance_Handler中打印异常消息

时间:2017-11-14 00:41:45

标签: ada gnat eabi

我正在使用AdaCore GPS(GPL)IDE使用GNAT编译器学习Ada,目标是ARM"裸板"硬件(使用Ravenscar SFP运行时的STM32F4)。

对于我的基于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结尾的字符串,表示   raise语句的源位置,由编译器生成,   或者,如果编译指示Suppress_Exception_Locations为,则为零长度字符串   使用

我一直试图弄清楚如何将null已终止的Msg字节转换为Ada字符串,以便我可以使用Put_Line()调用显示它(在调试时)我可以通过半主机机制访问这种类型的输出。

我之前通过将其'Address属性设置为常量值,将Ada记录(代表设备寄存器等)映射到物理内存地址。但是,这是我第一次通过变量中保存的System.Address值尝试访问内存。

有人可以建议我如何实施Address_To_String()程序吗?

我已经尝试过Ada字节数组和它们与System.Address之间未经检查的转换,还有Ada指针,但到目前为止我还没有取得任何成功。

非常感谢任何帮助或建议!

非常感谢,

...最大

3 个答案:

答案 0 :(得分:3)

您正在寻找的操作可能是Interfaces.C.Strings.Value。它需要Interfaces.C.Strings.chars_ptr类型的参数(相当于C中的char *)并返回String

答案 1 :(得分:3)

如果Jacob’s answer不清楚,你可以完全自由地宣布

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

请记住Msg

的文档说明

答案 2 :(得分:3)

如果你来到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;