C28x Compiler - Understanding Linking
C28x Compiler - Understanding Linking
Introduction
This page describes the compiler section names and how to link them in your project. This
article has been written with the C28x flash device in mind.
Other Resources
TMS320C28x Optimizing C/C++ Compiler User's Guide (spru514)
(https://www.ti.com/lit/pdf/spru514)
TMS320C28x Assembly Language Tools User's Guide (spru513) (https://www.ti.com
/lit/pdf/spru513)
The following application note describes in detail how to link code when running in RAM or
Flash. It also includes information on including DSP/BIOS.
The following is great general Code Generation Tools Information. Much of it applies to
C28x:
1 of 10 7/15/2021, 1:59 PM
C28x Compiler - Understanding Linking https://software-dl.ti.com/ccs/esd/documents/c2000_c28x-compiler-unde...
//
// Global variables x & y ==> .ebss
// Initial values 2 & 7 ==> .cinit
//
int x = 2;
int y = 7;
void main()
{
long z; // Local variable => .stack
z = x + y; // Code => .text
}
The Compiler sections are documented in the TMS320C28x Optimizing C/C++ Compiler
User's Guide (spru514) (https://www.ti.com/lit/pdf/spru514).
Once the initial debug is complete and the code works, initialized sections can be moved to
FLASH. Once this is done the code should be tested again.
2 of 10 7/15/2021, 1:59 PM
C28x Compiler - Understanding Linking https://software-dl.ti.com/ccs/esd/documents/c2000_c28x-compiler-unde...
Section Section
Name Description Type Link Location
Notes:
Time-critical code will typically be linked with a load address in flash, and a run
address in SARAM. The application will then copy it from flash to SARAM.
The exception to this rule is a 281x device with external interface. On this device zone 7
3 of 10 7/15/2021, 1:59 PM
C28x Compiler - Understanding Linking https://software-dl.ti.com/ccs/esd/documents/c2000_c28x-compiler-unde...
can be mapped such that the reset vector is in external memory. In this case the .reset
section might be useful.
It's suggested that you start with a linker file from a working example and then modify it
for your needs. The linker command file has two basic parts.
MEMORY
{
PAGE 0: /* Program Space */
H0SARAM: org = 0x00A000, len = 0x2000
PAGE 0 or PAGE 1
PAGE 0 is typically used for program sections. For example .text or other named sections
that contain code.
4 of 10 7/15/2021, 1:59 PM
C28x Compiler - Understanding Linking https://software-dl.ti.com/ccs/esd/documents/c2000_c28x-compiler-unde...
In some legacy Flash programming tools, such as SDFlash, only sections on "PAGE 0"
would be programmed into the flash. Consider the .const section which is data. If .const
was allocated to PAGE 1, the SDFlash flash programmer will ignore it and not program the
data into flash. Since this is initialized data that is constant you really want it programmed
into flash. In some of our examples you will find .const allocated to PAGE 0 for this reason.
Memory blocks on C28x are unified so it does not cause an issue.
In the MEMORY description, these unified blocks can be placed either in page 0 (i.e.
program) or page 1 (i.e. data). It is also possible to split a physical memory block so part
of the block is used by page 0 and another part used by page 1.
Sections Description
This part of the linker command file tells the linker:
5 of 10 7/15/2021, 1:59 PM
C28x Compiler - Understanding Linking https://software-dl.ti.com/ccs/esd/documents/c2000_c28x-compiler-unde...
/* Sections Description
Tell the linker where to allocate sections */
SECTIONS
{
.text: > H0SARAM PAGE 0
.ebss: > M0SARAM PAGE 1
.cinit: > H0SARAM PAGE 0
.stack: > M1SARAM PAGE 1
.reset: > H0SARAM PAGE 0, TYPE = DSECT
}
If you do not specify a generated section then the liker will try to place it for you. This may
result in it being placed somewhere you don't want it to be. For example, the .ebss section
may end up in flash which will not work! To receive a warning message when the linker
assigns unspecified sections use the -w linker switch.
For simple examples it may not matter much what memory is used. But in embedded
processing it quickly does become important.
The linker command file is how you describe your device to the tools and tell it where you
want different sections to go.
If you don't assign a particular section to a memory region then the tools will indeed try to
6 of 10 7/15/2021, 1:59 PM
C28x Compiler - Understanding Linking https://software-dl.ti.com/ccs/esd/documents/c2000_c28x-compiler-unde...
place it in any available memory. This may not be desired for the above reasons. Because
of this I suggest always linking with the -w flag so the tools will tell you it is assigning a
section to memory without your influence.
Q: The linker says "placement fails for object" but the available memory is
larger than the section
This is most likely happening because the section is "blocked" by the compiler. This means
it needs to either fit completely within a page or begin at a page boundary. Meeting that
requirement does not allow it to fit within the space available in the memory block. The
compiler does this to optimize the data page (DP) register load. For example, the compiler
can safely load DP for an array once and access all its elements (or the first 64-words)
without having to reload DP. If blocking is not enabled the compiler has to load DP for
accessing each element leading to much more inefficiencies in terms of code size and
performance.
The alternative would be to generate a DP load before every direct memory access.
Obviously this could have a serious negative impact on code size. There is an option
though that will cause DP loads on every access, and disable blocking. If you add the -md
switch to your project it will disable blocking but impact code size and performance - this is
not recommended.
You can confirm that a particular section is "blocked" by looking at the .bss and .usect
directives in the assembly listing file and checking that the blocking flag is set. The
blocking flag is documented in the C28x Assembly Language Tools Users Guide
(https://www.ti.com/lit/pdf/spru513) under "Uninitialized Sections".
Q: The linker says "placement fails for object '.text' ". How can I make more
memory available for .text?
Option 1
The linker command file (.cmd) specifies how memory will be allocated for the project. You
can try modifying the .cmd file to allow for a larger .text section. For example, you can try
combining contiguous RAM blocks or flash sectors to make a larger block for code.
Option 2
You can "split" the .text section among multiple memory regions using the following
syntax:
Option 3
You can tell the linker to allocate as a whole into the first memory range in which it fits
completely, by doing this:
7 of 10 7/15/2021, 1:59 PM
C28x Compiler - Understanding Linking https://software-dl.ti.com/ccs/esd/documents/c2000_c28x-compiler-unde...
For any of these options, keep in mind that all blocks may not be equal in functionality -
For example:
On the Piccolo devices with Control Law Accelerator only some memory blocks can
be used by the CLA.
On devices with the DMA not all memory can be accessed by the DMA.
Most SARAM blocks are single access (zero wait state) but on some devices there is
a wait state in program memory. For example on 2833x the memories that the DMA
can use are zero wait in data space, but 1 wait in program space. This makes them
more suited towards pure data accesses.
Q: In the linker command file, can I combine continuous flash blocks into one
section?
On the flash side, the thing to keep in mind is a sector is the smallest amount of flash that
can be erased at a time. Thus you may want to partition your code such that code you
upgrade (or don't upgrade) aligns to a sector.
Option 1
Combine two memory regions, in this case two sectors, into one:
Two sectors:
MEMORY
{
//
// Individual sectors E and F called out in the MEMORY description
//
...
FLASHF : origin = 0x310000, length = 0x008000 /* on-chip FLASH */
FLASHE : origin = 0x318000, length = 0x008000 /* on-chip FLASH */
...
}
8 of 10 7/15/2021, 1:59 PM
C28x Compiler - Understanding Linking https://software-dl.ti.com/ccs/esd/documents/c2000_c28x-compiler-unde...
MEMORY
{
//
// Sectors E and F merged into one in the MEMORY description
//
...
FLASHF_E : origin = 0x310000, length = 0x010000 /* on-chip FLASH F & FL
ASH E */
...
}
Option 2
Another option is to split the sections across multiple memory segments. This is described
in the TMS320C28x Assembly Language Tools User's Guide (spru513) (https://www.ti.com
/lit/pdf/spru513).
SECTIONS
{
.text: { *(.text) } >> FLASHE| FLASHH
}
Q: In the linker command file, I combine contiguous SARAM blocks into one
section?
Yes, you can do this by combining memory blocks or splitting the section across memory
blocks (described above for flash).
The thing to remember is the SARAM blocks are single access. So it is best to partition
code into a different physical SARAM block than data that code is accessing. Keeping this
partition will will improve performance.
After a project links successfully, a .map file can be generated which provides information
about memory utilization and symbol placement. Please see the TMS320C28x Assembly
Language Tools User's Guide (spru513) (https://www.ti.com/lit/pdf/spru513) for more
information.
9 of 10 7/15/2021, 1:59 PM
C28x Compiler - Understanding Linking https://software-dl.ti.com/ccs/esd/documents/c2000_c28x-compiler-unde...
Resources
TI Code Composer Studio Product Page (https://www.ti.com/tool/CCStudio)
Related Technical Documents (https://software-dl.ti.com/ccs/esd/documents
/ccs_documentation-overview.html)
TI E2E Technical Forums (https://e2e.ti.com)
(https://creativecommons.org/licenses/by-nc-nd/4.0/)
10 of 10 7/15/2021, 1:59 PM