本附录描述如何最小化SYS/BIOS应用程序的尺寸。
D.2.4 禁用Named模块
D.1 概览
本节对最小化SYS/BIOS基础应用的内存需求提供了一些窍门和建议。这是通过禁用操作系统中默认打开的功能、或通过减少特定缓冲的尺寸来实现的。
大多数小窍门的描述仅限于内核配置的尺寸基准。本章最后一节展现了最小化内存需求的完整配置脚本。
实际的尺寸基准是包含在SYS/BIOS 6安装路径下的ti.sysbios.benchamrks包(也就是在 BIOS_INSTALL_DIR\packages\ti\sysbios\benchmarks目录内)。每个目标都有单独的HTML文件。例如,'C64x尺寸信息可以c6400Sizing.html文件中找到。
以下小节描述不同配置选项和它闪对应用程序尺寸减少的影响。关于这些设置影响的详细描述请参考相关模块文档。
因为代码和数据片经常放置在不同的内存段,这对于只是减少代码尺寸和数据尺寸更为重要。因此对于是否减少代码尺寸或数据尺寸的建议是分开的。通常,减少数据尺寸比减少代码尺寸更简单。
D.2 减少代码尺寸
D.2.1 移除malloc Heap
对malloc的调用是用于满足单独的heap,它的大小是可配置的。以下代码移除heap以使数据占用最濉经。移除heap的应用程序不能动态分配内存。这样的应用程序不能使用SYS/BIOS内存模块APIs或其它SYS/BIOS APIs在内部从heap中分配内存。
BIOS.heapSize =
0;
|
D.2.2 减少栈尺寸
查阅3.5.3节获取有关系统栈尺寸需求信息,查阅3.6.3节获取有关任务栈尺寸需求信息。
Program变量自动对所有脚本可用。它定义了配置对象模块的“根”。它来自xdc.cfg.Program模块,并显式初始化如下:
var Program = xdc.useModule(
'xdc.cfg.Program');
|
系统栈(用于Hwis和Swis的中断服务程序)的尺寸是可配置的,并根据应用的需求减少。
Program.stack =
1024;
|
同样,每个Task栈的尺寸是单独配置的,并根据应用的需求减少。见3.6.3节获取task栈尺寸信息。
var tskParams =
new Task.Params;
tskParams.stackSize = 512; var task0 = Task.create( '&task0Fxn', tskParams); |
你可以配置Idle task栈尺寸如下:
Task.idleTaskStackSize =
512;
|
D.2.3 设置默认Task栈尺寸
如果在Task创建参数中没有提供尺寸,Task.defaultStackSize将指定task栈的尺寸:
Task.defaultStackSize =
1024;
|
用于存放模块名称字符串的空间可使用以下配置设置回收:
var Defaults = xdc.useModule(
'xdc.runtime.Defaults');
Defaults.common$.namedModule = false; |
D.2.5 将文本字符串从目标去除
默认情况下,所有系统中的文本字符串,如模块和实例名称和错误字符串,会载入到目标的内存。可使用以下设置将这些字符串从应用去除:
var Text = xdc.useModule(
'xdc.runtime.Text');
Text.isLoaded = false; |
D.2.6 减少atexit句柄的数量
默认情况下,在系统退出时,多达8个System_atexit()句柄可被指定用于执行。你可通过在运行时将句柄设置为实际需要使用的数量来减少数据空间的使用,如:
System.maxAtexitHandlers =
0;
|
D.3 减少代码尺寸
D.3.1 使用自定义生成的SYS/BIOS库
将
Build-Profile(当你创建一个新的CCS项目或修改
CCS General > RTSC设置所显示的)设置为“release”。
在配置设置中,将BIOS.libType参数更改为BIOS.LibType_Custom,这会导致SYS/BIOS库以优化的方式重新编译,从而减少代码尺寸。
var BIOS = xdc.useModule(
'ti.sysbios.BIOS');
BIOS.libType = BIOS.LibType_Custom; |
参考2.4.5节获取更多关于这些设置的信息。
D.3.2 禁用日志
可通过以下设置禁用日志和断言处理:
BIOS.assertsEnabled =
false;
BIOS.logsEnabled = false; |
D.3.3 设置存储策略
BIOS模块支持两种创建和删除对象的方法。如果应用中的所有对象可在配置脚本中静态创建,那么模块中所有关于动态创建实例的代码都可在应用中去除。这被称为静态存储策略。
BIOS.runtimeCreatesEnabled =
false;
|
D.3.4 禁用核心特性
某些SYS/BIOS的核心特性在需要时可启用或禁用。包括Swi、Clock和Task模块。
var BIOS = xdc.useModule(
'ti.sysbios.BIOS');
BIOS.swiEnabled = false; BIOS.clockEnabled = false; BIOS.taskEnabled = false;v |
应用通常启用Swi和Task句柄中的一个。某些应用可能Swi和Task都不需要使用,可禁用未使用的线程类型。
D.3.5 消除printf()
没有从应用中显式移除printf的方法。尽管如此,如果一个应用程序没有使用System_printf(),不会包含printf代码和相关数据结构。这需要:
- 应用程序中不能包含任何调用System_printf()的代码。
- 需要在SYS/BIOS中写入以下配置:
var System = xdc.useModule(
'xdc.runtime.System');
var SysMin = xdc.useModule( 'xdc.runtime.SysMin'); SysMin.bufSize = 0; SysMin.flushAtExit = false; System.SupportProxy = SysMin; //Remove Error_raiseHook, which brings System_printf var Error = xdc.useModule( 'xdc.runtime.Error'); Error.raiseHook = null; |
请参考模块文档获取详细信息。本质上这些设置将排除所有关于printf的代码。
D.3.6 禁用RTS线程保护
如果应用程序不需要RTS库来保障线程安全,可以指定在RTS库中不使用任意Gate模块。这可以防止应用程序引入另一种类型的Gate模块。
var BIOS = xdc.useModule(
'ti.sysbios.BIOS');
BIOS.rtsGateType = BIOS.NoLocking; |
D.3.8 Cortex-M3/M4异常管理
Cortex-M异常模块使用System_printf()发送一个异常的有用信息。在调试时这非常有用,但它需要使用一些代码和数据空间。如果将M3Hwi.excHandler设为“null”,当异常发生时,异常模块只是简单地在无限循环中旋转。
if ((Program.build.target.name ==
"M3") ||
(Program.build.target.name == "M4") || (Program.build.target.name == "M4F")) { M3Hwi = xdc.useModule( 'ti.sysbios.family.arm.m3.Hwi'); M3Hwi.excHandlerFunc = null; } |
D.4 基本尺寸基准配置脚本
基本尺寸基准配置脚本使用所有这些概念来创建一个应用程序,接近于一个系统DSP/BIOS的应用可能的最小尺寸。
注意,在一个真实的应用中,你至少希望启动Swi或Task句柄中的一个,所以你的应用程序将使用一些线程。
此配置脚本工作于任意目标:
var Defaults = xdc.useModule(
'xdc.runtime.Defaults');
var Diags = xdc.useModule( 'xdc.runtime.Diags'); var Error = xdc.useModule( 'xdc.runtime.Error'); var Main = xdc.useModule( 'xdc.runtime.Main'); var SysMin = xdc.useModule( 'xdc.runtime.SysMin'); var System = xdc.useModule( 'xdc.runtime.System'); var Text = xdc.useModule( 'xdc.runtime.Text'); var BIOS = xdc.useModule( 'ti.sysbios.BIOS'); var Hwi = xdc.useModule( 'ti.sysbios.hal.Hwi'); var Task = xdc.useModule( 'ti.sysbios.knl.Task'); /* * Keep module names from being loaded on the target. * The module name strings are placed in the .const section. Setting this * parameter to false will save space in the .const section. Error and * Assert messages will contain an "unknown module" prefix instead * of the actual module name. */ Defaults.common$.namedModule = false; /* * Minimize exit handler array in System. The System module includes * an array of functions that are registered with System_atexit() to be * called by System_exit(). */ System.maxAtexitHandlers = 4; /* * Disable the Error print function. * We lose error information when this is disabled since the errors are * not printed. Disabling the raiseHook will save some code space if * your app is not using System_printf() since the Error_print() function * calls System_printf(). */ Error.raiseHook = null; /* * Keep Error, Assert, and Log strings from being loaded on the target. * These strings are placed in the .const section. * Setting this parameter to false will save space in the .const section. * Error, Assert and Log message will print raw ids and args instead of * a formatted message. */ Text.isLoaded = false; /* * Disable the output of characters by SysMin when the program exits. * SysMin writes characters to a circular buffer. * This buffer can be viewed using the SysMin Output view in ROV. */ SysMin.flushAtExit = false; /* Circular buffer size for System_printf() */ SysMin.bufSize = 128; System.SupportProxy = SysMin; /* * The BIOS module will create the default heap for the system if this * value is non-zero. */ BIOS.heapSize = 0; /* * Tune the stack sizes. */ Program.stack = 1024; /* System stack size (used by ISRs and Swis) */ Task.defaultStackSize = 1024; Task.idleTaskStackSize = 1024; /* * Build a custom BIOS library. The custom library will be smaller than the * "instrumented" (default) and "non-instrumented" libraries. * * The BIOS.logsEnabled parameter specifies whether the Logging is enabled * within BIOS for this custom build. These logs are used by the RTA and * UIA analysis tools. * * The BIOS.assertsEnabled parameter specifies whether BIOS code will * include Assert() checks. Setting this parameter to 'false' will generate * smaller and faster code, but having asserts enabled is recommended for * early development as the Assert() checks will catch lots of programming * errors (invalid parameters, etc.) */ BIOS.libType = BIOS.LibType_Custom; BIOS.logsEnabled = false; BIOS.assertsEnabled = false; /* * Disable runtime ModXyz_create(). This can only be used in static systems * where all objects are created in the configuration tool. */ BIOS.runtimeCreatesEnabled = false; /* * Disable key features of BIOS. It would be unusual to set all of these * to false as this would disable all of the thread types except Hwi. */ BIOS.swiEnabled = false; BIOS.taskEnabled = false; BIOS.clockEnabled = false; /* * Do not provide any thread protection for the compiler runtime library. */ BIOS.rtsGateType = BIOS.NoLocking; /* * By default, the idle task checks the ISR and system stack to make sure that * they have not overflowed. The task scheduler also checks the task stacks to * make sure that they have not overflowed. You can eliminate this code by * setting the following variables to false. */ Hwi.checkStackFlag = false; Task.checkStackFlag = false; Task.initStackFlag = false; /* * Set the error and abort functions to simple spin loops. */ System.abortFxn = System.abortSpin; System.exitFxn = System.exitSpin; Error.policyFxn = Error.policySpin; /* * The Cortex-M exception module uses System_printf() to dump a lot of * useful information about the exception. This is very useful while * debugging but takes up some code and data space. If you set * M3Hwi.excHandler to 'null', the exception module will simply spin * in an infinite loop when and exception occurs. */ if ((Program.build.target.name == "M3") || (Program.build.target.name == "M4") || (Program.build.target.name == "M4F")) { M3Hwi = xdc.useModule( 'ti.sysbios.family.arm.m3.Hwi'); M3Hwi.excHandlerFunc = null; } |