NOTICE: The Processors Wiki will End-of-Life on January 15, 2021. It is recommended to download any files or other content you may need that are hosted on processors.wiki.ti.com. The site is now set to read only.
ROMing Software Components: An RTS Use Case (SPRAAN5)
The application note ROMing Software Components: An RTS Use Case tidoc:spraan5 discusses how to place part of a C6000 application in ROM, and the rest in RAM. This Wiki article discusses differences when doing the same thing for a C5500 system.
There are key items to be aware of when linking against a ROM image using a C5500 device.
- Include a -u option for the name of each function in the ROM that is to be visible to the application. The get_rom_sects.pl script can generate a file with the appropriate -u options.
- For C55x (but not for C55x+), when using the DSECT/NOLOAD Technique, DSECT must be used.
The “overlay” problem is more significant since it is an error message and thus prevents the link from generating and output. The following explains what causes it and why using DSECT is the correct thing to do.
The C55x ISA can perform two instructions in parallel. The way the instruction encoding differentiates between sequential execution of a pair of instructions, “Inst1; Inst2”, and parallel execution, “Inst1 || Inst2” is by turning on a “parallel bit” in Inst2 (not Inst1 as on the C6x). This creates a problem. When an output section created by the linker contains code, trouble can arise if the memory immediately following this section starts with data that appears to have the parallel bit set. When executed the last instruction of the code section would gobble up the data and treat it as a parallel instruction. To prevent this the linker always inserts a one-byte NOP after the end of an output code section. (Note that NOP can never be the first instruction in a parallel pair so the data following a NOP cannot affect the execution of a NOP.)
When building the ROM from functions each in its own section typically we put many .text input subsections together producing a single .text output section that might look something like
.text:_funcA /* 5 bytes of code */ .text:_funcB /* 16 bytes of code */ .text:_funcC NOP ; inserted by linker
Now consider the scripting that creates the file to use when linking against the ROM image. It has lines that look like
.dummy_ROMFinal_out0 { … } (.text:_funcA) > 0x12340, type=NOLOAD .dummy_ROMFinal_out0 { … } (.text:_funcB) > 0x12345, type=NOLOAD .dummy_ROMFinal_out0 { … } (.text:_funcC) > 0x12355, type=NOLOAD
When NOLOAD is used for a section, the linker runs its allocation algorithm for the section even though it does not include the section in the output. This can be useful in the ROM procedures described in the App Note because if the size of a function like funcA somehow ends up larger than the version of funcA that was used when the ROM image was created, the linker will stop with the now familiar error saying that funcA overlays funcB. And on most target architectures this would be fine. But for C55x, since each of the output sections (.dummy…) contains code the allocator inserts the extra one-byte NOP after each of these sections. Now the output section containing funcA requires 6, not 5, bytes and thus overlaps with the output section containing funcB. If these sections had actually been included in the output the layout would have been something like
.text:_funcA /* 5 bytes of code */ NOP ; inserted by linker .text:_funcB /* 16 bytes of code */ NOP ; inserted by linker .text:_funcC NOP ; inserted by linker
This means we have to used DSECT rather than NOLOAD. DSECT does not do the overlap check since the linker does to do allocation for a DSECT section. However, and this is important, the hard-coded addresses used to place the .dummy sections are correct, that is, they accurately reflect where the sections ended up in the actual linked ROM image. (Of course, we no longer will get any indication if one of the functions do change size.)