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
+217
@@ -0,0 +1,217 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
@file config_generator.py
|
||||
@brief Configuration file generator for Automotive RTOS
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Any
|
||||
|
||||
class ConfigGenerator:
|
||||
"""Generate RTOS configuration files"""
|
||||
|
||||
def __init__(self, project_root):
|
||||
self.project_root = Path(project_root)
|
||||
self.config_dir = self.project_root / 'config'
|
||||
|
||||
def load_configuration(self, config_file):
|
||||
"""Load configuration from JSON file"""
|
||||
with open(config_file, 'r') as f:
|
||||
return json.load(f)
|
||||
|
||||
def generate_kernel_config(self, config: Dict[str, Any]):
|
||||
"""Generate kernel_config.h"""
|
||||
print("Generating kernel_config.h...")
|
||||
|
||||
kernel = config.get('kernel', {})
|
||||
|
||||
content = f"""/**
|
||||
* @file kernel_config.h
|
||||
* @brief Kernel configuration (auto-generated)
|
||||
* @note This file is auto-generated. Do not modify manually.
|
||||
*/
|
||||
|
||||
#ifndef KERNEL_CONFIG_H
|
||||
#define KERNEL_CONFIG_H
|
||||
|
||||
/* ============================================================================
|
||||
* Basic Kernel Configuration
|
||||
* ============================================================================ */
|
||||
#define MAX_TASKS {kernel.get('max_tasks', 32)}
|
||||
#define MAX_PRIORITY_LEVELS {kernel.get('max_priorities', 16)}
|
||||
#define TICK_RATE_HZ {kernel.get('tick_rate', 1000)}
|
||||
#define MAX_TASK_NAME_LENGTH {kernel.get('max_task_name_length', 16)}
|
||||
|
||||
/* ============================================================================
|
||||
* Scheduler Configuration
|
||||
* ============================================================================ */
|
||||
#define SCHEDULER_TYPE SCHEDULER_PRIORITY_PREEMPTIVE
|
||||
#define ENABLE_ROUND_ROBIN {1 if kernel.get('round_robin', True) else 0}
|
||||
#define ROUND_ROBIN_TIME_SLICE {kernel.get('time_slice', 10)}
|
||||
#define ENABLE_DEADLINE_MONITORING {1 if kernel.get('deadline_monitoring', True) else 0}
|
||||
|
||||
/* ============================================================================
|
||||
* Synchronization Configuration
|
||||
* ============================================================================ */
|
||||
#define MAX_SEMAPHORES {kernel.get('max_semaphores', 32)}
|
||||
#define MAX_MUTEXES {kernel.get('max_mutexes', 16)}
|
||||
#define MAX_QUEUES {kernel.get('max_queues', 16)}
|
||||
#define MAX_TIMERS {kernel.get('max_timers', 16)}
|
||||
|
||||
/* ============================================================================
|
||||
* Memory Configuration
|
||||
* ============================================================================ */
|
||||
#define ENABLE_MEMORY_PROTECTION {1 if kernel.get('memory_protection', True) else 0}
|
||||
#define ENABLE_STACK_CHECK {1 if kernel.get('stack_check', True) else 0}
|
||||
#define DEFAULT_TASK_STACK_SIZE {kernel.get('default_stack_size', 1024)}
|
||||
#define HEAP_SIZE {kernel.get('heap_size', 65536)}
|
||||
|
||||
#endif /* KERNEL_CONFIG_H */
|
||||
"""
|
||||
|
||||
self._write_file(self.config_dir / 'kernel_config.h', content)
|
||||
|
||||
def generate_task_config(self, config: Dict[str, Any]):
|
||||
"""Generate task_config.h"""
|
||||
print("Generating task_config.h...")
|
||||
|
||||
tasks = config.get('tasks', [])
|
||||
|
||||
content = f"""/**
|
||||
* @file task_config.h
|
||||
* @brief Task configuration (auto-generated)
|
||||
* @note This file is auto-generated. Do not modify manually.
|
||||
*/
|
||||
|
||||
#ifndef TASK_CONFIG_H
|
||||
#define TASK_CONFIG_H
|
||||
|
||||
#include "kernel_config.h"
|
||||
|
||||
/* ============================================================================
|
||||
* Task Priority Definitions
|
||||
* ============================================================================ */
|
||||
"""
|
||||
|
||||
# Generate priority definitions
|
||||
for task in tasks:
|
||||
name = task['name'].upper().replace(' ', '_')
|
||||
priority = task.get('priority', 0)
|
||||
content += f"#define TASK_PRIORITY_{name:<30s} {priority}\n"
|
||||
|
||||
content += "\n/* ============================================================================\n"
|
||||
content += " * Task Period Definitions (ms)\n"
|
||||
content += " * ============================================================================ */\n"
|
||||
|
||||
# Generate period definitions
|
||||
for task in tasks:
|
||||
name = task['name'].upper().replace(' ', '_')
|
||||
period = task.get('period_ms', 10)
|
||||
content += f"#define TASK_PERIOD_{name:<30s} {period}\n"
|
||||
|
||||
content += "\n/* ============================================================================\n"
|
||||
content += " * Task Stack Sizes (bytes)\n"
|
||||
content += " * ============================================================================ */\n"
|
||||
|
||||
# Generate stack size definitions
|
||||
for task in tasks:
|
||||
name = task['name'].upper().replace(' ', '_')
|
||||
stack_size = task.get('stack_size', 1024)
|
||||
content += f"#define TASK_STACK_{name:<30s} {stack_size}\n"
|
||||
|
||||
content += "\n/* ============================================================================\n"
|
||||
content += " * Task Configuration Table\n"
|
||||
content += " * ============================================================================ */\n\n"
|
||||
|
||||
content += "static const TaskConfigEntry_t task_config_table[] = {\n"
|
||||
content += " /* Name, Priority, Period, Stack, Deadline, Periodic, Critical */\n"
|
||||
|
||||
for task in tasks:
|
||||
name = task['name']
|
||||
priority = task.get('priority', 0)
|
||||
period = task.get('period_ms', 10)
|
||||
stack_size = task.get('stack_size', 1024)
|
||||
deadline = task.get('deadline_ms', period)
|
||||
periodic = 'true' if task.get('periodic', True) else 'false'
|
||||
critical = 'true' if task.get('critical', False) else 'false'
|
||||
|
||||
content += f' {{"{name}", {priority}, {period}, {stack_size}, '
|
||||
content += f'{deadline}, {periodic}, {critical}}},\n'
|
||||
|
||||
content += "};\n\n"
|
||||
content += f"#define TASK_CONFIG_COUNT {len(tasks)}\n\n"
|
||||
content += "#endif /* TASK_CONFIG_H */\n"
|
||||
|
||||
self._write_file(self.config_dir / 'task_config.h', content)
|
||||
|
||||
def generate_can_config(self, config: Dict[str, Any]):
|
||||
"""Generate can_config.h"""
|
||||
print("Generating can_config.h...")
|
||||
|
||||
can_config = config.get('can', {})
|
||||
|
||||
content = f"""/**
|
||||
* @file can_config.h
|
||||
* @brief CAN configuration (auto-generated)
|
||||
*/
|
||||
|
||||
#ifndef CAN_CONFIG_H
|
||||
#define CAN_CONFIG_H
|
||||
|
||||
/* CAN Baudrate */
|
||||
#define CAN_BAUDRATE {can_config.get('baudrate', 500000)}
|
||||
#define CAN_FD_BAUDRATE {can_config.get('fd_baudrate', 2000000)}
|
||||
#define CAN_FD_ENABLED {1 if can_config.get('fd_enabled', False) else 0}
|
||||
|
||||
/* CAN Message IDs */
|
||||
"""
|
||||
|
||||
# Generate message ID definitions
|
||||
messages = can_config.get('messages', [])
|
||||
for msg in messages:
|
||||
name = msg['name'].upper().replace(' ', '_')
|
||||
msg_id = msg.get('id', 0x100)
|
||||
content += f"#define CAN_ID_{name:<30s} 0x{msg_id:03X}\n"
|
||||
|
||||
content += "\n#endif /* CAN_CONFIG_H */\n"
|
||||
|
||||
self._write_file(self.config_dir / 'can_config.h', content)
|
||||
|
||||
def _write_file(self, file_path: Path, content: str):
|
||||
"""Write content to file"""
|
||||
file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(file_path, 'w') as f:
|
||||
f.write(content)
|
||||
print(f" Generated: {file_path}")
|
||||
|
||||
def generate(self, config_file: str):
|
||||
"""Generate all configuration files"""
|
||||
print("=" * 60)
|
||||
print("Configuration Generator")
|
||||
print("=" * 60)
|
||||
|
||||
config = self.load_configuration(config_file)
|
||||
|
||||
# Generate configuration files
|
||||
self.generate_kernel_config(config)
|
||||
self.generate_task_config(config)
|
||||
self.generate_can_config(config)
|
||||
|
||||
print("\nConfiguration generation complete")
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Configuration generator')
|
||||
parser.add_argument('config_file', help='Configuration JSON file')
|
||||
parser.add_argument('--project', default='.', help='Project root directory')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
generator = ConfigGenerator(args.project)
|
||||
generator.generate(args.config_file)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
@file task_priority_calculator.py
|
||||
@brief Task priority calculator for Rate Monotonic Scheduling
|
||||
"""
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
from collections import defaultdict
|
||||
from math import ceil
|
||||
|
||||
class TaskPriorityCalculator:
|
||||
"""Calculate task priorities using RMS/DMS algorithms"""
|
||||
|
||||
def __init__(self):
|
||||
self.tasks = []
|
||||
|
||||
def add_task(self, name, period_ms, execution_time_ms, deadline_ms=None):
|
||||
"""Add task for analysis"""
|
||||
if deadline_ms is None:
|
||||
deadline_ms = period_ms
|
||||
|
||||
self.tasks.append({
|
||||
'name': name,
|
||||
'period': period_ms,
|
||||
'execution_time': execution_time_ms,
|
||||
'deadline': deadline_ms
|
||||
})
|
||||
|
||||
def calculate_utilization(self):
|
||||
"""Calculate CPU utilization"""
|
||||
total_utilization = 0
|
||||
|
||||
for task in self.tasks:
|
||||
utilization = task['execution_time'] / task['period']
|
||||
task['utilization'] = utilization
|
||||
total_utilization += utilization
|
||||
|
||||
return total_utilization
|
||||
|
||||
def rate_monotonic_priority(self):
|
||||
"""Assign priorities using Rate Monotonic Scheduling"""
|
||||
# Sort by period (shortest period = highest priority)
|
||||
sorted_tasks = sorted(self.tasks, key=lambda x: x['period'])
|
||||
|
||||
for i, task in enumerate(sorted_tasks):
|
||||
task['rms_priority'] = i
|
||||
|
||||
return sorted_tasks
|
||||
|
||||
def deadline_monotonic_priority(self):
|
||||
"""Assign priorities using Deadline Monotonic Scheduling"""
|
||||
# Sort by deadline (shortest deadline = highest priority)
|
||||
sorted_tasks = sorted(self.tasks, key=lambda x: x['deadline'])
|
||||
|
||||
for i, task in enumerate(sorted_tasks):
|
||||
task['dms_priority'] = i
|
||||
|
||||
return sorted_tasks
|
||||
|
||||
def check_schedulability(self):
|
||||
"""Check if task set is schedulable"""
|
||||
n = len(self.tasks)
|
||||
total_utilization = self.calculate_utilization()
|
||||
|
||||
# Liu & Layland bound for RMS
|
||||
rms_bound = n * (2 ** (1/n) - 1)
|
||||
|
||||
# Exact schedulability test
|
||||
schedulable = True
|
||||
|
||||
for i, task in enumerate(sorted(self.tasks, key=lambda x: x['priority'])):
|
||||
# Calculate response time
|
||||
response_time = task['execution_time']
|
||||
|
||||
while True:
|
||||
interference = 0
|
||||
for j in range(i):
|
||||
higher_task = self.tasks[j]
|
||||
interference += ceil(response_time / higher_task['period']) * \
|
||||
higher_task['execution_time']
|
||||
|
||||
new_response = task['execution_time'] + interference
|
||||
|
||||
if new_response == response_time:
|
||||
break
|
||||
|
||||
response_time = new_response
|
||||
|
||||
if response_time > task['deadline']:
|
||||
schedulable = False
|
||||
break
|
||||
|
||||
task['response_time'] = response_time
|
||||
|
||||
if not schedulable:
|
||||
break
|
||||
|
||||
return schedulable, total_utilization, rms_bound
|
||||
|
||||
def generate_report(self):
|
||||
"""Generate priority assignment report"""
|
||||
print("=" * 80)
|
||||
print("Task Priority Calculation Report")
|
||||
print("=" * 80)
|
||||
print()
|
||||
|
||||
# Calculate utilization
|
||||
total_utilization = self.calculate_utilization()
|
||||
|
||||
print("Task Set:")
|
||||
print("-" * 80)
|
||||
print(f"{'Task':20s} {'Period':>8s} {'Exec Time':>10s} {'Deadline':>8s} {'Util':>8s}")
|
||||
print("-" * 80)
|
||||
|
||||
for task in self.tasks:
|
||||
print(f"{task['name']:20s} {task['period']:8d} "
|
||||
f"{task['execution_time']:10d} {task['deadline']:8d} "
|
||||
f"{task['utilization']*100:7.2f}%")
|
||||
|
||||
print("-" * 80)
|
||||
print(f"{'Total':20s} {'':>8s} {'':>10s} {'':>8s} {total_utilization*100:7.2f}%")
|
||||
print()
|
||||
|
||||
# Rate Monotonic
|
||||
print("Rate Monotonic Priority Assignment:")
|
||||
print("-" * 40)
|
||||
rms_tasks = self.rate_monotonic_priority()
|
||||
for task in rms_tasks:
|
||||
print(f" Priority {task['rms_priority']}: {task['name']}")
|
||||
print()
|
||||
|
||||
# Deadline Monotonic
|
||||
print("Deadline Monotonic Priority Assignment:")
|
||||
print("-" * 40)
|
||||
dms_tasks = self.deadline_monotonic_priority()
|
||||
for task in dms_tasks:
|
||||
print(f" Priority {task['dms_priority']}: {task['name']}")
|
||||
print()
|
||||
|
||||
# Schedulability
|
||||
schedulable, utilization, bound = self.check_schedulability()
|
||||
|
||||
print("Schedulability Analysis:")
|
||||
print("-" * 40)
|
||||
print(f"CPU Utilization: {utilization*100:.2f}%")
|
||||
print(f"Theoretical Bound: {bound*100:.2f}%")
|
||||
|
||||
if schedulable:
|
||||
print("✓ Task set is schedulable")
|
||||
else:
|
||||
print("✗ Task set is NOT schedulable")
|
||||
|
||||
print()
|
||||
print("Response Times:")
|
||||
print("-" * 40)
|
||||
for task in self.tasks:
|
||||
if 'response_time' in task:
|
||||
print(f" {task['name']}: {task['response_time']}ms "
|
||||
f"(deadline: {task['deadline']}ms)")
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Task priority calculator')
|
||||
parser.add_argument('--tasks', nargs='+', help='Task definitions: name:period:exec[:deadline]')
|
||||
parser.add_argument('--file', help='Task definition file')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
calculator = TaskPriorityCalculator()
|
||||
|
||||
# Load tasks from file or command line
|
||||
if args.file:
|
||||
with open(args.file, 'r') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line and not line.startswith('#'):
|
||||
parts = line.split(':')
|
||||
if len(parts) >= 3:
|
||||
name = parts[0]
|
||||
period = int(parts[1])
|
||||
exec_time = int(parts[2])
|
||||
deadline = int(parts[3]) if len(parts) > 3 else period
|
||||
calculator.add_task(name, period, exec_time, deadline)
|
||||
elif args.tasks:
|
||||
for task_def in args.tasks:
|
||||
parts = task_def.split(':')
|
||||
if len(parts) >= 3:
|
||||
name = parts[0]
|
||||
period = int(parts[1])
|
||||
exec_time = int(parts[2])
|
||||
deadline = int(parts[3]) if len(parts) > 3 else period
|
||||
calculator.add_task(name, period, exec_time, deadline)
|
||||
else:
|
||||
# Example tasks
|
||||
print("Using example task set:")
|
||||
calculator.add_task("Engine Control", 1, 0.5)
|
||||
calculator.add_task("Brake Control", 5, 1)
|
||||
calculator.add_task("CAN Communication", 10, 2)
|
||||
calculator.add_task("Sensor Reading", 2, 0.3)
|
||||
calculator.add_task("Display Update", 50, 10)
|
||||
|
||||
calculator.generate_report()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user