Files
templates/c/global-time/tests/run_tests.py
T
Andrey 2da7e7b525 feat(global-time): Добавь общие часы и порт TMS320F28335
Вынеси программные часы, коррекцию по ProtoCAN RTCSETUP и атомарную метку логгера в переносимое ядро без глобального состояния.

Подключи eCAN-A и CPU Timer2 отдельным портом F28335; зафиксируй календарные границы, переполнение, задержку RX и защиту IRQ в хостовых тестах.
2026-10-23 14:16:21 +03:00

37 lines
6.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Проверяет ядро и настоящий порт на host; опционально компилирует их TI C28x.""" # Описывает границу проверки без обещания аппаратного испытания.
import argparse # Принимает явные пути TI SDK вместо привязки библиотеки к рабочему компьютеру.
import os # Настраивает PATH компилятора, чтобы Windows находила его DLL.
from pathlib import Path # Строит пути относительно самого тестового набора.
import shutil # Находит GCC или Clang в окружении разработчика.
import subprocess # Запускает компиляторы аргументами без shell-интерполяции.
import tempfile # Изолирует все исполняемые и объектные файлы во временном каталоге.
root = Path(__file__).resolve().parents[1] # Определяет корень c/global-time независимо от текущего каталога.
parser = argparse.ArgumentParser(description=__doc__) # Показывает назначение host- и TI-проверок при --help.
parser.add_argument("--cc", default=os.environ.get("CC")) # Разрешает явно выбрать совместимый host-компилятор.
parser.add_argument("--ti-cgt", type=Path) # Принимает каталог TI C2000 compiler с bin/cl2000 и include.
parser.add_argument("--ti-headers", type=Path) # Принимает каталог с настоящим DSP2833x_Device.h проекта или TI SDK.
parser.add_argument("--ti-common", type=Path) # Принимает дополнительный каталог DSP2833x_GlobalPrototypes.h из DSP2833x_common/include.
args = parser.parse_args() # Проверяет параметры до создания любых файлов сборки.
candidates = [args.cc, shutil.which("gcc"), shutil.which("clang"), "C:/msys64/ucrt64/bin/gcc.exe"] # Последний путь обеспечивает привычное Windows-окружение без изменения глобального PATH.
compiler = next((str(Path(p).resolve()) for p in candidates if p and Path(p).is_file()), None) # Выбирает первый существующий компилятор, сохраняя явный --cc в приоритете.
if not compiler: # Не заменяет отсутствие компилятора успешным пустым запуском.
parser.error("Укажите --cc с путём к GCC/Clang") # Даёт воспроизводимое требование для запуска регрессий.
if bool(args.ti_cgt) != bool(args.ti_headers): # TI проверка требует одновременно компилятор и аппаратные заголовки.
parser.error("--ti-cgt и --ti-headers нужно указать вместе") # Предотвращает случайную проверку порта с host-моделью вместо SDK.
env = dict(os.environ) # Сохраняет исходное окружение остальных инструментов.
env["PATH"] = str(Path(compiler).parent) + os.pathsep + env.get("PATH", "") # Добавляет соседние DLL GCC только в дочерние процессы тестов.
with tempfile.TemporaryDirectory(prefix="global-time-") as output: # Удаляет только собственный временный каталог после завершения проверок.
for name, sources, includes in [("core", ["src/global_time.c", "tests/test_global_time.c"], ["include"]), ("f28335", ["src/global_time.c", "ports/tms320f28335/global_time_f28335.c", "tests/test_f28335.c"], ["include", "ports/tms320f28335", "tests/f28335_stubs"])]: # Проверяет ядро отдельно и реальный порт с модельными регистрами.
exe = Path(output) / (name + (".exe" if os.name == "nt" else "")) # Сохраняет host-программы за пределами исходного дерева.
command = [compiler, "-std=c99", "-Wall", "-Wextra", "-Werror", "-pedantic", *["-I" + str(root / p) for p in includes], *[str(root / p) for p in sources], "-o", str(exe)] # Считает все предупреждения ошибками и использует реальные исходники библиотеки.
subprocess.run(command, check=True, env=env, timeout=60) # Не маскирует ошибку компиляции успешным запуском старого EXE.
subprocess.run([str(exe)], check=True, env=env, timeout=30) # Выполняет календарные и аппаратные сценарии с ограниченным временем.
if args.ti_cgt: # Дополнительная проверка нужна для ABI с 16-битным char и настоящих регистров TI.
ti = args.ti_cgt.resolve() # Фиксирует абсолютный корень выбранного SDK компилятора.
for source in ["src/global_time.c", "ports/tms320f28335/global_time_f28335.c"]: # Компилирует оба поставляемых MCU исходника без изменения прошивки потребителя.
obj = Path(output) / (Path(source).stem + ".obj") # Разделяет объектные файлы ядра и аппаратного адаптера.
include_paths = [root / "include", root / "ports/tms320f28335", args.ti_headers.resolve(), ti / "include", *([args.ti_common.resolve()] if args.ti_common else [])] # Отдельно подключает common-заголовки старого TI SDK, не смешивая их с host-моделью.
command = [str(ti / "bin/cl2000.exe"), "--compile_only", "-v28", "-ml", "-mt", "--float_support=fpu32", "--abi=coffabi", "--c99", "-O2", "--opt_for_speed=0", "--display_error_number", *["--include_path=" + str(p) for p in include_paths], "--output_file=" + str(obj), str(root / source)] # Использует large/COFF ABI действующего проекта F28335 и штатные заголовки.
subprocess.run(command, check=True, timeout=60) # Ошибка TI C28x останавливает проверку вместо объявления host-модели достаточной.
print("global-time: TI C28x large/COFF compilation OK") # Подтверждает именно компиляцию объектов, не аппаратные испытания или полную линковку прошивки.