2.3.3. 构建用于非半主机环境的应用程序

如果不想使用任何半主机功能,则必须删除对半主机函数的所有调用,或者使用非半主机函数重新实现它们。

要构建不使用半主机功能的应用程序,请执行以下操作:

  1. 创建源文件以实现与目标相关的功能,例如,使用半主机调用或依赖于目标内存映射的函数。

  2. __use_no_semihosting 符号添加到源文件中。 请参阅避免使用半主机

  3. 将新对象与应用程序进行链接。

  4. 在创建与目标相关的应用程序时使用新配置。

必须重新实现 C 库所使用的函数,以将其自身不再具有目标相关性。 例如,如果使用 fputc() 函数,则必须重新实现 printf() 函数。 如果不使用高级输入/输出函数(如 fputc()),则不必重新实现低级函数(如 printf())。

如果为不同的执行环境构建应用程序,则可以重新实现与目标相关的函数。 例如,使用半主机调用或依赖于目标内存映射的函数。 C++ 库中没有与目标相关的函数,但某些 C++ 函数使用与目标相关的基本 C 库函数。

主示例目录的 ...\emb_sw_dev 中包含不使用主机环境的嵌入式应用程序示例。

有关创建嵌入式应用程序的示例,请参阅开发指南

非半主机环境中的 C++ 异常

C++ 标准需要使用缺省 C++ abort() 处理程序来调用 std::terminate()abort() 的缺省 C 库实现使用需要半主机支持的函数。 因此,如果在非半主机环境中使用异常,则必须提供 abort() 的替代实现。

半主机相关性概述

Table 2.3 显示了直接依赖于半主机的函数。

Table 2.3. 直接半主机相关性 

函数 说明
__user_initial_stackheap() 请参阅调整运行时内存模型。 如果使用分散加载,则可能需要重新实现此函数。
_sys_exit() _ttywrch() 请参阅调整错误信号、错误处理和程序退出
                    _sys_command_string()、


                    _sys_close()、_sys_ensure()、

_sys_iserror()、_sys_istty()、

_sys_flen()、_sys_open()、

_sys_read()、_sys_seek()、

_sys_write()
                    、_sys_tmpnam()
                  
请参阅调整输入/输出函数
                    clock()、

_clock_init()
                    remove()、


                    rename()
                    system()、
                    time()
                  
请参阅调整其他 C 库函数

Table 2.4 显示的函数间接依赖于Table 2.3 中列出的一个或多个函数。

Table 2.4. 间接半主机相关性 

函数 用法
__raise() 捕获、处理或诊断 C 库异常,没有 C 信号支持。 请参阅调整错误信号、错误处理和程序退出
__default_signal_handler() 捕获、处理或诊断 C 库异常,具有 C 信号支持。 请参阅调整错误信号、错误处理和程序退出
__Heap_Initialize() 选择或重新定义内存分配。 请参阅调整存储管理
ferror()、 fputc()、 __stdout 重新实现 printf 系列。 请参阅调整输入/输出函数
__backspace()、fgetc()__stdin
重新实现 scanf 系列。 请参阅调整输入/输出函数
fwrite()、fputs()、puts()fread()、fgets()、gets()ferror()
重新实现流输出系列。 请参阅调整输入/输出函数

避免使用半主机

如果使用 C 编写应用程序,则必须将其与 C 库进行链接,即使应用程序不直接使用 C 库函数。 C 库包含编译器辅助函数和初始化代码。 某些 C 库函数使用半主机。

要避免使用半主机,请执行以下任一操作:

  • 在您自己的应用程序中重新实现这些函数

  • 按某种方式编写应用程序,以使其不调用任何半主机函数。

要确保应用程序中不包含任何使用半主机的函数,请使用以下任一方法:

  • 汇编语言中的 IMPORT __use_no_semihosting

  • C 中的 #pragma import(__use_no_semihosting)

如果包含使用半主机的库函数,并且还引用了 __use_no_semihosting,库将检测发生冲突的符号,并且链接器将报告错误。 要找出使用半主机的对象,请使用 --verbose --list=out.txt 进行链接,搜索输出以查找符号,然后找出引用它的对象。 有关详细信息,请参阅链接器和实用程序指南中的第 2-32 页的 控制链接器诊断消息

API 定义

除了Table 2.3Table 2.4 中列出的半主机函数外,Table 2.5 还显示了为不同环境构建应用程序时可能用到的函数和文件。

Table 2.5. 已公布的 API 定义 

文件或函数 说明
                    __main()
                    __rt_entry()
                  
初始化运行时环境并执行用户应用程序。
                    __rt_lib_init()


                    __rt_exit()
                    __rt_lib_shutdown()
                  
初始化或结束运行时库。
LC_CTYPE 区域设置 为局部字母表定义字符属性。 请参阅使用汇编程序宏调整区域设置和 CTYPE
rt_sys.h C 头文件,用于描述缺省(半主机)实现使用半主机调用的所有函数。
rt_heap.h C 头文件,用于描述存储管理抽象数据类型。
rt_locale.h C 头文件,用于描述 5 个区域设置类别文件编排系统,并定义一些用于描述区域设置类别内容的宏。
rt_misc.h C 头文件,用于描述 C 库的其他无关公共接口。
rt_memory.s 内存模型的带注释空原型实现。 有关该文件的说明,请参阅编写您自己的内存模型

如果重新实现标准 ARM 库中存在的函数,链接器将使用工程中的对象或库,而不是使用标准 ARM 库。 添加到工程中的任何库不必遵循 ARM 库命名约定。

Caution

不要替换或删除 ARM Limited 提供的库。 切勿覆盖提供的库文件, 而应将重新实现的函数放在单独的库中。

Copyright © 2007 ARM Limited. All rights reserved. ARM DUI 0349AC
Non-Confidential