Skip to content

hw/tricore: add AURIX peripheral models and board support for TC3x and TC4x#1

Closed
parthitce wants to merge 12 commits into
masterfrom
dev/ifx/tricore-upstream
Closed

hw/tricore: add AURIX peripheral models and board support for TC3x and TC4x#1
parthitce wants to merge 12 commits into
masterfrom
dev/ifx/tricore-upstream

Conversation

@parthitce
Copy link
Copy Markdown
Member

@parthitce parthitce commented Apr 5, 2026

Summary

Add peripheral device models and board support for Infineon TriCore AURIX
microcontrollers, enabling QEMU-based emulation of the TC397B (TC3x family)
and TC4D7 (TC4x family). Zephyr RTOS boots to shell with UART console output
on both emulated machines.

This work enables CI testing for the TriCore architecture port of Zephyr RTOS
without requiring physical hardware.

Background

The TriCore peripheral patches originate from the EFS-OpenSource QEMU fork:
https://github.com/EFS-OpenSource/qemu-tricore-patches

The EFS patches targeted QEMU 9.x (March 2024 baseline). This series ports
them to the current QEMU 11.0-rc2 baseline, fixing all API changes and adding
TC3x and TC4x-specific register support required for Zephyr RTOS boot.

Changes from EFS baseline

  • Ported all device models to QEMU 11 APIs (resettable phases, const
    class_init, legacy_reset, CharFrontend, cpu_ldl_le_data, etc.)
  • Replaced deprecated headers (hw/sysbus.h -> hw/core/sysbus.h, etc.)
  • Replaced DEVICE_NATIVE_ENDIAN with DEVICE_LITTLE_ENDIAN
  • Removed DEFINE_PROP_END_OF_LIST and empty property arrays
  • Fixed error_get_pretty(NULL) crashes in link resolution
  • SCU: Added generic register array for WDT and unmodeled register fallback
  • SCU: Added PERPLLSTAT (0x24) and SYSPLLSTAT (0x14) status registers
    returning PLL locked/ready state for Zephyr clock driver
  • SCU: Added CCUCON LCK bit auto-clearing on configuration update
  • SCU: Added division-by-zero guards for clock divider functions
  • SCU: Replaced pow() with integer shift operations
  • STM: Fixed peripheral address from 0xF0000000 to 0xF0001000 (TC3x offset)
  • STM: Switched from QEMU_CLOCK_HOST to monotonic counter for deterministic
    guest timing, avoiding multi-minute busy-wait stalls
  • IR: Fixed peripheral address from 0xF0038000 to 0xF0037000 (TC3x offset)

TC4x additions (TC1.8 ISA)

  • target/tricore: Added RFH (Return From Hypervisor) instruction. TC1.8 CPUs
    start in hypervisor mode after reset; firmware calls RFH to transition to
    the default VM context before normal execution. Without this, TC4x ELFs
    trap with an illegal instruction fault during startup.
  • target/tricore: Fixed 16-bit CALLI decoding (SR format, OP2=1), which was
    previously decoded as JI and lost the return address save.
  • ASCLIN: Expanded MMIO to 0x200 bytes and added TC4x register offsets. TC4x
    uses a different register layout from TC3x: CSR at 0x13C, TXDATA at 0x140,
    RXDATA at 0x160, TXFIFOCON at 0x104, RXFIFOCON at 0x108. Added reg_addr
    bounds check to guard sub-word RMW against out-of-range TC4x offsets.
  • STM: Added tc4x-mode property. In TC4x mode the ABS register at offset 0x20
    returns the unshifted counter value instead of TIM4 (counter >> 16).
  • SCU: Expanded MMIO to 0x1000 bytes and added TC4x CCU register offsets:
    RAMPSTAT (0x20C), SYSPLLSTAT (0x30C), PERPLLSTAT (0x38C), CCUSTAT (0x404).
    SYSPLLSTAT and PERPLLSTAT track PLLPWR writes so the Zephyr clock driver
    can power-cycle PLLs during initialization.
  • hw/tricore: Added TC4Dx SoC and KIT_A3G_TC4D7_LITE machine. TC4D7 is a
    six-core AURIX MCU (TC1.8 ISA) with per-core DSPR (240K), PSPR (64K), and
    DLMU (512K) regions, six program flash banks, and local PSPR/DSPR aliases
    at 0xC0000000/0xD0000000 for CPU0. Peripheral addresses: STM0 at
    0xF8800000, ASCLIN0 at 0xF46C0000, IR at 0xF4430000, SCU at 0xF0064000.
    Uses memory_region_add_subregion_overlap to resolve conflicts between the
    SFR catch-all region (priority -1) and specific peripherals (priority 1).

Build

git clone https://github.com/linumiz/qemu-tricore.git
cd qemu-tricore
git checkout dev/ifx/tricore-upstream

mkdir build && cd build
../configure --target-list=tricore-softmmu
make -j$(nproc)

Run

# List available machines
./build/bin/qemu-system-tricore -machine help

# Boot Zephyr ELF on TC397B (TC3x, TC1.6P ISA)
./build/bin/qemu-system-tricore \
    -machine KIT_AURIX_TC397B_TRB \
    -nographic \
    -kernel /path/to/zephyr.elf

# Boot Zephyr ELF on TC4D7 (TC4x, TC1.8 ISA)
./build/bin/qemu-system-tricore \
    -machine KIT_A3G_TC4D7_LITE \
    -nographic \
    -kernel /path/to/zephyr.elf

# Exit with Ctrl-A X

Expected output

*** Booting Zephyr OS build v4.4.0-rc1-386-g3c10dc1bd9fc ***
Hello World! kit_a2g_tc397xa_3v3_tft/tc397xp/cpu0

*** Booting Zephyr OS build v4.4.0-rc1-386-g3c10dc1bd9fc ***
Hello World! kit_a3g_tc4d7_lite/tc4d7xp/cpu0

Testing

Verified with Zephyr RTOS hello_world sample on both board targets.

TC397B (TC3x):

west build -p -b kit_a2g_tc397xa_3v3_tft/tc397xp/cpu0 samples/hello_world
./path/to/qemu-system-tricore -machine KIT_AURIX_TC397B_TRB \
    -nographic -kernel build/zephyr/zephyr.elf

TC4D7 (TC4x):

west build -p -b kit_a3g_tc4d7_lite/tc4d7xp/cpu0 samples/hello_world
./path/to/qemu-system-tricore -machine KIT_A3G_TC4D7_LITE \
    -nographic -kernel build/zephyr/zephyr.elf

Known limitations

  • Single-core emulation only (CPU0), secondary cores not started
  • STM uses monotonic counter (increment-per-read) instead of real-time clock
  • PLL status registers return static locked/ready values
  • No pinctrl, GPIO, or ADC peripheral models
  • STM SRC register writes produce harmless warnings on console

Next steps

  • Upstream to zephyrproject-rtos/qemu for Zephyr CI integration
  • Add qemu board targets to Zephyr for twister testing

Signed-off-by: Parthiban Nallathambi parthiban@linumiz.com

TriCore AURIX microcontrollers use the ASCLIN module as their
primary serial interface. Add an ASCLIN UART model to enable
console I/O when emulating TriCore SoCs under QEMU.

The model implements TX/RX FIFO with configurable interrupt
generation, clock source selection via the CSR register, and
character backend integration for host-side I/O. Register
layout follows the Infineon ASCLIN specification with support
for FLAGS, FLAGSENABLE, FLAGSCLEAR, and FLAGSSET registers
controlling interrupt and status reporting.

Originally-by: David Brenken <david.brenken@efs-auto.de>
Signed-off-by: Bastian Koppelmann <bastian-qemu@tensor.gmbh>
Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
TriCore AURIX SoCs use a centralized interrupt router (IR) to
manage all peripheral interrupt sources. Without IR support,
no peripheral interrupts can be delivered to the CPU, making
timer and UART interrupt-driven operation impossible in QEMU.

Add the IR bus model implementing Service Request Control
registers (SRC) with configurable priority (SRPN), enable
(SRE), and service provider fields. The IR evaluates pending
requests and delivers the highest priority interrupt to the
CPU via the ICR register.

Extend the TriCore CPU model with do_interrupt for context
save/restore through the CSA mechanism, and exec_interrupt
for polling pending hardware interrupts during execution.

Originally-by: Bastian Koppelmann <bastian-qemu@tensor.gmbh>
Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
The SCU is the central clock and reset controller in AURIX SoCs.
Zephyr RTOS configures PLLs and clock dividers through the SCU
during early boot, and the watchdog timer (WDT) must be serviced
before any peripheral initialization can proceed.

Add an SCU model implementing:
- OSCCON, SYSPLLSTAT, PERPLLSTAT, SYSPLLCON, PERPLLCON registers
  for PLL lock and divider ready status
- CCUCON0-8 registers for clock divider configuration with
  automatic LCK bit clearing on update completion
- WDT register access via generic register array fallback,
  allowing read-back of any written value for unmodeled registers
- Clock frequency calculation consumed by the STM timer module
- Software reset via SWRSTCON triggering CPU reset

PLL status registers return locked and ready state to satisfy
Zephyr clock driver polling during initialization. Clock divider
functions guard against division by zero when dividers are
transiently zero during reconfiguration.

Originally-by: David Brenken <david.brenken@efs-auto.de>
Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
The STM is a free-running 64-bit counter used as the system tick
source in Zephyr RTOS on AURIX SoCs. Zephyr k_busy_wait and the
clock control driver rely on STM reads for timing during early
boot when the kernel tick interrupt is not yet running.

Add an STM model with TIM0-TIM6 registers providing shifted
views of the 64-bit counter, a capture register (CAP), and
compare match 0 with interrupt generation via the IR.

The counter uses a monotonic increment-per-read approach rather
than host or virtual clock sources. This avoids MMIO timing
distortion where host clock barely advances between back-to-back
guest reads in tight polling loops, which would cause guest
busy-waits to take minutes of real time to complete.

The STM obtains its frequency from the SCU clock control module
to maintain correct relative timing for compare match interrupts.

Originally-by: David Brenken <david.brenken@efs-auto.de>
Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
Add a simple virtual device for TriCore emulation providing
host-side console output, timed sleep, and clean emulator exit.
This enables test frameworks to print results and signal pass/fail
without requiring a fully modeled UART peripheral.

Originally-by: Georg Hofstetter <bastian-qemu@tensor.gmbh>
Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
The existing tc27x SoC model only provided CPU and memory regions
without any peripheral support. Rename to tc27xd to match the
specific silicon stepping (D-step TC277D) and integrate all
peripheral models into the SoC and TriBoard machine.

Wire ASCLIN UART, STM timer, SCU clock control, interrupt router,
and Virt device into the tc27xd SoC realize path with proper
link setup between peripherals (STM to SCU for clock frequency,
IR to CPU for interrupt delivery, SCU to CPU for reset).

Add an SFR catch-all device covering the 0xF0000000 peripheral
address space to silently absorb accesses to unmodeled registers,
preventing guest faults on configuration writes to peripherals
that are not yet emulated.

Update Kconfig to select all peripheral dependencies and add
TC39XB_SOC config for the follow-on tc39xb board support.

Originally-by: Andreas Konopik <andreas.konopik@efs-auto.de>
Originally-by: David Brenken <david.brenken@efs-auto.de>
Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
The TC397 is the flagship AURIX TC3x microcontroller with six
TriCore CPU cores, widely used in automotive powertrain and ADAS
applications. Add a tc39xb SoC model and TriBoard TC397B machine
to enable QEMU-based CI testing for Zephyr RTOS.

The SoC model implements the TC397B memory map with per-core
DSPR, PSPR, cache, and tag RAM regions for all six cores, six
program flash banks, data flash, LMU/DLMU shared memory, BROM,
and EMEM. Local PSPR/DSPR aliases at 0xC0000000/0xD0000000 map
to CPU0 scratchpad for single-core emulation.

Peripheral addresses follow the TC39xB User Manual:
- STM0 at 0xF0001000 (differs from TC27x at 0xF0000000)
- IR at 0xF0037000
- SCU at 0xF0036000
- ASCLIN0 at 0xF0000600

Verified booting Zephyr RTOS to shell with UART console output
using: qemu-system-tricore -machine KIT_AURIX_TC397B_TRB
       -nographic -kernel zephyr.elf

Originally-by: Andreas Konopik <andreas.konopik@efs-auto.de>
Originally-by: David Brenken <david.brenken@efs-auto.de>
Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
@parthitce parthitce requested review from go2sh, sivaifx and ssekar15 April 5, 2026 07:08
@parthitce parthitce force-pushed the dev/ifx/tricore-upstream branch from 94d2bc8 to eaea926 Compare April 5, 2026 07:24
TC1.8 introduces RFH (Return From Hypervisor). CPU starts in hypervisor
mode after reset and firmware calls RFH to transition to the default VM
context. Without this, TC4x ELFs trap with an illegal instruction fault
during tricore_cpu_disable_virtualization.

RFH restores an upper context from PCXI like RFE, then clears ICR.IE
and ICR.CCPN for the hypervisor-to-supervisor transition. QEMU does
not model the full virtualization state machine; this is sufficient for
Zephyr RTOS startup.

Also fix 16-bit CALLI (SR format, OP2=1): was decoded as JI, losing
the return address save. Add OPC2_32_SYS_RFH opcode constant.

Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
TC4x SoCs use different register layouts than TC3x. Extend ASCLIN,
STM, and SCU to handle both families.

ASCLIN: expand MMIO to 0x200 bytes and add TC4x register offsets. CSR
is at 0x13C, TXDATA at 0x140, RXDATA at 0x160, TXFIFOCON at 0x104,
RXFIFOCON at 0x108. Guard sub-word RMW against out-of-range reg_addr
for TC4x offsets that exceed the TC3x register array size.

STM: add tc4x-mode property. In TC4x mode the ABS register at offset
0x20 returns the unshifted counter value instead of TIM4 (counter>>16).

SCU: expand MMIO to 0x1000 bytes and add TC4x CCU register offsets:
RAMPSTAT 0x20C, SYSPLLSTAT 0x30C, PERPLLSTAT 0x38C, CCUSTAT 0x404.
SYSPLLSTAT and PERPLLSTAT track PLLPWR writes to SYSPLLCON0 and
PERPLLCON0 so the Zephyr clock driver can power-cycle PLLs during init.

Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
Add TC4Dx SoC model for Infineon AURIX TC4x and KIT_A3G_TC4D7_LITE
evaluation board machine.

TC4D7 is a third-generation AURIX MCU (TC1.8 ISA) with six CPU cores.
The SoC model maps per-core DSPR (240K) and PSPR (64K) for six cores,
six program flash banks, DLMU (512K) per core, and local aliases at
0xC0000000/0xD0000000 for CPU0.

Peripheral addresses per TC4Dx User Manual:
  STM0   0xF8800000  tc4x-mode, ABS counter at +0x20
  ASCLIN 0xF46C0000
  IR     0xF4430000
  SCU    0xF0064000

Use memory_region_add_subregion_overlap with priority -1 for the SFR
catch-all region and priority 1 for specific peripherals to resolve
address conflicts.

Verified booting Zephyr RTOS with UART console output on TC4D7.

Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
Add GitHub Actions workflow to build QEMU with tricore-softmmu target,
verify the binary reports both TC397 and TC4D7 machines, package as a
tarball, and publish a release artifact on version tags.

Builds on ubuntu-24.04 with minimal dependencies (no GUI/audio/VNC).
Triggers on push to master and dev/ifx/tricore-upstream, and on pull
requests to master.

Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
@parthitce parthitce force-pushed the dev/ifx/tricore-upstream branch from eaea926 to 54ab630 Compare April 6, 2026 09:06
@parthitce parthitce changed the title hw/tricore: Add TriCore AURIX peripheral models and TC397B board support hw/tricore: add AURIX peripheral models and board support for TC3x and TC4x Apr 6, 2026
@go2sh
Copy link
Copy Markdown

go2sh commented Apr 6, 2026

Crasy work <3 I'll build and test it tomorrow.

@parthitce
Copy link
Copy Markdown
Member Author

Crasy work <3 I'll build and test it tomorrow.

It still lacks many instructions. Added qemu boards in Zephyr RTOS and running the CI locally in my end now. Will post the results and also likely needs many fixes and additional instructions.

But sure, basic should work. Please give a try!

Add peripheral and CPU support needed to boot Zephyr RTOS on the
TC4Dx (TC1.8) QEMU machine with working interrupts and timers.

IRBUS: Add tc4x-mode for TC4x SRC bit positions, reg_addr_to_srcnum
mapping for TC4x offsets, LWSR/LASR register region at 0xF4430000,
auto-clear SRR on delivery, PIPN clear on no pending interrupt, and
re-evaluate on SRC writes.

STM: Replace ptimer with QEMUTimer on QEMU_CLOCK_VIRTUAL, add TC4x
register remapping (ABS, VM1 CMP/CMCON/ICR/ISCR), implement CMCON
MSTART/MSIZE compare window, call update_irqs from ISCR writes.

CPU: Add WAIT instruction (opcode 0x16) using cpu_loop_exit without
halting, keeping QEMU_CLOCK_VIRTUAL advancing for timer operation.

SoC: Set tc4x-mode on IRBUS, map IR INT region, move SRC base to
0xF4432000.

Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
@parthitce
Copy link
Copy Markdown
Member Author

@parthitce parthitce closed this Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants