Tutorial#
This tutorial walks you through the basics of working with objutils: creating sections and images, converting between HEX formats, controlling join behavior, and using typed access helpers.
If you prefer runnable examples, see the scripts and examples in the repository.
Before you start#
Install the package:
pip install objutilsBasic familiarity with Python byte sequences
Hello, HEX world#
Start by importing the primary entry points:
from objutils import Image, Section, dump, load, dumps, loads
Create two sections and inspect them:
sec0 = Section(start_address=0x1000, data=b"Hello HEX world!")
sec1 = Section(0x2000, range(1, 17))
img = Image([sec0, sec1])
img.hexdump()
Persist as S‑Records and read back as Intel HEX:
dump("srec", "example.srec", img)
img2 = load("srec", "example.srec")
dump("ihex", "example.hex", img2)
Join vs. no-join#
By default, consecutive sections are joined into a single section when possible. You can disable this:
s0 = Section(0x100, range(1, 9))
s1 = Section(0x108, range(9, 17))
img_joined = Image([s0, s1]) # default join=True
img_nojoin = Image([s0, s1], join=False)
img_joined.hexdump()
img_nojoin.hexdump()
Typed access (strings, numbers, arrays)#
Use the typed helpers to read/write structured binary data with explicit endianness.
img = Image([Section(0x1000, bytes(64))])
# Strings (C-style NUL-terminated)
img.write_string(0x1000, "Hello HEX world!")
# Scalars with endianness
img.write_numeric(0x1010, 0x10203040, "uint32_be")
img.write_numeric(0x1014, 0x50607080, "uint32_le")
# Arrays
img.write_numeric_array(0x1018, [0x1000, 0x2000, 0x3000], "uint16_le")
img.hexdump()
Supported scalar types:
uint8, int8
uint16, int16
uint32, int32
uint64, int64
float32, float64
An endianness suffix (_be or _le) is required.
ASAM byte order and datatype helpers#
For ECU/ASAM style type names and byte orders (including word-swap variants), use the dedicated ASAM helpers:
Use these helpers when your calibration metadata uses ASAM type names
(ULONG, UWORD, FLOAT32_IEEE) and ECU byte-order terms
(MSB_FIRST, MSB_LAST_MSW_FIRST).
When to use ASAM helpers instead of plain read_numeric*/write_numeric*:
Your metadata comes from A2L/ASAM naming (for example
UWORD/ULONG).You need ECU-specific byte order terms and MSW swapping.
You want one consistent API for scalars, Python lists, and NumPy arrays.
For signatures and parameter semantics of the array helpers, see the
ASAM Array Cheat Sheet below.
The example below shows ASAM scalars, Python arrays, NumPy arrays, and strings side by side in one small image.
from objutils import Image, Section
import numpy as np
img = Image([Section(0x3000, bytes(96))])
# ASAM numerics
img.write_asam_numeric(0x3000, 0x11223344, "ULONG", "MSB_FIRST")
img.write_asam_numeric(0x3004, 0x11223344, "ULONG", "MSB_FIRST_MSW_LAST")
img.write_asam_numeric(0x3008, 0x11223344, "ULONG", "MSB_LAST_MSW_FIRST")
# Roundtrip reads
a = img.read_asam_numeric(0x3000, "ULONG", "MSB_FIRST")
b = img.read_asam_numeric(0x3004, "ULONG", "MSB_FIRST_MSW_LAST")
c = img.read_asam_numeric(0x3008, "ULONG", "MSB_LAST_MSW_FIRST")
# ASAM numeric arrays
img.write_asam_numeric_array(0x3020, [0x11223344, 0x55667788], "ULONG", "MSB_LAST_MSW_FIRST")
arr_values = img.read_asam_numeric_array(0x3020, 2, "ULONG", "MSB_LAST_MSW_FIRST")
# ASAM ndarrays
arr = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint16)
img.write_asam_ndarray(0x3040, arr, "UWORD", "MSB_FIRST", index_mode="COLUMN_DIR")
arr_roundtrip = img.read_asam_ndarray(0x3040, 6, "UWORD", shape=(3, 2), index_mode="COLUMN_DIR", byte_order="MSB_FIRST")
# ASAM strings
img.write_asam_string(0x3010, "MOTOR", "ASCII")
img.write_asam_string(0x3030, "Drehzahl", "UTF8")
s0 = img.read_asam_string(0x3010, "ASCII")
s1 = img.read_asam_string(0x3030, "UTF8")
NumPy ASAM roundtrip with matrix data
from objutils import Image, Section
import numpy as np
img = Image([Section(0x5000, bytes(64))])
matrix = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint16)
img.write_asam_ndarray(0x5000, matrix, "UWORD", "MSB_FIRST", index_mode="COLUMN_DIR")
matrix_rt = img.read_asam_ndarray(0x5000, 6, "UWORD", shape=(3, 2), index_mode="COLUMN_DIR", byte_order="MSB_FIRST")
assert np.array_equal(matrix_rt, matrix)
Supported ASAM byte orders
MSB_FIRST(big-endian)MSB_LAST(little-endian)MSB_FIRST_MSW_LAST(word-swapped)MSB_LAST_MSW_FIRST(word-swapped)LITTLE_ENDIAN(legacy alias forMSB_LAST)BIG_ENDIAN(legacy alias forMSB_FIRST)
Supported ASAM numeric datatypes
UBYTE,SBYTEUWORD,SWORDULONG,SLONGA_UINT64,A_INT64FLOAT16_IEEE,FLOAT32_IEEE,FLOAT64_IEEE
Supported ASAM string datatypes
ASCIIUTF8UTF16UTF32
ASAM Array Cheat Sheet
Quick reference for the ASAM array helpers on Image and Section.
Method |
|
Returns |
Typical usage |
|---|---|---|---|
|
element count |
|
scalar lists/tuples |
|
n/a (from |
|
scalar lists/tuples |
|
element count |
|
matrix/tensor data |
|
n/a (from |
|
matrix/tensor data |
Minimal signatures
read_asam_numeric_array(addr, length, dtype, byte_order="MSB_LAST")write_asam_numeric_array(addr, data, dtype, byte_order="MSB_LAST")read_asam_ndarray(addr, length, dtype, shape=None, byte_order="MSB_LAST", index_mode="ROW_DIR")write_asam_ndarray(addr, array, dtype, byte_order="MSB_LAST", index_mode="ROW_DIR")
Note
ASAM index modes
index_mode="ROW_DIR" (default) uses C-like row-major layout
where X increments fastest. index_mode="COLUMN_DIR" swaps only
X and Y (not true Fortran-order for dims > 2).
shape uses ASAM convention (X, Y, Z, …) which is reversed
compared to numpy (…, Z, Y, X). length is the element count,
not byte count.
Warning
Frequent pitfalls
Confusing element count vs. byte count for
length.Forgetting that byte order is applied per element, not per full buffer.
Passing unsupported ASAM dtype names (must be values like
UWORD/ULONG).Assuming MSW swapping affects 8-bit types (it does not).
Copy/paste example: ULONG array roundtrip
from objutils import Image, Section
img = Image([Section(0x6000, bytes(32))])
img.write_asam_numeric_array(0x6000, [0x11223344, 0x55667788], "ULONG", "MSB_LAST_MSW_FIRST")
# Optional: verify raw in-memory bytes.
assert img.read(0x6000, 8) == b"\x33\x44\x11\x22\x77\x88\x55\x66"
# Main check: logical values roundtrip correctly.
values = img.read_asam_numeric_array(0x6000, 2, "ULONG", "MSB_LAST_MSW_FIRST")
assert values == (0x11223344, 0x55667788)
CLI companions#
The library ships with handy command-line tools. A few favorites:
oj-hex-info: inspect HEX files, optionally with a hexdump (-d)oj-elf-extract: extract loadable sections from an ELF to HEX (ihex/shf/srec)oj-elf-arm-attrs: dump.ARM.attributesfrom an ELF
Examples:
oj-hex-info srec example.srec -d
oj-elf-extract build/app.elf app.srec -t srec
What next?#
See HOW-TOs for short, task-oriented recipes.
Explore the full API reference in the modules section.