Please note as of Wednesday, August 15th, 2018 this wiki has been set to read only. If you are a TI Employee and require Edit ability please contact x0211426 from the company directory.


From Texas Instruments Wiki
Jump to: navigation, search

Making a debug-able Custom SYS/BIOS Library

By default, the following setting in your .cfg script:

var BIOS = xdc.useModule('ti.sysbios.BIOS');
BIOS.libType = BIOS.LibType_Custom;

... will generate a highly optimized, minimally debug-able custom SYS/BIOS library that your application will link with.

The optimizations are achieved by including the "-o3" compiler option during the compilation phase. This aggressive optimization setting results in very efficient code at the expense of debug-ability.

To create a custom library that is more debug-able, you can modify the optimization setting by adding the following line to your config script:

BIOS.customCCOpts = BIOS.customCCOpts.replace("-o3", "-o0");

This will change the optimization level from "-o3" to "-o0". (You can replace "-o0" with whatever setting you want).

For ARM targets (ie 'M3', 'A8Fnv', 'Arm9'), you should also add the following line to your config script to remove the "--opt_for_speed=2" compiler option:

BIOS.customCCOpts = BIOS.customCCOpts.replace("--opt_for_speed=2", "");

Note: This modification will result in much slower SYS/BIOS performance as well as a larger code footprint.

To view the set of compiler options used to create the custom SYS/BIOS library, add the following to your config script:


Note: Whatever you do, DO NOT REMOVE the "--program_level_compile" compiler option from BIOS.customCCOpts.

Note: The 'BIOS.libType' option was added in 6.32.01

Removing Asserts from the Custom SYS/BIOS Library

Runtime Assert checking is very useful during application development. However, there is a significant performance penalty associated with them. Once your application is up and running to your satisfaction, you can remove the runtime Assert checking code from the custom SYS/BIOS library by adding the following line to your config script:

BIOS.assertsEnabled = false;

This configuration parameter only applies when you are using the custom SYS/BIOS build option:

BIOS.libType = BIOS.LibType_Custom;

Note: The 'BIOS.libType' option was added in SYS/BIOS 6.32.01

Placing SYS/BIOS code in different memory segments

Placing SYS/BIOS code in different memory regions can be done by adding a secondary .cmd file to your project. The linker can handle more than one .cmd file. Placing interrupt-related code and scheduler code in on-chip or L2 memory can help in systems with tight latency requirements since this code will always be "close" to the CPU and not out in slower off-chip memory. The cache will try to keep code in L1/L2, but forcing time critical code to L2 RAM will help. The L2 memory can be split between Cache and RAM and on some devices there is dedicated L2 that cannot be used for cache.

/* place all the knl APIs in IRAM */
.knl: { *.*(.text:*ti_sysbios_knl*) } > IRAM
/* place all the Hwi APIs in IROM */
.hwi: { *.*(.text:*ti_sysbios*_Hwi_*) } > IROM
/* place the remainder of the SYS/BIOS APIs in DDR */
.sysbios: { *.*(.text:*ti_sysbios*) } > DDR

Similar functionality can be achieved by adding the following Program.sectMap[] commands to your config script:

/* place all the knl APIs in IRAM */
Program.sectMap[".knl: { *.*(.text:*ti_sysbios_knl*) }"] = "IRAM";
/* place all the Hwi APIs in IROM */
Program.sectMap[".hwi: { *.*(.text:*ti_sysbios*_Hwi_*) }"] = "IROM";
/* place the remainder of the SYS/BIOS APIs in DDR */
Program.sectMap[".sysbios: { *.*(.text:*ti_sysbios*) }"] = "DDR";

Exception Dump Decoding Using the CCS Register View

Beginning with SYS/BIOS release, the various Exception modules provide an exception CallStack ROV view and the Task module provides a per task CallStack ROV view. The instructions below are for older versions of SYS/BIOS that do not support these built in ROV views.

SYS/BIOS provides several target unique exception handlers:

  • - used by all Arm9 and A8 targets
  • - used by all cortex-M3 targets
  • - used by all C6x targets

By default, beginning with the 6.32 SYS/BIOS releases, all of these exception handlers print a complete register context dump to the CCS console when an exception is detected.

If you copy the exception dump's values for the PC, SP, (and LR for ARM targets, B3 for C6X targets) into the corresponding registers in the CCS register view, CCS will usually provide a very useful call stack back trace in the debug window.

For example, below is a snaphot of CCS just after an exception has occurred on a Stellaris LM3S8962 evaluation board (Cortex-M3):


And here is a snapshot after the PC, SP, and LR register contents were copied from the exception dump into the CCS register view. Notice the call stack backtrace in the debug window.


Using CCS and ROV to view a core dump file

If you can get your data memory into one or more COFF/.out files, you can use CCS and ROV to review the core dump. You need to have the original .out file and the 'rov.xs' file associated with the given .out file. The rov.xs file is usually in the configPkg/package/cfg directory in your CCS project.

Step 1 is the hard part. You need to get your data memory into a COFF file. On architectures with cache, reading external memory is not enough. You have to first flush the cache to get the data out to external memory. If you are using CCS, this is not an issue since CCS reads the memory using CPU view so it looks through the cache just like CPU would. Here's a screen shot showing how to save a block of RAM from the CCS Memory window:


Step 2 is to start CCS and connect to an active board or simulator with the same data memory configuration (or super-set) as the application you want to analyze.

Step 3 is to load the memory files using the "Load Program" option. Note that you are loading COFF files to simply fill the data memory. These COFF files do not have any symbol information.


Step 4 is to load the symbols from the corresponding .out file using "Load Symbol" option. Here you are only loading the symbols from the COFF file and are not loading any code or data from the file. This is important since you do not want to disturb any of the data from the core dump files you saved in step 1 and loaded in step 3.


You should now be able to open ROV and look at the assorted modules for clues about the state of the system at the time the core dump was taken.


That's It!

Overriding the default Timer frequency

To override the default Timer frequency used by SYS/BIOS to calculate the configured timer period (for the ti.sysbios.timers.dmtimer.Timer module):

/* set the Timer frequency to 20MHz */
var Timer = xdc.useModule('ti.sysbios.timers.dmtimer.Timer');
Timer.intFreq.hi = 0;
Timer.intFreq.lo = 20000000;

Note, this article contains more DM Timer details specific for TI81XX devices.

How to build SYS/BIOS apps on Linux using an external makefile

See attached example.tar.gz file File:Example.tar.gz for an example of how to build 3 sample SYS/BIOS apps using a makefile. For this example, we build a single configuration using the configuro tool. And we use this common configuration for all 3 sample projects. You can also have separate configuration for each project or a mix. This example is tailored for the Stellaris platform, but can be updated for other platforms. You can get the Linux version of the XDC tools and SYS/BIOS on the external download page:

Making an Error site’s file name available to an Error raise hook

By default, SYS/BIOS modules are built such that the file name of the site where an Error is raised is not accessible to a registered Error raise hook (xdc_runtime_Error.raiseHook). In other words, by default, the modules are built such that xdc_FILE is NULL, so the file names are optimized out. [See the description of xdc_FILE in “Controlling File Name Strings” here:]. To have the file name accessible to the Error raise hook, the SYS/BIOS libraries need to be rebuilt with xdc_FILE=__FILE__.

The easiest way to do this with SYS/BIOS v6.32 or later is to use the Custom build type (i.e., BIOS.LibType_Custom, as described under “Compiler and Linker Optimization” in Bios_User_Guide.pdf), and specify xdc_FILE via a compiler option. You can do this by adding statements like the following to your application configuration script:

BIOS.libType = BIOS.LibType_Custom;
BIOS.customCCOpts += " -Dxdc_FILE=__FILE__ ";

For other (non BIOS.LibType_Custom) application builds, the alternative is to rebuild the SYS/BIOS libraries as described in Appendix B of Bios_User_Guide.pdf, with the additional specification of xdc_FILE=__FILE__.

Relocating/Renaming the SYS/BIOS 'src' subdirectory for BIOS.LibType_Custom

By default, when using the BIOS.LibType_Custom (or BIOS.LibType_Debug beginning with SYS/BIOS 6.35) build flows, SYS/BIOS will create a directory named 'src' and a subdirectory named 'sysbios' within the application's project directory as a build area for the custom SYS/BIOS library. Similarly, IPC will build its custom "ti.sdo.ipc" and/or "ti.sdo.utils" libraries in subdirectories named 'ipc' and 'utils' respectively.

For users who for some reason absolutely need to change the default 'src' root directory, the following example is provided.

To change the custom libraries' root directory from 'src' to 'libs' follow these steps:

1) Add this line to your config script:

BIOS.libDir = "../../libs";

2) If you use the ti.sdo.ipc package add these lines:

var ipcBuild = xdc.useModule('ti.sdo.ipc.Build')
ipcBuild.libDir = BIOS.libDir;

3) If you use the ti.sdo.utils package add these lines:

var utilsBuild = xdc.useModule('ti.sdo.utils.Build')
utilsBuild.libDir = BIOS.libDir;

4) Within your project directory edit the 'makefile.defs' file by changing this line:

CFG_SRCDIR = ../src

to this:

CFG_SRCDIR = ../libs

Then clean and rebuild your project.

No further writes to the 'src' directory will take place after the above changes.

If you are not using the old 'src' directory, you can manually delete it at this time.


The success of this procedure relies on using undocumented features that are not guaranteed to behave consistently in future releases of the SYS/BIOS and/or IPC products. An enhancement request has been filed to more formally support this feature in a future release. At such time as this enhancement request is honored, this FAQ will be updated accordingly.

Example showing how to add Task hooks to the system

SYS/BIOS allows users to add their own application specific task hooks to the system. These hooks will be called at key points during thread lifecycle (create, delete, switch, exit, etc.). See the SYS/BIOS User's Guide and APIs for more info. This example shows how to add these hooks in the .cfg file (Task.addHooks()) along with sample C code for sample hook functions. The sample app is similar to the mutex example that ships with SYS/BIOS, but a call to Task_delete() has been added to exercise the delete() hook.

Add this to your .cfg file:

    registerFxn: '&myRegisterFxn',
    createFxn: '&myCreateFxn',
    deleteFxn: '&myDeleteFxn',
    switchFxn: '&mySwitchFxn'

And these sample implementations to your .c file:

#include <xdc/std.h>
#include <xdc/runtime/Memory.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>
#include <ti/sysbios/knl/Task.h>
 * Task Hook Functions
#define TLSSIZE 32
Int hookId;
 * ======== myRegisterFxn ========
 * This function is called at boot time.
Void myRegisterFxn(Int id)
     hookId = id;
 * ======== myCreateFxn ========
Void myCreateFxn(Task_Handle task, Error_Block *eb)
    Ptr tls;
     System_printf("myCreateFxn: task = 0x%x\n", task);
     tls = Memory_alloc(NULL, TLSSIZE, 0, eb);
     Task_setHookContext(task, hookId, tls);
Void myDeleteFxn(Task_Handle task)
    Ptr tls;
    System_printf("myDeleteFxn: task = 0x%x\n", task);
    tls = Task_getHookContext(task, hookId);
    Memory_free(NULL, tls, TLSSIZE);
Void mySwitchFxn(Task_Handle from, Task_Handle to)
     // System_printf("mySwitchFxn: from = 0x%x, to = 0x%x", from, to);

Example showing how use custom output functions with SysMin

The SysMin module allows users to add their own application specific output function. For example, this can be used to redirect the output to a UART or other peripheral. SysMin buffers data in a circular buffer. When you call System_flush() this data gets pushed to the output function. By default, this output function calls fwrite() (it is actually an internal function used by fwrite in the TI-compiler case) to output the characters to the CIO window in CCS.

Add this to your .cfg file:

SysMin = xdc.useModule('xdc.runtime.SysMin');
System.SupportProxy = SysMin;
SysMin.outputFxn = "&myOutputFunc";

And this output function to your .c file. You can replace the call to fwrite() below with a call to the IO operation of your choice.

#include <stdio.h>
Void myOutputFunc(Char *buf, UInt size)
    fwrite(buf, sizeof(Char), size, stdout);

The circular buffer is output via the System_flush() API. You can call System_flush() after you call to System_printf() or you can call it in a background thread at lower priority. Note that your output function is called with interrupt disabled so you should be careful with the amount of time that your output function takes.

Tricking the CCS M3 Debugger into Providing a Blocked Task's Call Stack

Beginning with SYS/BIOS release, the Task module provides a per task CallStack ROV view, and the various Exception modules provide an exception CallStack ROV view. The instructions below are for older versions of SYS/BIOS that do not support these built in ROV views.

After connecting to the M3 core:

  1. Using the disassembler window, find the address of this symbol: ti_sysbios_knl_Task_swapReturn
  2. Put that address + 4 into the PC register.
  3. In the Task ROV 'Raw' view, find the 'context' field of the task Instance State you're interested in.
  4. Place the value of 'context' into both the MSP and PSP registers.
  5. Single step ONE instruction (using "Assembly Step Into").

The debugger window should now show you the task's call stack.

The program is NOT continue-able at this point because the register context at the point of halting the CPU is lost.

Controlling the placement of the "c_int00" program entry point

The following Program.sectMap entries in a .cfg file will align c_int00 on a 0x800 byte boundary within the "SDRAM" memory segment:

Program.sectMap[".c_int00 { boot.ae64P<boot.oe64P> (.text) }"] = new Program.SectionSpec();
Program.sectMap[".c_int00 { boot.ae64P<boot.oe64P> (.text) }"].loadSegment = "SDRAM";
Program.sectMap[".c_int00 { boot.ae64P<boot.oe64P> (.text) }"].loadAlign = 0x800;

Basically, you're telling the linker to extract the .text section in boot.oe64P from the library file boot.ae64P and place it in a section called ".c_int00" and place that section in SDRAM aligned on a 0x800 byte boundary. Since there is only one function, 'c_int00' in the boot.oe64P, this will align the function c_int00 on a 0x800 byte boundary.

You can even precisely place the address of c_int00 by doing this:

Program.sectMap[".c_int00 { boot.ae64P<boot.oe64P> (.text) }"] = new Program.SectionSpec();
Program.sectMap[".c_int00 { boot.ae64P<boot.oe64P> (.text) }"].loadAddress = 0x80012000;

For various flavors of C6x targets, you'll need to modify the above file extension accordingly (ie use .ae66 and .oe66 for the C66 ELF target).

The same pattern follows for Arm targets. Here are similar examples for the M4F target:

Program.sectMap[".c_int00 { boot.aem4f<boot.oem4f> (.text) }"] = new Program.SectionSpec();
Program.sectMap[".c_int00 { boot.aem4f<boot.oem4f> (.text) }"].loadSegment = "FLASH";
Program.sectMap[".c_int00 { boot.aem4f<boot.oem4f> (.text) }"].loadAlign = 0x800;

The above will place c_int00 somewhere in FLASH, aligned on a 0x800 byte boundary.

Program.sectMap[".c_int00 { boot.aem4f<boot.oem4f> (.text) }"] = new Program.SectionSpec();
Program.sectMap[".c_int00 { boot.aem4f<boot.oem4f> (.text) }"].loadAddress = 0x1000;

The above will place c_int00 at location 0x1000

Enabling Semi-Hosting for Cortex-A GNU targets

Step1: Import a GNU Example for an A8 device. In the below example, a TI814x Swi example for GNU targets is being imported.

SemiHosting Screenshot1.PNG

Step2: Click on the"RTSC" tab and ensure the latest SYS/BIOS and XDCTools are being used. Semi-Hosting requires SYS/BIOS or newer and XDCTools or newer. After making the selection click "OK". The example will be imported and will show up in the project explorer window.

SemiHosting Screenshot2.PNG

Step3: Open the build settings for this example.

SemiHosting Screenshot3.PNG

Step4: Delete the "gcc", "c" and "m" libraries in the "GNU Linker" -> "Libraries" view.

SemiHosting Screenshot4.PNG

SemiHosting Screenshot5.PNG

Step5: In the "GNU Linker" view, append the Command-line pattern with the following options:

           -Wl,-( -l"gcc" -l"c" -l"m" -l"rdimon" -Wl,-)

           The above options link the application with librdimon.a library which is a Semi-Hosting enabled BSP library.

SemiHosting Screenshot6.PNG

Step6: Open swi.cfg and manually edit the config script. Add the following line:

          var SemiHostSupport = xdc.useModule('ti.sysbios.rts.gnu.SemiHostSupport');

           This module does the required setup (install SVC_Handler and do the required file handle init) to support SemiHosting.

SemiHosting Screenshot7.PNG

Step7: Build the example.

SemiHosting Screenshot8.PNG

Step8: Open "Program/Memory Load Options" and ensure semihosting is enabled.


That's it! If you now load and run this example, it will use Semi-Hosting to do IO.

Build options and C runtime library re-entrancy for Cortex-A GNU targets

The C runtime APIs are not inherently re-entrant. In order to make them re-entrant, there are 2 options:

  1. The user should call the re-entrant version of the API (i.e. API appended with a _r) and pass a re-entrancy structure as an argument, OR
  2. The OS implements __getreent() which will return a different re-entrancy structure based on which thread (Task) is currently executing. With this solution, the user can call the standard C runtime APIs (not the _r version) and is guaranteed that the APIs will be re-entrant. This solution however requires re-compiling the C runtime libraries (i.e. libc, libm, etc) provided with the GNU tools. The libraries need to be recompiled with a special _DYNAMIC_REENT_ option. This flag tells the library that the OS will implement a __getreent() function and to use __getreent() to get a handle to the re-entrancy structure. Re-entrancy structure is basically thread local storage for static variables that are required by the C runtime libraries.

SYS/BIOS implements the 2nd solution mentioned above and the re-compiled libraries are distributed with XDC Tools. Based on the build flow you are using, here are the extra steps you need to take at build time:

  • package.bld build flow:

        If the user is using package.bld, then XDC Tools will ensure the right libraries are picked up from XDC Tools. The user does not have to do anything special, just selecting gnu.targets.arm.A8F/A15F target for the build is enough. Please note that by default, the libnosys.a library

        is linked (does not support IO). In order to support semi-hosting (to make IO work), the following lines need to be added to a config.bld file:

/* GCC bare metal targets */
var gccArmTargets = xdc.loadPackage('gnu.targets.arm');
gccArmTargets.A15F.bspLib = "rdimon";
  • Using configuro in a makefile based project or building a CCS project:

        In this case, you need to add "-lgcc -lc -lm -lnosys -L$(XDCTOOLS)/packages/gnu/targets/arm/libs/install-native/arm-none-eabi/lib/fpu" to the link line. This tells the linker that the libc, libm, ... libraries are present in the XDCTOOLS package in the specified directory. If you plan to

        build a semi-hosted application, replace -lnosys with -lrdimon. For more info on how to enable semi-hosting please refer this FAQ ->

Section placement and changing stack size for IAR targets

To make it easier for the user to place sections and change stack sizes, certain features (i.e. Program.sectMap, Memory.staticPlace and Program.stack) are not available when developing applications for IAR. Instead of using Program.sectMap or Memory.staticPlace, the user can manually place sections by modifying the linker command file (.xcl for MSP430, .icf for ARM). Users can use the GUI to change the stack size. The stack size is generally available under the project options in IAR Embedded Workbench.

For more detailed information about section placement and changing stack sizes through IAR Embedded Workbench, please refer to the development guides in your IAR Embedded Workbench installation.

Viewing constructed objects in ROV

ROV can display constructed objects in various module views but there are a few restrictions. The constructed objects should be global. Currently the support is limited to ELF/DWARF format.

Note: Mostly debug profile is supported for ELF/DWARF since some code generation tools do not generate DWARF information in release profile.

For other formats like COFF and UBROF or if the user would like to view constructed objects in release profile for ELF/DWARF, an alternate feature has been added in ROV. This requires the user to manually create a file ‘<executable_name>.rov.json’ in the same directory as executable (or one directory level above, or two directory levels above). ROV looks for the file in this order and picks the first file.

The format of the file is shown below. It should contain the name and type information of constructed objects to be displayed by ROV.

       "type": "ti_sysbios_knl_Task_Struct",
       "name": "myTask1",
       "type": "ti_sysbios_knl_Task_Struct",
       "name": "myTask2",
       "type": "ti_sysbios_knl_Semaphore_Struct",
       "name": "mySem",

Placing RTS library functions in a SYS/BIOS C28x Application

SYS/BIOS defines and provides its own entry point function which runs the SYS/BIOS reset and startup functions before jumping to main(). If the user places an RTS library function in their application’s linker cmd file, a reference to the code gen tool’s library is added and the entry point function reference is resolved from the code gen tool's library instead of the SYS/BIOS boot library. This is a problem as SYS/BIOS reset and startup functions will not be called.

Linker.cmd code to place RTS functions in a specific section:

.mySect : {rts2800_fpu32.lib <sin.obj> (.text) } > FLASH PAGE = 0

In order to ensure that SYS/BIOS entry function is picked over the code gen tool's version, a reference to the SYS/BIOS boot library must be added above the RTS function section placement in the linker.cmd file.

Here's an example:

.mySect : {rts2800_fpu32.lib <sin.obj> (.text) } > FLASH PAGE = 0

Clock initialization on Multi-core devices

SYS/BIOS does not perform boot time clock initialization for multi-core class of devices such as OMAP 3/4/5, Jacinto 6 and Keystone 2 family of devices. The bootloader is expected to perform clock and other hardware initialization before loading the SYS/BIOS application and jumping to it. During the development phase, a CCS GEL file may be used to perform clock initialization before loading and running the application.


The "Intro to TI-RTOS Kernel Workshop" is now available. Follow the link below to find out more. The TI-RTOS Kernel Workshop covers the SYS/BIOS operating system available for all TI embedded processors - C28x, MSP430, Tiva-C, C6000 and AM335x (Cortex A-8). You can take a LIVE workshop (scheduled at various sites around the U.S.) or download/stream the videos of each chapter online and watch at your own pace. All of the labs, solutions, powerpoint slides, student guides, installation instructions, lab procedures, etc., are all available to you. The workshop labs run on all MCU platforms and the C6000. Check it out...

Intro to TI-RTOS Kernel Workshop