ARM Assembly
Language Tools
v15.9.0.STS User's Guide
SPNU118 - REVISED SEPTEMBER, 2015
12 Hex Conversion Utility Description
The ARM assembler and linker create object files which are in binary formats that encourage modular programming and provide powerful and flexible methods for managing code segments and target system memory.
Most EPROM programmers do not accept object files as input. The hex conversion utility converts an object file into one of several standard ASCII hexadecimal formats, suitable for loading into an EPROM programmer. The utility is also useful in other applications requiring hexadecimal conversion of an object file (for example, when using debuggers and loaders).
The hex conversion utility can produce these output file formats:
- ASCII-Hex, supporting 16-bit addresses
- Extended Tektronix (Tektronix)
- Intel MCS-86 (Intel)
- Motorola Exorciser (Motorola-S), supporting 16-bit addresses
- Texas Instruments SDSMAC (TI-Tagged), supporting 16-bit addresses
- Texas Instruments TI-TXT format, supporting 16-bit addresses
12.1 The Hex Conversion Utility's Role in the Software Development Flow
Figure 12-1 highlights the role of the hex conversion utility in the software development process.
12.2 Invoking the Hex Conversion Utility
There are two basic methods for invoking the hex conversion utility:
- Specify the options and filenames on the command line. The following example converts the file firmware.out into TI-Tagged format, producing two output files, firm.lsb and firm.msb.
- Specify the options and filenames in a command file. You can create a file that stores command line options and filenames for invoking the hex conversion utility. The following example invokes the utility using a command file called hexutil.cmd:
armhex -t firmware -o firm.lsb -o firm.msb
armhex hexutil.cmd
In addition to regular command line information, you can use the hex conversion utility ROMS and SECTIONS directives in a command file.
12.2.1 Invoking the Hex Conversion Utility From the Command Line
To invoke the hex conversion utility, enter:
armhex [options] filename |
armhex | is the command that invokes the hex conversion utility. |
options |
supplies additional information that controls the hex conversion process. You can use options on the command line or in a command file. Table 12-1 lists the basic options.
|
filename | names an object file or a command file (for more information, see Section 12.2.2). |
Table 12-1 Basic Hex Conversion Utility Options
Option | Alias | Description | See |
---|---|---|---|
General Options | |||
--byte | -byte | Number output locations by bytes rather than by target addressing | -- |
--entrypoint=addr | -e | Specify the entry point at which to begin execution after boot loading | Table 12-2 |
--exclude={fname(sname) | sname} |
-exclude | If the filename (fname) is omitted, all sections matching sname will be excluded. | Section 12.7 |
--fill=value | -fill | Fill holes with value | Section 12.9.2 |
--help | -options, -h | Display the syntax for invoking the utility and list available options. If the option is followed by another option or phrase, detailed information about that option or phrase is displayed. | Section 12.2.2 |
--image | -image | Select image mode | Section 12.9.1 |
--linkerfill | -linkerfill | Include linker fill sections in images | -- |
--map=filename | -map | Generate a map file | Section 12.4.2 |
--memwidth=value | -memwidth | Define the system memory word width (default 16 bits) | Section 12.3.2 |
--outfile=filename | -o | Specify an output filename | Section 12.8 |
--quiet | -q | Run quietly (when used, it must appear before other options) | Section 12.2.2 |
--romwidth=value | -romwidth | Specify the ROM device width (default depends on format used). This option is ignored for the TI-TXT and TI-Tagged formats. | Section 12.3.3 |
--zero | -zero, -z | Reset the address origin to 0 in image mode | Section 12.9.3 |
Diagnostic Options | |||
--diag_error=id | Categorizes the diagnostic identified by id as an error | Section 12.12 | |
--diag_remark=id | Categorizes the diagnostic identified by id as a remark | Section 12.12 | |
--diag_suppress=id | Suppresses the diagnostic identified by id | Section 12.12 | |
--diag_warning=id | Categorizes the diagnostic identified by id as a warning | Section 12.12 | |
--display_error_number | Displays a diagnostic's identifiers along with its text | Section 12.12 | |
--issue_remarks | Issues remarks (nonserious warnings) | Section 12.12 | |
--no_warnings | Suppresses warning diagnostics (errors are still issued) | Section 12.12 | |
--set_error_limit=count | Sets the error limit to count. The linker abandons linking after this number of errors. (The default is 100.) | Section 12.12 | |
Output Options | |||
--ascii | -a | Select ASCII-Hex | Section 12.13.1 |
--intel | -i | Select Intel | Section 12.13.2 |
--motorola=1 | -m1 | Select Motorola-S1 | Section 12.13.3 |
--motorola=2 | -m2 | Select Motorola-S2 | Section 12.13.3 |
--motorola=3 | -m3 | Select Motorola-S3 (default -m option) | Section 12.13.3 |
--tektronix | -x | Select Tektronix (default format when no output option is specified) | Section 12.13.4 |
--ti_tagged | -t | Select TI-Tagged | Section 12.13.5 |
--ti_txt | Select TI-Txt | Section 12.13.6 | |
Load Image Options | |||
--load_image | Select load image | Section 12.6 | |
--section_name_prefix=string | Specify the section name prefix for load image object files | Section 12.6 |
12.2.2 Invoking the Hex Conversion Utility With a Command File
A command file is useful if you plan to invoke the utility more than once with the same input files and options. It is also useful if you want to use the ROMS and SECTIONS hex conversion utility directives to customize the conversion process.
Command files are ASCII files that contain one or more of the following:
- Options and filenames. These are specified in a command file in exactly the same manner as on the command line.
- ROMS directive. The ROMS directive defines the physical memory configuration of your system as a list of address-range parameters. (See Section 12.4.)
- SECTIONS directive. The hex conversion utility SECTIONS directive specifies which sections from the object file are selected. (See Section 12.5.)
- Comments. You can add comments to your command file by using the /* and */ delimiters. For example:
/* This is a comment. */
To invoke the utility and use the options you defined in a command file, enter:
armhex command_filename
You can also specify other options and files on the command line. For example, you could invoke the utility by using both a command file and command line options:
armhex firmware.cmd --map=firmware.mxp
The order in which these options and filenames appear is not important. The utility reads all input from the command line and all information from the command file before starting the conversion process. However, if you are using the -q option, it must appear as the first option on the command line or in a command file.
The --help option displays the syntax for invoking the compiler and lists available options. If the --help option is followed by another option or phrase, detailed information about the option or phrase is displayed. For example, to see information about options associated with generating a boot table use --help boot.
The --quiet option suppresses the hex conversion utility's normal banner and progress information.
- Assume that a command file named firmware.cmd contains these lines:
- This example shows how to convert a file called appl.out into eight hex files in Intel format. Each output file is one byte wide and 4K bytes long.
firmware.out /* input file */
--ti-tagged /* TI-Tagged */
--outfile=firm.lsb /* output file */
--outfile=firm.msb /* output file */
You can invoke the hex conversion utility by entering:
armhex firmware.cmd
appl.out /* input file */
--intel /* Intel format */
--map=appl.mxp /* map file */
ROMS
{
ROW1: origin=0x00000000 len=0x4000 romwidth=8
files={ appl.u0 appl.u1 app1.u2 appl.u3 }
ROW2: origin=0x00004000 len=0x4000 romwidth=8
files={ app1.u4 appl.u5 appl.u6 appl.u7 }
}
SECTIONS
{ .text, .data, .cinit, .sect1, .vectors, .const:
}
12.3 Understanding Memory Widths
The hex conversion utility makes your memory architecture more flexible by allowing you to specify memory and ROM widths. To use the hex conversion utility, you must understand how the utility treats word widths. Three widths are important in the conversion process:
- Target width
- Memory width
- ROM width
The terms target word, memory word, and ROM word refer to a word of such a width.
Figure 12-2 illustrates the separate and distinct phases of the hex conversion utility's process flow.
12.3.1 Target Width
Target width is the unit size (in bits) of the target processor's word. The width is fixed for each target and cannot be changed. The ARM targets have a width of 32 bits.
12.3.2 Specifying the Memory Width
Memory width is the physical width (in bits) of the memory system. Usually, the memory system is physically the same width as the target processor width: a 16-bit processor has a 32-bit memory architecture. However, some applications require target words to be broken into multiple, consecutive, and narrower memory words.
By default, the hex conversion utility sets memory width to the target width (in this case, 32 bits).
You can change the memory width (except for TI-TXT format) by:
- Using the --memwidth option. This changes the memory width value for the entire file.
- Setting the memwidth parameter of the ROMS directive. This changes the memory width value for the address range specified in the ROMS directive and overrides the --memwidth option for that range. See Section 12.4.
For both methods, use a value that is a power of 2 greater than or equal to 8.
You should change the memory width default value of 16 only when you need to break single target words into consecutive, narrower memory words.
NOTE
TI-TXT Format is 8 Bits WideYou cannot change the memory width of the TI-TXT format. The TI-TXT hex format supports an 8-bit memory width only.
Figure 12-3 demonstrates how the memory width is related to object file data.
12.3.3 Partitioning Data Into Output Files
ROM width determines how the hex conversion utility partitions the data into output files. ROM width specifies the physical width (in bits) of each ROM device and corresponding output file (usually one byte or eight bits). After the object file data is mapped to the memory words, the memory words are broken into one or more output files. The number of output files is determined by the following formulas:
- If memory width ≥ ROM width:
- If memory width < ROM width:
number of files = memory width ÷ ROM width
number of files = 1
For example, for a memory width of 32, you could specify a ROM width value of 32 and get a single output file containing 32-bit words. Or you can use a ROM width value of 16 to get two files, each containing 16 bits of each word.
The default ROM width that the hex conversion utility uses depends on the output format:
- All hex formats except TI-Tagged are configured as lists of 8-bit bytes; the default ROM width for these formats is 8 bits.
- TI-Tagged is a 16-bit format; the default ROM width for TI-Tagged is 16 bits.
NOTE
The TI-Tagged Format is 16 Bits WideYou cannot change the ROM width of the TI-Tagged format. The TI-Tagged format supports a 16-bit ROM width only.
NOTE
TI-TXT Format is 8 Bits WideYou cannot change the ROM width of the TI-TXT format. The TI-TXT hex format supports only an 8-bit ROM width.
You can change ROM width (except for TI-Tagged and TI-TXT formats) by:
- Using the --romwidth option. This option changes the ROM width value for the entire object file.
- Setting the romwidth parameter of the ROMS directive. This parameter changes the ROM width value for a specific ROM address range and overrides the --romwidth option for that range. See Section 12.4.
For both methods, use a value that is a power of 2 greater than or equal to 8.
If you select a ROM width that is wider than the natural size of the output format, the utility simply writes multibyte fields into the file. The --romwidth option is ignored for the TI-TXT and TI-Tagged formats.
Figure 12-4 illustrates how the object file data, memory, and ROM widths are related to one another.
Memory width and ROM width are used only for grouping the object file data; they do not represent values. Thus, the byte ordering of the object file data is maintained throughout the conversion process. To refer to the partitions within a memory word, the bits of the memory word are always numbered from right to left as follows:
12.4 The ROMS Directive
The ROMS directive specifies the physical memory configuration of your system as a list of address-range parameters.
Each address range produces one set of files containing the hex conversion utility output data that corresponds to that address range. Each file can be used to program one single ROM device.
The ROMS directive is similar to the MEMORY directive of the ARM linker: both define the memory map of the target address space. Each line entry in the ROMS directive defines a specific address range. The general syntax is:
ROMS { |
|||
romname: | [origin=value,] [length=value,] [romwidth=value,] [memwidth=value,] [fill=value] [files={filename1, filename2, ...}] |
||
romname: | [origin=value,] [length=value,] [romwidth=value,] [memwidth=value,] [fill=value] [files={filename1, filename2, ...}] |
||
... | |||
} |
ROMS | begins the directive definition. |
romname | identifies a memory range. The name of the memory range can be one to eight characters in length. The name has no significance to the program; it simply identifies the range, except when the output is for a load image in which case it denotes the section name. (Duplicate memory range names are allowed.) |
origin | specifies the starting address of a memory range. It can be entered as origin, org, or o. The associated value must be a decimal, octal, or hexadecimal constant. If you omit the origin value, the origin defaults to 0. The following table summarizes the notation you can use to specify a decimal, octal, or hexadecimal constant: |
Constant | Notation | Example |
---|---|---|
Hexadecimal | 0x prefix or h suffix | 0x77 or 077h |
Octal | 0 prefix | 077 |
Decimal | No prefix or suffix | 77 |
length | specifies the length of a memory range as the physical length of the ROM device. It can be entered as length, len, or l. The value must be a decimal, octal, or hexadecimal constant. If you omit the length value, it defaults to the length of the entire address space. |
romwidth | specifies the physical ROM width of the range in bits (see Section 12.3.3). Any value you specify here overrides the --romwidth option. The value must be a decimal, octal, or hexadecimal constant that is a power of 2 greater than or equal to 8. |
memwidth | specifies the memory width of the range in bits (see Section 12.3.2). Any value you specify here overrides the --memwidth option. The value must be a decimal, octal, or hexadecimal constant that is a power of 2 greater than or equal to 8. When using the memwidth parameter, you must also specify the paddr parameter for each section in the SECTIONS directive. (See Section 12.5.) |
fill | specifies a fill value to use for the range. In image mode, the hex conversion utility uses this value to fill any holes between sections in a range. A hole is an area between the input sections that comprises an output section that contains no actual code or data. The fill value must be a decimal, octal, or hexadecimal constant with a width equal to the target width. Any value you specify here overrides the --fill option. When using fill, you must also use the --image command line option. (See Section 12.9.2.) |
files | identifies the names of the output files that correspond to this range. Enclose the list of names in curly braces and order them from least significant to most significant output file, where the bits of the memory word are numbered from right to left. The number of file names must equal the number of output files that the range generates. To calculate the number of output files, see Section 12.3.3. The utility warns you if you list too many or too few filenames. |
Unless you are using the --image option, all of the parameters that define a range are optional; the commas and equal signs are also optional. A range with no origin or length defines the entire address space. In image mode, an origin and length are required for all ranges.
Ranges must not overlap and must be listed in order of ascending address.
12.4.1 When to Use the ROMS Directive
If you do not use a ROMS directive, the utility defines a single default range that includes the entire address space. This is equivalent to a ROMS directive with a single range without origin or length.
Use the ROMS directive when you want to:
- Program large amounts of data into fixed-size ROMs. When you specify memory ranges corresponding to the length of your ROMs, the utility automatically breaks the output into blocks that fit into the ROMs.
- Restrict output to certain segments. You can also use the ROMS directive to restrict the conversion to a certain segment or segments of the target address space. The utility does not convert the data that falls outside of the ranges defined by the ROMS directive. Sections can span range boundaries; the utility splits them at the boundary into multiple ranges. If a section falls completely outside any of the ranges you define, the utility does not convert that section and issues no messages or warnings. Thus, you can exclude sections without listing them by name with the SECTIONS directive. However, if a section falls partially in a range and partially in unconfigured memory, the utility issues a warning and converts only the part within the range.
- Use image mode. When you use the --image option, you must use a ROMS directive. Each range is filled completely so that each output file in a range contains data for the whole range. Holes before, between, or after sections are filled with the fill value from the ROMS directive, with the value specified with the --fill option, or with the default value of 0.
12.4.2 An Example of the ROMS Directive
The ROMS directive in Example 12-1 shows how 16K bytes of 16-bit memory could be partitioned for two 8K-byte 8-bit EPROMs. Figure 12-5 illustrates the input and output files.
Example 12-1 A ROMS Directive Example
infile.out
--image
--memwidth 16
ROMS
{
EPROM1: org = 0x00004000, len = 0x2000, romwidth = 8
files = { rom4000.b0, rom4000.b1}
EPROM2: org = 0x00006000, len = 0x2000, romwidth = 8,
fill = 0xFF00FF00,
files = { rom6000.b0, rom6000.b1}
}
The map file (specified with the --map option) is advantageous when you use the ROMS directive with multiple ranges. The map file shows each range, its parameters, names of associated output files, and a list of contents (section names and fill values) broken down by address. Example 12-2 is a segment of the map file resulting from the example in Example 12-1.
Example 12-2 Map File Output From Example 12-1 Showing Memory Ranges
-----------------------------------------------------
00004000..00005fff Page=0 Width=8 "EPROM1"-----------------------------------------------------
OUTPUT FILES: rom4000.b0 [b0..b7]
rom4000.b1 [b8..b15]
CONTENTS: 00004000..0000487f .text
00004880..00005b7f FILL = 00000000
00005b80..00005fff .data
-----------------------------------------------------
00006000..00007fff Page=0 Width=8 "EPROM2"-----------------------------------------------------
OUTPUT FILES: rom6000.b0 [b0..b7]
rom6000.b1 [b8..b15]
CONTENTS: 00006000..0000633f .data
00006340..000066ff FILL = ff00ff00
00006700..00007c7f .table
00007c80..00007fff FILL = ff00ff00
EPROM1 defines the address range from 0x00004000 through 0x00005FFF with the following sections:
This section ... | Has this range ... | |
---|---|---|
.text | 0x00004000 through 0x0000487F | |
.data | 0x00005B80 through 0x00005FFF |
The rest of the range is filled with 0h (the default fill value), converted into two output files:
- rom4000.b0 contains bits 0 through 7
- rom4000.b1 contains bits 8 through 15
EPROM2 defines the address range from 0x00006000 through 0x00007FFF with the following sections:
This section ... | Has this range ... | |
---|---|---|
.data | 0x00006000 through 0x0000633F | |
.table | 0x00006700 through 0x00007C7F |
The rest of the range is filled with 0xFF00FF00 (from the specified fill value). The data from this range is converted into two output files:
- rom6000.b0 contains bits 0 through 7
- rom6000.b1 contains bits 8 through 15
12.5 The SECTIONS Directive
You can convert specific sections of the object file by name with the hex conversion utility SECTIONS directive. You can also specify those sections that you want to locate in ROM at a different address than the load address specified in the linker command file. If you:
- Use a SECTIONS directive, the utility converts only the sections that you list in the directive and ignores all other sections in the object file.
- Do not use a SECTIONS directive, the utility converts all initialized sections that fall within the configured memory.
Uninitialized sections are never converted, whether or not you specify them in a SECTIONS directive.
NOTE
Sections Generated by the C/C++ CompilerThe ARM C/C++ compiler automatically generates these sections:
- Initialized sections: .text, .const, .cinit, and .switch
- Uninitialized sections:.bss, .stack, and .sysmem
Use the SECTIONS directive in a command file. (See Section 12.2.2.) The general syntax is:
SECTIONS { |
|
oname(sname)[:] [paddr=value] oname(sname)[:] [paddr= boot] oname(sname)[:] [boot] ... } |
SECTIONS | begins the directive definition. |
oname | identifies the object filename the section is located within. The filename is optional when only a single input file is given, but required otherwise. |
sname | identifies a section in the input file. If you specify a section that does not exist, the utility issues a warning and ignores the name. |
paddr=value | specifies the physical ROM address at which this section should be located. This value overrides the section load address given by the linker. This value must be a decimal, octal, or hexadecimal constant. It can also be the word boot (to indicate a boot table section for use with a boot loader). If your file contains multiple sections, and if one section uses a paddr parameter, then all sections must use a paddr parameter. |
boot | configures a section for loading by a boot loader. This is equivalent to using paddr=boot. Boot sections have a physical address determined by the location of the boot table. The origin of the boot table is specified with the --bootorg option. |
For more similarity with the linker's SECTIONS directive, you can use colons after the section names (in place of the equal sign on the boot keyboard). For example, the following statements are equivalent:
SECTIONS { .text: .data: boot }
SECTIONS { .text: .data = boot }
In the example below, the object file contains six initialized sections: .text, .data, .const, .vectors, .coeff, and .tables. Suppose you want only .text and .data to be converted. Use a SECTIONS directive to specify this:
SECTIONS { .text: .data: }
To configure both of these sections for boot loading, add the boot keyword:
SECTIONS { .text = boot .data = boot }
12.6 The Load Image Format (--load_image Option)
A load image is an object file which contains the load addresses and initialized sections of one or more executable files. The load image object file can be used for ROM masking or can be relinked in a subsequent link step.
12.6.1 Load Image Section Formation
The load image sections are formed by collecting the initialized sections from the input executables. There are two ways the load image sections are formed:
- Using the ROMS Directive. Each memory range that is given in the ROMS directive denotes a load image section. The romname is the section name. The origin and length parameters are required. The memwidth, romwidth, and files parameters are invalid and are ignored.
- Default Load Image Section Formation. If no ROMS directive is given, the load image sections are formed by combining contiguous initialized sections in the input executables. Sections with gaps smaller than the target word size are considered contiguous.
When using the ROMS directive and the load_image option, the --image option is required.
The default section names are image_1, image_2, ... If another prefix is desired, the --section_name_prefix=prefix option can be used.
12.6.2 Load Image Characteristics
All load image sections are initialized data sections. In the absence of a ROMS directive, the load/run address of the load image section is the load address of the first input section in the load image section. If the SECTIONS directive was used and a different load address was given using the paddr parameter, this address will be used.
The load image format always creates a single load image object file. The format of the load image object file is determined based on the input files. The file is not marked executable and does not contain an entry point. The default load image object file name is ti_load_image.obj. This can be changed using the --outfile option. Only one --outfile option is valid when creating a load image, all other occurrences are ignored.
NOTE
Concerning Load Image FormatThese options are invalid when creating a load image:
- --memwidth
- --romwidth
- --zero
- --byte
If a boot table is being created, either using the SECTIONS directive or the --boot option, the ROMS directive must be used.
12.7 Excluding a Specified Section
The --exclude section_name option can be used to inform the hex utility to ignore the specified section. If a SECTIONS directive is used, it overrides the --exclude option.
For example, if a SECTIONS directive containing the section name mysect is used and an --exclude mysect is specified, the SECTIONS directive takes precedence and mysect is not excluded.
The --exclude option has a limited wildcard capability. The * character can be placed at the beginning or end of the name specifier to indicate a suffix or prefix, respectively. For example, --exclude sect* disqualifies all sections that begin with the characters sect.
If you specify the --exclude option on the command line with the * wildcard, use quotes around the section name and wildcard. For example, --exclude"sect*". Using quotes prevents the * from being interpreted by the hex conversion utility. If --exclude is in a command file, do not use quotes.
If multiple object files are given, the object file in which the section to be excluded can be given in the form oname(sname). If the object filename is not provided, all sections matching the section name are excluded. Wildcards cannot be used for the filename, but can appear within the parentheses.
12.8 Assigning Output Filenames
When the hex conversion utility translates your object file into a data format, it partitions the data into one or more output files. When multiple files are formed by splitting memory words into ROM words, filenames are always assigned in order from least to most significant, where bits in the memory words are numbered from right to left. This is true, regardless of target or endian ordering.
The hex conversion utility follows this sequence when assigning output filenames:
- It looks for the ROMS directive. If a file is associated with a range in the ROMS directive and you have included a list of files (files = {. . .}) on that range, the utility takes the filename from the list.
- It looks for the --outfile options. You can specify names for the output files by using the --outfile option. If no filenames are listed in the ROMS directive and you use --outfile options, the utility takes the filename from the list of --outfile options. The following line has the same effect as the example above using the ROMS directive:
- It assigns a default filename. If you specify no filenames or fewer names than output files, the utility assigns a default filename. A default filename consists of the base name from the input file plus a 2- to 3-character extension. The extension has three parts:
- A format character, based on the output format (see Section 12.13):
- The range number in the ROMS directive. Ranges are numbered starting with 0. If there is no ROMS directive, or only one range, the utility omits this character.
- The file number in the set of files for the range, starting with 0 for the least significant file.
a for ASCII-Hex i for Intel m for Motorola-S t for TI-Tagged x for Tektronix
For example, assume that the target data is 32-bit words being converted to four files, each eight bits wide. To name the output files using the ROMS directive, you could specify:
ROMS
{
RANGE1: romwidth=8, files={ xyz.b0 xyz.b1 xyz.b2 xyz.b3 }
}
The utility creates the output files by writing the least significant bits to xyz.b0 and the most significant bits to xyz.b3.
--outfile=xyz.b0 --outfile=xyz.b1 --outfile=xyz.b2 --outfile=xyz.b3
If both the ROMS directive and --outfile options are used together, the ROMS directive overrides the --outfile options.
For example, assume a.out is for a 32-bit target processor and you are creating Intel format output. With no output filenames specified, the utility produces four output files named a.i0, a.i1, a.i2, a.i3.
If you include the following ROMS directive when you invoke the hex conversion utility, you would have eight output files:
ROMS
{
range1: o = 0x00001000 l = 0x1000
range2: o = 0x00002000 l = 0x1000
}
These output files ... | Contain data in these locations ... |
---|---|
a.i00, a.i01, a.i02, a.i03 | 0x00001000 through 0x00001FFF |
a.i10, a.i11, a.i12, a.i13 | 0x00002000 through 0x00002FFF |
12.9 Image Mode and the --fill Option
This section points out the advantages of operating in image mode and describes how to produce output files with a precise, continuous image of a target memory range.
12.9.1 Generating a Memory Image
With the --image option, the utility generates a memory image by completely filling all of the mapped ranges specified in the ROMS directive.
An object file consists of blocks of memory (sections) with assigned memory locations. Typically, all sections are not adjacent: there are holes between sections in the address space for which there is no data. When such a file is converted without the use of image mode, the hex conversion utility bridges these holes by using the address records in the output file to skip ahead to the start of the next section. In other words, there may be discontinuities in the output file addresses. Some EPROM programmers do not support address discontinuities.
In image mode, there are no discontinuities. Each output file contains a continuous stream of data that corresponds exactly to an address range in target memory. Any holes before, between, or after sections are filled with a fill value that you supply.
An output file converted by using image mode still has address records, because many of the hexadecimal formats require an address on each line. However, in image mode, these addresses are always contiguous.
NOTE
Defining the Ranges of Target MemoryIf you use image mode, you must also use a ROMS directive. In image mode, each output file corresponds directly to a range of target memory. You must define the ranges. If you do not supply the ranges of target memory, the utility tries to build a memory image of the entire target processor address space. This is potentially a huge amount of output data. To prevent this situation, the utility requires you to explicitly restrict the address space with the ROMS directive.
12.9.2 Specifying a Fill Value
The --fill option specifies a value for filling the holes between sections. The fill value must be specified as an integer constant following the --fill option. The width of the constant is assumed to be that of a word on the target processor. For example, specifying --fill=0xFFFF results in a fill pattern of 0x0000FFFF. The constant value is not sign extended.
The hex conversion utility uses a default fill value of 0 if you do not specify a value with the fill option. The --fill option is valid only when you use --image; otherwise, it is ignored.
12.9.3 Steps to Follow in Using Image Mode
Step 1: | Define the ranges of target memory with a ROMS directive. See Section 12.4. |
Step 2: | Invoke the hex conversion utility with the --image option. You can optionally use the --zero option to reset the address origin to 0 for each output file. If you do not specify a fill value with the ROMS directive and you want a value other than the default of 0, use the --fill option. |
12.10 Building a Table for an On-Chip Boot Loader
The ARM hex utility provides the ability to create a boot table for use with an on-chip boot loader. The supported boot formats are intended for use on C28x devices with ARM cores. The boot table is stored in memory or loaded from a device peripheral to initialize code or data.
See Section 3.1.2 for a general discussion of bootstrap loading.
12.10.1 Description of the Boot Table
The input for a boot loader is the boot table. The boot table contains records that instruct the on-chip loader to copy blocks of data contained in the table to specified destination addresses. The table can be stored in memory (such as EPROM) or read in through a device peripheral (such as a serial or communications port).
The hex conversion utility automatically builds the boot table for the boot loader. Using the utility, you specify the sections you want the boot loader to initialize and the table location. The hex conversion utility builds a complete image of the table according to the format specified and converts it into hexadecimal in the output files. Then, you can burn the table into ROM or load it by other means.
12.10.2 The Boot Table Format
The boot table format is simple. Typically, there is a header record containing a key value that indicates memory width, entry point, and values for control registers. Each subsequent block has a header containing the size and destination address of the block followed by data for the block. Multiple blocks can be entered. The table ends with a header containing size zero.
12.10.3 How to Build the Boot Table
Table 12-2 summarizes the hex conversion utility options available for the boot loader.
Table 12-2 Boot-Loader Options
Option | Description |
---|---|
--boot | Convert all sections into bootable form (use instead of a SECTIONS directive). |
--bootorg=value | Specify the source address of the boot-loader table. |
--entrypoint=value | Specify the entry point at which to begin execution after boot loading. The value can be an address or a global symbol. |
--gpio8 | Specify the source of the boot-loader table as the GP I/O port, 8-bit mode |
--gpio16 | Specify the source of the boot-loader table as the GP I/O port, 16-bit mode |
--lospcp=value | Specify the initial value for the LOSPCP register. The value is used only for the spi8 boot table format and is ignored for all other formats. A value greater than 0x7F is truncated to 0x7F. |
--spi8 | Specify the source of the boot-loader table as the SPI-A port, 8-bit mode |
--spibrr=value | Specify the initial value for the SPIBRR register. The value is used only for the spi8 boot table format and is ignored for all other formats. A value greater than 0x7F is truncated to 0x7F. |
12.10.3.1 Building the Boot Table
To build the boot table, follow these steps:
Step 1: | Link the file. Each block of the boot table data corresponds to an initialized section in the object file. Uninitialized sections are not converted by the hex conversion utility (see Section 12.5). |
When you select a section for placement in a boot-loader table, the hex conversion utility places the section's load address in the destination address field for the block in the boot table. The section content is then treated as raw data for that block. The hex conversion utility does not use the section run address. When linking, you need not worry about the ROM address or the construction of the boot table; the hex conversion utility handles this. | |
Step 2: | Identify the bootable sections. You can use the --boot option to tell the hex conversion utility to configure all sections for boot loading. Or, you can use a SECTIONS directive to select specific sections to be configured (see Section 12.5). If you use a SECTIONS directive, the --boot option is ignored. |
Step 3: | Set the boot table format. Specify the --gpio8, --gpio16, or --spi8 options to set the source format of the boot table. You do not need to specify the memwidth and romwidth as the utility will set these formats automatically. If --memwidth and --romwidth are used after a format option, they override the default for the format. |
Step 4: | Set the ROM address of the boot table. Use the --bootorg option to set the source address of the complete table. |
Step 5: | Set boot-loader-specific options. Set entry point and control register values as needed. |
Step 6: | Describe your system memory configuration. See Section 12.3 and Section 12.4. |
12.10.3.2 Leaving Room for the Boot Table
The complete boot table is similar to a single section containing all of the header records and data for the boot loader. The address of this section is the boot table origin. As part of the normal conversion process, the hex conversion utility converts the boot table to hexadecimal format and maps it into the output files like any other section.
Be sure to leave room in your system memory for the boot table, especially when you are using the ROMS directive. The boot table cannot overlap other nonboot sections or unconfigured memory. Usually, this is not a problem; typically, a portion of memory in your system is reserved for the boot table. Simply configure this memory as one or more ranges in the ROMS directive, and use the --bootorg option to specify the starting address.
12.10.4 Booting From a Device Peripheral
You can choose the port to boot from by using the --gpio8, --gpio16, or --spi8 boot table format option.
The initial value for the LOSPCP register can be specified with the --lospcp option. The initial value for the SPIBRR register can be specified with the --spibrr option. Only the --spi8 format uses these control register values in the boot table.
If the register values are not specified for the --spi8 format, the hex conversion utility uses the default values 0x02 for LOSPCP and 0x7F for SPIBRR. When the boot table format options are specified and the ROMS directive is not specified, the ASCII format hex utility output does not produce the address record.
12.10.5 Setting the Entry Point for the Boot Table
After completing the boot load process, execution starts at the default entry point specified by the linker and contained in the object file. By using the --entrypoint option with the hex conversion utility, you can set the entry point to a different address.
For example, if you want your program to start running at address 0x0123 after loading, specify --entrypoint=0x0123 on the command line or in a command file. You can determine the --entrypoint address by looking at the map file that the linker generates.
NOTE
Valid Entry PointsThe value can be a constant, or it can be a symbol that is externally defined (for example, with a .global) in the assembly source.
12.10.6 Using the ARM Boot Loader
This subsection explains how to use the hex conversion utility with the boot loader for C28x devices with ARM cores. The boot loader accepts the formats listed in Table 12-3.
Table 12-3 Boot Table Source Formats
Format | Option |
---|---|
Parallel boot GP I/O 8 bit | --gpio8 |
Parallel boot GP I/O 16 bit | --gpio16 |
8-bit SPI boot | --spi8 |
The ARM on C28x devices with ARM cores can boot through the SPI-A 8-bit, GP I/O 8-bit, or GP I/I 16-bit interface. The format of the boot table is shown in Table 12-4.
Table 12-4 Boot Table Format
Description | Bytes | Content |
---|---|---|
Boot table header | 1-2 | Key value (0x10AA or 0x08AA) |
3-18 | Register initialization value or reserved for future use | |
19-22 | Entry point | |
Block header | 23-24 | Block size in number of bytes (nl) |
25-28 | Destination address of the block | |
Block data | 29-30 | Raw data for the block (nl bytes) |
Block header | 31 + nl | Block size in number of bytes |
. | Destination address of the block | |
Block data | . | Raw data for the block |
Additional block headers and data, as required | ... | Content as appropriate |
Block header with size 0 | 0x0000; indicates the end of the boot table. |
The ARM on C28x devices with ARM cores can boot through either the serial 8-bit or parallel interface with either 8- or 16-bit data. The format is the same for any combination: the boot table consists of a field containing the destination address, a field containing the length, and a block containing the data. You can boot only one section. If you are booting from an 8-bit channel, 8-bit bytes are stored in the table with MSBs first; the hex conversion utility automatically builds the table in the correct format. Use the following options to specify the boot table source:
- To boot from a SPI-A port, specify --spi8 when invoking the utility. Do not specify --memwidth or --romwidth. Use --lospcp to set the initial value for the LOSPCP register and --spibrr to set the initial value for the SPIBRR register. If the register values are not specified for the --spi8 format, the hex conversion utility uses the default value 0x02 for LOSPCP and 0x7F for SPIBRR.
- To load from a general-purpose parallel I/O port, invoke the utility with --gpio8 or --gpio16. Do not specify --memwidth or --romwidth.
The command file in Example 12-3 allows you to boot the .text and .cinit sections of test.out from a 16-bit-wide EPROM at location 0x3FFC00. The map file test.map is also generated.
Example 12-3 Sample Command File for Booting From 8-Bit SPI Boot
/*---------------------------------------------------------------------------*/
/* Hex converter command file. */
/*---------------------------------------------------------------------------*/
test.out /* Input file */
--ascii /* Select ASCII format */
--map=test.map /* Specify the map file */
--outfile=test_spi8.hex /* Hex utility out file */
--boot /* Consider all the input sections as boot sections */
--spi8 /* Specify the SPI 8-bit boot format */
--lospcp=0x3F /* Set the initial value for the LOSPCP as 0x3F */
/* The -spibrr option is not specified to show that */
/* the hex utility uses the default value (0x7F) */
--entrypoint=0x3F0000 /* Set the entry point */
The command file in Example 12-3 generates the out file in Figure 12-6. The control register values are coded in the boot table header and that header has the address that is specified with the --entrypoint option.
The command file in Example 12-4 allows you to boot the .text and .cinit sections of test.out from the 16-bit parallel GP I/O port. The map file test.map is also generated.
Example 12-4 Sample Command File for ARM 16-Bit Parallel Boot GP I/O
/*---------------------------------------------------------------------*/
/* Hex converter command file. */
/*---------------------------------------------------------------------*/
test.out /* Input file */
--ascii /* Select ASCII format */
--map=test.map /* Specify the map file */
--outfile=test_gpio16.hex /* Hex utility out file */
--gpio16 /* Specify the 16-bit GP I/O boot format */
SECTIONS
{
.text: paddr=BOOT
.cinit: paddr=BOOT
}
The command file in Example 12-4 generates the out file in Figure 12-7.
12.11 Controlling the ROM Device Address
The hex conversion utility output address field corresponds to the ROM device address. The EPROM programmer burns the data into the location specified by the hex conversion utility output file address field. The hex conversion utility offers some mechanisms to control the starting address in ROM of each section. However, many EPROM programmers offer direct control of the location in ROM in which the data is burned.
The address field of the hex-conversion utility output file is controlled by the following items, which are listed from low to high priority:
- The linker command file. By default, the address field of the hex conversion utility output file is the load address (as given in the linker command file).
- The paddr parameter of the SECTIONS directive. When the paddr parameter is specified for a section, the hex conversion utility bypasses the section load address and places the section in the address specified by paddr.
- The --zero option. When you use the --zero option, the utility resets the address origin to 0 for each output file. Since each file starts at 0 and counts upward, any address records represent offsets from the beginning of the file (the address within the ROM) rather than actual target addresses of the data.
- The --byte option. Some EPROM programmers may require the output file address field to contain a byte count rather than a word count. If you use the −byte option, the output file address increments once for each byte. For example, if the starting address is 0h, the first line contains eight words, and you use no −byte option, the second line would start at address 8 (8h). If the starting address is 0h, the first line contains eight words, and you use the −byte option, the second line would start at address 16 (010h). The data in both examples are the same; −byte affects only the calculation of the output file address field, not the actual target processor address of the converted data.
You must use the --zero option in conjunction with the --image option to force the starting address in each output file to be zero. If you specify the --zero option without the --image option, the utility issues a warning and ignores the --zero option.
The --byte option causes the address records in an output file to refer to byte locations within the file, whether the target processor is byte-addressable or not.
12.12 Control Hex Conversion Utility Diagnostics
The hex conversion utility uses certain C/C++ compiler options to control hex-converter-generated diagnostics.
--diag_error=id | Categorizes the diagnostic identified by id as an error. To determine the numeric identifier of a diagnostic message, use the --display_error_number option first in a separate link. Then use --diag_error=id to recategorize the diagnostic as an error. You can only alter the severity of discretionary diagnostics. |
--diag_remark=id | Categorizes the diagnostic identified by id as a remark. To determine the numeric identifier of a diagnostic message, use the --display_error_number option first in a separate link. Then use --diag_remark=id to recategorize the diagnostic as a remark. You can only alter the severity of discretionary diagnostics. |
--diag_suppress=id | Suppresses the diagnostic identified by id. To determine the numeric identifier of a diagnostic message, use the --display_error_number option first in a separate link. Then use --diag_suppress=id to suppress the diagnostic. You can only suppress discretionary diagnostics. |
--diag_warning=id | Categorizes the diagnostic identified by id as a warning. To determine the numeric identifier of a diagnostic message, use the --display_error_number option first in a separate link. Then use --diag_warning=id to recategorize the diagnostic as a warning. You can only alter the severity of discretionary diagnostics. |
--display_error_number | Displays a diagnostic's numeric identifier along with its text. Use this option in determining which arguments you need to supply to the diagnostic suppression options (--diag_suppress, --diag_error, --diag_remark, and --diag_warning). This option also indicates whether a diagnostic is discretionary. A discretionary diagnostic is one whose severity can be overridden. A discretionary diagnostic includes the suffix -D; otherwise, no suffix is present. See the ARM Optimizing C/C++ Compiler User's Guide for more information on understanding diagnostic messages. |
--issue_remarks | Issues remarks (nonserious warnings), which are suppressed by default. |
--no_warnings | Suppresses warning diagnostics (errors are still issued). |
--set_error_limit=count | Sets the error limit to count, which can be any decimal value. The linker abandons linking after this number of errors. (The default is 100.) |
--verbose_diagnostics | Provides verbose diagnostics that display the original source with line-wrap and indicate the position of the error in the source line |
12.13 Description of the Object Formats
The hex conversion utility has options that identify each format. Table 12-5 specifies the format options. They are described in the following sections.
- You need to use only one of these options on the command line. If you use more than one option, the last one you list overrides the others.
- The default format is Tektronix (--tektronix option).
Table 12-5 Options for Specifying Hex Conversion Formats
Option | Alias | Format | Address Bits | Default Width |
---|---|---|---|---|
--ascii | -a | ASCII-Hex | 16 | 8 |
--intel | -i | Intel | 32 | 8 |
--motorola=1 | -m1 | Motorola-S1 | 16 | 8 |
--motorola=2 | -m2 | Motorola-S2 | 24 | 8 |
--motorola=3 | -m3 | Motorola-S3 | 32 | 8 |
--ti-tagged | -t | TI-Tagged | 16 | 16 |
--ti_txt | TI_TXT | 8 | 8 | |
--tektronix | -x | Tektronix | 32 | 8 |
Address bits determine how many bits of the address information the format supports. Formats with 16-bit addresses support addresses up to 64K only. The utility truncates target addresses to fit in the number of available bits.
The default width determines the default output width of the format. You can change the default width by using the --romwidth option or by using the romwidth parameter in the ROMS directive. You cannot change the default width of the TI-Tagged format, which supports a 16-bit width only.
12.13.1 ASCII-Hex Object Format (--ascii Option)
The ASCII-Hex object format supports 16-bit addresses. The format consists of a byte stream with bytes separated by spaces. Figure 12-8 illustrates the ASCII-Hex format.
The file begins with an ASCII STX character (ctrl-B, 02h) and ends with an ASCII ETX character (ctrl-C, 03h). Address records are indicated with $AXXXXXXX, in which XXXXXXXX is a 8-digit (16-bit) hexadecimal address. The address records are present only in the following situations:
- When discontinuities occur
- When the byte stream does not begin at address 0
You can avoid all discontinuities and any address records by using the --image and --zero options. This creates output that is simply a list of byte values.
12.13.2 Intel MCS-86 Object Format (--intel Option)
The Intel object format supports 16-bit addresses and 32-bit extended addresses. Intel format consists of a 9-character (4-field) prefix (which defines the start of record, byte count, load address, and record type), the data, and a 2-character checksum suffix.
The 9-character prefix represents three record types:
Record Type | Description |
---|---|
00 | Data record |
01 | End-of-file record |
04 | Extended linear address record |
Record type00, the data record, begins with a colon ( : ) and is followed by the byte count, the address of the first data byte, the record type (00), and the checksum. The address is the least significant 16 bits of a 32-bit address; this value is concatenated with the value from the most recent 04 (extended linear address) record to create a full 32-bit address. The checksum is the 2s complement (in binary form) of the preceding bytes in the record, including byte count, address, and data bytes.
Record type 01, the end-of-file record, also begins with a colon ( : ), followed by the byte count, the address, the record type (01), and the checksum.
Record type 04, the extended linear address record, specifies the upper 16 address bits. It begins with a colon ( : ), followed by the byte count, a dummy address of 0h, the record type (04), the most significant 16 bits of the address, and the checksum. The subsequent address fields in the data records contain the least significant bytes of the address.
Figure 12-9 illustrates the Intel hexadecimal object format.
12.13.3 Motorola Exorciser Object Format (--motorola Option)
The Motorola S1, S2, and S3 formats support 16-bit, 24-bit, and 32-bit addresses, respectively. The formats consist of a start-of-file (header) record, data records, and an end-of-file (termination) record. Each record consists of five fields: record type, byte count, address, data, and checksum. The three record types are:
Record Type | Description |
---|---|
S0 | Header record |
S1 | Code/data record for 16-bit addresses (S1 format) |
S2 | Code/data record for 24-bit addresses (S2 format) |
S3 | Code/data record for 32-bit addresses (S3 format) |
S7 | Termination record for 32-bit addresses (S3 format) |
S8 | Termination record for 24-bit addresses (S2 format) |
S9 | Termination record for 16-bit addresses (S1 format) |
The byte count is the character pair count in the record, excluding the type and byte count itself.
The checksum is the least significant byte of the 1s complement of the sum of the values represented by the pairs of characters making up the byte count, address, and the code/data fields.
Figure 12-10 illustrates the Motorola-S object format.
12.13.4 Extended Tektronix Object Format (--tektronix Option)
The Tektronix object format supports 32-bit addresses and has two types of records:
Data records | contains the header field, the load address, and the object code. |
Termination records | signifies the end of a module. |
The header field in the data record contains the following information:
Item | Number of ASCII Characters | Description |
---|---|---|
% | 1 | Data type is Tektronix format |
Block length | 2 | Number of characters in the record, minus the % |
Block type | 1 | 6 = data record 8 = termination record |
Checksum | 2 | A 2-digit hex sum modulo 256 of all values in the record except the % and the checksum itself. |
The load address in the data record specifies where the object code will be located. The first digit specifies the address length; this is always 8. The remaining characters of the data record contain the object code, two characters per byte.
Figure 12-11 illustrates the Tektronix object format.
12.13.5 Texas Instruments SDSMAC (TI-Tagged) Object Format (--ti_tagged Option)
The Texas Instruments SDSMAC (TI-Tagged) object format supports 16-bit addresses, including start-of-file record, data records, and end-of-file record. Each data records consists of a series of small fields and is signified by a tag character:
Tag Character | Description |
---|---|
K | Followed by the program identifier |
7 | Followed by a checksum |
8 | Followed by a dummy checksum (ignored) |
9 | Followed by a 16-bit load address |
B | Followed by a data word (four characters) |
F | Identifies the end of a data record |
* | Followed by a data byte (two characters) |
Figure 12-12 illustrates the tag characters and fields in TI-Tagged object format.
If any data fields appear before the first address, the first field is assigned address 0000h. Address fields may be expressed but not required for any data byte. The checksum field, preceded by the tag character 7, is the 2s complement of the sum of the 8-bit ASCII values of characters, beginning with the first tag character and ending with the checksum tag character (7 or 8). The end-of-file record is a colon ( : ).
12.13.6 TI-TXT Hex Format (--ti_txt Option)
The TI-TXT hex format supports 16-bit hexadecimal data. It consists of section start addresses, data byte, and an end-of-file character. These restrictions apply:
- The number of sections is unlimited.
- Each hexadecimal start address must be even.
- Each line must have 16 data bytes, except the last line of a section.
- Data bytes are separated by a single space.
- The end-of-file termination tag q is mandatory.
The data record contains the following information:
Item | Description |
---|---|
@ADDR | Hexadecimal start address of a section |
DATAn | Hexadecimal data byte |
q | End-of-file termination character |
Example 12-5 TI-TXT Object Format
@F000
31 40 00 03 B2 40 80 5A 20 01 D2 D3 22 00 D2 E3
21 00 3F 40 E8 FD 1F 83 FE 23 F9 3F
@FFFE
00 F0
Q
Copyright© 2015, Texas Instruments Incorporated. An IMPORTANT NOTICE for this document addresses availability, warranty, changes, use in safety-critical applications, intellectual property matters and other important disclaimers.