srec: Motorola S-records
| (require srec) | package: srec |
The "srec" package reads and writes Motorola S-record files — the line-oriented firmware image format (also known as SRECORD, S19/S28/S37) burned into microcontrollers and attached to bug reports everywhere. Everything is implemented in pure Racket: no FFI, no system dependency.
The writer is validated byte-for-byte against the Python bincopy library (its outputs ship as golden fixtures), and the parser accepts everything bincopy produces — plus a few things it gets wrong: record types are strictly validated, byte counts and checksums are enforced, and addresses are checked against the declared record width (bincopy silently emits malformed 16-bit records for larger addresses).
1 Quick start
> (define image (bytes 222 173 190 239))
> (define text (bytes->srec image #:base-address 4096 #:address-length-bits 16 #:start-address 8192)) > (display text)
S1071000DEADBEEFB0
S5030001FB
S9032000DC
> (srec->bytes text) #"\336\255\276\357"
> (srec-start-address text) 8192
2 Records
An S-record line is S<type><count><address><data><checksum>, all hexadecimal, where count covers the address, the data and the checksum itself. The checksum is the one’s complement of the LSB of the sum of count, address and data bytes — srec-checksum.
struct
(struct srec-record (kind address data))
kind : (or/c 'header 'data 'count 'start) address : exact-nonnegative-integer? data : bytes?
procedure
(parse-srec text) → (listof srec-record?)
text : string?
procedure
(parse-srec-line line line-no) → srec-record?
line : string? line-no : exact-nonnegative-integer?
3 Writing
procedure
(write-srec-record rec [ #:address-length-bits bits]) → string? rec : srec-record? bits : (or/c 16 24 32) = 32
procedure
(bytes->srec bs [ #:base-address base #:address-length-bits bits #:data-bytes-per-line per-line #:header header #:start-address start #:trailing-newline? trailing-newline?]) → string? bs : bytes? base : exact-nonnegative-integer? = 0 bits : (or/c 16 24 32) = 32 per-line : (integer-in 1 253) = 32 header : (or/c bytes? #f) = #f start : (or/c exact-nonnegative-integer? #f) = #f trailing-newline? : boolean? = #t
4 Images
procedure
(srec->bytes text [#:fill fill]) → bytes?
text : string? fill : (integer-in 0 255) = 255
procedure
(srec-start-address text)
→ (or/c exact-nonnegative-integer? #f) text : string?
5 License
MIT.