Initial
This commit is contained in:
361
as68hc11/DOCS/S-RECORD.TXT
Normal file
361
as68hc11/DOCS/S-RECORD.TXT
Normal file
@@ -0,0 +1,361 @@
|
||||
S-Record Format
|
||||
|
||||
A file in Motorola S-record format is an ASCII file. There are three different
|
||||
formats:
|
||||
|
||||
S19 for 16-bit address
|
||||
S2 for 24-bit address
|
||||
S3 for 32-bit address
|
||||
|
||||
|
||||
The files consist of optional symbol table information, data specifications
|
||||
for loading memory, and a terminator record.
|
||||
|
||||
[ $$ {module_record}
|
||||
symbol records
|
||||
$$ [ module_record ]
|
||||
symbol_records
|
||||
$$]
|
||||
header_record
|
||||
data_records
|
||||
record_count_record
|
||||
terminator_record
|
||||
|
||||
|
||||
Module Record (Optional)
|
||||
|
||||
Each object file contains one record for each module that is a component of it. This
|
||||
record contains the name of the module. There is one module record for each relocatable
|
||||
object created by the assembler. The name of the relocatable object module
|
||||
contained in the record comes from the IDNT directive. For absolute objects created
|
||||
by the linker, there is one module record for each relocatable object file linked,
|
||||
plus an additional record whose name comes from the NAME command for the
|
||||
linker.
|
||||
|
||||
Example:
|
||||
|
||||
$$ MODNAME
|
||||
|
||||
|
||||
Symbol Record (Optional)
|
||||
|
||||
As many symbol records as needed can be contained in the object module. Up to 4
|
||||
symbols per line can be used, but it is not mandatory that each line contain 4
|
||||
symbols. A module can contain only symbol records.
|
||||
|
||||
Example:
|
||||
|
||||
APPLE $00000 LABEL1 $ODOC3
|
||||
MEM $OFFFF ZEEK $01947
|
||||
|
||||
The module name associated with the symbols can be specified in the
|
||||
module_record preceding the symbol records.
|
||||
|
||||
Example:
|
||||
|
||||
$$MAIN
|
||||
|
||||
Symbols are assumed to be in the module named in the preceding module_record
|
||||
until another module is specified with another module_record. Symbols defined by
|
||||
the linker's PUBLIC command appear following the first module record, which
|
||||
indicates the name of the output object module specified by the linker's NAME
|
||||
command.
|
||||
|
||||
|
||||
*****************************************************************************************
|
||||
|
||||
Header Record (SO)
|
||||
|
||||
Each object module has exactly one header record with the following format:
|
||||
|
||||
S00600004844521B
|
||||
|
||||
Description:
|
||||
|
||||
S0 Identifies the record as a header record
|
||||
06 The number of bytes following this one
|
||||
0000 The address field, which is ignored
|
||||
484452 The string HDR in ASCII
|
||||
1B The checksum
|
||||
|
||||
|
||||
|
||||
*****************************************************************************************
|
||||
|
||||
Data Record (S1)
|
||||
|
||||
A data record specifies data bytes that are to be loaded into memory. Figure 1
|
||||
shows the format for such a record. The columns shown in the figure represent half
|
||||
of a byte (4 bits).
|
||||
|
||||
---------------------------------------------
|
||||
| 1 2 3 4 5 6 7 8 9 ... 40 41 42 |
|
||||
| |
|
||||
| S ID byte load data...data checksum |
|
||||
| count address 1 n |
|
||||
---------------------------------------------
|
||||
Figure 1: Data Record Formatter 16-Bit Load Address
|
||||
|
||||
|
||||
Column Description
|
||||
|
||||
1 Contains the ASCII character S, which indicates the start of
|
||||
a record in Motorola S-record format.
|
||||
|
||||
2 Contains the ASCII character identifying the record type.
|
||||
For data records, this character is 1.
|
||||
|
||||
3 to 4 Contain the count of the number of bytes following this one
|
||||
within the record. The count includes the checksum and the
|
||||
load address bytes but not the byte count itself.
|
||||
|
||||
5 to 8 Contain the load address. The first data byte is to be loaded
|
||||
into this address and subsequent bytes into the next sequential
|
||||
address. Columns 5 and 6 contain the high-order address
|
||||
byte, and columns 7 and 8 contain the low-order address byte.
|
||||
|
||||
9 to 40 Contain the specifications for up to 16 bytes of data.
|
||||
|
||||
41 to 42 Contain a checksum for the record. To calculate this, take the
|
||||
sum of the values of all bytes from the byte count up to the
|
||||
last data byte, inclusive, modulo 256. Subtract this result
|
||||
from 255.
|
||||
|
||||
|
||||
*****************************************************************************************
|
||||
|
||||
Data Record (S2)
|
||||
|
||||
|
||||
A data record specifies data bytes that are to be loaded into memory. Figure 2
|
||||
shows the format for such a record. The columns shown in the figure represent half
|
||||
of a byte (4 bits).
|
||||
|
||||
|
||||
----------------------------------------------------
|
||||
| 1 2 3 4 5 6 7 8 9 10 11 ... 42 43 44 |
|
||||
| |
|
||||
| S ID byte load data...data checksum |
|
||||
| count address 1 n |
|
||||
----------------------------------------------------
|
||||
Figure 2: Data Record Format for 24-Bit Load Address
|
||||
|
||||
Column Description
|
||||
|
||||
1 Contains the ASCII character S, which indicates the start of
|
||||
a record in Motorola S-record format.
|
||||
|
||||
2 Contains the ASCII character identifying the record type.
|
||||
For data records, this character is 2.
|
||||
|
||||
3 to 4 Contain the count of the number of bytes following this one
|
||||
within the record. The count includes the checksum and the
|
||||
load address bytes but not the byte count itself.
|
||||
|
||||
5 to 10 Contain the load address. The first data byte is to be loaded
|
||||
into this address and subsequent bytes into the next sequential
|
||||
address. Columns 5 and 6 contain the high-order address
|
||||
byte, and columns 9 and 10 contain the low-order address byte.
|
||||
|
||||
11 to 42 Contain the specifications for up to 16 bytes of data.
|
||||
|
||||
43 to 44 Contain a checksum for the record. To calculate this, take the
|
||||
sum of the values of all bytes from the byte count up to the
|
||||
last data byte, inclusive, modulo 256. Subtract this result
|
||||
from 255.
|
||||
|
||||
|
||||
*****************************************************************************************
|
||||
|
||||
Data Record (S3)
|
||||
|
||||
|
||||
A data record specifies data bytes that are to be loaded into memory. Figure 3
|
||||
shows the format for such a record. The columns shown in the figure represent half
|
||||
of a byte (4 bits).
|
||||
|
||||
----------------------------------------------------------
|
||||
| 1 2 3 4 5 6 7 8 9 10 11 12 13 ... 44 45 46 |
|
||||
| |
|
||||
| S ID byte load data...data checksum |
|
||||
| count address 1 n |
|
||||
----------------------------------------------------------
|
||||
Figure 3: Data Record Format for 32-Bit Load Address
|
||||
|
||||
Column Description
|
||||
|
||||
1 Contains the ASCII character S, which indicates the start of
|
||||
a record in Motorola S-record format.
|
||||
|
||||
2 Contains the ASCII character identifying the record type.
|
||||
For data records, this digit is 3 for 32-bit addresses.
|
||||
|
||||
3 to 4 Contain the count of the number of bytes following this one
|
||||
within the record. The count includes the checksum and the
|
||||
load address bytes but not the byte count itself.
|
||||
|
||||
5 to 12 Contain the load address. The first data byte is to be loaded
|
||||
into this address and subsequent bytes into the next sequential
|
||||
address. Columns 5 and 6 contain the high-order address
|
||||
byte, and columns 11 and 12 contain the low-order address byte.
|
||||
|
||||
13 to 44 Contain the specifications for up to 15 bytes of data.
|
||||
|
||||
45 to 46 Contain a checksum for the record. To calculate this, take the
|
||||
sum of the values of all bytes from the byte count up to the
|
||||
last data byte, inclusive, modulo 256. Subtract this result
|
||||
from 255.
|
||||
|
||||
|
||||
*****************************************************************************************
|
||||
|
||||
Record Count Record (S5)
|
||||
|
||||
|
||||
The record count record verifies the number of data records preceding it. Figure 4
|
||||
shows the format for such a record. The columns shown in the figure represent half
|
||||
of a byte (4 bits).
|
||||
|
||||
--------------------------------------
|
||||
| 1 2 3 4 5 6 7 8 9 10 |
|
||||
| |
|
||||
| S ID byte # of data checksum |
|
||||
| count records |
|
||||
--------------------------------------
|
||||
Figure 4: Record Count Record Format
|
||||
|
||||
Column Description
|
||||
|
||||
1 Contains the ASCII character S, which indicates the start of
|
||||
a record in Motorola S-record format.
|
||||
|
||||
2 Contains the ASCII character 5, which indicates a record
|
||||
count record.
|
||||
|
||||
3 to 4 Contain the byte count, ASCII string 03.
|
||||
|
||||
5 to 8 Contain the number of data records in this file. The high-
|
||||
order byte is in columns 5 and 6.
|
||||
|
||||
9 to 10 Contain the checksum for the record.
|
||||
|
||||
Example:
|
||||
|
||||
S503010DEE
|
||||
|
||||
The example above shows a record count record indicating a total of 269 records
|
||||
(0x010D) and a checksum of 0xEE.
|
||||
|
||||
|
||||
|
||||
*****************************************************************************************
|
||||
|
||||
Terminator Record for 32-bit address (S7)
|
||||
|
||||
A terminator record specifies the end of the data records. Figure 5 shows the
|
||||
format for such a record. The columns shown in the figure represent half of a byte
|
||||
(4 bits).
|
||||
|
||||
-------------------------------------
|
||||
| 1 2 3 4 5...12 13 14 |
|
||||
| |
|
||||
| S ID byte load checksum |
|
||||
| count address |
|
||||
-------------------------------------
|
||||
Figure5: Terminator Record Format for 32-Bit Load Address
|
||||
|
||||
Column Description
|
||||
|
||||
1 Contains the ASCII character S, which indicates the start of
|
||||
a record in Motorola S-record format.
|
||||
|
||||
2 Contains the ASCII character 7, which indicates a 32-bit
|
||||
load address.
|
||||
|
||||
3 to 4 Contain the byte count, ASCII string 04.
|
||||
|
||||
5 to 12 Contain the load address that is either set to zero or to the
|
||||
starting address specified in the END directive or START
|
||||
command (there are no data bytes).
|
||||
|
||||
13 to 14 Contain the checksum for the record.
|
||||
|
||||
*****************************************************************************************
|
||||
|
||||
Terminator Record for 24-bit address (S8)
|
||||
|
||||
|
||||
A terminator record specifies the end of the data records. Figure 6 shows the
|
||||
format for such a record. The columns shown in the figure represent half of a byte
|
||||
(4 bits).
|
||||
|
||||
----------------------------------------
|
||||
| 1 2 3 4 5 6 7 8 9 10 11 12 |
|
||||
| |
|
||||
| S ID byte load checksum |
|
||||
| count address |
|
||||
----------------------------------------
|
||||
Figure 6: Terminator Record Format for 24-Bit Load Address
|
||||
|
||||
Column Description
|
||||
|
||||
1 Contains the ASCII character S, which indicates the start of
|
||||
a record in Motorola S-record format.
|
||||
|
||||
2 Contains the ASCII character 8, which indicates a 24-bit
|
||||
load address.
|
||||
|
||||
3 to 4 Contain the byte count, ASCII string 04.
|
||||
|
||||
5 to 10 Contain the load address, which is either set to zero or to the
|
||||
starting address specified in the END directive or START
|
||||
command. There are no data bytes.
|
||||
|
||||
11 to 12 Contain the checksum for the record.
|
||||
|
||||
Example:
|
||||
|
||||
S804000AF0001
|
||||
|
||||
The previous example shows a terminator record with a 24-bit load address of
|
||||
0x000AF0 and a checksum of 0x01.
|
||||
|
||||
|
||||
*****************************************************************************************
|
||||
|
||||
Terminator Record for 16-bit address (S9)
|
||||
|
||||
|
||||
A terminator record specifies the end of the data records. Figure 7 shows the
|
||||
format for such a record. The columns shown in the figure represent half of a byte
|
||||
(4 bits).
|
||||
|
||||
-------------------------------------
|
||||
| 1 2 3 4 5 6 7 8 9 10 |
|
||||
| |
|
||||
| S ID byte load checksum |
|
||||
| count address |
|
||||
-------------------------------------
|
||||
Figure 7: Terminator Record Format for 16-Bit Load Address
|
||||
|
||||
|
||||
Column Description
|
||||
|
||||
1 Contains the ASCII character S, which indicates the start of
|
||||
a record in Motorola S-record format.
|
||||
|
||||
2 Contains the ASCII character 9, which indicates a 16-bit
|
||||
load address.
|
||||
|
||||
3 to 4 Contain the byte count, ASCII string 04.
|
||||
|
||||
5 to 8 Contain the load address, which is either set to zero or to the
|
||||
starting address specified in the END directive or START
|
||||
command (there are no data bytes).
|
||||
|
||||
9 to 10 Contain the checksum for the record.
|
||||
|
||||
|
||||
|
||||
*****************************************************************************************
|
||||
hagen.v.tronje@on-line.de
|
||||
100
as68hc11/DOCS/S19.TXT
Normal file
100
as68hc11/DOCS/S19.TXT
Normal file
@@ -0,0 +1,100 @@
|
||||
A brief explanation of the Motorola S19 file format.
|
||||
|
||||
Motorola S19 file records are a text representation of Hexadecimal coded binary
|
||||
data. All data uses only ASCII characters, so the format is portable across
|
||||
virtually all computer platforms. The S19 format, described here, is for
|
||||
eight bit data.
|
||||
|
||||
(The '$' will be used throughout to indicate a hexadecimal value.)
|
||||
|
||||
Each line in a Motorola S19 file is called a 'record'. Records always begin with a
|
||||
the letter 'S', followed by a '1' if the record contains data, or a '9' if this
|
||||
is the last record in the file.
|
||||
|
||||
The next byte represents the number of bytes in this record, including the
|
||||
starting address, data bytes, and the checksum.
|
||||
|
||||
The next pair of numbers represent the 16-bit starting address of the data in
|
||||
the record. This is the absolute location in the EPROM.
|
||||
|
||||
Following the address are the hex representations of the data to be stored.
|
||||
|
||||
The last byte is an eight-bit one's-complement checksum of all of the bytes in
|
||||
the record (not including the S1). Note that this value is derived from the
|
||||
binary values of the bytes, not the ASCII representation.
|
||||
|
||||
A standard CR/LF pair (carriage return/linefeed, $0D $0A) terminates each line.
|
||||
|
||||
|
||||
This a sample Motorola S19 record.
|
||||
|
||||
S1130170707172737475767778797A7B7C7D7E7F03
|
||||
|
||||
Broken down, it looks as follows:
|
||||
|
||||
S - Indicates that this is Motorola
|
||||
|
||||
1 - 1 means this is a data record
|
||||
|
||||
13 - Number of bytes to follow = $13, or 19 decimal. This number
|
||||
can be thought of as the number of data bytes plus three.
|
||||
Therefore there will be 16 data bytes in the record.
|
||||
|
||||
0170 - Starting address in the EPROM for this record.
|
||||
|
||||
70 - These are the data bytes (in hex) - 16 of them as noted above
|
||||
71 The first byte ($70) will be stored at $0170, with the
|
||||
72 remaining bytes following in sequence.
|
||||
73
|
||||
74
|
||||
75
|
||||
76
|
||||
77
|
||||
78
|
||||
79
|
||||
7A
|
||||
7B
|
||||
7C
|
||||
7D
|
||||
7E
|
||||
7F
|
||||
|
||||
03 - This is the checksum. If you add all of the successive bytes
|
||||
(note that the address is treated as two individual bytes) the
|
||||
result is $7FC. Truncating this to eight bits yields $FC. The
|
||||
one's complement of $FC is $06. (This may be derived by
|
||||
subtracting $FC from $FF, or by inverting the bits.)
|
||||
|
||||
(CR/LF) - End of this record -- I think the linefeed may be optional.
|
||||
|
||||
The use of the starting address in each record makes it possible to store data
|
||||
in non-contiguous areas of the EPROM. Each line of data is therefore entirely
|
||||
self-contained. This is useful when areas of the EPROM are unused, as no space
|
||||
in the Motorola S19 file need be wasted by representation of blank data. It is
|
||||
perfectly possible, albeit not recommended, to scramble all of the record lines
|
||||
in a Motorola S19 file and still end up with a correct EPROM image.
|
||||
|
||||
The end record (end of file) is almost the same:
|
||||
|
||||
S9030000FC
|
||||
|
||||
S - Indicates that this is Motorola
|
||||
|
||||
9 - 9 means this is the end record
|
||||
|
||||
03 - Number of bytes - should be three, as no data bytes will be in
|
||||
this record.
|
||||
|
||||
0000 - Address, usually zero.
|
||||
|
||||
- Zero data bytes here (obviously)
|
||||
|
||||
FC - The checksum, calculated as above.
|
||||
|
||||
|
||||
You may also see records starting with S0 - I believe these are called comment
|
||||
records. They do not contain any data that will be stored in the EPROM.
|
||||
|
||||
I hope this helps.
|
||||
Sanjaya Vatuk 11/4/96
|
||||
sanjaya@concentric.net
|
||||
447
as68hc11/DOCS/SREC.TXT
Normal file
447
as68hc11/DOCS/SREC.TXT
Normal file
@@ -0,0 +1,447 @@
|
||||
S-Records
|
||||
|
||||
|
||||
-S-Record Format-
|
||||
|
||||
Chaplin@keinstr.uucp (Roger Chaplin) reposted an article written
|
||||
by mcdchg!motmpl!ron (Ron Widell) that explained how Motorola
|
||||
S-Records are formatted. This comes from a unix man page. No
|
||||
mention of which version of Unix is specified. This section
|
||||
of the FAQ is a bit long. An anonymous ftp archive is currently
|
||||
being sought. When one is found, the section will be placed in
|
||||
the archive.
|
||||
|
||||
|
||||
SREC(4) UNIX 5.0 (03/21/84) SREC(4)
|
||||
|
||||
|
||||
An S-record file consists of a sequence of specially formatted
|
||||
ASCII character strings. An S-record will be less than or equal to
|
||||
78 bytes in length.
|
||||
|
||||
The order of S-records within a file is of no significance and no
|
||||
particular order may be assumed.
|
||||
|
||||
The general format of an S-record follow:
|
||||
|
||||
+------------------//-------------------//-----------------------+
|
||||
| type | count | address | data | checksum |
|
||||
+------------------//-------------------//-----------------------+
|
||||
|
||||
type A char-2- field. These characters describe the
|
||||
type of record (S0, S1, S2, S3, S5, S7, S8, or
|
||||
S9).
|
||||
count A char-2- field. These characters when paired and
|
||||
interpreted as a hexadecimal value, display the
|
||||
count of remaining character pairs in the record.
|
||||
|
||||
address A char-4,6, or 8- field. These characters grouped
|
||||
and interpreted as a hexadecimal value, display
|
||||
the address at which the data field is to be
|
||||
loaded into memory. The length of the field
|
||||
depends on the number of bytes necessary to hold
|
||||
the address. A 2-byte address uses 4 characters,
|
||||
a 3-byte address uses 6 characters, and a 4-byte
|
||||
address uses 8 characters.
|
||||
data A char -0-64- field. These characters when paired
|
||||
and interpreted as hexadecimal values represent
|
||||
the memory loadable data or descriptive
|
||||
information.
|
||||
|
||||
checksum A char-2- field. These characters when paired and
|
||||
interpreted as a hexadecimal value display the
|
||||
least significant byte of the ones complement of
|
||||
the sum of the byte values represented by the
|
||||
pairs of characters making up the count, the
|
||||
address, and the data fields.
|
||||
|
||||
Each record is terminated with a line feed. If any
|
||||
additional or different record terminator(s) or delay
|
||||
characters are needed during transmission to the target
|
||||
system it is the responsibility of the transmitting program
|
||||
to provide them.
|
||||
|
||||
S0 Record The type of record is 'S0' (0x5330). The address
|
||||
|
||||
|
||||
field is unused and will be filled with zeros
|
||||
(0x0000). The header information within the data
|
||||
field is divided into the following subfields.
|
||||
|
||||
mname is char-20- and is the
|
||||
module name.
|
||||
ver is char-2- and is the
|
||||
version number.
|
||||
|
||||
rev is char-2- and is the
|
||||
revision number.
|
||||
description is char-0-36- and is a
|
||||
text comment.
|
||||
|
||||
Each of the subfields is composed of ASCII bytes
|
||||
whose associated characters, when paired,
|
||||
represent one byte hexadecimal values in the case
|
||||
of the version and revision numbers, or represent
|
||||
the hexadecimal values of the ASCII characters
|
||||
comprising the module name and description.
|
||||
|
||||
S1 Record The type of record field is 'S1' (0x5331). The
|
||||
address field is interpreted as a 2-byte address.
|
||||
The data field is composed of memory loadable
|
||||
data.
|
||||
S2 Record The type of record field is 'S2' (0x5332). The
|
||||
address field is interpreted as a 3-byte address.
|
||||
The data field is composed of memory loadable
|
||||
data.
|
||||
|
||||
S3 Record The type of record field is 'S3' (0x5333). The
|
||||
address field is interpreted as a 4-byte address.
|
||||
The data field is composed of memory loadable
|
||||
data.
|
||||
S5 Record The type of record field is 'S5' (0x5335). The
|
||||
address field is interpreted as a 2-byte value
|
||||
and contains the count of S1, S2, and S3 records
|
||||
previously transmitted. There is no data field.
|
||||
|
||||
S7 Record The type of record field is 'S7' (0x5337). The
|
||||
address field contains the starting execution
|
||||
address and is interpreted as 4-byte address.
|
||||
There is no data field.
|
||||
S8 Record The type of record field is 'S8' (0x5338). The
|
||||
address field contains the starting execution
|
||||
address and is interpreted as 3-byte address.
|
||||
There is no data field.
|
||||
|
||||
S9 Record The type of record field is 'S9' (0x5339). The
|
||||
address field contains the starting execution
|
||||
address and is interpreted as 2-byte address.
|
||||
There is no data field.
|
||||
|
||||
EXAMPLE
|
||||
|
||||
Shown below is a typical S-record format file.
|
||||
|
||||
S00600004844521B
|
||||
S1130000285F245F2212226A000424290008237C2A
|
||||
S11300100002000800082629001853812341001813
|
||||
S113002041E900084E42234300182342000824A952
|
||||
S107003000144ED492
|
||||
S5030004F8
|
||||
S9030000FC
|
||||
|
||||
The file consists of one S0 record, four S1 records, one S5
|
||||
record and an S9 record.
|
||||
|
||||
The S0 record is comprised as follows:
|
||||
|
||||
S0 S-record type S0, indicating it is a header
|
||||
record.
|
||||
06 Hexadecimal 06 (decimal 6), indicating that six
|
||||
character pairs (or ASCII bytes) follow.
|
||||
|
||||
00 00 Four character 2-byte address field, zeroes in
|
||||
this example.
|
||||
48 ASCII H, D, and R - "HDR".
|
||||
|
||||
1B The checksum.
|
||||
|
||||
The first S1 record is comprised as follows:
|
||||
S1 S-record type S1, indicating it is a data record
|
||||
to be loaded at a 2-byte address.
|
||||
|
||||
13 Hexadecimal 13 (decimal 19), indicating that
|
||||
nineteen character pairs, representing a 2 byte
|
||||
address, 16 bytes of binary data, and a 1 byte
|
||||
checksum, follow.
|
||||
00 00 Four character 2-byte address field; hexidecimal
|
||||
address 0x0000, where the data which follows is to
|
||||
be loaded.
|
||||
|
||||
28 5F 24 5F 22 12 22 6A 00 04 24 29 00 08 23 7C Sixteen
|
||||
character pairs representing the actual binary
|
||||
data.
|
||||
2A The checksum.
|
||||
|
||||
The second and third S1 records each contain 0x13 (19)
|
||||
character pairs and are ended with checksums of 13 and 52,
|
||||
respectively. The fourth S1 record contains 07 character
|
||||
pairs and has a checksum of 92.
|
||||
|
||||
The S5 record is comprised as follows:
|
||||
|
||||
S5 S-record type S5, indicating it is a count record
|
||||
indicating the number of S1 records.
|
||||
|
||||
|
||||
|
||||
03 Hexadecimal 03 (decimal 3), indicating that three
|
||||
character pairs follow.
|
||||
|
||||
00 04 Hexadecimal 0004 (decimal 4), indicating that
|
||||
there are four data records previous to this
|
||||
record.
|
||||
F8 The checksum.
|
||||
|
||||
The S9 record is comprised as follows:
|
||||
|
||||
S9 S-record type S9, indicating it is a termination
|
||||
record.
|
||||
03 Hexadecimal 03 (decimal 3), indicating that three
|
||||
character pairs follow.
|
||||
|
||||
00 00 The address field, hexadecimal 0 (decimal 0)
|
||||
indicating the starting execution address.
|
||||
FC The checksum.
|
||||
|
||||
|
||||
-Intel Hex ASCII Format-
|
||||
|
||||
Intel HEX-ASCII format takes the form:
|
||||
|
||||
+----------------------------------- Start Character
|
||||
|
|
||||
| +-------------------------------- Byte Count
|
||||
| | (# of data bytes)
|
||||
| |
|
||||
| | +-------------------------- Address of first data.
|
||||
| | |
|
||||
| | | +-------------------- Record Type (00 data,
|
||||
| | | | 01 end of record)
|
||||
| | | |
|
||||
| | | | +------------ Data Bytes
|
||||
| | | | |
|
||||
| | | | | +---- Checksum
|
||||
| | | | | |
|
||||
| / \ / \ / \ / \ / \
|
||||
: B C A A A A T T H H ... H H C C
|
||||
|
||||
An examples:
|
||||
|
||||
:10000000DB00E60F5F1600211100197ED300C3004C
|
||||
:1000100000000101030307070F0F1F1F3F3F7F7FF2
|
||||
:01002000FFE0
|
||||
:00000001FF
|
||||
|
||||
This information comes from _Microprocessors and Programmed
|
||||
Logic_, Second Edition, Kenneth L. Short, 1987, Prentice-Hall,
|
||||
ISBN 0-13-580606-2.
|
||||
|
||||
Provisions have been made for data spaces larger than 64 kBytes.
|
||||
The above reference does not discuss them. I suspect there is
|
||||
a start of segment type record, but I do not know how it is
|
||||
implemented.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
/* This file contains source code to read a Motorola S-record file into
|
||||
** a memory image. The size of the file cannot exceed BUFSIZE of data.
|
||||
** The image is then written to disk either as binary data starting at
|
||||
** address 0 with no data gaps, or as a C array of unsigned longs.
|
||||
** Input lines must be no longer than MAXLINE. No check is made!
|
||||
**
|
||||
** Author: Eric McRae, Electro-Logic Machines, Inc.
|
||||
** Date: Copyright 1994
|
||||
**
|
||||
** This source code is made available to the public "as is". No
|
||||
** warranty is given or implied for it's proper operation. This source
|
||||
** code may be used in whole or in part as long as this copyright is
|
||||
** included.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Comment the following line for non PC applications */
|
||||
#define PCDOS
|
||||
|
||||
/* Uncomment the following line if you want a binary output instead of
|
||||
** a structure
|
||||
*/
|
||||
/* #define BINARY */
|
||||
|
||||
#ifdef PCDOS /* Intel x86 architecture */
|
||||
#define BUFSIZE 49152 /* 48K to avoid segment hopping */
|
||||
#else /* Any reasonable (non-segmented) arch... */
|
||||
#define BUFSIZE 65536 /* As big as you want */
|
||||
#endif
|
||||
|
||||
#define MAXLINE 256 /* Length of longest input line + 1 */
|
||||
/* Globals */
|
||||
FILE *infilePH, *outfilePH; /* Handles for input and output files */
|
||||
unsigned char *bufAC, /* Allocated image buffer */
|
||||
*highestPC = NULL; /* Highest buffer address written */
|
||||
|
||||
/* Change this string to reflect the name of the output array */
|
||||
char headerAC[] = "unsigned long sRec[] =\n{\n";
|
||||
|
||||
/* Predeclarations */
|
||||
int parsebufN( char * ); /* Does the actual parsing */
|
||||
|
||||
void main(int argc, const char * argv[])
|
||||
{
|
||||
int c, /* Temp char storage */
|
||||
resN; /* result status */
|
||||
char *lbufPC, lbufAC[MAXLINE];
|
||||
int linectrN = 0; /* Used to correlate parse fail to input line */
|
||||
|
||||
#ifndef BINARY
|
||||
int i;
|
||||
unsigned long *codePL;
|
||||
unsigned char *codePC;
|
||||
#endif
|
||||
|
||||
/* Check the argument count */
|
||||
if( argc != 3 ) /* If didn't specify input and output files */
|
||||
{
|
||||
printf("Usage: %s: infile outfile\n", argv[0] );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* OK, let's open some files */
|
||||
if( ( infilePH = fopen( argv[1], "r" ) )== NULL )
|
||||
{
|
||||
printf("%s: Couldn't open input file %s\n", argv[0], argv[1] );
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if( ( outfilePH = fopen( argv[2], "w" ) ) == NULL )
|
||||
{
|
||||
printf("%s: Couldn't open output file %s\n", argv[0], argv[3] );
|
||||
exit(3);
|
||||
}
|
||||
|
||||
/* OK, get a buffer and clear it. */
|
||||
if( (bufAC = calloc( (size_t)BUFSIZE, (size_t)1 )) == NULL )
|
||||
{
|
||||
printf("%s: Couldn't malloc memory for buffer\n", argv[0] );
|
||||
exit(4);
|
||||
}
|
||||
|
||||
lbufPC = lbufAC; /* Point at beginning of line buffer */
|
||||
while( c = fgetc( infilePH ))
|
||||
{
|
||||
if( (c == '\n') || (c == EOF) ) /* If found end of line or file */
|
||||
{ /* Parse the Line */
|
||||
if( ( c == EOF ) && ( ferror( infilePH ) ) )
|
||||
{
|
||||
printf("%s: Error reading input file\n", argv[0] );
|
||||
exit(5);
|
||||
}
|
||||
else
|
||||
{ /* OK, have a complete line in buffer */
|
||||
linectrN++; /* Increment line counter */
|
||||
if( lbufPC == lbufAC )
|
||||
break; /* ignore blank lines */
|
||||
*lbufPC = 0; /* Terminate the line string */
|
||||
if( resN = parsebufN( lbufAC ) ) /* Parse data record to mem */
|
||||
{
|
||||
printf("%s: Error reading input file at line %d, return code = %d\n",
|
||||
argv[0], linectrN, resN );
|
||||
exit( resN );
|
||||
}
|
||||
lbufPC = lbufAC; /* Repoint line buffer pointer */
|
||||
} /* End of have a complete line */
|
||||
}
|
||||
else
|
||||
*lbufPC++ = c; /* Place char into line buffer */
|
||||
}
|
||||
|
||||
/* At this point, the input file has been emptied. Now dispose of the
|
||||
** output data according to compilation mode.
|
||||
*/
|
||||
|
||||
#ifdef BINARY
|
||||
|
||||
/* Write the buffer back to disk as a binary image */
|
||||
resN = fwrite( bufAC, 1, (size_t)((highestPC - bufAC) + 1), outfilePH );
|
||||
if( resN != (int)( (highestPC - bufAC) + 1) )
|
||||
{
|
||||
printf("%s: Error writing output file\n", argv[0] );
|
||||
exit( 6 );
|
||||
}
|
||||
|
||||
#else
|
||||
/* Produce a file that can be included in a C program. Data is read
|
||||
** from buffer as bytes to avoid portability/endian problems with
|
||||
** this program.
|
||||
*/
|
||||
/* Output header first, then 1 long per line */
|
||||
fwrite( (void *)headerAC, 1, (size_t)(sizeof( headerAC )-1), outfilePH );
|
||||
|
||||
codePL = (unsigned long *)bufAC;
|
||||
for( i = (highestPC - bufAC + 1) / 4; i; i-- ) /* for each long */
|
||||
{
|
||||
codePC = (unsigned char *)codePL++;
|
||||
sprintf(lbufAC, "0x%02x%02x%02x%02x%s",
|
||||
*codePC, *(codePC + 1), *(codePC + 2), *(codePC + 3),
|
||||
i == 1 ? "\n" : ",\n" ); /* No comma after final long */
|
||||
fwrite( lbufAC, 1, (size_t)(strlen( lbufAC )), outfilePH );
|
||||
}
|
||||
/* OK, data has been written out, close end of array */
|
||||
fwrite( "};\n", 1, (size_t)3, outfilePH );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Function: parsebufV
|
||||
** Parses an S-record in the buffer and writes it into the buffer
|
||||
** if it is has a valid checksum.
|
||||
**
|
||||
** Args: pointer to character buffer for null terminated line
|
||||
** Returns: int result code: 0 = success, else failure
|
||||
*/
|
||||
int parsebufN( char *lbufPC )
|
||||
{
|
||||
unsigned long addrL;
|
||||
unsigned char cksmB, /* checksum of addr, count, & data length */
|
||||
*bufPC; /* Pointer into memory array */
|
||||
int i, countN, /* Number of bytes represented in record */
|
||||
oheadN, /* Number of overhead (addr + chksum) bytes */
|
||||
tvalN; /* Temp for check checksum */
|
||||
|
||||
switch( *(lbufPC+1) ) /* examine 2nd character on the line */
|
||||
{
|
||||
case '1': /* 16 bit address field */
|
||||
if( sscanf(lbufPC, "S1%2x%4lx", &countN, &addrL ) != 2 )
|
||||
return( 10 ); /* Flag error in S1 record */
|
||||
oheadN = 3; /* 2 address + 1 checksum */
|
||||
break;
|
||||
|
||||
case '2': /* 24 bit address field */
|
||||
if( sscanf(lbufPC, "S2%2x%6lx", &countN, &addrL ) != 2 )
|
||||
return( 11 ); /* Flag error in S2 record */
|
||||
oheadN = 4; /* 3 address + 1 checksum */
|
||||
break;
|
||||
|
||||
case '3': /* 32 bit address field */
|
||||
if( sscanf(lbufPC, "S3%2x%8lx", &countN, &addrL ) != 2 )
|
||||
return( 12 ); /* Flag error in S3 record */
|
||||
oheadN = 5; /* 4 address + 1 checksum */
|
||||
break;
|
||||
|
||||
default: /* ignore all but S1,2,3 records. */
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if( addrL > BUFSIZE ) return( 13 ); /* if address exceeds buffer size */
|
||||
bufPC = bufAC + addrL; /* otherwise, point to right spot in buffer */
|
||||
|
||||
/* OK now see if checksum is OK, while reading data to buffer */
|
||||
cksmB = 0;
|
||||
countN++; /* Bump counter to read final checksum too */
|
||||
for( i = 1; i <= countN; i++ )
|
||||
{
|
||||
sscanf( lbufPC + i*2, "%2x", &tvalN ); /* Scan a 2 hex digit byte */
|
||||
cksmB += (unsigned char)tvalN;
|
||||
if( ( i > oheadN ) && ( i < countN ) ) /* If scanned a data byte */
|
||||
*bufPC++ = (unsigned char) tvalN; /* write it to the buffer */
|
||||
}
|
||||
if( cksmB += 1 ) return( 14 ); /* flag checksum error */
|
||||
|
||||
if( (bufPC - 1) > highestPC )
|
||||
highestPC = bufPC - 1; /* track highest address loaded */
|
||||
|
||||
return( 0 ); /* Successful return */
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user