S-Record Manipulation with GNU objcopy and Burner Utility

In my earlier post “S-Record Generation with gcc for ARM/Kinetis” I documented how to have the ARM GNU gcc toolchain to produce a S19 (Motorola (or now Freescale) S-Record) file. Here are a few more tips on that subject:

  1. Changing length of S-Records
  2. Only using 32bit addresses
  3. Combining S19 files

Changing the Length of S-Record Lines

Many S-Record reading tools (or bootloader) have a limit how long a S19 line can be. By default, the GNU objcopy produces this:


Using the option


I can get shorter (or longer) lines:

objcopy with --srec-len option

objcopy with –srec-len option


💡 The length covers both address, data and crc fields.

Forcing 32bit S3 Records

To use only S3 (32bit address) records, then the option


is useful. This uses S3 records for lines which would otherwise be S1 or S2 records:


Combining and Merging S19 Files

For a bootloader it is interesting to combine to S19 files (e.g. the application file with the bootloader file). Unfortunately the GNU objcopy cannot handle this. But the Burner utility (see S-Record, Intel Hex and Binary Files) can do this 🙂

The burner has following command line language definition (from the manual):

StatementList = Statement {Separator Statement}.
Statement = [IfSat | ForStat | Open | Send | Close | Pause 
             | Echo | Format | SFormat | Origin | Len 
             | BusWidth | Parity | SwapByte | Header 
             | BaudRate | DataBit | UndefByte 
             | Destination | AssignExpr | SLineLen].
IfStat = "IF" RelExpr "THEN" StatementList
             ["ELSE" StatementList] "END".
Assign = ("=" | ":=").
ForStat = "FOR" Ident Assign SimpleExpr "TO" SimpleExpr
               "DO" StatementList "END".
Open = ("OPENFILE" String) | ("OPENCOM" SimpleExpr).
Send = ("SENDBYTE" | "SENDWORD") SimpleExpr String.
Close = "CLOSE".
Pause = "PAUSE" [String].
Echo = "ECHO" [String].
Format = "format" Assign ("freescale" | "intel" | "binary").
SFormat = "SRECORD" Assign ("Sx" | "S1" | "S2" | "S3").
Origin = "origin" Assign SimpleExpr.
Len = "len" Assign SimpleExpr.
BusWidth = "busWidth" Assign ("1" | "2" | "4").
Parity = "parity" Assign ("none" | "even" | "odd").
SwapByte = "swapByte" Assign ("yes" | "no").
Header = "header" Assign string.
BaudRate = "baudRate" Assign ( "300" | "600" | "1200" 
                             | "2400" | "4800" | "9600" 
                             | "19200" | "38400").
DataBit = "dataBit" Assign ("7" | "8").
UndefByte = "undefByte" Assign SimpleExpr.
Destination = "destination" Assign SimpleExpr.
SLineLen = "SLINELEN" Assign SimpleExpr.
AssignExpr = Ident Assign SimpleExpr.
RelExpr = SimpleExpr {RelOp SimpleExpr}.
RelOp = "=" | "==" | "#" | "<>" | "!=" | "<" 
            | "<=" | ">" | ">=".
SimpleExpr = ["+" | "-"] Term {AddOp Term}.
AddOp = "+" | "-".
Term = Number | String | Ident.
Number = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | {Number}
Ident = "i".
String = '"' {char} '"'.

I have two S19 files in my FLASH output folder: Part1.S19 and Part2.S19. I want to merge and combine them into merge.S19. Using the above syntax, I write my burner.bbl file as:

/* open destination file: */
/* set format to S19: */
/* we are sending byte by byte: */
/* start at address zero: */
/* cover the full flash range */
/* no destination offset to add: */
/* use standard record format */
/* now send to the files to merge them into one: */
SENDBYTE 1 "%FLASH_DIR%/part2.S19"
/* close output file */

I’m using an environment variable %FLASH_DIR% to keep things portable.

In the (post)build step I’m passing it as variable to the burner:

"${MCU_TOOLS_HOME}/prog/piper.exe" "${MCU_TOOLS_HOME}/prog/burner.exe" -F="${ProjDirPath}\burner.bbl" -Env"FLASH_DIR=${ProjDirPath}\FLASH"

With this, I get the two S19 files merged:

Burner Post Build Step

Burner Post Build Step

❗ The post build step is only executed if something is built.


The GNU objcopy has basic S19 file generation support which is enough for simple things. If I need to do advanced scripts, I’m using the burner utility. The burner utility has a scripting language to automate many things dealing with object files and programming files.

Happy S-Recording

12 thoughts on “S-Record Manipulation with GNU objcopy and Burner Utility

    • Yes, this is supported with the undefByte command. But it cannot be applied directly on S19 files. If I need the undefByte, I first produce a Intel Hex file (with undefByte), and then convert it to a S19 file.


  1. Pingback: Converting S19 Files into Binary Files with GNU objcopy | MCU on Eclipse

  2. Pingback: Executing Multiple Commands as Post-Build Steps in Eclipse | MCU on Eclipse

  3. Hi Erich,
    your posts are useful even 3 years later! Thanks a lot!
    I have a bootloader s19 file developed and built apart from the application on an S08 architecture. So I built the application and created the merge.s19 as you explained.

    Just 2 issues/questions reading your post and working on something quite similar:
    1) Can I debug my merge.s19? Do I need to merge the .abs file too? How can I do it?
    2) Is the command line in post build step only to set the FLASH_DIR environment variable? Let’s suppose I want to use a working set for bootloader and application projects. How should I modify the command line to merge both files?

    Thank you very much
    Best Regards


    • Hi Roberto,
      thanks :-), and I still answer questions even 3 years later 🙂
      1) The .s19 does not have any debug information. So you need to load the symbols/debug information into the debugger if you want to debug it. You should not merge the .abs and the .s19 file
      2) The postbuild step calls the piper.exe which calls the burner.exe. The piper.exe creates a ‘pipe’ between the command line version and the GUI version so the GUI application can execute as a command line version.

      Not sure which debugger you are using. In HI-Wave there should be an option to load only the symbols. A similar option exists in the Eclipse launch configuration of CodeWarrior.
      I hope this helps,


      • Hi Erich,
        thank you for replying so soon.
        As a matter of facts my questions were not well explained, I apoligize for that.
        First of all I’m using the CodeWarrior 10.6, Eclipse based, for an HCS908SG32.

        Let’s suppose I have 2 different projects, let’s call them booloader and application, now I have learnt how to merge bootloader.s19 and application.s19 producing overallproject.s19: but I need to go further…

        So I will try to better formulate the 2 questions:
        1) If I liked to debug the overallproject, I would need overallproject.abs = bootloader.abs + application.abs: how can I create it?
        2) Can I build overallproject (both abs and s19) as a working set of bootloader + application and tell the “working set” burner to get all files in the build folder of their projects?

        Thanks again
        Best Regards


        • For debugging your overall application, you don’t need the abs: all what the debugger needs is the symbols/debug information for the whole part.
          For downloading you can either use a combined s19 file or download the .abs individually (make sure you do not erase the other part).
          As for 2) Yes, you could do this. You can build the .abs for each the bootloader and the application. Create the S19 file for each and then tell the burner to combine the two S19 files (you could write a script or use the SRecord utility too).
          I hope this helps,


  4. Pingback: MCUXpresso IDE: S-Record, Intel Hex and Binary Files | MCU on Eclipse

  5. Pingback: Enhancing Binary Utilities in MCUXpresso IDE | MCU on Eclipse

Leave a Reply to Roberto Paolinelli Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.