TriCore architecture for ECU reverse engineers
Ghidra · ECU Reverse Engineering
TriCore architecture for ECU reverse engineers
Every chip tuner hits the same ceiling. You have mastered WinOLS®. You find maps, adjust values, build Stage 1 and Stage 2 files. Then a client asks for MapSwitch, or VIN protection, or launch control — and you realise you can change the ECU’s data, but not its code. The code is a program, the program runs on a processor, and inside almost every modern Bosch ECU that processor is TriCore. This guide explains the architecture you need to read that program: where things live in memory, what the registers do, and why understanding them is the difference between changing a number and changing behaviour.
What TriCore is, and why a chip tuner cares
TriCore is a processor architecture made by Infineon, designed specifically for automotive use: real-time processing, hardware safety features, and a memory layout built for the kind of work an ECU does. It sits inside practically every modern Bosch controller — EDC17, MED17, MG1, MD1 — and has done since around 2006. Infineon markets these automotive parts under the SAK prefix, so the exact chip in a file often reads as something like SAK-TC1797.
Here is the sentence that makes it matter to a tuner. TriCore runs the program that uses your maps. When you change a map value in WinOLS, TriCore is the brain that reads that value and decides what to do with it. So map work is working with the inputs to someone else’s algorithm. Reading TriCore is reading the algorithm itself.
The ceiling, in one line
Maps let you change what numbers the program uses. The code lets you change what the program does. MapSwitch, launch control, and VIN handling live in the second place — which is why they need architecture, not just map identification.
Memory layout: where everything lives
A TriCore ECU maps a lot of memory. Open the Memory Map window in Ghidra and you will see dozens of regions — several kinds of RAM, plus ports, CAN, timers, DMA, and other peripherals. Most of them you will never touch. In practice the reverse engineer works with two:
- Flash (the
0x80000000region) — the firmware code and the calibration data, in one persistent block. It is what you read and write with a KESS or KTAG, and your maps live here, in the calibration area, separate from the program code. - RAM (the
0xD0000000region) — runtime variables. Lost on power-off. This is where the ECU keeps live sensor readings, calculated values, and counters while the engine runs.
Everything else — the scratchpad RAMs, the peripheral registers — is there in the memory map, but it rarely matters for reading calibration logic. Learn to spot Flash and RAM first; the rest you name as you need it.
An analogy that holds up: Flash is the recipe book you keep on the shelf, and RAM is the kitchen counter where you are actually cooking. When the ECU reads the Driver’s Wish map from an address in Flash, it loads that value into RAM, works it through the torque path, and writes the final command to a hardware register. Follow that path in the code and you are no longer guessing what a map does — you are watching it be used.
Registers: the ECU’s working hands
This is where most people new to disassembly get lost, so keep it concrete. TriCore has 32 registers, split into two kinds:
- Data registers D0–D15 hold the numbers the ECU is calculating with — fuel mass, RPM, torque values.
- Address registers A0–A15 hold memory addresses — where to read a value from, where to write a result to.
That is the whole vocabulary at the start: numbers go in D registers, locations go in A registers. Everything the code does is moving values between these registers and memory. When you open a function in Ghidra, the instructions you read are almost all variations on “load this address into an A register, read the value into a D register, do arithmetic, store it back.”
Upper and lower context
The single idea that turns register soup into readable code is context. The 32 registers are divided into two halves, and they behave differently across a function call.
Upper context — A8–A15 and D8–D15 — is preserved by the system automatically. On a CALL the processor saves it; on RET it restores it. That means inside a subroutine you can use D8–D15 as free scratch registers: whatever the caller had in them is safe, because the system will put it back. If a value in D15 changes inside a called function, the caller’s D15 is untouched after the return.
Lower context — A2–A7 and D0–D7 — is not preserved. That is not a flaw; it is the point. Lower context is how parameters get passed between the caller and the called function. In practice compilers stick to D2–D7 and A2–A7 for this. So when you see a value arrive in D4 at the top of a function and a result leave in A4 or D2 at the bottom, you are reading the function’s inputs and outputs directly.
Once you hold this split in your head, a disassembled function stops being a wall of registers. You can look at any line and say: this one carries a parameter, this one is temporary, this one is the return value.
The four registers you never touch
Four registers are system registers, and modifying them can crash the ECU:
- A0 and A1 control contexts and processing zones.
- A8 and A9 are tied to the stack pointer, the data area, and the vector table.
The working rule from the course is simple: among the upper-context address registers, prefer A11–A15 for your own work and leave A8–A10 alone (A10 is the stack pointer). Treat A0, A1, A8, and A9 as off-limits. Everything else is fair game once you understand what it carries.
Learn to read real TriCore code
Ghidra TriCore Fundamental takes you from firmware structure to reading real Bosch EDC17 and MED17 code — registers, memory, and the first practical mods. The only structured Ghidra course built for chip tuners, not programmers.
See the TriCore course →Why this is the next level
None of this is theory for its own sake. Memory and registers are the vocabulary; the sentences they build are the ECU’s actual logic. Once you can read that logic, you can do the work that has no map: build MapSwitch from scratch, add launch control, change behaviour with RAM coding instead of a full reflash, recover a VIN. These are the jobs a customer asks for when the reference file from a similar ECU does not work — because the algorithm is different, and only the code shows you the algorithm.
That is the line between working with maps and understanding the ECU. Maps tell you what the ECU is doing. The architecture — memory and registers — is how you read why. And once you can read why, you can change it. If you want the practical next step, the sibling to this article walks the workflow: how to disassemble ECU firmware, from raw readout to readable code.
See where reverse engineering fits
TriCore reading is Level 3 of the path — the point where you stop editing data and start editing behaviour. See how the levels build toward it.
See the learning path →Frequently asked questions
What processor is inside a Bosch ECU?
Most modern Bosch ECUs — EDC17, MED17, MG1, MD1 — run an Infineon TriCore processor, marked under Infineon’s SAK automotive prefix (for example SAK-TC1797). TriCore has been the automotive standard in Bosch controllers since roughly 2006.
Do I need to learn TriCore assembly to tune?
For map work, no. To do the things maps cannot — MapSwitch, launch control, VIN handling, custom features — yes. Those live in the program code, and on a Bosch ECU that code runs on TriCore. Reading it means reading TriCore.
Where do maps live in TriCore memory?
In Flash, at the 0x80000000 region, inside the calibration area — separate from the program code. RAM (the 0xD0000000 region) holds runtime values such as live sensor readings and calculations, not the maps themselves. You read and write Flash with a tool like KESS or KTAG.
What is upper and lower context in TriCore?
TriCore splits its 32 registers into two halves. Upper context (A8–A15, D8–D15) is saved by the system on CALL and restored on RET, so those registers are safe to use inside a function. Lower context (A2–A7, D0–D7) is not preserved and is used to pass parameters between the caller and the called function. Knowing which is which is what lets you read a function and see where the data flows.
Is TriCore the same as ARM?
No. TriCore is an Infineon architecture built for automotive use — real-time processing, hardware safety features, and a memory layout designed for ECU workloads — with its own instruction set. Experience with ARM or x86 transfers partly, but the registers and calling conventions are TriCore-specific.
About this guide: Written by Stanislav Kasin, co-founder of Tuners Guild, based on the Ghidra TriCore Fundamental curriculum by Thomas Pirowski — 30+ years in ECU reverse engineering and university lecturer at AGH Kraków.
Related: How to disassemble ECU firmware · Bosch EDC17 Tuning Guide · TriCore Reverse Engineering · Learning Path · Which registers are safe to modify? · Jumps to nowhere? The compressed-readout thread
