TriCore AURIX Developer Guide

Overview

This page describes the status of the Infineon TriCore AURIX architecture port in Zephyr and the aspects that matter when developing Zephyr applications for AURIX platforms.

The TriCore architecture is a unified 32-bit microcontroller-DSP architecture for real-time embedded systems. It combines microcontroller real-time capability, DSP computational power and RISC load/store performance in a single core.

The port covers two AURIX SoC families:

Both are currently supported through QEMU boards only, see Supported boards.

Key supported features

The table below summarizes the status of key OS features across the supported AURIX SoC families.

Feature support

Feature

TC3xx

TC4x

ISA version

TC1.6.2P

TC1.8P

OS features

Single-thread kernel support

Y

Y

Multi-thread kernel support

Y

Y

Userspace

N

N

Interrupt handling

Regular interrupts (SW ISR table)

Y

Y

Nested interrupts

Y

Y

Dynamic interrupts

Y

Y

Direct interrupts

N

N

CPU idling

Y

Y

Memory protection

MPU

N

N

Timer

System timer (STM)

Y

Y

Cache

Instruction/data cache control

N

N

Floating point

Single-precision FPU

Y

Y

Double-precision FPU

N

Y

Multiprocessing

SMP

N

N

AMP

N

N

Architecture

Registers

The TriCore architecture provides 32 General Purpose Registers (GPRs) split into sixteen 32-bit data registers (D[0] through D[15]) and sixteen 32-bit address registers (A[0] through A[15]). In addition, the Program Counter (PC), Program Status Word (PSW) and Previous Context Information register (PCXI) form the core system state.

Several address and data registers have dedicated roles:

  • A[10]: Stack Pointer (SP)

  • A[11]: Return Address (RA)

  • A[0], A[1], A[8], A[9]: Global address registers

  • D[15]: Implicit data register

  • A[15]: Implicit base address register

The TC1.8P cores of TC4x implement a hypervisor extension and start in virtualization mode. The boot code drops to the default virtual machine when the SoC selects CONFIG_CPU_HAS_TRICORE_VIRTUALIZATION.

Context Save Areas (CSA)

The TriCore architecture saves and restores context in hardware using Context Save Areas (CSAs). Each CSA is a 64-byte memory block aligned to a 64-byte boundary. CSAs are linked together to form two lists:

  • Free Context List (FCX): Pool of available CSAs

  • Previous Context List (PCX): Chain of saved contexts for the current execution path

The register set is split into an upper context and a lower context:

  • Upper context (saved automatically on interrupts, traps and calls): A[10]-A[15], D[8]-D[15], PSW and PCXI.

  • Lower context (saved explicitly with the SVLCX or BISR instructions): A[2]-A[7], D[0]-D[7], A[11] and PCXI.

Software therefore does not push and pop registers on context switches, interrupt entry or function calls.

In Zephyr, the CSA pool is a static array of CONFIG_TRICORE_CSA_COUNT entries. The boot code in arch/tricore/core/reset.S links all CSAs into the free list and programs the FCX and LCX registers. LCX is set CONFIG_TRICORE_CSA_FCD_RESERVE entries before the end of the list, so the free context list depletion (FCD) trap handler has CSAs left to report the fault and abort the thread.

OS features

Threads

Thread stack alignment

Zephyr threads on TriCore use an 8-byte stack alignment (ARCH_STACK_PTR_ALIGN = 8), matching the EABI requirement for the stack pointer.

Stack pointers

The TriCore architecture uses a single stack pointer register A[10]. The PSW.IS bit tells whether the processor runs on the thread stack or on the interrupt stack. On interrupt or trap entry with PSW.IS == 0, the hardware loads A[10] from the Interrupt Stack Pointer (ISP) register and sets PSW.IS = 1.

In Zephyr, a single interrupt stack is shared among all exceptions and interrupts. The size is controlled by CONFIG_ISR_STACK_SIZE.

Thread context switching

Context switching uses the SYSCALL instruction. arch_switch() issues syscall 1, which enters the system call trap handler in supervisor mode. The handler saves the lower context and calls z_tricore_switch(), which:

  • stores the current PCXI, the head of the outgoing thread’s CSA chain, in the outgoing thread,

  • loads the PCXI of the incoming thread and returns.

The handler then restores the lower context of the incoming thread with RSLCX and returns with RFE, which restores its upper context.

When a thread aborted itself, the kernel hands it over in to_reclaim and the handler returns its CSA chain to the free list after the switch.

A context switch is also triggered from interrupt context. _isr_wrapper asks the scheduler for the next thread after the outermost interrupt returns (nested == 0) and no higher-priority interrupt is pending (ICR.PIPN == 0).

The implementation is in arch/tricore/core/switch.S, arch/tricore/core/syscall_wrapper.S and arch/tricore/core/isr_wrapper.S.

Interrupt handling

Interrupt priority

The TriCore architecture supports up to 255 interrupt priority levels. Each interrupt source is assigned a Service Request Priority Number (SRPN) in its Service Request Control (SRC) register of the Interrupt Router (IR). The ICR (Interrupt Control Register) holds the Current CPU Priority Number (CCPN) and the Pending Interrupt Priority Number (PIPN).

An interrupt is taken when ICR.IE == 1 and PIPN > CCPN.

On interrupt entry, the hardware:

  • saves the upper context to a CSA,

  • sets PCXI.PIE = ICR.IE and PCXI.PCPN = ICR.CCPN,

  • sets ICR.CCPN = ICR.PIPN and ICR.IE = 0,

  • loads A[10] from ISP if not already on the interrupt stack,

  • jumps to the vector entry at BIV + 32 * PIPN.

Zephyr provides 256 vector entries with 32-byte spacing. Each entry saves the lower context and jumps to _isr_wrapper, which reads the active interrupt number from the interrupt router and dispatches through the software ISR table. _isr_wrapper re-enables interrupts before calling the handler, so a higher-priority interrupt can nest.

On return from interrupt (RFE), the hardware restores the upper context and the previous ICR state from PCXI.

The vectors are in arch/tricore/core/vectors.c.

Locking and unlocking IRQs

arch_irq_lock() returns the current ICR value as the key and executes the DISABLE instruction, which clears ICR.IE. arch_irq_unlock() executes ENABLE if ICR.IE was set in the key.

Dynamic interrupts

Interrupts can be connected at run time through the software ISR table with CONFIG_DYNAMIC_INTERRUPTS.

CPU idling

arch_cpu_idle() enables interrupts and arch_cpu_atomic_idle() restores the interrupt state from its key; both then execute WAIT, and the core wakes on the next interrupt.

The implementation is in arch/tricore/core/cpu_idle.c.

Trap handling

The TriCore architecture defines 8 trap classes with 32-byte vector spacing, addressed via the BTV (Base Trap Vector) register:

  • Class 0: MMU traps

  • Class 1: Internal protection traps (privileged instruction, memory protection, global register write protection)

  • Class 2: Instruction errors (illegal or unimplemented opcode, invalid operand, alignment, invalid local memory address)

  • Class 3: Context management (free context depletion, call depth overflow)

  • Class 4: System bus and peripheral errors

  • Class 5: Assertion traps

  • Class 6: System call (SYSCALL instruction)

  • Class 7: Non-Maskable Interrupt (NMI)

Zephyr routes trap classes 0 to 5 and 7 through z_tricore_fault(), which logs the trap class, the Trap Identification Number (TIN) and a register dump and then calls z_fatal_error(). A free context list underflow (FCU, class 3 TIN 4) leaves no CSA to handle the trap and halts the core.

The system call trap (class 6) is used for context switching (syscall 1), raising exceptions (syscall 2) and IRQ offloading (syscall 3).

The implementation is in arch/tricore/core/fatal.c and arch/tricore/core/vectors.c.

Floating point

The TriCore FPU is integrated into the data path and operates on the D[0]-D[15] data registers. There are no separate FPU data registers. The FPU rounding mode and exception flags are held in the PSW, which is saved and restored as part of the upper context on interrupts, traps and calls.

The FPU trap control and capture registers (FPU_TRAP_CON and the FPU_TRAP_* registers after it) are not part of the context. Zephyr does not enable the FPU traps, so the FPU state that matters for threads is in the saved contexts and needs no extra handling in multi-threaded applications.

  • TC3xx (TC1.6.2P): Single-precision FPU (IEEE 754)

  • TC4x (TC1.8P): Single-precision and double-precision FPU (IEEE 754)

Toolchain

The TriCore port builds with the AURIX GCC toolchain provided by Infineon, version 11.3.1: Infineon AURIX GCC

export ZEPHYR_TOOLCHAIN_VARIANT=tricore
export TRICORE_TOOLCHAIN_PATH=/path/to/tricore-gcc

TRICORE_TOOLCHAIN_PATH defaults to /opt/toolchains/tricore-elf.

Note

The Zephyr SDK does not include a TriCore toolchain.

Supported boards

QEMU boards

Board

SoC

ISA

QEMU Emulation for Infineon AURIX TC39x

TC39x

TC1.6.2P

QEMU Emulation for Infineon AURIX TC4Dx

TC4Dx

TC1.8P

QEMU for TriCore AURIX is maintained at linumiz/qemu-aurix, which adds AURIX peripheral emulation. The board documentation describes how to set it up and run an application.

Drivers

The following table lists the peripheral drivers available in the TriCore port:

Driver

TC3xx

TC4x

Interrupt Router (IR)

Y

Y

System Timer (STM)

Y

Y

UART (ASCLIN), polling mode only

Y

Y

Architecture references

Maintainers and collaborators

The status of the TriCore AURIX architecture port in Zephyr is: maintained.

The list of maintainers and collaborators can be found in MAINTAINERS.yml under the TriCore arch and Infineon AURIX Platforms areas.