Add full automotive RTOS project

Add kernel (Cortex-M0/M3/M4, Tricore, S32K, RISC-V ports), drivers,
middleware (CAN stack, diagnostics, safety), applications, board
support, build/test tooling, and documentation.
This commit is contained in:
root
2026-08-23 03:35:29 -04:00
parent f113bf0a05
commit ca13734bf0
151 changed files with 23945 additions and 0 deletions
+262
View File
@@ -0,0 +1,262 @@
/**
* @file port.c
* @brief Infineon TriCore TC3xx architecture specific port
* @note TriCore is widely used in automotive powertrain and safety applications
*/
#include "kernel.h"
#include "task.h"
#include "scheduler.h"
#include "portmacro.h"
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxStm.h"
#include "IfxScuWdt.h"
/* Context storage */
uint32_t* current_task_sp = NULL;
uint32_t* next_task_sp = NULL;
/* STM configuration for system tick */
static IfxStm_CompareConfig stmCompareConfig;
static volatile uint32_t stmTickCount = 0;
/* CSA (Context Save Area) management */
#define MAX_CSA_AREAS 64
static uint32_t csa_areas[MAX_CSA_AREAS][16] __attribute__((aligned(64)));
static uint32_t csa_index = 0;
/* Interrupt priorities */
#define SYSTICK_PRIORITY 255
#define PENDSV_PRIORITY 255
#define SVC_PRIORITY 0
/* Initialize Architecture Port */
void port_init(void) {
/* Initialize CPU configuration */
IfxCpu_init();
/* Disable global interrupts during initialization */
IfxCpu_disableInterrupts();
/* Initialize CSA areas */
for (uint32_t i = 0; i < MAX_CSA_AREAS; i++) {
/* Initialize PCXI register for each CSA */
uint32_t pcxi_value = ((uint32_t)&csa_areas[i][0]) & 0xFFFFF000;
pcxi_value |= (i << 16); /* Set previous context pointer */
csa_areas[i][0] = pcxi_value;
}
/* Configure STM for 1ms tick */
IfxStm_initCompareConfig(&stmCompareConfig);
stmCompareConfig.triggerPriority = SYSTICK_PRIORITY;
stmCompareConfig.typeOfService = IfxSrc_Tos_cpu0;
stmCompareConfig.ticks = IfxStm_getFrequency(&MODULE_STM0) / 1000;
/* Initialize STM compare */
IfxStm_initCompare(&MODULE_STM0, &stmCompareConfig);
/* Enable safety watchdog */
IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
IfxScuWdt_clearCpuEndinit(IfxScuWdt_getCpuWatchdogPassword());
IfxScuWdt_enableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword(),
100, 200);
IfxScuWdt_setCpuEndinit(IfxScuWdt_getCpuWatchdogPassword());
/* Enable global interrupts */
IfxCpu_enableInterrupts();
}
/* Start First Task */
void port_start_first_task(void) {
TaskHandle_t first_task = scheduler_get_current_task();
if (first_task == NULL) {
return;
}
/* Get task context from CSA */
uint32_t* context = (uint32_t*)first_task->context;
uint32_t pcxi = context[0];
uint32_t pc = context[1];
uint32_t sp = context[2];
/* Set up context for first task execution */
__asm volatile (
"mov.a %%sp, %0\n" /* Set stack pointer */
"mov %%a11, %1\n" /* Set return address */
"mtsv %%pcxi, %2\n" /* Set context */
"rslcx\n" /* Restore lower context */
"rfe\n" /* Return from exception */
:
: "r" (sp), "r" (pc), "r" (pcxi)
: "a11", "memory"
);
}
/* Context Switch */
void port_context_switch(uint32_t* current_context, uint32_t* next_context) {
current_task_sp = current_context;
next_task_sp = next_context;
/* Trigger software interrupt for context switch */
__asm volatile (
"syscall 0\n" /* System call for context switch */
);
}
/* Initialize Task Stack */
uint32_t* port_initialize_task_stack(TaskFunction_t task_function,
void* parameters,
uint32_t* stack_top) {
uint32_t* stack_ptr = stack_top;
/* Align to 64 bytes */
stack_ptr = (uint32_t*)((uint32_t)stack_ptr & ~0x3F);
/* Allocate CSA for task */
if (csa_index >= MAX_CSA_AREAS) {
return NULL; /* Out of CSA areas */
}
uint32_t* csa = csa_areas[csa_index];
csa_index++;
/* Initialize CSA */
csa[0] = 0; /* PCXI will be set during first context switch */
csa[1] = (uint32_t)task_function; /* PC */
csa[2] = (uint32_t)stack_ptr; /* SP */
csa[3] = (uint32_t)parameters; /* A4 (first argument) */
/* Initialize upper context registers */
csa[4] = 0; /* A5 */
csa[5] = 0; /* A6 */
csa[6] = 0; /* A7 */
csa[7] = 0; /* A8 */
csa[8] = 0; /* A9 */
csa[9] = 0; /* A10 */
csa[10] = 0; /* A11 */
csa[11] = 0; /* A12 */
csa[12] = 0; /* A13 */
csa[13] = 0; /* A14 */
csa[14] = 0; /* A15 */
csa[15] = 0; /* D8 */
/* Store CSA pointer in task context */
TaskHandle_t task = scheduler_get_current_task();
if (task != NULL) {
task->context[0] = (uint32_t)csa;
}
return stack_ptr;
}
/* System Timer Interrupt Handler */
IFX_INTERRUPT(stm_compare_match_isr, 0, SYSTICK_PRIORITY) {
/* Clear interrupt flag */
IfxStm_clearCompareFlag(&MODULE_STM0, stmCompareConfig.comparator);
/* Update compare value for next interrupt */
IfxStm_increaseCompare(&MODULE_STM0, stmCompareConfig.comparator,
IfxStm_getFrequency(&MODULE_STM0) / 1000);
/* Call kernel tick handler */
extern void kernel_tick_handler(void);
kernel_tick_handler();
/* Refresh watchdog */
IfxScuWdt_clearSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());
}
/* Software Interrupt Handler for Context Switch */
IFX_INTERRUPT(software_context_switch_isr, 0, PENDSV_PRIORITY) {
__asm volatile (
/* Save current context */
"svlcx\n" /* Save lower context */
"mov %%d15, %%a11\n" /* Save return address */
/* Store current stack pointer */
"mov.a %%a15, %%sp\n"
"mov.aa %0, %%a15\n"
/* Load next stack pointer */
"mov.aa %%a15, %1\n"
"mov.a %%sp, %%a15\n"
/* Restore lower context */
"rslcx\n"
"mov %%a11, %%d15\n" /* Restore return address */
"rfe\n" /* Return from exception */
:
: "m" (current_task_sp), "m" (next_task_sp)
: "a15", "d15", "memory"
);
}
/* System Call Handler */
IFX_INTERRUPT(syscall_handler, 0, SVC_PRIORITY) {
/* Get system call number */
uint32_t syscall_number;
__asm volatile (
"mov %0, %%d15\n" /* Get syscall number from D15 */
: "=r" (syscall_number)
);
/* Handle system calls */
switch (syscall_number) {
case 0: /* Context switch */
software_context_switch_isr();
break;
case 1: /* Yield */
scheduler_yield();
break;
case 2: /* Task exit */
task_delete(scheduler_get_current_task());
break;
default:
break;
}
}
/* Trap Handlers */
IFX_INTERRUPT(trap_handler, 0, 0) {
/* Get trap information */
uint32_t trap_class;
uint32_t trap_id;
__asm volatile (
"mov %0, %%d15\n" /* Trap class */
"mov %1, %%d14\n" /* Trap ID */
: "=r" (trap_class), "=r" (trap_id)
);
/* Call fault handler */
extern void fault_handler_process(uint32_t type, uint32_t address, uint32_t status);
fault_handler_process(trap_class, trap_id, 0);
/* Enter safe state */
while(1) {
/* Safe state - wait for watchdog */
IfxScuWdt_clearSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());
}
}
/* Enter Critical Section */
void port_disable_interrupts(void) {
IfxCpu_disableInterrupts();
}
/* Exit Critical Section */
void port_enable_interrupts(void) {
IfxCpu_enableInterrupts();
}
/* Get Current Exception Number */
uint32_t port_get_current_exception(void) {
uint32_t icr;
__asm volatile (
"mfcr %0, $ICR\n" /* Get Interrupt Control Register */
: "=r" (icr)
);
return (icr >> 16) & 0xFF; /* Extract current CPU priority */
}
@@ -0,0 +1,105 @@
/**
* @file port_asm.s
* @brief Infineon TriCore TC3xx assembly routines
*/
.section .text
.align 2
/* Global symbols */
.global current_task_sp
.global next_task_sp
.global port_context_switch
.global port_start_first_task
.global port_disable_interrupts
.global port_enable_interrupts
/* Variables */
.section .bss
.align 2
current_task_sp: .word 0
next_task_sp: .word 0
.section .text
/* Start First Task */
port_start_first_task:
/* Load task context */
mov.a a15, [next_task_sp]
ld.a a14, [a15] /* Load CSA pointer */
/* Set up context */
mtsv pcxi, a14 /* Set previous context */
ld.a sp, [a14+8] /* Load stack pointer */
ld.a a11, [a14+4] /* Load return address */
/* Restore context and start */
rslcx /* Restore lower context */
rfe /* Return from exception */
/* Context Switch */
port_context_switch:
/* Save current context */
svlcx /* Save lower context */
/* Store current stack pointer */
mov.a a15, sp
mov.aa [current_task_sp], a15
/* Load next stack pointer */
mov.aa a15, [next_task_sp]
mov.a sp, a15
/* Restore next context */
rslcx /* Restore lower context */
rfe /* Return from exception */
/* Disable Interrupts */
port_disable_interrupts:
disable /* Disable interrupts */
ret
/* Enable Interrupts */
port_enable_interrupts:
enable /* Enable interrupts */
ret
/* System Timer Interrupt */
stm_compare_match_isr:
/* Save context */
svlcx
/* Clear interrupt */
movh.a a15, 0xF000 /* STM base address */
lea a15, [a15]0x0010 /* STM interrupt clear register */
st.w [a15], 0x1 /* Clear compare match flag */
/* Update compare value */
movh.a a15, 0xF000
lea a15, [a15]0x0020 /* STM compare register */
ld.w d15, [a15]
movh.a a14, 0xF000
lea a14, [a14]0x0024 /* STM compare update register */
add d15, d15, 1000 /* Add 1ms */
st.w [a14], d15
/* Call kernel tick handler */
call kernel_tick_handler
/* Restore context */
rslcx
rfe
/* Trap Handler */
trap_handler:
/* Save trap information */
mov d15, d15 /* Trap class */
mov d14, d14 /* Trap ID */
/* Call fault handler */
call fault_handler_process
/* Enter safe state */
j .
.end
@@ -0,0 +1,52 @@
/**
* @file portmacro.h
* @brief Infineon TriCore TC3xx specific macros
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include <stdint.h>
#include "Ifx_Types.h"
#include "IfxCpu.h"
/* Data Types */
typedef uint32_t port_stack_type_t;
typedef uint32_t port_base_type_t;
/* Architecture Constants */
#define PORT_STACK_GROWTH_DIRECTION (-1)
#define PORT_BYTE_ALIGNMENT 64
/* Critical Section Macros */
#define portENTER_CRITICAL() IfxCpu_disableInterrupts()
#define portEXIT_CRITICAL() IfxCpu_enableInterrupts()
/* Interrupt Control */
#define portENABLE_INTERRUPTS() IfxCpu_enableInterrupts()
#define portDISABLE_INTERRUPTS() IfxCpu_disableInterrupts()
/* Context Switch */
#define portYIELD() __asm volatile("syscall 0")
#define portYIELD_FROM_ISR() __asm volatile("syscall 0")
/* Memory Barriers */
#define portMEMORY_BARRIER() __asm volatile("dsync")
#define portSYNC_BARRIER() __asm volatile("dsync")
#define portINSTRUCTION_BARRIER() __asm volatile("isync")
/* NOP */
#define portNOP() __asm volatile("nop")
/* CSA Management */
#define portALLOCATE_CSA() __port_allocate_csa()
#define portFREE_CSA(csa) __port_free_csa(csa)
/* Safety Features */
#define portENABLE_SAFETY_WATCHDOG(timeout) \
IfxScuWdt_enableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword(), timeout, timeout*2)
#define portSERVICE_WATCHDOG() \
IfxScuWdt_clearSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword())
#endif /* PORTMACRO_H */