本章描述的是一些基本支持特性和配置参数提供API的模块,这些特性和配置参数管理整个应用程序行为。
应用程序支持和管理的模块
SYS/BIOS和XDCtools提供了许多模块,其中包含用于支持和管理整个应用程序行为的函数。以下模块提供了属于这一类的api和配置设置:
- BIOS Module(ti.sysbios.BIOS): 负责SYS/BIOS启动和全局参数维护
- System(xdc.runtime.System): 提供低级"系统"服务
- SysMin(xdc.runtime.SysMin): 为系统模块推荐代理
- SysCallback(xdc.runtime.SysCallback): 代理自定义系统行为
- Program(xdc.cfg.Program): 作为配置名称空间的根
- Startup(xdc.runtime.Startup): 管理应用程序启动和初始化
- Reset(xdc.runtime.Reset): 允许特定目标的复位功能在系统复位后立即运行
- Error(xdc.runtime.Error): 提供处理错误机制
- Text(xdc.runtime.Text): 使用公共字符串管理字符串
- Memory(xdc.runtime.Memory): 管理内存使用
BIOS模块
BIOS模块负责设置SYS/BIOS使用的全局参数,并执行SYS/BIOS启动顺序。
BIOS模块的包的路径为ti.sysbios.BIOS,因此SYS/BIOS应用程序应该包含以下#include语句:
#include<ti/sysbios/BIOS.h>
配置文件(*.cfg)应该启用该模块,如下所示:
var BIOS = xdc.useModule('ti.sysbios.BIOS');
以下的BIOS模块APIs在SYS/BIOS应用程序中是有用的:
- BIOS_start() — 在将控制权交给SYS/BIOS线程调度程序之前,应用程序main()函数必须将此函数作为执行的最后一条语句调用。该调用应该在所有应用程序所需的所有初始化都执行之后执行。这个函数执行所有剩余的SYS/BIOS初始化,然后将控制转移到准备运行的最高优先级Task。如果Task没有启用,控制将直接被转移到Idle Loop。BIOS_start()函数不返回值。
- BIOS_getCpuFreq() — 该函数返回CPU的频率(赫兹)
- BIOS_setCpuFreq() — 该函数设置CPU的频率(赫兹)
- BIOS_exit() — 当想要SYS/BIOS应用程序终止时,调用此函数。BIOS_exit()不会返回到名为BIOS_start()函数。相反,BIOS_exit()调用System_exit()并终止。所有通过System_atexit()或ANSI C标准库ateexit()函数绑定的所有函数。对于SYS/BIOS应用程序,建议调用BIOS_exit()而不是System_exit(),因为BIOS_exit()在调用System_exit()之前执行内部清理。如果应用程序需要错误条件终止,它应该调用System_abort()或System_abortSpin()。
- BIOS_getThreadType() — 这个函数返回调用这个函数的线程类型。这可用的线程类型有:BIOS_TreadType_Hwi,BIOS_ThreadType_Swi,BIOS_ThreadType_Task,和BIOS_ThreadType_Main。
BIOS模块定义了BIOS_WAIT_FOREVER和BIOS_NO_WAIT常量,可以与带有timeout参数的API一起使用。
System模块
System模块提供基本的低级"系统"服务,如字符输出、类似printf的输出和退出处理
System模块的包路径是xdc.runtime.System,所以SYS/BIOS应用程序应该包含以下#include语句:
#include <xdc/runtime/System.h>
配置文件(*.cfg)应该启用该模块,如下所示:
var System = xdc.useModule('xdc.runtime.System');
以下系统模块api在SYS/BIOS应用程序中是有用的:
-
System_printf() — 提供了几个类似于printf的函数。其中包括System_putch(),System_sprintf(),System_vprintf(),System_aprintf()(类型为lArg的参数)和System_vsnprintf(使用可变参数列表将指定数量的字符打印到字符缓冲区以传递参数)
强烈建议SYS/BIOS应用程序调用System_printf()及其相关函数来代替标准的printf()函数。System模块提供了熟悉的类似printf的功能,但选项少。内存开销比传统的printf()小得多。System_printf()允许用户指定使用系统提供程序处理字符输出。
由于系统模块的功能在许多情况下更容易使用,所以也推荐使用系统模块打印功能。Log模块旨在与主机工具一起使用,它有更多的选项来禁用/启用日志记录。
-
System_abort() — 应用程序可以在需要异常中止并返回错误消息时调用此函数。这个函数允许返回一个描述所发生错误的字符串。当调用该函数时,进入System gate,调用SupportProxy的abort函数,然后System.abortFxn被调用。没有调用System_atexit()或ANSI C标准库atexit()函数绑定的退出函数
-
System_flush — 这个函数将任何缓冲的输出字符发送到输出设备。它还向IDE发出一个断点。因为调用这个会暂停目标,所以调用它会影响实时执行的细节。输出字符的目的地由SupportProxy模块决定。
-
System_exit() — 建议SYS/BIOS应用程序调用BIOS_exit()而不是System_exit()函数。BIOS_exit()函数在调用System_exit()之前执行内部清理。System_exit()可以从Task调用,但不能从Swi或Hwi调用。
-
System_atexit() — 调用这个函数可以向调用System_exit()时要执行的函数的内部堆栈添加一个退出处理程序。System.maxAtexitHandlers配置属性控制可以堆叠多少个出口处理程序。默认值为8。
系统模块使用一个支持代理模块来实现所需的低级服务。这个实现由System.SupportProxy配置参数指定。默认是SysMin模块。另一个是SysCallback模块
系统模块是门控的。其他模块可以通过Gate_enterSystem()和Gate_leaveSystem()函数使用它的gate
Exit Functions
默认情况下,当应用程序在没有错误条件的情况下退出时,System模块调用它的标准退出函数,而标准退出函数又调用ANSI C标准exit()函数。如果希望应用程序无限期旋转,以便调用应用程序的状态,请将以下语句添加到配置中:
System.exitFxn = System.exitSpin;
配置这个"spin"函数可以减少应用程序的代码大小。应用程序不应该直接调用System_exitSpin() API。
还可以在C代码中使用System_atexit()函数在运行时指定多个出口处理程序。自定义出口处理程序的原型是:
typedef Void (*System_AtexitHandler)(Int);
Abort Functions
默认情况下,当应用程序由于错误条件而中止时,System模块调用其标准终止函数,而标准中止函数又调用ANSI C标准 abort() 函数。如果希望应用程序无限期运行,以便调式应用程序的状态,要将下列的语句添加到配置中:
System.abortFxn = System.abortSpin;
配置这个"spin"功能还可以减少应用程序的代码大小。应用程序不应该直接调用System_abortSpin() API。
自定义中止处理程序的原型是:
typedef Void (*System_AbortFxn)();
SysMin模块
SysMin模块是大多数SYS/BIOS示例和模板使用的SupportProxy模块。该模块提供了系统SupportProxy所需功能的实现。这包括刷新缓冲字符,输出单个字符以执行退出和中止操作函数
大多数应用程序都推荐使用SysMin模块,因为它将字符放置到一个循环缓冲区中,Runtime Object View(ROV)工具知道如何查找和呈现该缓冲区
该模块在目标上维护一个内部循环缓冲区来存储"输出"字符。当缓冲区满时,数据将被覆盖。当调用用于刷新缓冲区函数时,内部循环缓冲区中的字符使用配置的"outputFxn"输出。除非您提供了自定义的outputFxn,否则TI目标上,在TI C Run Time支持库中的Hostwrite()函数将用于输出字符缓冲区。对于非TI目标,使用ANSI C标准库函数fwrite()
应用程序不应该直接调用SysMin函数,但是SysMin模块提供了配置参数来控制用于内部存储输出的缓冲区站点和包含该缓冲区的内存部分。配置文件(*.cfg)可以启用该模块,如下所示:
var BIOS = xdc.useModule('xdc.runtime.SysMin');
SysCallback模块
SysCallback模块时SysMin代理模块的替代方案。它要求提供自定义函数来处理中止,退出,刷新,启动和准备操作。如果需要自定义应用程序的输出行为,要使用此模块
Program模块
Program模块充当名称空间的“root”。他在配置中使用,但不提供任何C APIs。
配置文件不需要使用useModule()来启用该模块。
Program模块提供了控制运行时内存大小的配置参数。这包括Program.stack,包括控制应用程序堆栈的大小,该堆栈与单个Task所使用的堆栈是分开的。
Program模块还提供了控制自动生成链接器命令文件内容的配置参数。这包括Program.sectMap[]数组和Program.sectionsExclude参数
Startup模块
Startup模块管理在调用C的main()函数之前发生的非常早的启动初始化。这个初始化通常包括设置硬件特定的寄存器,控制看门狗定时器,访问内存,缓存设置,时钟速度等。
除了允许用户添加自定义启动函数的配置参数外,该模块还提供了允许模块自动将初始化函数添加到启动序列的服务。
配置Startup模块的配置文件(*.cfg)应该启用该模块,如下所示:
var BIOS = xdc.useModule('xdc.runtime.Startup');
Reset模块
Reset模块通过配置Reset.fxns[]数组属性来定义初始复位功能。在应用程序启动时尽可能早地调用Reset函数,用于特定平台的硬件初始化。
注意,只有特定的目标族在运行之前执行设备复位。因此,并不是所有平台都支持reset功能。不要将你想要移植的代码放在这个函数中。相反,使用Startup模块来定义跨平台应用程序的启动函数。
配置Reset模块的配置文件(*.cfg)应该启用该模块,如下所示:
var BIOS = xdc.useModule('xdc.runtime.Reset');
Reset模块允许配置一个启动函数数组,允许您未葛总外设的启动活动提供单独的函数
Error模块
Error模块提供了在程序中引发、检查和处理错误的机制。
Error模块的包路径是xdc.runtime.Error,因此SYS/BIOS应用程序应该包含以下#include语句:
#include <xdc/runtime/Error.h>
配置Error模块的配置文件(*.cfg)应该启用该模块,如下所示:
var BIOS = xdc.useModule('xdc.runtime.Error');
许多SYS/BIOS APIs — 特别是那些创建对象和分配内存的函数都有一个期望的Error_Block的参数。
下面的Error模块 APIs可能在SYS/BIOS应用程序中可能有用:
- Error_init() — 将错误模块放入其初始状态
- Error_check() — 如果引发错误则返回true
- Error_getData() — 得到一个错误的参数列表
- Error_getMsg() — 得到一个错误的"printf"格式字符串
- Error_print() — 使用System_printf()打印一个错误
- Error_raise() — 抛出了一个错误
这个例子在调用System_printf()时使用了错误APIs:
System_printf(Error_getMsg(eb),
Error_getData(eb)->arg[0],
Error_getData(eb)->arg[1]);
这个例子在错误条件下引发一个错误:
if (val % 2) {
Error_raise(eb, Error_E_generic, "Value is not a multiple of 2", 0);
}
你可以使用Error.policy、Error.policyFxn和Error.raiseHook配置参数SYS/BIOS应用程序如何响应引发的错误
默认情况下,Error.policy将向调用函数返回错误(Error_UNWIND)。如果Error.policy是Error_TERMINATE,所有引发的错误都是致命的,对Error_raise()的调用不会返回给调用者。
默认情况下,Error.policyFxn是Error_policyDefault(),它根据error.policy处理错误并在返回给调用者或终止之前记录它。或者,可以使用Error_policySpin(),它只是无限循环,以最小化目标占用空间。
可以指定一个Error.raiseHook函数,以便在每次引发错误时调用,即使Error.policy已终止。默认情况下,此函数设置为Error_print(),这会导致错误格式化并由System_printf()输出。将此配置参数设置为null表示不应调用函数挂钩。
Text模块
Text模块有效地管理带有公共字符串的字符集合。具有高度通用性的集合的存储空间要比由独立字符串组成的普通表小得多。文本字符串的压缩表示的总可用空间被限制为64K个字符。
为了进一步节省空间,"压缩"表示甚至不需要加载到目标内存中。默认情况下,文本字符被加载到目标内存中。
可以在运行时使用Text_isLoaded布尔常量来控制传递给System_printf()函数的格式字符串,例如:
if (Text_isLoaded) {
System_asprintf(tempStr, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
}
else {
System_asprintf(tempStr, "{evt: fmt=%p, args=[0x%x, 0x%x ...]}", fmt, a1, a2);
}
Text模块的包路径是xdc.runtime.Text,所以使用Text APIs和常量的SYS/BIOS应用程序应该包含以下#include语句:
#include <xdc/runtime/Text.h>
配置Text模块的配置文件(*.cfg)应该启用该模块,如下所示:
var BIOS = xdc.useModule('xdc.runtime.Text');
参考文献:
- 《TI-RTOS Kernel (SYS/BIOS) User’s Guide》