C28x Code Generation Tips and Tricks

From Texas Instruments Wiki
Jump to: navigation, search

Contents

Introduction

A listing of tips and tricks related to the Code Generation Tools for C28x based devices.

Other Resources

  • TMS320C28x Optimizing C/C++ Compiler User's Guide (spru514)
  • TMS320C28x Assembly Language Tools User's Guide (spru513)

The following is great general Code Generation Tools Information. Much of it applies to 28x:

Compiler Support Options

Frequently Asked Questions

A Minimal Project

Q: What is the minimum that I need in my project to get started?

The easiest way is to start with a project supplied from TI. Examples are provided with your kit, or can be downloaded as part of ControlSUITE. Some very simple "hello world" type examples are included in the in the "C/C++ header files and peripheral example packages".

The following examples are simplified lists of what these projects include:

Any minimal C based project for a fixed-point 28x will have:
Any minimal C based project for a 28x with Floating-Point will have:

If your project also includes CLA code, then you will need to add the switch to enable the support (--cla_support=cla0). Likewise if your project includes VCU assembly code, then use --vcu_support=vcu0 to enable support.

Compiler and Linker Options

Q: What are recommended compiler options for the main CPU?

These are the basic recommended options to get started. As you develop your code you may change the optimizer settings (see the optimizer section).

Commonly Used Compiler Options for the C28x CPU
Options to Specify Processor Type Option Alias Notes
Specify TMS320C28x architecture --silicon_version=28 -v28 Required
C28x based projects require this option.
Failure to use it will generate 27x (legacy) object code.
Specify C28x with Single Precision Floating-Point --float_support=fpu32
This option requires Codegen V5.0.x or later
Enables generation of single-precision (32-bit) floating-point assembly instructions.
This setting also requires -v28 and assumes large memory model (-ml)
Enable support for the Viterbi, Complex Math and CRC Unit (VCU)
--vcu_support=vcuN
where:
  • N = 0 for vcu type 0
  • N = 2 for vcu type 2

Enables the assembler to accept VCU assembly instructions
  • vcu0 requires Codegen V6.0.1 or later
  • vcu2 requires Codegen V6.2.4 or later
Accept 24x assembly instructions
--c2xlp_src_compatible -m20 This option is ONLY used if you are migrating C24x code to the C28x.
Required Memory Model Options
Generate large memory model code --large_memory_model -ml This forces the compiler to view the architecture as having a flat 22-bit address space. All pointers are considered to be 22-bit pointers.
All TI supplied code uses -ml.
Using --float_support assumes large memory model.
Generates code for the unified memory model --unified_memory -mt Indicates memory is available in both program and data space.
This allows the compiler to use instructions such as PREAD/PWRITE and MAC that require unified memory.
Debug/Optimizer
Generate symbolic debug information --symdebug:dwarf -g When first writing code turn on full symbolic debug and get the code working.
Once code is debugged and stable the user can try --symdebug:skelatal instead. Doing so can, however, severely limit debug capability so you may only want to apply it to time critical code.
Highly Recommended for Troubleshooting
Issues remarks (non-serious warnings) --issue_remarks -pdr These remarks often point out real issues in the code that should be addressed to avoid bugs.
TI recommends ALWAYS building with -pdr
Link step: warn sections --warn_sections -w Displays a message when an undefined output section is created.
Issue diagnostics in verbose form --verbose diagnostics
Provides verbose diagnostics that display the original source with line-wrap and indicate the position of the error in the source line.
This can be very useful if an error message is not clear.

Q: What are recommended compiler options for the CLA CPU?

These are the basic recommended options to get started.

Commonly Used Compiler Options for the CLA
Options to Specify Processor Type Option Alias Notes
Enable support for the Control Law Accelerator
--cla_support=claN
where:
  • N = 0 for cla type 0
  • N = 1 for cla type 1

Enables the assembler to accept CLA assembly instructions
  • cla0: requires Codegen V5.2.x and later (assembly only) or 6.1.0 and later (for C and assembly)
  • cla1: requires Codegen V6.2.4 or later

Q: What is the difference between "Large memory model" and "Small memory model"

  • Large memory model assumes data can be anywhere in the memory space.
  • Small memory model assumes all data is in the lower 64k of memory unless it is specified as 'far'.
For 28x code TI uses large memory model. The small memory model is really there for legacy porting of another core (called the C27x) based code.

Q: What is "Unified Memory Model"?

Unified memory model means that any memory block can be used as either program memory or data memory.

All memory blocks including SARAM, flash, ROM, OTP and XINTF memory is unified on the 28x devices. Peripheral registers are typically only mapped to data space.

Specifying unified memory model in the build options is important because it allows the compiler to generate efficient instructions like PREAD/PWRITE/MAC. The compiler will not access anything that is volatile using the program space bus (i.e. peripheral registers).

Run-Time Support Library

Q: What is the runtime library for?

There is a lot of information on this in the TMS320C28x Optimizing C/C++ Compiler User's Guide (spru514). At a high level, the run-time-support library contains the following:

  • ANSI/ISO C/C++ standard library
  • C I/O library
  • Low-level support functions that provide I/O to the host operating system
  • System startup routine, _c_int00

Q: Where are the RTS functions documented?

  • TI does not provide documentation about the standard C libraries. Several references in the form of internet pages and books have already been published about this subject.
  • Similarly, if you are using the C++ STL library and have questions about the API, TI does not provide documentation for that. The file <readme.1st> contains the following references:
  1. The Standard C++ Library: A Tutorial and Reference, Nicolai M. Josuttis, Addison-Wesley, ISBN 0-201-37926-0
  2. The C++ Programming Language (Third or Special Editions), Bjarne Stroustrup, Addison-Wesley, ISBN 0-201-88954-4 or 0-201-70073-5.
  3. Dinkumware's online reference at http://dinkumware.com/manuals/
  4. C++ online reference at http://www.cplusplus.com/

Q: Which runtime support library should I use?

In the past, there have been a number of RTS library builds provided by default with the Codgen tools. To allow for quicker compiler release downloads, current compiler releases pre-build only a small number of very commonly-used libraries. The missing libraries, or libraries with custom build options, can be built by the user as desired.
To learn how to modify and rebuild the library, please refer to the Mklib wiki article.
C28x Run-Time Support Libraries
Most Commonly Used Description Option Requirements
rts2800_ml.lib C/C++ large memory model run-time object library
This is the library to use for the fixed-point CPU
-v28 -ml
rts2800_fpu32.lib C/C++ run-time object library for FPU targets
Assumes large memory model
Can be combined with the FPU FastRTS library.
-v28 --float_support=fpu32 -ml
For C++ Exception Handling Description Option Requirements
rts2800_ml_eh.lib C/C++ large memory model run-time object library with exception handling support
Note: exception handling is costly in cycles and size, even if an exception is never thrown
Only use this library if you require exception handling
-v28 -ml --exceptions
rts2800_fpu32_eh.lib C/C++ run-time object library for FPU targets with exception handling support
Note: exception handling is costly in cycles and size, even if an exception is never thrown
Only use this library if you require exception handling
-v28 --float_support=fpu32 -ml --exceptions
Not Recommended
(Small Memory Model)
Description Option Requirements
rts2800.lib C/C++ small memory model run-time object library
It is better to use the large memory model on 28x.
This version of the library is no longer shipped by default with the codegen tools.
-v28
rts2800_eh.lib C/C++ small memory model run-time object library with exception handling support
It is better to use the large memory model on 28x.
This version of the library is no longer shipped by default with the codegen tools.
-v28


Q: Where is the runtime support library located?

It will be in the /lib directory of your codegen install directory.
  • For a newer install of Code Composer Studio (CCS), look in the tools directory of your CCS install. For example: C:\ti\ccsv5\tools\compiler
  • Previously compilers were being installed in Program Files. For example: C:\Program Files\Texas Instruments\C2000 Code Generation Tools 5.2.4

Q: How do I add the RTS library to my project?

Command Line:

Use the -l <library name> option to include the library.

In CCS 5:

  1. In Code perspective, right click on the project name and select "properties".
  2. Expand the C2000 linker -> File search path options.
  3. Under "Include Library File" specify the RTS library
  4. The search path should already be specified for the codegen install / lib directory
CCS 5: Adding an RTS Library

In CCS 4:

  1. In Code perspective, right click on the project name and select "properties".
  2. Under C/C++ Build->Tool Setting Tab, expand the "C2000 Linker" options.
  3. Under "File Search Path" specify the RTS library in the Include Library File box
CCS 4: Adding an RTS Library

In CCS 3.3:

There are two options:
  • Project->Add Files To Project, Select obj/lib, Browse to the library and add it
  • Project->Build Options->Linker->Libraries and add the RTS library. This will use the RTS library from the /lib directory of the compiler you are using.
CCS 3.3: Adding an RTS Library


Q: I want to modify and rebuild the library or I want to build it with different compiler options. How can I rebuild it?

Newer versions of the compiler (6.0.2 and later) provide a utility for rebuilding the RTS library. Please see the Mklib wiki article for more information.
For older toolsets, in the codegen tools lib directory, unzip the rtssrc.zip file. There should be a rtssrc_zip_README.txt file that describes the steps to rebuild the libraries.

Q: I need to be able to build the rts library for audit purposes. How can I do this?

Newer versions of the compiler (6.0.2 and later) provide a utility for rebuilding the RTS library. Please see the Mklib wiki article for more information.
For older versions of the compiler: in the codegen tools lib directory, unzip the rtssrc.zip file. There should be a rtssrc_zip_README.txt file that describes the steps to rebuild the libraries.

Optimization

Q: Can you give me some tips on using the optimizer?

There are a lot of options when it comes to using optimization. Refer to the TMS320C28x Optimizing C/C++ Compiler User's Guide (spru514) for a detailed explanation. A simple plan would be:

  • Partition code into separate files to allow for selective optimization levels.
  • Start with Symbolic Debug Enabled
  • Write, compile, and debug code without using the optimizer: Get the code functioning!
  • Use full symbolic debug (--symdebug:dwarf or -g) at this time to have full symbolic debug.
  • Turn on the optimizer and verify code functionality. Debug if necessary.
  • The optimizer has different levels (0, 1, 2, and 3), which controls the type and degree of optimization.
  • You must specify an optimization level option, otherwise the optimizer is not used.
  • Level 0 (--opt_level=0 or -o0) is the lowest level
  • Level 3 (--opt_level=3 or -o3) is the highest level
  • Start with the lowest level and work your way up.
  • Level 4: As of Codegen 6.0.1, a 4th level has been added (--opt_level=4 or -o4).
  • This level will perform a post-link optimization of the code. The downside is it will increase build time but has the potential to improve performance by having a view of the entire application after the link step.
  • To debug optimized code, use the --opt_level option in conjunction with symbolic debug (-g)
  • This yields the maximum optimization that is still compatible with debug.
  • See also Debug versus Optimization Tradeoff
  • Optimization Level 2 (-o2) is often a good compromise.
  • Use -mn:
  • If you want to use symbolic debugging (-g) and enable some optimizations, then use the --optimize_with_debug (-mn) option
  • Keep in mind that portions of the debugger's functionality will be unreliable.
  • Remove symbolic debug (-g) and use --symdebug:skeletal:
  • As a final step, you may wish to compile critical code using --symdebug:skeletal instead of full symbolic debug. This will allow the scheduler to move instructions that it could not move with symbolic debug enabled. For example, with the FPU32 instruction set the compiler may be able to make use of more parallel instructions or reduce the number of NOPs in the code. This "moving around" may change the ability to debug the code, however, so you may want to consider only applying this option to particular files with time critical code.
  • Do not use -ss
  • Using C source interlisting (-ss) will hinder optimization. Note: -s does not hinder optimization.

Q: What else can I do to improve performance?

  • If you are running code from flash, make sure to enable the prefetch buffer and configure the waitstates appropriately. Examples of how to do this are provided in the device support package for each particular device.
  • Copy time critical code from its load address in flash to RAM for execution. This application note explains how: Running an Application from Flash (spra958)
  • Evaluate the partitioning of the code and data and modify the linker file if needed:
  • If code accesses data within the same physical memory, then performance will degrade due to resource conflicts. It is better to place code and the data it accesses separate blocks.
  • Wait states will degrade performance. Most SARAM is zero-wait on 28x devices. There are some blocks, however, that are not on 2833x devices. Always check the data manual to find the wait states for each physical block and whether it applies to program or data accesses.
  • If code makes extensive use of two data buffers, putting each buffer in a different RAM block may improve performance. The goal is to reduce the pipeline stalls due to write and read occurring in the same cycle to different buffers.
  • For Frequently Asked Linker questions - Please see the C28x_Compiler - Understanding Linking Wiki Article
  • Use the --unified_memory compiler switch. This will allow the compiler to use instructions like MAC and PREAD/PWRITE that require unified memory.
  • Constant arrays: If access to a constant array is time critical, then consider copying it from its load address in flash to a RAM address for execution time. This application note explains how: Running an Application from Flash (spra958).
  • For code which will run in flash or external memory, apply the -me compiler option. This will change "prefetch branch" instructions (SBF/BF) to normal branch instructions (SB/B). Prefetch branch instructions are efficient from RAM but slower from waitstated memory. Apply this option to files that contain code that will be run from flash. (In CCS you can right click on a file to apply a per-file option).
  • Avoid some calls and return operations by allowing the compiler to inline some of your functions.
  • Other tips can be found here: C2000 Performance Tips and Tricks

Q: My code worked well until I turned on optimization. What could be the issue?

Enabling optimizations may uncover bugs such as:

  • Uninitialized variables
  • Loose adherence to ANSI standard
  • Failure to use volatile
  • Assembly function not correctly saving/restoring registers

Q: How can volatile help?

Volatile tells the compiler that a variable may change in another context. If it is not used then the compiler will often decide the variable can not change and therefore there is no reason to read it more than once, or even at all. Examples of volatile:

  • Variables that can change in an interrupt or another task
  • Peripheral registers that change via hardware
  • Variables that other processors can change.

Variable Types

Q: I defined an array of char, but each value is taking up 16 bits!

On 28x bytes and words are equivalent - that is, both int and char are 16-bits. This yields sizeof(int) == sizeof(char) == 1.

Q: Doesn't sizeof(int) == sizeof(char) == 1 go against the ANSI standard?

By ANSI/ISO C definition, the sizeof operator yields the number of bytes required to store an object. ANSI/ISO further stipulates that when sizeof is applied to char, the result is 1. Since the TMS320C28x char is 16 bits (to make it separately addressable), a byte is also 16 bits.

Q: If char is 16 bits, how can I access 8-bit values efficiently?

To access data in increments of 8 bits, use the __byte() and __mov_byte() intrinsics described in TMS320C28x Optimizing C/C++ Compiler User's Guide (spru514). Also please refer to this wiki article: Byte Accesses with the C28x_CPU

Accessing Assembly from C Questions

Q: Is there a way to access specific assembly instructions from C code?

The C28x compiler includes some intrinsics to do this. They are documented in the compiler reference guide (spru514).

Q: I have a function in assembly and I want to call it from C - How can I access the arguments inside the function?

You are looking for the C calling conventions. These are documented in the compiler reference guide (spru514).

The calling conventions describe:

  • How the C environment passes arguments to a function
  • Where the called function should store the return value
  • Which registers will be saved and restored by the caller
  • Which registers will be saved and restored by the called function

Also refer to:

Undefined Symbols

Q: When I build I get a bunch of undefined symbols with $ in them like FS$$MPY, FS$$TOL - what are these?

It appears that you need to include the Run-Time Support (RTS) Library in your project. The RTS library should be in your code generation tools ./lib directory.

Q: When I build I get a linker error that _c_int00 is not defined?

_c_int00 is a sample bootstrap routine is provided in the Run-Time Support (RTS) Library. The RTS library should be in your code generation tools ./lib directory.

Linker Questions

Q: Where is the linker command file format documented?

Please refer to TMS320C28x Assembly Language Tools User's Guide (spru513)

Q: Where can I learn more about linking?

For Frequently Asked Linker questions - Please see the C28x_Compiler - Understanding Linking Wiki Article

C I/O (printf(), sprintf(), puts())

Q: I'm trying to add printf() to my project and it doesn't work. Help!

Please see Tips for using printf Wiki Article.

Q: printf()/sprintf() in 5.2.x seems to be using a lot more stack than older tools?

The printf routines were reworked to support multiple levels of support for printf format specifiers and general clean up to reduce code size and overall memory size (including bss). The function _printf (which is indirectly called from sprintf) uses a local array with a size of 400 elements. This has always been there and needs to be that big to be compliant, and we want to avoid using malloc. The difference is that in earlier versions of the tools, this array was previously static and went into bss instead of on the stack. The thinking behind this was that if the user is using C I/O they would probably be using a decent stack size anyway and still want to minimize bss.

Q: I don't need all the features of printf()/sprintf(). Can I do something to minimize size?

Knowing that the C I/O support may not suit every user as provided, we support the different levels of format specifier (via the compiler option --printf_support=full, minimal, nofloat) and also provide source so customers can change it to suit their needs. For instance, the source file _printfi.c can be changed to make the array static and _printfi.c can be recompiled.

Enable support for smaller, limited versions of the printf and sprintf run-time-support functions:
--printf_support={full|nofloat|minimal}
The valid values are:
  • full: Supports all format specifiers. This is the default.
  • nofloat: Excludes support for printing floating point values. Supports all format specifiers except %f, %g, %G, %e, and %E.
  • minimal: Supports the printing of integer, char, or string values without width or precision flags. Specifically, only the %%, %d, %o, %c, %s, and %x format specifiers are supported

There is no run-time error checking to detect if a format specifier is used for which support is not included. The --printf_support option precedes the --run_linker option, and must be used when performing the final link.

Industry Standards

Q: Does the 28x compiler conform to any industry standard?

Please see TI_Compilers_and_Industry_Standards Wiki Article

Extensions

Q: Does the 28x compiler support GCC extensions?

Please see the GCC Extensions in TI Compilers Wiki Article

Q: Does the 28x compiler support C99 extensions?

Please see the C99 Extensions Supported in C89 Mode in TI Compilers Wiki Article

Error Messages

Please refer to the C28x Common Compiler Errors and Warinings Wiki article.

Updates and Issues

Q: How can I keep abreast of the known issues with the codegen tools?

The known issues are stored in a ClearQuest database. There are two ways to access that database:
  1. Access incident reports can be achieved via that link: https://cqweb.ext.ti.com/cqweb/main?command=GenerateMainFrame&service=CQ&schema=SDo-Web&contextid=SDOWP&username=readonly&password=readonly. Individual incident reports can be accessed (‘SDSCM000XXXXX’) in the ‘Find Record ID’ box.
  2. Extended account creation and other resources can be performed via that page: https://cqweb.ext.ti.com/pages/SDO-Web.html
  • Customers with special needs (e.g. privacy) can request the creation of personalized ClearQuest accounts at this page: https://cqweb.ext.ti.com/cgi-bin/Groups/SDO-Web/AccountRequest.pl
    Such an account allows customers to create and store own database queries. As the reasoning for the special need might already by special its rather recommended to ask your FAE about that instead of using that web method. Also the right for creating your own incident reports might be granted only by going via your FAE contact.
  • On that page there is also a link to the ClearQuest web based help: https://cqweb.ext.ti.com/pages/help/CQWEB-help.htm
There are a number of ways a customer can keep up-to-date on C2000 compiler issues through the ClearQuest web interface. There are "Public Query" folders that follow the forum structure.
To access compiler bugs open the "Public Queries" folder, then the "Development Tools" folder, then the "TI C-C++ Compiler" folder.
There are several C28x specific queries available from that point. For example, there is a "5.1.X Compiler" defect query that will list all issues against 5.1.X releases.