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:
Executable
+215
@@ -0,0 +1,215 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
@file timing_analyzer.py
|
||||
@brief Timing analyzer for Automotive RTOS
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import argparse
|
||||
import json
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
class TimingAnalyzer:
|
||||
"""Analyze timing requirements and performance"""
|
||||
|
||||
def __init__(self, project_root):
|
||||
self.project_root = Path(project_root)
|
||||
self.tasks = {}
|
||||
self.timing_data = defaultdict(list)
|
||||
self.violations = []
|
||||
|
||||
def analyze_task_configuration(self):
|
||||
"""Analyze task timing configuration"""
|
||||
print("Analyzing task configuration...")
|
||||
|
||||
task_config_file = self.project_root / 'config' / 'task_config.h'
|
||||
if not task_config_file.exists():
|
||||
print("Task configuration file not found")
|
||||
return
|
||||
|
||||
with open(task_config_file, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Parse task priorities and periods
|
||||
task_pattern = re.compile(
|
||||
r'\{"([^"]+)",\s*(\d+),\s*(\d+),\s*(\d+),\s*(\d+),\s*(true|false),\s*(true|false)\}'
|
||||
)
|
||||
|
||||
print("\nTask Configuration:")
|
||||
print("-" * 80)
|
||||
print(f"{'Task Name':25s} {'Priority':>8s} {'Period':>8s} {'Deadline':>8s}")
|
||||
print("-" * 80)
|
||||
|
||||
for match in task_pattern.finditer(content):
|
||||
task_name = match.group(1)
|
||||
priority = int(match.group(2))
|
||||
period = int(match.group(3))
|
||||
deadline = int(match.group(5))
|
||||
|
||||
self.tasks[task_name] = {
|
||||
'priority': priority,
|
||||
'period': period,
|
||||
'deadline': deadline
|
||||
}
|
||||
|
||||
print(f"{task_name:25s} {priority:8d} {period:8d} {deadline:8d}")
|
||||
|
||||
print("-" * 80)
|
||||
|
||||
def analyze_schedulability(self):
|
||||
"""Analyze task schedulability"""
|
||||
print("\nSchedulability Analysis:")
|
||||
print("-" * 60)
|
||||
|
||||
# Calculate CPU utilization
|
||||
total_utilization = 0
|
||||
for task_name, config in self.tasks.items():
|
||||
if config['period'] > 0:
|
||||
utilization = config['deadline'] / config['period']
|
||||
total_utilization += utilization
|
||||
|
||||
print(f"{task_name:25s} {utilization*100:6.2f}%")
|
||||
|
||||
print("-" * 60)
|
||||
print(f"Total CPU Utilization: {total_utilization*100:.2f}%")
|
||||
|
||||
# Check schedulability
|
||||
if total_utilization < 0.69: # Liu & Layland bound for RM
|
||||
print("✓ System is schedulable (Rate Monotonic)")
|
||||
else:
|
||||
print("⚠ System may not be schedulable")
|
||||
self.violations.append("High CPU utilization")
|
||||
|
||||
def analyze_timing_logs(self, log_file):
|
||||
"""Analyze timing logs"""
|
||||
if not os.path.exists(log_file):
|
||||
print(f"Timing log not found: {log_file}")
|
||||
return
|
||||
|
||||
print(f"\nAnalyzing timing log: {log_file}")
|
||||
|
||||
with open(log_file, 'r') as f:
|
||||
for line in f:
|
||||
# Parse timing data
|
||||
match = re.match(
|
||||
r'\[(\d+)\]\s+(\w+):\s+start=(\d+)\s+end=(\d+)\s+duration=(\d+)'
|
||||
, line)
|
||||
|
||||
if match:
|
||||
timestamp = int(match.group(1))
|
||||
task_name = match.group(2)
|
||||
duration = int(match.group(5))
|
||||
|
||||
self.timing_data[task_name].append({
|
||||
'timestamp': timestamp,
|
||||
'duration': duration
|
||||
})
|
||||
|
||||
# Calculate statistics
|
||||
print("\nTiming Statistics:")
|
||||
print("-" * 80)
|
||||
print(f"{'Task Name':25s} {'Count':>6s} {'Min':>8s} {'Max':>8s} {'Avg':>8s} {'Jitter':>8s}")
|
||||
print("-" * 80)
|
||||
|
||||
for task_name, measurements in self.timing_data.items():
|
||||
if measurements:
|
||||
durations = [m['duration'] for m in measurements]
|
||||
count = len(durations)
|
||||
min_duration = min(durations)
|
||||
max_duration = max(durations)
|
||||
avg_duration = sum(durations) / count
|
||||
jitter = max_duration - min_duration
|
||||
|
||||
print(f"{task_name:25s} {count:6d} {min_duration:8d} "
|
||||
f"{max_duration:8d} {avg_duration:8.1f} {jitter:8d}")
|
||||
|
||||
# Check for violations
|
||||
if task_name in self.tasks:
|
||||
deadline = self.tasks[task_name]['deadline']
|
||||
if max_duration > deadline:
|
||||
self.violations.append(
|
||||
f"{task_name} exceeds deadline: {max_duration} > {deadline}"
|
||||
)
|
||||
|
||||
def analyze_interrupt_timing(self):
|
||||
"""Analyze interrupt timing"""
|
||||
print("\nInterrupt Timing Analysis:")
|
||||
print("-" * 40)
|
||||
|
||||
# Common interrupt latencies
|
||||
interrupts = {
|
||||
'SysTick': {'priority': 15, 'typical_latency': 1},
|
||||
'CAN': {'priority': 5, 'typical_latency': 2},
|
||||
'UART': {'priority': 6, 'typical_latency': 1},
|
||||
'SPI': {'priority': 7, 'typical_latency': 1},
|
||||
'I2C': {'priority': 7, 'typical_latency': 2},
|
||||
'ADC': {'priority': 8, 'typical_latency': 3},
|
||||
'Timer': {'priority': 8, 'typical_latency': 1},
|
||||
}
|
||||
|
||||
for irq_name, config in interrupts.items():
|
||||
print(f"{irq_name:15s} Priority: {config['priority']:2d} "
|
||||
f"Latency: {config['typical_latency']}ms")
|
||||
|
||||
def generate_report(self, output_file):
|
||||
"""Generate timing analysis report"""
|
||||
print(f"\nGenerating report: {output_file}")
|
||||
|
||||
with open(output_file, 'w') as f:
|
||||
f.write("=" * 80 + "\n")
|
||||
f.write("Timing Analysis Report\n")
|
||||
f.write("=" * 80 + "\n\n")
|
||||
|
||||
# Task configuration
|
||||
f.write("Task Configuration:\n")
|
||||
f.write("-" * 40 + "\n")
|
||||
for task_name, config in self.tasks.items():
|
||||
f.write(f"{task_name}: Priority={config['priority']}, "
|
||||
f"Period={config['period']}ms, Deadline={config['deadline']}ms\n")
|
||||
|
||||
f.write("\n")
|
||||
|
||||
# Violations
|
||||
if self.violations:
|
||||
f.write("Timing Violations:\n")
|
||||
f.write("-" * 40 + "\n")
|
||||
for violation in self.violations:
|
||||
f.write(f"✗ {violation}\n")
|
||||
else:
|
||||
f.write("No timing violations detected.\n")
|
||||
|
||||
def analyze(self, timing_log=None):
|
||||
"""Run complete analysis"""
|
||||
print("=" * 60)
|
||||
print("Timing Analyzer")
|
||||
print("=" * 60)
|
||||
|
||||
self.analyze_task_configuration()
|
||||
self.analyze_schedulability()
|
||||
self.analyze_interrupt_timing()
|
||||
|
||||
if timing_log:
|
||||
self.analyze_timing_logs(timing_log)
|
||||
|
||||
# Generate report
|
||||
report_file = self.project_root / 'build' / 'timing_report.txt'
|
||||
report_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
self.generate_report(report_file)
|
||||
|
||||
print(f"\nReport saved to: {report_file}")
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Timing analyzer')
|
||||
parser.add_argument('--project', default='.', help='Project root directory')
|
||||
parser.add_argument('--timing-log', help='Timing log file')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
analyzer = TimingAnalyzer(args.project)
|
||||
analyzer.analyze(args.timing_log)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user