openc166
An open-source assembler for the Infineon C166 and C167 microcontroller family (including ST10 parts), compatible with the Keil A166 assembler.
It turns Keil-style assembly source into a raw binary image at a fixed address, or into an Intel HEX or Motorola S-record file. That suits small programs loaded into RAM or flash and started directly, such as ECU payloads, bootstrap loaders, and test code. No linker or object-file converter is needed.
openc166 runs on Linux, Windows and macOS. It needs only a C++20 compiler and CMake.
Status
Early development (version 0.x). What works today:
- The complete C166 and C167 instruction set, with all addressing modes. Every instruction form is checked byte for byte against Keil A166 V5.38: over 5,000 checks of code bytes, addresses and symbol values, all identical.
- Keil expression syntax: operators,
HIGH/LOW,SOF/SEG/PAG/POF,BOF,DATA3/DATA4/DATA8/DATA16, character constants, bit addresses such asPSW.3or0FD00H.5, and extended-SFR checks insideEXTRsequences. - Sections with an address (
SECTION CODE AT 0E000H) and without one. openc166 places sections withoutATas Keil's L166 linker would, or at addresses you give (--section NAME=ADDR), so code that leaves placement to the linker can still be assembled straight to a binary.DGROUPandCGROUPkeep sections in one data page or code segment, as in L166.BITsections andDBIThold bit variables, placed bit by bit as L166 places them. PROC/ENDP,ORG,EVEN,EQU/SET/BIT,DB/DW/DD,DS/DSB/DSW/DSD, andDPPTR/DSPTR/DBPTR, including Keil's automatic alignment of word data.- Segmented mode (
$SEGMENTED):ASSUME,DPPn:prefixes, and Keil's rules for which data page register an address goes through. DEFR/DEFA/DEFB, the register-definition directives that register files use, with Keil's rules for repeated definitions.- A built-in
REG167.INCregister file, written from Infineon's manuals, so$INCLUDE(REG167.INC)works without Keil installed. - Keil's rules for label arithmetic, which decide between short and long instruction forms.
- Generic
JMPandCALL: like Keil, openc166 picks the shortest instruction that reaches the target and shortens forward jumps over several passes. Label types (NEAR,FAR,WORD, ...) and theSHORTand type operators (FAR x,WORD PTR x, ...) work as in Keil. $INCLUDEand$INCDIR, with Keil's search order and listing format.- Conditional assembly:
$SET/$RESET,$IF/$ELSEIF/$ELSE/$ENDIFand theIF/ELSEIF/ELSE/ENDIFstatements, with Keil's quirks (only bit 0 of a condition counts) and listing format. LITtext replacement (PORT LIT 'R2'), with Keil's rules for where names are replaced.- Keil's standard macros:
MACRO/ENDMwith parameters andLOCALlabels,REPT,IRP,IRPC,EXITM,NUL,&and%, with Keil's rules for splitting arguments.$GEN/$NOGENchoose whether the listing shows expanded lines. - The
$MOD167,$CASE,$SEGMENTEDand$TABScontrols, with Keil's rule that these come before the first statement. Listing-only controls are accepted and ignored. - Keil error and warning codes (A74, A111, ...), so messages line up with the Keil manual.
- Raw binary, Intel HEX and Motorola S-record output. The HEX records match
Keil OH166's
H167format. - Several source files linked into one program, as L166 does:
EXTERN,PUBLICandGLOBALsymbols, and sections of the same name combined across files. Each file is assembled separately (a "module"), so a name that is notPUBLICstays private to its file. - Register banks (
REGBANK/REGDEF), placed in0FC00H..0FDFFHas L166 places them, and theNAME,SSKDEF,PECDEFandTYPEDECdirectives. - TASKING sources (
--dialect tasking): the common part of TASKING's m166 preprocessor (@SET,@EVAL,@IF/@ELSE/@ENDI,@DEFINED), TASKING's controls andSTDNAMESregister files, and the places where its assembler differs from Keil's. Infineon's MiniMon monitor and flash drivers, which gkflasher's ECU code comes from, rebuild byte for byte from their TASKING sources. See docs/tasking.md. - A Python package and a C API, for tools that assemble code themselves.
Not done yet:
- Keil's MPL macro language (
%DEFINEand the like); put$NOMPLat the top of the file to use%as text - OMF-166 object files and libraries
- TASKING's m166 macros with parameters (
@DEFINE), loops and string functions
See docs/compatibility.md for exact behaviour and the few places where openc166 deliberately differs from Keil.
Building
cmake -S . -B build
cmake --build build
ctest --test-dir build
The program is build/cli/openc166. On Windows with Visual Studio it is
under build\cli\Debug\ or build\cli\Release\. The shared library with
the C API is built in build/src/.
Usage
openc166 payload.a66 # writes payload.bin
openc166 payload.a66 -o out.bin -l out.lst # choose names, add a listing
openc166 payload.a66 -o payload.hex # Intel HEX
openc166 payload.a66 -o payload.s19 # S-records (S1)
openc166 main.a66 lib.a66 -o payload.bin # link two source files
Several source files are linked into one program, the way Keil's L166 linker joins the object files of A166:
- An
EXTERNname in one file takes the value of thePUBLICorGLOBALname in another. A name that no file exports is an error. - Sections with the same name and class are joined into one: the parts of
a
PUBLICorGLOBALsection follow one another, the parts of aCOMMONsection lie on top of each other. - Without
-o, the output is named after the first file. With-l, the listing has one part per file and a symbol table that names the file each symbol comes from. - Code outside sections starts at
--originin every file, so normally each file puts its code in sections.
$INCLUDE looks in each file's own directory.
docs/compatibility.md
has the exact rules.
The output format follows the extension of the -o file: .hex, .h86
and .ihx give Intel HEX; .srec, .s19, .s28, .s37, .mot and
.sx give S-records; anything else gives a raw binary. --format chooses
it explicitly.
A raw binary starts at the lowest address used. For example, code in
SECTION CODE AT 0E000H produces a file whose first byte belongs at
0E000H. Gaps between pieces of code are filled. HEX and S-record files
carry the address of every record, so they hold only the bytes used.
| Option | Meaning |
|---|---|
-f, --format FMT |
bin, hex or srec (default: from the output extension) |
--origin ADDR |
address of code outside sections, and the lowest address for sections without AT (default 0) |
--section NAME=ADDR |
put section NAME, which has no AT, at ADDR (may be repeated) |
--base ADDR |
binary: address of the first byte of the file |
--fill BYTE |
binary: value of gaps between pieces of code (default 0FFh) |
--record-size N |
HEX and S-records: data bytes per record (default 16) |
--cpu c166|c167 |
instruction set ($MOD167 in the source also selects C167) |
-I DIR |
also search DIR for $INCLUDE files (may be repeated) |
--dialect D |
keil (default) or tasking, for TASKING a166 sources |
-c, --control TEXT |
controls read before the sources, e.g. -c "CASE STDNAMES(reg167.def)" (may be repeated) |
Sections without AT go in order of first appearance to the first free,
suitably aligned place from the origin on, as L166 places them by default.
--section overrides that for chosen sections, like L166's SECTIONS
control. The listing ends with a table of where each section went.
examples/sections.a66 shows both.
Intel HEX files use extended linear address records (type 04) for addresses
above 64 KB, like OH166 with its H167 option. S-records use S1, S2 or S3
records by extension (.s19, .s28, .s37); otherwise the smallest kind
that holds every address.
The exit status is 0 on success, 1 on assembly errors (no output is
written), and 2 for usage or file errors. Messages use the format
file:line:column: error A74: ....
examples/payload.a66 is a short, commented example. examples/mtos/ holds real ECU payloads for Siemens SIMK43 ECUs, taken from gkflasher.
Python
pip install openc166 # or "pip install ." in a checkout
Wheels are published for Linux, Windows and macOS on x86 and ARM; other
systems build from source, which needs CMake and a C++20 compiler. To get
just the openc166 command, pipx install openc166 works too.
import openc166
result = openc166.assemble("""
$MOD167
PROG SECTION CODE AT 0E000H
MOV R4, #0BEEFH
RET
PROG ENDS
END
""")
image = result.image() # raises openc166.AssemblyError if there are errors
image.base # 0xE000, the address of image.data[0]
image.data # b'\xe6\xf4\xef\xbe\xcb\x00'
openc166.assemble(source, *, file_name=None, cpu=None, origin=0, include_dirs=(), sections=None, dialect="keil", controls=())assembles astrorbytes.sectionsgives addresses for sections withoutAT, e.g.{"VARS": 0xF600}.dialect="tasking"reads TASKING source;controlsis a list of controls read before the source, as with-c.openc166.assemble_file(path, ...)reads a file;$INCLUDEthen also searches the file's directory.- The result has
ok,diagnostics(each withseverity,code,message,file,line,column;str()gives the usual one-line message),errors,warnings,chunks(address and bytes of each piece of code),symbols(a dict of name toSymbol),symbol(name)(lookup ignoring case),sections(a dict of name toSection:type,align,address,size, andplacement, which is"at","given"or"located"),listingandcpu. openc166.assemble_many({"main.a66": text1, "lib.a66": text2}, ...)links several sources into one program, like several files on the command line;openc166.assemble_files([path1, path2], ...)reads them from files. EachSymbolthen says which file defines it (module) and whether it isPUBLICorGLOBAL(exported).result.moduleslists the file names;result.symbolsholds one symbol per name (the exported one if there is one),result.all_symbolsall of them. EachSectionhas itsclass_nameandgroup.result.image(base=None, fill=0xFF)lays all code out as one block, like the command-line tool.result.intel_hex(record_size=16)andresult.srec(record_size=16, address_size=None)return Intel HEX and S-record text (address_size2, 3 or 4 picks S1, S2 or S3 records).
The package needs Python 3.9 or newer. It also installs the openc166
command. It loads the library through ctypes, so one wheel works with
every Python version.
C API
include/openc166/openc166.h declares a plain C
interface, exported by the shared library (libopenc166.so,
libopenc166.dylib or openc166.dll). Any language that can call C can
use it: oc166_assemble assembles one source, oc166_assemble_many
links several. The header documents every function; the Python package is
an example of a complete binding.
Testing
-
ctest --test-dir buildruns the unit tests, the C API test and the Python package tests, and assembles the examples, checking every byte. -
tests/acceptance/minimon.pyrebuilds Infineon's MiniMon from its TASKING sources and compares the result with its HEX files. MiniMon is not included; setMINIMON_DIRto its directory (the one that holdsMCPROGandDriver) andctestruns it too. -
tests/diff/contains the differential test against Keil A166. Keil is not included. If you have your own copy, run:KEIL_A166=/path/to/A166.EXE python3 tests/diff/keil_diff.py tests/diff/cases/*.a66
It compares every line: address, code bytes, warnings and errors, and the final value of every symbol. Add
--imageto also link Keil's output with L166 and OH166 and compare the complete memory image, and--codesto list lines where both assemblers report an error but with different codes. Lines marked; DIVERGES:are deliberate differences (see docs/compatibility.md) and are skipped.Given a directory instead of a file, it treats each
.a66file in it as one module, links Keil's objects with L166, and compares the linked image and the linker's errors with openc166's:KEIL_A166=/path/to/A166.EXE python3 tests/diff/keil_diff.py tests/diff/cases/link/*/
On Linux and macOS, Keil runs under Wine. To generate test lines that cover the whole instruction set, run
tests/diff/gen_sweep.py build/generated/openc166/isa.json c167 > sweep.a66.The test inputs were written independently for this project. Keil's output is used only for the local comparison and is never stored in the repository.
License
MIT; see LICENSE. The bundled doctest test framework is also MIT.
openc166 is not affiliated with Arm/Keil or Infineon. "Keil", "A166", "C166", "C167" and "TASKING" are trademarks of their respective owners. The names are used only to describe compatibility.
Metadata
Release files for openc166 0.1.15
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| openc166-0.1.15.tar.gz | 330.1 kB | With provenance | Details for openc166-0.1.15.tar.gz |
Built distributions (wheels)
Total release size: 8.9 MB
Release files / openc166-0.1.15.tar.gz
| Download URL | openc166-0.1.15.tar.gz |
|---|---|
| Size | 330.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1cfcf6e6a75071e356b70fd42b2f1febd5175c4e8727d7438af820c22d43e39f
|
|
BLAKE2b-256 checksum How to use checksums |
42783c20025cf21733f13a8073cd59d12bf649ce6153d9a0d5a57ef557ba4c55
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logRelease files / openc166-0.1.15-py3-none-win_arm64.whl
| Download URL | openc166-0.1.15-py3-none-win_arm64.whl |
|---|---|
| Size | 769.0 kB |
| Tags | Python 3 Windows ARM64 |
|
SHA-256 checksum How to use checksums |
75e511d809a5c0892cd736ea363b8698e1816b1fb7898bc0eaafc04f2ab7bfed
|
|
BLAKE2b-256 checksum How to use checksums |
a0d5e13394d9020ab88a79fc96c7797b12c5e2891df8d0fbcfc66540774a33e3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logRelease files / openc166-0.1.15-py3-none-win_amd64.whl
| Download URL | openc166-0.1.15-py3-none-win_amd64.whl |
|---|---|
| Size | 805.9 kB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
4fde217e2eb6afc3593695373b07fd1ec8bbb3f88fa804485582074e81dab5d1
|
|
BLAKE2b-256 checksum How to use checksums |
5e8eeace3cad4746c16937d0f06d7c23e6cc9b6a30eeb3eb0a54fbf1679bd819
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logRelease files / openc166-0.1.15-py3-none-win32.whl
| Download URL | openc166-0.1.15-py3-none-win32.whl |
|---|---|
| Size | 704.4 kB |
| Tags | Python 3 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
abb49a0b7d72f078dba58b94c3346d007b201e181924db812b7cccb30c1545aa
|
|
BLAKE2b-256 checksum How to use checksums |
21f58f4f3918858155ab633af8efba710ae06c7dec2cc65fdf2ba73f31eaa3ff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logRelease files / openc166-0.1.15-py3-none-musllinux_1_2_x86_64.whl
| Download URL | openc166-0.1.15-py3-none-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 1.8 MB |
| Tags | Linux musl 1.2+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
dc4ad15d9c113808c0476b97a4ae450b0114f28ee24766c9ba33b0defff99759
|
|
BLAKE2b-256 checksum How to use checksums |
ce6aba4b02ec95b32ca718a0710aee026a6e2a807b5ed49f075fb77f9bf88e85
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logRelease files / openc166-0.1.15-py3-none-musllinux_1_2_aarch64.whl
| Download URL | openc166-0.1.15-py3-none-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | Linux musl 1.2+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
91b24ee46b60ce6935d4a3932b9b62601a3b4384f52994e99cd452af6a6382d1
|
|
BLAKE2b-256 checksum How to use checksums |
3433f4ebadb45790dce05aa4c2107d2b52e2c8d83362f10e77e4f2cc7df6c9c0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logRelease files / openc166-0.1.15-py3-none-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
| Download URL | openc166-0.1.15-py3-none-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 860.7 kB |
| Tags | Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
c2386e97306b037a75ae33f91ca4241877e52598a14d257520ef423ba3fa3708
|
|
BLAKE2b-256 checksum How to use checksums |
40eaead513d3630bcab855e9970d9ca1fba9dcee142c54a98ceecb550aa3c8a3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logRelease files / openc166-0.1.15-py3-none-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
| Download URL | openc166-0.1.15-py3-none-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl |
|---|---|
| Size | 774.2 kB |
| Tags | Linux glibc 2.24+ ARM64 Linux glibc 2.28+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
3ea7ef1a1b3be84556721d9a815a31a86404ff26245f1fed162dc1e05ec42480
|
|
BLAKE2b-256 checksum How to use checksums |
7ab8203751aef782a32329737e7d9c44bb86da99645ba2e5907f53c08f9293fe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logRelease files / openc166-0.1.15-py3-none-macosx_11_0_arm64.whl
| Download URL | openc166-0.1.15-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 610.2 kB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
f7b6316e2efded03768d26090529579b06a4cb3d8683801d75b0270dcc2b1abe
|
|
BLAKE2b-256 checksum How to use checksums |
1f58659c43ba36607a860a7c1c7d2a6dfac4090c128e865e1433904994237260
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logRelease files / openc166-0.1.15-py3-none-macosx_10_15_x86_64.whl
| Download URL | openc166-0.1.15-py3-none-macosx_10_15_x86_64.whl |
|---|---|
| Size | 654.7 kB |
| Tags | Python 3 macOS 10.15+ x86-64 |
|
SHA-256 checksum How to use checksums |
230851f14e39138281e5dcf0501708498c3a57b7a578141e44bfbc73408b83be
|
|
BLAKE2b-256 checksum How to use checksums |
c4aebd4c9f89892fc7f8c41a91a6ac2a9eb5104ab509c945058b582f3aba2576
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logSecurity for openc166 0.1.15
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 10 files in this release have been uploaded with provenance metadata.
Attestation for openc166-0.1.15.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.