Сохранить русские комментарии и настройки проекта в UTF-8

Добавить пояснения к исходникам, заголовкам TI, настройкам CCS и существующим проверкам. Зафиксировать правила кодировки, обзор модулей и аудит комментариев.
This commit is contained in:
2026-10-12 12:24:48 +03:00
parent 378e06a281
commit f741741cf8
137 changed files with 21576 additions and 2134 deletions

262
tests/comments/run_test.py Normal file
View File

@@ -0,0 +1,262 @@
# Проверка comments на модели пк. Комментарии и исходный текст в UTF-8.
# Продолжает текущий вызов, список или выражение: """Проверка UTF-8 и русских пояснений к каждой строке исходного кода."""; порядок аргументов сохраняется.
"""Проверка UTF-8 и русских пояснений к каждой строке исходного кода."""
# Подключает модуль argparse для этой проверки или подготовки сборки.
import argparse
# Подключает модуль io для этой проверки или подготовки сборки.
import io
# Импортирует необходимые имена: from pathlib import Path.
from pathlib import Path
# Подключает модуль re для этой проверки или подготовки сборки.
import re
# Подключает модуль subprocess для этой проверки или подготовки сборки.
import subprocess
# Подключает модуль tokenize для этой проверки или подготовки сборки.
import tokenize
# Задаёт ROOT по выражению справа; значение используется последующими операциями.
ROOT = Path(__file__).resolve().parents[2]
# Задаёт RUSSIAN по выражению справа; значение используется последующими операциями.
RUSSIAN = re.compile("[А-Яа-яЁё]")
# Задаёт C_SUFFIXES по выражению справа; значение используется последующими операциями.
C_SUFFIXES = {".c", ".h", ".cmd", ".inc"}
# Задаёт TEXT_SUFFIXES по выражению справа; значение используется последующими операциями.
TEXT_SUFFIXES = C_SUFFIXES | {".asm", ".py", ".md", ".bat", ".old", ".prefs", ".json", ".pjt", ".lkf"}
# Задаёт TEXT_NAMES по выражению справа; значение используется последующими операциями.
TEXT_NAMES = {".project", ".cproject", ".ccsproject", ".gitignore", ".editorconfig"}
# Объявляет функцию c_code_lines и её входные параметры.
def c_code_lines(text):
# Задаёт block по выражению справа; значение используется последующими операциями.
block = False
# Перебирает line in text.splitlines() в указанном порядке.
for line in text.splitlines():
# Задаёт out по выражению справа; значение используется последующими операциями.
out = []
# Задаёт i по выражению справа; значение используется последующими операциями.
i = 0
# Задаёт quote по выражению справа; значение используется последующими операциями.
quote = None
# Повторяет блок при выполнении i < len(line).
while i < len(line):
# Проверяет условие if block перед выполнением следующего блока.
if block:
# Задаёт end по выражению справа; значение используется последующими операциями.
end = line.find("*/", i)
# Проверяет условие if end < 0 перед выполнением следующего блока.
if end < 0:
# Продолжает текущий вызов, список или выражение: break; порядок аргументов сохраняется.
break
# Задаёт block по выражению справа; значение используется последующими операциями.
block = False
# Задаёт i по выражению справа; значение используется последующими операциями.
i = end + 2
# Продолжает текущий вызов, список или выражение: out.append(" "); порядок аргументов сохраняется.
out.append(" ")
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
continue
# Задаёт c по выражению справа; значение используется последующими операциями.
c = line[i]
# Проверяет условие if quote перед выполнением следующего блока.
if quote:
# Продолжает текущий вызов, список или выражение: out.append(c); порядок аргументов сохраняется.
out.append(c)
# Проверяет условие if c == "\\" and i + 1 < len(line) перед выполнением следующего блока.
if c == "\\" and i + 1 < len(line):
# Задаёт i + по выражению справа; значение используется последующими операциями.
i += 1
# Продолжает текущий вызов, список или выражение: out.append(line[i]); порядок аргументов сохраняется.
out.append(line[i])
# Проверяет условие elif c == quote перед выполнением следующего блока.
elif c == quote:
# Задаёт quote по выражению справа; значение используется последующими операциями.
quote = None
# Задаёт i + по выражению справа; значение используется последующими операциями.
i += 1
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
continue
# Проверяет условие if line.startswith("//", i) перед выполнением следующего блока.
if line.startswith("//", i):
# Продолжает текущий вызов, список или выражение: break; порядок аргументов сохраняется.
break
# Проверяет условие if line.startswith("/*", i) перед выполнением следующего блока.
if line.startswith("/*", i):
# Задаёт block по выражению справа; значение используется последующими операциями.
block = True
# Задаёт i + по выражению справа; значение используется последующими операциями.
i += 2
# Продолжает текущий вызов, список или выражение: out.append(" "); порядок аргументов сохраняется.
out.append(" ")
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
continue
# Проверяет условие if c in "\"'" перед выполнением следующего блока.
if c in "\"'":
# Задаёт quote по выражению справа; значение используется последующими операциями.
quote = c
# Продолжает текущий вызов, список или выражение: out.append(c); порядок аргументов сохраняется.
out.append(c)
# Задаёт i + по выражению справа; значение используется последующими операциями.
i += 1
# Продолжает текущий вызов, список или выражение: yield "".join(out).strip(); порядок аргументов сохраняется.
yield "".join(out).strip()
# Объявляет функцию python_code_lines и её входные параметры.
def python_code_lines(text):
# Задаёт active по выражению справа; значение используется последующими операциями.
active = set()
# Задаёт strings по выражению справа; значение используется последующими операциями.
strings = set()
# Перебирает token in tokenize.generate_tokens(io.StringIO(text).readline) в указанном порядке.
for token in tokenize.generate_tokens(io.StringIO(text).readline):
# Проверяет условие if token.type == tokenize.STRING and token.end[0] > token.start[0] перед выполнением следующего блока.
if token.type == tokenize.STRING and token.end[0] > token.start[0]:
# Продолжает текущий вызов, список или выражение: strings.update(range(token.start[0] + 1, token.end[0] + 1)); порядок аргументов сохраняется.
strings.update(range(token.start[0] + 1, token.end[0] + 1))
# Проверяет условие if token.type not in {tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE, tokenize.INDENT, tokenize.DEDENT, tokenize.ENDMARKER} перед выполнением следующего блока.
if token.type not in {tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE, tokenize.INDENT, tokenize.DEDENT, tokenize.ENDMARKER}:
# Продолжает текущий вызов, список или выражение: active.add(token.start[0]); порядок аргументов сохраняется.
active.add(token.start[0])
# Задаёт lines по выражению справа; значение используется последующими операциями.
lines = text.splitlines()
# Возвращает [line.strip() if n in active and n not in strings else "" for n, line in enumerate(lines, 1)] вызывающему коду и завершает функцию.
return [line.strip() if n in active and n not in strings else "" for n, line in enumerate(lines, 1)]
# Объявляет функцию audit и её входные параметры.
def audit(path, text):
# Задаёт lines по выражению справа; значение используется последующими операциями.
lines = text.splitlines()
# Проверяет условие if path.suffix in C_SUFFIXES перед выполнением следующего блока.
if path.suffix in C_SUFFIXES:
# Задаёт code по выражению справа; значение используется последующими операциями.
code = list(c_code_lines(text))
# Проверяет условие elif path.suffix == ".asm" перед выполнением следующего блока.
elif path.suffix == ".asm":
# Задаёт code по выражению справа; значение используется последующими операциями.
code = [line.split(";")[0].strip() for line in lines]
# Проверяет условие elif path.suffix == ".py" перед выполнением следующего блока.
elif path.suffix == ".py":
# Задаёт code по выражению справа; значение используется последующими операциями.
code = python_code_lines(text)
# Обрабатывает альтернативу предыдущего условия.
else:
# Возвращает 0, [] вызывающему коду и завершает функцию.
return 0, []
# Задаёт missing по выражению справа; значение используется последующими операциями.
missing = []
# Задаёт count по выражению справа; значение используется последующими операциями.
count = 0
# Перебирает i, value in enumerate(code) в указанном порядке.
for i, value in enumerate(code):
# Проверяет условие if not value перед выполнением следующего блока.
if not value:
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
continue
# Задаёт count + по выражению справа; значение используется последующими операциями.
count += 1
# Проверяет условие if RUSSIAN.search(lines[i]) or (i and RUSSIAN.search(lines[i-1])) перед выполнением следующего блока.
if RUSSIAN.search(lines[i]) or (i and RUSSIAN.search(lines[i-1])):
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
continue
# Явное продолжение Python-выражения относится к пояснённой начальной строке.
# Проверяет условие if path.suffix == ".py" and i and lines[i-1].rstrip().endswith("\\") перед выполнением следующего блока.
if path.suffix == ".py" and i and lines[i-1].rstrip().endswith("\\"):
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
continue
# Продолжает текущий вызов, список или выражение: missing.append(i+1); порядок аргументов сохраняется.
missing.append(i+1)
# Возвращает count, missing вызывающему коду и завершает функцию.
return count, missing
# Объявляет функцию main и её входные параметры.
def main():
# Задаёт parser по выражению справа; значение используется последующими операциями.
parser = argparse.ArgumentParser(description=__doc__)
# Задаёт parser.add_argument("--report", type по выражению справа; значение используется последующими операциями.
parser.add_argument("--report", type=Path, help="Сохранить таблицу покрытия в Markdown")
# Задаёт args по выражению справа; значение используется последующими операциями.
args = parser.parse_args()
# Задаёт names по выражению справа; значение используется последующими операциями.
names = subprocess.check_output(["git", "ls-files", "-z"], cwd=ROOT).decode("utf-8").split("\0")
# Задаёт names по выражению справа; значение используется последующими операциями.
names = sorted(set(filter(None, names)) | {"tests/comments/run_test.py", ".editorconfig"})
# Задаёт rows по выражению справа; значение используется последующими операциями.
rows = []
# Задаёт errors по выражению справа; значение используется последующими операциями.
errors = []
# Задаёт checked по выражению справа; значение используется последующими операциями.
checked = 0
# Перебирает name in names в указанном порядке.
for name in names:
# Задаёт path по выражению справа; значение используется последующими операциями.
path = ROOT / name
# Проверяет условие if path.suffix.lower() not in TEXT_SUFFIXES and path.name not in TEXT_NAMES перед выполнением следующего блока.
if path.suffix.lower() not in TEXT_SUFFIXES and path.name not in TEXT_NAMES:
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
continue
# Начинает блок обработки возможной ошибки.
try:
# Читает исходный файл или образ для последующей проверки и разбора.
text = path.read_text(encoding="utf-8")
# Перехватывает указанный тип ошибки и выполняет обработку.
except UnicodeError as error:
# Продолжает текущий вызов, список или выражение: errors.append(f"{name}: неверная кодировка UTF-8: {error}"); порядок аргументов сохраняется.
errors.append(f"{name}: неверная кодировка UTF-8: {error}")
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
continue
# Задаёт checked + по выражению справа; значение используется последующими операциями.
checked += 1
# Задаёт count, missing по выражению справа; значение используется последующими операциями.
count, missing = audit(path, text)
# Проверяет условие if missing перед выполнением следующего блока.
if missing:
# Продолжает текущий вызов, список или выражение: errors.append(f"{name}: нет русского пояснения, строки {missing[:20]}"); порядок аргументов сохраняется.
errors.append(f"{name}: нет русского пояснения, строки {missing[:20]}")
# Проверяет условие if path.suffix in C_SUFFIXES or path.suffix in {".asm", ".py"} перед выполнением следующего блока.
if path.suffix in C_SUFFIXES or path.suffix in {".asm", ".py"}:
# Продолжает текущий вызов, список или выражение: rows.append((name, count, count-len(missing))); порядок аргументов сохраняется.
rows.append((name, count, count-len(missing)))
# Проверяет условие if args.report перед выполнением следующего блока.
if args.report:
# Задаёт report по выражению справа; значение используется последующими операциями.
report = [
# Продолжает текущий вызов, список или выражение: "# Проверка комментариев и кодировки",; порядок аргументов сохраняется.
"# Проверка комментариев и кодировки",
# Продолжает текущий вызов, список или выражение: "",; порядок аргументов сохраняется.
"",
# Продолжает текущий вызов, список или выражение: "Проверка относится к редактируемым исходникам C/H, ASM, CMD, тестовым INC и Python.",; порядок аргументов сохраняется.
"Проверка относится к редактируемым исходникам C/H, ASM, CMD, тестовым INC и Python.",
# Продолжает текущий вызов, список или выражение: "Каждая непустая строка кода имеет русское пояснение перед ней или на ней. Пустые строки,",; порядок аргументов сохраняется.
"Каждая непустая строка кода имеет русское пояснение перед ней или на ней. Пустые строки,",
# Продолжает текущий вызов, список или выражение: "текст существующих комментариев и содержимое многострочных строк данных не считаются кодом.",; порядок аргументов сохраняется.
"текст существующих комментариев и содержимое многострочных строк данных не считаются кодом.",
# Продолжает текущий вызов, список или выражение: "Исходные уведомления TI сохранены. JSON-паспорта, индексы IDE, таблицы XLS и двоичные",; порядок аргументов сохраняется.
"Исходные уведомления TI сохранены. JSON-паспорта, индексы IDE, таблицы XLS и двоичные",
# Продолжает текущий вызов, список или выражение: "результаты сборки не допускают исходных комментариев; их назначение описано в документации.",; порядок аргументов сохраняется.
"результаты сборки не допускают исходных комментариев; их назначение описано в документации.",
# Продолжает текущий вызов, список или выражение: "",; порядок аргументов сохраняется.
"",
# Продолжает текущий вызов, список или выражение: f"UTF-8 проверен в {checked} текстовых файлах. Строк кода: {sum(r[1] for r in rows)}.",; порядок аргументов сохраняется.
f"UTF-8 проверен в {checked} текстовых файлах. Строк кода: {sum(r[1] for r in rows)}.",
# Продолжает текущий вызов, список или выражение: "",; порядок аргументов сохраняется.
"",
# Продолжает текущий вызов, список или выражение: "| Файл | Строк кода | С русским пояснением |",; порядок аргументов сохраняется.
"| Файл | Строк кода | С русским пояснением |",
# Продолжает текущий вызов, список или выражение: "| --- | ---: | ---: |",; порядок аргументов сохраняется.
"| --- | ---: | ---: |",
# Продолжает текущий вызов, список или выражение: ]; порядок аргументов сохраняется.
]
# Задаёт report + по выражению справа; значение используется последующими операциями.
report += [f"| {name} | {count} | {covered} |" for name,count,covered in rows]
# Сохраняет подготовленный файл в указанном формате для следующего шага.
args.report.write_text("\n".join(report)+"\n", encoding="utf-8")
# Проверяет условие if errors перед выполнением следующего блока.
if errors:
# Останавливает текущую операцию с исключением SystemExit("\n".join(errors)).
raise SystemExit("\n".join(errors))
# Продолжает текущий вызов, список или выражение: print(f"PASS UTF-8: {checked} files; Russian comments: {len(rows)} source files, {sum(r[1] for r in rows)} code lines"); порядок аргументов сохраняется.
print(f"PASS UTF-8: {checked} files; Russian comments: {len(rows)} source files, {sum(r[1] for r in rows)} code lines")
# Проверяет условие if __name__ == "__main__" перед выполнением следующего блока.
if __name__ == "__main__":
# Продолжает текущий вызов, список или выражение: main(); порядок аргументов сохраняется.
main()

View File

@@ -1,21 +1,42 @@
# Проверка eeprom_profiles на модели пк. Комментарии и исходный текст в UTF-8.
# Продолжает текущий вызов, список или выражение: """Check SPI wire address widths for both production EEPROM configurations."""; порядок аргументов сохраняется.
"""Check SPI wire address widths for both production EEPROM configurations."""
# Импортирует необходимые имена: from pathlib import Path.
from pathlib import Path
# Подключает модуль subprocess для этой проверки или подготовки сборки.
import subprocess
# Подключает модуль os для этой проверки или подготовки сборки.
import os
# Подключает модуль shutil для этой проверки или подготовки сборки.
import shutil
# Подключает модуль tempfile для этой проверки или подготовки сборки.
import tempfile
# Задаёт root по выражению справа; значение используется последующими операциями.
root = Path(__file__).resolve().parents[2]
# Задаёт protocol по выражению справа; значение используется последующими операциями.
protocol = root.parent / 'newProject/SETGUI/third_party/templates/c/set-protocol'
# Задаёт compiler по выражению справа; значение используется последующими операциями.
compiler = os.environ.get('CC') or shutil.which('gcc') or 'C:/msys64/mingw64/bin/gcc.exe'
# Задаёт os.environ['PATH'] по выражению справа; значение используется последующими операциями.
os.environ['PATH'] = str(Path(compiler).resolve().parent) + os.pathsep + os.environ['PATH']
# Открывает управляемый ресурс tempfile.TemporaryDirectory() as folder с автоматическим освобождением.
with tempfile.TemporaryDirectory() as folder:
# Перебирает profile in (0, 1) в указанном порядке.
for profile in (0, 1):
# Задаёт exe по выражению справа; значение используется последующими операциями.
exe = Path(folder) / f'spi{profile}.exe'
# Запускает внешний компилятор, генератор или тест; ненулевой результат проверяется параметрами вызова.
subprocess.run([compiler, '-std=c99',
# Задаёт f'-DEEPROM_M95M02 по выражению справа; значение используется последующими операциями.
f'-DEEPROM_M95M02={profile}', '-Itests/eeprom_profiles/stubs',
# Продолжает текущий вызов, список или выражение: '-ISource/Internal/Include', '-I' + str(protocol),; порядок аргументов сохраняется.
'-ISource/Internal/Include', '-I' + str(protocol),
# Продолжает текущий вызов, список или выражение: 'tests/eeprom_profiles/spi_test.c', '-o', str(exe)],; порядок аргументов сохраняется.
'tests/eeprom_profiles/spi_test.c', '-o', str(exe)],
# Задаёт cwd по выражению справа; значение используется последующими операциями.
cwd=root, check=True)
# Запускает внешний компилятор, генератор или тест; ненулевой результат проверяется параметрами вызова.
subprocess.run([str(exe)], check=True, timeout=10)
# Продолжает текущий вызов, список или выражение: print(f'PASS SPI profile {profile}'); порядок аргументов сохраняется.
print(f'PASS SPI profile {profile}')

View File

@@ -1,47 +1,93 @@
/* Проверка eeprom_profiles на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Exercise the production Timer2 SPI state machine; no hardware writes. */
/* Подключает <assert.h>: настройки и интерфейс assert. */
#include <assert.h>
/* Подключает "../../Source/Internal/spise2p.c": драйвер SPI EEPROM, адресация, страницы и автомат завершения операций. */
#include "../../Source/Internal/spise2p.c"
/* Продолжает список аргументов, полей или выражение static unsigned trace[300], widths[300], used;; порядок элементов сохраняется. */
static unsigned trace[300], widths[300], used;
/* Начинает функцию transfer; назначение модуля — проверка eeprom_profiles на модели ПК. */
static void transfer(unsigned long address, int write)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает buf[2] значением {0x1234,0x5678}, i; данные buf. */
unsigned buf[2]={0x1234,0x5678}, i;
/* Записывает message значением {buf,2,address}; данные message. */
SE2P_DATA message={buf,2,address};
/* Записывает used значением 0; данные used. */
used=0;
/* Проверяет if(write) spiSe2pWrite(&se2p,&message); else spiSe2pRead(&se2p,&message); последующий оператор выполняется только при истинном условии. */
if(write) spiSe2pWrite(&se2p,&message); else spiSe2pRead(&se2p,&message);
/* Цикл for(i=0;i<100 && !spiSe2pFree(&se2p);i++) ; задаёт начальное значение, условие продолжения и шаг перебора. */
for(i=0;i<100 && !spiSe2pFree(&se2p);i++) {
/* Записывает SpiaRegs.SPITXBUF значением 0xdead; данные SPITXBUF. */
SpiaRegs.SPITXBUF=0xdead;
SpiaRegs.SPIRXBUF=0; /* WIP clear for write, deterministic read data. */
SpiaRegs.SPIRXBUF=0; /* WIP clear for write, deterministic read data. */ /* Записывает SpiaRegs.SPIRXBUF значением 0; данные SPIRXBUF. */
/* Записывает SpiaRegs.SPISTS.bit.INT_FLAG значением 1; INT флаг. */
SpiaRegs.SPISTS.bit.INT_FLAG=1;
/* Вызывает SPISE2P_DRV_tick. Продвигает неблокирующий автомат SPI EEPROM: команда, адрес, данные и ожидание завершения записи. */
SPISE2P_DRV_tick(&se2p);
/* Проверяет if(SpiaRegs.SPITXBUF!=0xdead); последующий оператор выполняется только при истинном условии. */
if(SpiaRegs.SPITXBUF!=0xdead) {
/* Вызывает assert с аргументами (GpioDataRegs.GPADAT.bit.GPIO19==0) в текущей последовательности операций. */
assert(GpioDataRegs.GPADAT.bit.GPIO19==0);
/* Записывает trace[used] значением SpiaRegs.SPITXBUF; данные trace. */
trace[used]=SpiaRegs.SPITXBUF;
/* Записывает widths[used++] значением (SpiaRegs.SPICCR.all&15)+1; данные widths. */
widths[used++]=(SpiaRegs.SPICCR.all&15)+1;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Вызывает assert с аргументами (spiSe2pFree(&se2p) && GpioDataRegs.GPADAT.bit.GPIO19==1) в текущей последовательности операций. */
assert(spiSe2pFree(&se2p) && GpioDataRegs.GPADAT.bit.GPIO19==1);
/* Записывает i значением 0; данные i. */
i=0;
/* Проверяет if(write); последующий оператор выполняется только при истинном условии. */
if(write) { assert(trace[i]==0x0600 && widths[i++]==8); }
/* Вызывает assert с аргументами (trace[i]==(write ? 0x0200 : 0x0300) && widths[i++]==8) в текущей последовательности операций. */
assert(trace[i]==(write ? 0x0200 : 0x0300) && widths[i++]==8);
/* Условие компиляции EEPROM_M95M02: выбранный блок включается в текущий вариант прошивки. */
#if EEPROM_M95M02
/* Вызывает assert с аргументами (trace[i]==((address>>16)<<8) && widths[i++]==8) в текущей последовательности операций. */
assert(trace[i]==((address>>16)<<8) && widths[i++]==8);
/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */
#endif
/* Вызывает assert с аргументами (trace[i]==(address&65535) && widths[i++]==16) в текущей последовательности операций. */
assert(trace[i]==(address&65535) && widths[i++]==16);
/* Вызывает assert с аргументами (trace[i]==(write ? 0x1234 : 0) && widths[i++]==16) в текущей последовательности операций. */
assert(trace[i]==(write ? 0x1234 : 0) && widths[i++]==16);
/* Вызывает assert с аргументами (trace[i]==(write ? 0x5678 : 0) && widths[i++]==16) в текущей последовательности операций. */
assert(trace[i]==(write ? 0x5678 : 0) && widths[i++]==16);
/* Проверяет if(write); последующий оператор выполняется только при истинном условии. */
if(write) { assert(trace[i]==0x0500 && widths[i++]==8); assert(trace[i++]==0); }
/* Вызывает assert с аргументами (i==used) в текущей последовательности операций. */
assert(i==used);
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Точка входа: настраивает периферию, загружает параметры и обслуживает команды в главном цикле. */
int main(void)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Вызывает SPISE2P_DRV_init с аргументами (&se2p) в текущей последовательности операций. */
SPISE2P_DRV_init(&se2p);
/* Вызывает transfer с аргументами (0x7ffc,0); transfer(0x7ffc,1) в текущей последовательности операций. */
transfer(0x7ffc,0); transfer(0x7ffc,1);
/* Условие компиляции EEPROM_M95M02: выбранный блок включается в текущий вариант прошивки. */
#if EEPROM_M95M02
/* Вызывает assert с аргументами (BALSAM167_EEPROM_FIRMWARE_BYTES==261884UL) в текущей последовательности операций. */
assert(BALSAM167_EEPROM_FIRMWARE_BYTES==261884UL);
/* Вызывает transfer с аргументами (0xfffe,0); transfer(0x10000,0) в текущей последовательности операций. */
transfer(0xfffe,0); transfer(0x10000,0);
/* Вызывает transfer с аргументами (0x20000,1); transfer(0x3fffc,0); transfer(0x3fffc,1) в текущей последовательности операций. */
transfer(0x20000,1); transfer(0x3fffc,0); transfer(0x3fffc,1);
/* Выбирает альтернативный блок текущего условия компиляции. */
#else
/* Вызывает assert с аргументами (BALSAM167_EEPROM_FIRMWARE_BYTES==32508) в текущей последовательности операций. */
assert(BALSAM167_EEPROM_FIRMWARE_BYTES==32508);
/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */
#endif
/* Завершает main и возвращает 0. */
return 0;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}

View File

@@ -1,22 +1,45 @@
/* Проверка eeprom_profiles/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Начинает условие: EEPROM_TEST_DEVICE_H ещё не определён; защищает повторное включение или задаёт значение сборки. */
#ifndef EEPROM_TEST_DEVICE_H
/* Определяет защитный символ или переключатель EEPROM_TEST_DEVICE_H для последующей компиляции. */
#define EEPROM_TEST_DEVICE_H
/* Подключает <stdint.h>: настройки и интерфейс stdint. */
#include <stdint.h>
/* Определяет защитный символ или переключатель interrupt для последующей компиляции. */
#define interrupt
/* Определяет защитный символ или переключатель EALLOW для последующей компиляции. */
#define EALLOW
/* Определяет защитный символ или переключатель EDIS для последующей компиляции. */
#define EDIS
/* Задаёт CLKMULT = 2; данные CLKMULT. */
#define CLKMULT 2
/* Задаёт SYSCLKOUT = 60000000UL; данные SYSCLKOUT. */
#define SYSCLKOUT 60000000UL
/* Задаёт M_INT14 = 0x2000; данные M_INT14. */
#define M_INT14 0x2000
/* Продолжает список аргументов, полей или выражение static unsigned IER;; порядок элементов сохраняется. */
static unsigned IER;
/* Описывает структуру bits; порядок полей определяет расположение данных. */
struct bits { unsigned GPIO16,GPIO17,GPIO18,GPIO19,SPISWRESET,BUFFULL_FLAG,INT_FLAG; };
/* Описывает структуру reg; порядок полей определяет расположение данных. */
struct reg { unsigned all; struct bits bit; };
/* Продолжает список аргументов, полей или выражение static struct { struct reg GPAMUX2,GPADIR; } GpioCtrlRegs;; порядок элементов сохраняется. */
static struct { struct reg GPAMUX2,GPADIR; } GpioCtrlRegs;
/* Продолжает список аргументов, полей или выражение static struct { struct reg GPADAT; } GpioDataRegs;; порядок элементов сохраняется. */
static struct { struct reg GPADAT; } GpioDataRegs;
/* Продолжает список аргументов, полей или выражение static struct { void (*TINT2)(void); } PieVectTable;; порядок элементов сохраняется. */
static struct { void (*TINT2)(void); } PieVectTable;
/* Продолжает список аргументов, полей или выражение static struct { unsigned InterruptCount; } CpuTimer2;; порядок элементов сохраняется. */
static struct { unsigned InterruptCount; } CpuTimer2;
/* Продолжает список аргументов, полей или выражение static struct { struct reg TCR; } CpuTimer2Regs;; порядок элементов сохраняется. */
static struct { struct reg TCR; } CpuTimer2Regs;
/* Продолжает список аргументов, полей или выражение static struct { struct reg SPICCR,SPICTL,SPISTS,SPIFFTX,SPIFFRX,SPIFFCT,SPIPRI;; порядок элементов сохраняется. */
static struct { struct reg SPICCR,SPICTL,SPISTS,SPIFFTX,SPIFFRX,SPIFFCT,SPIPRI;
/* Продолжает список аргументов, полей или выражение unsigned SPIBRR; uint16_t SPITXBUF,SPIRXBUF; } SpiaRegs;; порядок элементов сохраняется. */
unsigned SPIBRR; uint16_t SPITXBUF,SPIRXBUF; } SpiaRegs;
/* Начинает функцию InitCpuTimers; назначение модуля — проверка eeprom_profiles/stubs на модели ПК. */
static void InitCpuTimers(void) {}
/* Начинает функцию ConfigCpuTimer; назначение модуля — проверка eeprom_profiles/stubs на модели ПК. */
static void ConfigCpuTimer(void *p, unsigned long f, unsigned t) {(void)p;(void)f;(void)t;}
/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */
#endif

View File

@@ -1,3 +1,5 @@
# Проверка firmware_identity на модели пк. Комментарии и исходный текст в UTF-8.
# Продолжает текущий вызов, список или выражение: """Independent test oracle: does this built SCI8 file contain its manifest identity?; порядок аргументов сохраняется.
"""Independent test oracle: does this built SCI8 file contain its manifest identity?
This is a build test, not a second production protocol codec. The 12-word vector
@@ -5,38 +7,72 @@ is deliberately constructed independently of the C implementation to detect a
stale compilation unit, incorrect byte order or a mismatched pre-build JSON.
Usage: python tests/firmware_identity/check_build.py path/to/firmware.bin
"""
# Импортирует необходимые имена: from datetime import datetime.
from datetime import datetime
# Подключает модуль hashlib для этой проверки или подготовки сборки.
import hashlib
# Подключает модуль json для этой проверки или подготовки сборки.
import json
# Импортирует необходимые имена: from pathlib import Path.
from pathlib import Path
# Подключает модуль struct для этой проверки или подготовки сборки.
import struct
# Подключает модуль sys для этой проверки или подготовки сборки.
import sys
# Задаёт image по выражению справа; значение используется последующими операциями.
image = Path(sys.argv[1])
# Читает исходный файл или образ для последующей проверки и разбора.
data = image.read_bytes()
meta = json.loads(image.with_suffix(image.suffix + '.manifest.json').read_text())
# Читает исходный файл или образ для последующей проверки и разбора.
meta = json.loads(image.with_suffix(image.suffix + '.manifest.json').read_text(encoding="utf-8"))
# Проверяет обязательное условие hashlib.sha256(data).hexdigest() == meta['sha256'], 'Wrong file hash'; нарушение делает тест неуспешным.
assert hashlib.sha256(data).hexdigest() == meta['sha256'], 'Wrong file hash'
# Проверяет обязательное условие len(data) == meta['size_bytes'], 'Wrong image size'; нарушение делает тест неуспешным.
assert len(data) == meta['size_bytes'], 'Wrong image size'
# Задаёт stamp по выражению справа; значение используется последующими операциями.
stamp = datetime.fromisoformat(meta['built_at_utc'])
# Задаёт build_id по выражению справа; значение используется последующими операциями.
build_id = meta['build_id']
# Задаёт words по выражению справа; значение используется последующими операциями.
words = [1, *meta['version'], stamp.year, stamp.month * 256 + stamp.day,
# Продолжает текущий вызов, список или выражение: stamp.hour * 256 + stamp.minute, stamp.second]; порядок аргументов сохраняется.
stamp.hour * 256 + stamp.minute, stamp.second]
# Задаёт words + по выражению справа; значение используется последующими операциями.
words += [ord(build_id[i]) * 256 + ord(build_id[i+1]) for i in range(0, 8, 2)]
# Задаёт expected по выражению справа; значение используется последующими операциями.
expected = struct.pack('<12H', *words)
# Проверяет обязательное условие data[:2] == b'\xaa\x08', 'Not SCI8'; нарушение делает тест неуспешным.
assert data[:2] == b'\xaa\x08', 'Not SCI8'
# Задаёт offset по выражению справа; значение используется последующими операциями.
offset = 22
# Задаёт found по выражению справа; значение используется последующими операциями.
found = 0
# Повторяет блок при выполнении True.
while True:
# Задаёт count, по выражению справа; значение используется последующими операциями.
count, = struct.unpack_from('<H', data, offset)
# Задаёт offset + по выражению справа; значение используется последующими операциями.
offset += 2
# Проверяет условие if not count перед выполнением следующего блока.
if not count:
# Продолжает текущий вызов, список или выражение: break; порядок аргументов сохраняется.
break
# Задаёт offset + по выражению справа; значение используется последующими операциями.
offset += 4 # destination address, not part of the loaded section payload
# Задаёт end по выражению справа; значение используется последующими операциями.
end = offset + count * 2
# Проверяет обязательное условие end <= len(data), 'Truncated boot block'; нарушение делает тест неуспешным.
assert end <= len(data), 'Truncated boot block'
# Задаёт block по выражению справа; значение используется последующими операциями.
block = data[offset:end]
# Задаёт found + по выражению справа; значение используется последующими операциями.
found += sum(block[i:i+24] == expected for i in range(0, len(block)-23, 2))
# Задаёт offset по выражению справа; значение используется последующими операциями.
offset = end
# Проверяет обязательное условие offset == len(data), 'Trailing data'; нарушение делает тест неуспешным.
assert offset == len(data), 'Trailing data'
# Проверяет обязательное условие found == 1, f'Expected one embedded identity, found {found}'; нарушение делает тест неуспешным.
assert found == 1, f'Expected one embedded identity, found {found}'
# Продолжает текущий вызов, список или выражение: print(f'PASS: SCI8 contains manifest identity {meta["version"]}, {build_id}, {stamp.isoformat()}'); порядок аргументов сохраняется.
print(f'PASS: SCI8 contains manifest identity {meta["version"]}, {build_id}, {stamp.isoformat()}')

View File

@@ -1,33 +1,63 @@
/* Проверка firmware_identity на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Test the actual 167 binding, not just a fake protocol backend. Build against
* the generated header from the firmware build under test. No MCU registers. */
/* Подключает "firmware_identity.h": настройки и интерфейс firmware_identity. */
#include "firmware_identity.h"
/* Подключает "firmware_info_static.h": настройки и интерфейс firmware_info_static. */
#include "firmware_info_static.h"
/* Подключает "ump_tms28335.h": настройки и интерфейс ump_tms28335. */
#include "ump_tms28335.h"
/* Подключает <assert.h>: настройки и интерфейс assert. */
#include <assert.h>
/* Продолжает список аргументов, полей или выражение static unsigned logger_reads, logger_writes;; порядок элементов сохраняется. */
static unsigned logger_reads, logger_writes;
/* Проверяет область чтения регистратора и возвращает слова состояния либо архивной записи. */
unsigned int ump_log_read(unsigned int address)
/* Изменяет счётчик в выражении { (void)address; ++logger_reads; return 0x554dU; } на один для следующего шага. */
{ (void)address; ++logger_reads; return 0x554dU; }
/* Применяет допустимые команды управления регистратором, сохраняя ограничения адресов. */
int ump_log_write(unsigned int address, unsigned int value)
/* Изменяет счётчик в выражении { (void)address; (void)value; ++logger_writes; return 1; } на один для следующего шага. */
{ (void)address; (void)value; ++logger_writes; return 1; }
/* Точка входа: настраивает периферию, загружает параметры и обслуживает команды в главном цикле. */
int main(void)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Объявляет words — слова. */
uint16_t words[UMP_MAX_WORDS];
/* Продолжает список аргументов, полей или выражение ump_octet wire[UMP_RTU_CAPACITY];; порядок элементов сохраняется. */
ump_octet wire[UMP_RTU_CAPACITY];
/* Продолжает список аргументов, полей или выражение unsigned error, i;; порядок элементов сохраняется. */
unsigned error, i;
/* Вызывает assert с аргументами (ump_tms28335_prepare(3, UMP_FIRMWARE_INFO, 12, words, &error) == 12 && !error) в текущей последовательности операций. */
assert(ump_tms28335_prepare(3, UMP_FIRMWARE_INFO, 12, words, &error) == 12 && !error);
/* Вызывает assert с аргументами (words[0] == 1 && words[1] == FIRMWARE_VERSION_MAJOR) в текущей последовательности операций. */
assert(words[0] == 1 && words[1] == FIRMWARE_VERSION_MAJOR);
/* Вызывает assert с аргументами (words[2] == FIRMWARE_VERSION_MINOR && words[3] == FIRMWARE_VERSION_PATCH) в текущей последовательности операций. */
assert(words[2] == FIRMWARE_VERSION_MINOR && words[3] == FIRMWARE_VERSION_PATCH);
/* Вызывает assert с аргументами (words[4] == FI_YEAR && words[5] == FI_PAIR(FI_MONTH, FI_DAY)) в текущей последовательности операций. */
assert(words[4] == FI_YEAR && words[5] == FI_PAIR(FI_MONTH, FI_DAY));
/* Вызывает assert с аргументами (words[8] == FI_PAIR(FI_ID_0, FI_ID_1)) в текущей последовательности операций. */
assert(words[8] == FI_PAIR(FI_ID_0, FI_ID_1));
/* Вызывает assert с аргументами (logger_reads == 0) в текущей последовательности операций. */
assert(logger_reads == 0);
/* Вызывает assert с аргументами (ump_tms28335_rtu(1,3,UMP_FIRMWARE_INFO,12,wire,UMP_RTU_CAPACITY) == 29) в текущей последовательности операций. */
assert(ump_tms28335_rtu(1,3,UMP_FIRMWARE_INFO,12,wire,UMP_RTU_CAPACITY) == 29);
/* Цикл for (i=0; i<12; ++i) assert(((wire[3+i*2]<<8) | wire[4+i*2]) == words[i]);; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i=0; i<12; ++i) assert(((wire[3+i*2]<<8) | wire[4+i*2]) == words[i]);
/* Вызывает assert с аргументами (ump_crc(wire,29) == 0) в текущей последовательности операций. */
assert(ump_crc(wire,29) == 0);
/* Вызывает ump_tms28335_prepare с аргументами (6,UMP_FIRMWARE_INFO,123,words,&error) в текущей последовательности операций. */
ump_tms28335_prepare(6,UMP_FIRMWARE_INFO,123,words,&error);
/* Вызывает assert с аргументами (error == 2 && logger_writes == 0) в текущей последовательности операций. */
assert(error == 2 && logger_writes == 0);
/* Firmware reads must not steal the existing logger window. */
/* Вызывает assert с аргументами (ump_tms28335_prepare(3,UMP_BASE,16,words,&error) == 16 && !error) в текущей последовательности операций. */
assert(ump_tms28335_prepare(3,UMP_BASE,16,words,&error) == 16 && !error);
/* Вызывает assert с аргументами (logger_reads == 16 && words[0] == 0x554dU) в текущей последовательности операций. */
assert(logger_reads == 16 && words[0] == 0x554dU);
/* Завершает main и возвращает 0. */
return 0;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}

View File

@@ -1,48 +1,93 @@
# Проверка gas167 на модели пк. Комментарии и исходный текст в UTF-8.
# Продолжает текущий вызов, список или выражение: """Validate the PM35 RAM-load SCI8 image against the selected EEPROM profile."""; порядок аргументов сохраняется.
"""Validate the PM35 RAM-load SCI8 image against the selected EEPROM profile."""
# Подключает модуль argparse для этой проверки или подготовки сборки.
import argparse
# Импортирует необходимые имена: from pathlib import Path.
from pathlib import Path
# Подключает модуль struct для этой проверки или подготовки сборки.
import struct
# Объявляет функцию check_image и её входные параметры.
def check_image(path, eeprom):
# Читает исходный файл или образ для последующей проверки и разбора.
data = path.read_bytes()
# Задаёт limit по выражению справа; значение используется последующими операциями.
limit = {"AT25256B": 32508, "M95M02": 261884}[eeprom]
# Проверяет условие if not 24 <= len(data) <= limit перед выполнением следующего блока.
if not 24 <= len(data) <= limit:
# Останавливает текущую операцию с исключением ValueError(f"Image size {len(data)} outside 24..{limit}").
raise ValueError(f"Image size {len(data)} outside 24..{limit}")
# Проверяет условие if struct.unpack_from("<H", data)[0] != 0x08AA перед выполнением следующего блока.
if struct.unpack_from("<H", data)[0] != 0x08AA:
# Останавливает текущую операцию с исключением ValueError("Not a SCI8 boot image").
raise ValueError("Not a SCI8 boot image")
# Задаёт high, low по выражению справа; значение используется последующими операциями.
high, low = struct.unpack_from("<HH", data, 18)
# Задаёт entry по выражению справа; значение используется последующими операциями.
entry = (high << 16) | low
# Задаёт position, blocks по выражению справа; значение используется последующими операциями.
position, blocks = 22, []
# Повторяет блок при выполнении True.
while True:
# Проверяет условие if position + 2 > len(data) перед выполнением следующего блока.
if position + 2 > len(data):
# Останавливает текущую операцию с исключением ValueError("Missing boot terminator").
raise ValueError("Missing boot terminator")
# Задаёт words по выражению справа; значение используется последующими операциями.
words = struct.unpack_from("<H", data, position)[0]
# Задаёт position + по выражению справа; значение используется последующими операциями.
position += 2
# Проверяет условие if not words перед выполнением следующего блока.
if not words:
# Проверяет условие if position != len(data) перед выполнением следующего блока.
if position != len(data):
# Останавливает текущую операцию с исключением ValueError("Trailing bytes after boot terminator").
raise ValueError("Trailing bytes after boot terminator")
# Продолжает текущий вызов, список или выражение: break; порядок аргументов сохраняется.
break
# Проверяет условие if position + 4 + words * 2 > len(data) перед выполнением следующего блока.
if position + 4 + words * 2 > len(data):
# Останавливает текущую операцию с исключением ValueError("Truncated boot block").
raise ValueError("Truncated boot block")
# Задаёт high, low по выражению справа; значение используется последующими операциями.
high, low = struct.unpack_from("<HH", data, position)
# Задаёт address по выражению справа; значение используется последующими операциями.
address = (high << 16) | low
# Задаёт end по выражению справа; значение используется последующими операциями.
end = address + words
# Проверяет условие if not 0x8000 <= address < end <= 0xD000 перед выполнением следующего блока.
if not 0x8000 <= address < end <= 0xD000:
# Останавливает текущую операцию с исключением ValueError(f"Boot destination {address:#x}..{end:#x} outside code RAM").
raise ValueError(f"Boot destination {address:#x}..{end:#x} outside code RAM")
# Проверяет условие if any(address < old_end and old_start < end for old_start, old_end in blocks) перед выполнением следующего блока.
if any(address < old_end and old_start < end for old_start, old_end in blocks):
# Останавливает текущую операцию с исключением ValueError("Overlapping boot blocks").
raise ValueError("Overlapping boot blocks")
# Продолжает текущий вызов, список или выражение: blocks.append((address, end)); порядок аргументов сохраняется.
blocks.append((address, end))
# Задаёт position + по выражению справа; значение используется последующими операциями.
position += 4 + words * 2
# Проверяет условие if not any(start <= entry < end for start, end in blocks) перед выполнением следующего блока.
if not any(start <= entry < end for start, end in blocks):
# Останавливает текущую операцию с исключением ValueError("Entry point not loaded by the boot table").
raise ValueError("Entry point not loaded by the boot table")
# Возвращает len(data), len(blocks), limit - len(data) вызывающему коду и завершает функцию.
return len(data), len(blocks), limit - len(data)
# Проверяет условие if __name__ == "__main__" перед выполнением следующего блока.
if __name__ == "__main__":
# Задаёт parser по выражению справа; значение используется последующими операциями.
parser = argparse.ArgumentParser(description=__doc__)
# Задаёт parser.add_argument("image", type по выражению справа; значение используется последующими операциями.
parser.add_argument("image", type=Path)
# Задаёт parser.add_argument("--eeprom", choices по выражению справа; значение используется последующими операциями.
parser.add_argument("--eeprom", choices=("AT25256B", "M95M02"), required=True)
# Задаёт args по выражению справа; значение используется последующими операциями.
args = parser.parse_args()
# Задаёт size, blocks, free по выражению справа; значение используется последующими операциями.
size, blocks, free = check_image(args.image, args.eeprom)
# Продолжает текущий вызов, список или выражение: print(f"PASS SCI8 {args.eeprom}: {size} bytes, {blocks} RAM blocks, {free} bytes free"); порядок аргументов сохраняется.
print(f"PASS SCI8 {args.eeprom}: {size} bytes, {blocks} RAM blocks, {free} bytes free")

View File

@@ -1,196 +1,386 @@
/* Проверка gas167 на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Подключает <assert.h>: настройки и интерфейс assert. */
#include <assert.h>
/* Подключает <stdbool.h>: настройки и интерфейс stdbool. */
#include <stdbool.h>
/* Подключает <stdint.h>: настройки и интерфейс stdint. */
#include <stdint.h>
/* Подключает <stdio.h>: настройки и интерфейс stdio. */
#include <stdio.h>
/* Подключает <string.h>: настройки и интерфейс string. */
#include <string.h>
/* Подключает "gas167.h": дополнительная карта GAS 167/v1 только для новой EEPROM M95M02. */
#include "gas167.h"
/* Подключает "ump_protocol.h": настройки и интерфейс ump_protocol. */
#include "ump_protocol.h"
/* Подключает "ump_tms28335.h": настройки и интерфейс ump_tms28335. */
#include "ump_tms28335.h"
/* Подключает "include/balsam167_eeprom_block.h": настройки и интерфейс balsam167_eeprom_block. */
#include "include/balsam167_eeprom_block.h"
/* Задаёт ANSWER_LEN = 128U; данные ANSWER_LEN. */
#define ANSWER_LEN 128U
/* Задаёт MAX_SEND_LENGTH = 400U; MAX SEND длина. */
#define MAX_SEND_LENGTH 400U
/* Задаёт CNTRL_ADDR = 16U; данные CNTRL_ADDR. */
#define CNTRL_ADDR 16U
/* Задаёт CMD_MODBUS_3 = 3U; данные CMD_MODBUS_3. */
#define CMD_MODBUS_3 3U
/* Задаёт CMD_MODBUS_6 = 6U; данные CMD_MODBUS_6. */
#define CMD_MODBUS_6 6U
/* Задаёт dsk_LOAD = 6; код платы нагрузки. */
#define dsk_LOAD 6
/* Задаёт LOBYTE = ((v) & 255U); данные LOBYTE. */
#define LOBYTE(v) ((v) & 255U)
/* Задаёт HIBYTE = (((v) >> 8) & 255U); данные HIBYTE. */
#define HIBYTE(v) (((v) >> 8) & 255U)
/* Задаёт UMP_CAN_MAX_WORDS = UMP_MAX_WORDS; UMP CAN MAX слова. */
#define UMP_CAN_MAX_WORDS UMP_MAX_WORDS
/* Задаёт ump_can_prepare = ump_tms28335_prepare; ump CAN prepare. */
#define ump_can_prepare ump_tms28335_prepare
/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */
typedef struct { int all; } WORDE;
/* Задаёт Modbus = ((WORDE *)modbus); данные Modbus. */
#define Modbus ((WORDE *)modbus)
/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */
typedef struct {
/* Объявляет RS_Header — данные RS_Header; buffer — буфер. */
uint16_t RS_Header[8], buffer[MAX_SEND_LENGTH];
/* Продолжает список аргументов, полей или выражение unsigned flag_TIMEOUT_to_Send;; порядок элементов сохраняется. */
unsigned flag_TIMEOUT_to_Send;
/* Продолжает список аргументов, полей или выражение } RS_DATA;; порядок элементов сохраняется. */
} RS_DATA;
/* Объявляет modbus — массив технологических регистров; слово int на C28x занимает 16 бит; Desk — аппаратно определённый тип платы; dsk_LOAD — код платы нагрузки. Начальное значение задаётся справа от знака равенства. */
int modbus[129], Desk = dsk_LOAD;
/* Продолжает список аргументов, полей или выражение static unsigned captures, spi_reads, sent, irq_depth, legacy_reads;; порядок элементов сохраняется. */
static unsigned captures, spi_reads, sent, irq_depth, legacy_reads;
/* Начинает функцию __disable_interrupts; назначение модуля — проверка gas167 на модели ПК. */
static unsigned __disable_interrupts(void) {
/* Записывает saved значением irq_depth; данные saved. */
unsigned saved = irq_depth;
/* Изменяет счётчик в выражении ++irq_depth; на один для следующего шага. */
++irq_depth;
/* Завершает __disable_interrupts и возвращает saved. */
return saved;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Начинает функцию __restore_interrupts; назначение модуля — проверка gas167 на модели ПК. */
static void __restore_interrupts(unsigned saved) { irq_depth = saved; }
/* Регистрирует изменение слова команд после записи по последовательному интерфейсу. */
void ump_log_rs(void) { ++captures; }
/* Проверяет область чтения регистратора и возвращает слова состояния либо архивной записи. */
unsigned int ump_log_read(unsigned int address) { ++legacy_reads; return address; }
/* Применяет допустимые команды управления регистратором, сохраняя ограничения адресов. */
int ump_log_write(unsigned int address, unsigned int value) { return 1; }
/* Начинает функцию get_crc_16; назначение модуля — проверка gas167 на модели ПК. */
static unsigned get_crc_16(unsigned seed, const uint16_t *data, unsigned size) {
/* Вызывает assert с аргументами (seed == 0xFFFFU) в текущей последовательности операций. */
assert(seed == 0xFFFFU);
/* Завершает get_crc_16 и возвращает ump_crc(data, size). */
return ump_crc(data, size);
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Передаёт массив слов через SCI в выбранном режиме упаковки. */
static void RS_Send(RS_DATA *rs, uint16_t *data, unsigned size) {
/* Вызывает assert с аргументами (irq_depth == 0) в текущей последовательности операций. */
assert(irq_depth == 0);
/* Записывает sent значением size; данные sent. */
sent = size;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Читает EEPROM порциями; адрес задаётся словами C28x, размер переводится в число передаваемых слов. */
static void Seeprom_read(unsigned long word, uint16_t *data, unsigned bytes) {
/* Продолжает список аргументов, полей или выражение unsigned i;; порядок элементов сохраняется. */
unsigned i;
assert(irq_depth == 0); /* The Timer2 SPI driver must retain interrupts. */
assert(irq_depth == 0); /* The Timer2 SPI driver must retain interrupts. */ /* Вызывает assert с аргументами (irq_depth == 0) в текущей последовательности операций. */
/* Изменяет счётчик в выражении ++spi_reads; на один для следующего шага. */
++spi_reads;
/* Цикл for (i = 0; i < bytes/2; ++i) data[i] = (uint16_t)(0xBEEFU+i);; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i = 0; i < bytes/2; ++i) data[i] = (uint16_t)(0xBEEFU+i);
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */
static unsigned Load_protection_prepare(unsigned fn, unsigned a, unsigned n,
/* Объявляет out — данные out. Хранит указатель на данные. */
uint16_t *out, unsigned *error) {
/* Записывает out[0] значением (uint16_t)a; out[1] = (uint16_t)n; *error = 0; данные out. */
out[0] = (uint16_t)a; out[1] = (uint16_t)n; *error = 0;
/* Завершает Load_protection_prepare и возвращает 2. */
return 2;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Описывает структуру mock_reg; порядок полей определяет расположение данных. */
struct mock_reg { uint32_t all; };
/* Продолжает список аргументов, полей или выражение static struct {; порядок элементов сохраняется. */
static struct {
/* Описывает структуру mock_reg CANTA, CANAA, CANTRR, CANTRS;; порядок полей определяет расположение данных. */
struct mock_reg CANTA, CANAA, CANTRR, CANTRS;
/* Продолжает список аргументов, полей или выражение } ECanaRegs;; порядок элементов сохраняется. */
} ECanaRegs;
/* Продолжает список аргументов, полей или выражение static struct {; порядок элементов сохраняется. */
static struct {
/* Описывает структуру ; порядок полей определяет расположение данных. */
struct { struct mock_reg MDH, MDL; } MBOX2;
/* Продолжает список аргументов, полей или выражение } ECanaMboxes;; порядок элементов сохраняется. */
} ECanaMboxes;
/* Продолжает список аргументов, полей или выражение static struct { unsigned long InterruptCount; } CpuTimer1;; порядок элементов сохраняется. */
static struct { unsigned long InterruptCount; } CpuTimer1;
/* Подключает "production_routes.inc": настройки и интерфейс production_routes. */
#include "production_routes.inc"
/* Начинает функцию request; назначение модуля — проверка gas167 на модели ПК. */
static void request(RS_DATA *rs, unsigned fn, unsigned a, unsigned n) {
/* Продолжает список аргументов, полей или выражение unsigned crc;; порядок элементов сохраняется. */
unsigned crc;
/* Вызывает memset с аргументами (rs, 0, sizeof(*rs)) в текущей последовательности операций. */
memset(rs, 0, sizeof(*rs));
/* Записывает rs->RS_Header[0] значением CNTRL_ADDR; rs->RS_Header[1] = fn; данные rs->RS_Header. */
rs->RS_Header[0] = CNTRL_ADDR; rs->RS_Header[1] = fn;
/* Записывает rs->RS_Header[2] значением a >> 8; rs->RS_Header[3] = a & 255U; данные rs->RS_Header. */
rs->RS_Header[2] = a >> 8; rs->RS_Header[3] = a & 255U;
/* Записывает rs->RS_Header[4] значением n >> 8; rs->RS_Header[5] = n & 255U; данные rs->RS_Header. */
rs->RS_Header[4] = n >> 8; rs->RS_Header[5] = n & 255U;
/* Записывает crc значением ump_crc(rs->RS_Header, 6); данные crc. */
crc = ump_crc(rs->RS_Header, 6);
/* Записывает rs->RS_Header[6] значением crc & 255U; rs->RS_Header[7] = crc >> 8; данные rs->RS_Header. */
rs->RS_Header[6] = crc & 255U; rs->RS_Header[7] = crc >> 8;
/* Записывает sent значением 0; данные sent. */
sent = 0;
/* Проверяет if (fn == 3) ReceiveCommandModbus3(rs); последующий оператор выполняется только при истинном условии. */
if (fn == 3) ReceiveCommandModbus3(rs);
/* Выполняет альтернативу, если предыдущее условие if оказалось ложным. */
else ReceiveCommandModbus6(rs);
/* Вызывает assert с аргументами (irq_depth == 0 && rs->flag_TIMEOUT_to_Send) в текущей последовательности операций. */
assert(irq_depth == 0 && rs->flag_TIMEOUT_to_Send);
/* Вызывает assert с аргументами (ump_crc(rs->buffer, rs->buffer[1] & 128U ? 5 : в текущей последовательности операций. */
assert(ump_crc(rs->buffer, rs->buffer[1] & 128U ? 5 :
/* Продолжает список аргументов, полей или выражение (fn == 6 ? 8 : 5+rs->buffer[2])) == 0);; порядок элементов сохраняется. */
(fn == 6 ? 8 : 5+rs->buffer[2])) == 0);
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Начинает функцию can_request; назначение модуля — проверка gas167 на модели ПК. */
static void can_request(unsigned fn, unsigned a, unsigned n) {
/* Вызывает memset с аргументами (&ECanaRegs, 0, sizeof(ECanaRegs)) в текущей последовательности операций. */
memset(&ECanaRegs, 0, sizeof(ECanaRegs));
/* Вызывает memset с аргументами (&ECanaMboxes, 0, sizeof(ECanaMboxes)) в текущей последовательности операций. */
memset(&ECanaMboxes, 0, sizeof(ECanaMboxes));
/* Записывает ump_can_waiting значением 0; ump_can_length = 0; ump_can_index = 0; ump CAN waiting. */
ump_can_waiting = 0; ump_can_length = 0; ump_can_index = 0;
/* Записывает ump_can_pending значением 1; ump_can_tag = 0x0100U | fn; флаг ожидающего запроса служебного CAN между ISR и главным циклом. */
ump_can_pending = 1; ump_can_tag = 0x0100U | fn;
/* Записывает ump_can_address значением a; ump_can_value = n; ump CAN адрес. */
ump_can_address = a; ump_can_value = n;
/* Вызывает UMP_CAN_service. В главном цикле готовит замороженный ответ служебного CAN и отправляет его двухсловными фрагментами. */
UMP_CAN_service();
/* Вызывает assert с аргументами (irq_depth == 0 && !ump_can_pending) в текущей последовательности операций. */
assert(irq_depth == 0 && !ump_can_pending);
/* Вызывает assert с аргументами (ECanaRegs.CANTRS.all == 4U) в текущей последовательности операций. */
assert(ECanaRegs.CANTRS.all == 4U);
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Точка входа: настраивает периферию, загружает параметры и обслуживает команды в главном цикле. */
int main(void) {
/* Объявляет rs — данные rs. */
RS_DATA rs;
/* Продолжает список аргументов, полей или выражение unsigned i;; порядок элементов сохраняется. */
unsigned i;
/* Цикл for (i = 0; i < 129; ++i) modbus[i] = (int)i;; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i = 0; i < 129; ++i) modbus[i] = (int)i;
/* Записывает modbus[128] значением 0xD00D; массив технологических регистров; слово int на C28x занимает 16 бит. */
modbus[128] = 0xD00D;
/* Exercise the real native handlers in both builds. */
/* Вызывает request с аргументами (&rs, 6, 1, 0xFEDC) в текущей последовательности операций. */
request(&rs, 6, 1, 0xFEDC);
/* Вызывает assert с аргументами (modbus[1] == 0xFEDC && sent == 10) в текущей последовательности операций. */
assert(modbus[1] == 0xFEDC && sent == 10);
/* Вызывает request с аргументами (&rs, 3, 0, 2) в текущей последовательности операций. */
request(&rs, 3, 0, 2);
/* Вызывает assert с аргументами (rs.buffer[2] == 4 && rs.buffer[5] == 0xFE && rs.buffer[6] == 0xDC) в текущей последовательности операций. */
assert(rs.buffer[2] == 4 && rs.buffer[5] == 0xFE && rs.buffer[6] == 0xDC);
/* Вызывает request с аргументами (&rs, 6, 0x52, 0) в текущей последовательности операций. */
request(&rs, 6, 0x52, 0);
/* Вызывает assert с аргументами (rs.buffer[1] == 0x86 && rs.buffer[2] == 3 && modbus[0x52] == 0x52) в текущей последовательности операций. */
assert(rs.buffer[1] == 0x86 && rs.buffer[2] == 3 && modbus[0x52] == 0x52);
/* Вызывает request с аргументами (&rs, 6, 0x7C, 9) в текущей последовательности операций. */
request(&rs, 6, 0x7C, 9);
/* Вызывает assert с аргументами (rs.buffer[2] == 2 && modbus[0x7C] == 0x7C) в текущей последовательности операций. */
assert(rs.buffer[2] == 2 && modbus[0x7C] == 0x7C);
/* Existing UMP and protection routing must still work. */
/* Вызывает request с аргументами (&rs, 3, 0x1000, 2) в текущей последовательности операций. */
request(&rs, 3, 0x1000, 2);
/* Вызывает assert с аргументами (rs.buffer[1] == 3 && rs.buffer[3] == 0x10 && legacy_reads == 2) в текущей последовательности операций. */
assert(rs.buffer[1] == 3 && rs.buffer[3] == 0x10 && legacy_reads == 2);
/* Вызывает request с аргументами (&rs, 3, 0x1300, 2) в текущей последовательности операций. */
request(&rs, 3, 0x1300, 2);
/* Вызывает assert с аргументами (rs.buffer[1] == 3 && rs.buffer[3] == 0x13) в текущей последовательности операций. */
assert(rs.buffer[1] == 3 && rs.buffer[3] == 0x13);
/* Условие компиляции EEPROM_M95M02: выбранный блок включается в текущий вариант прошивки. */
#if EEPROM_M95M02
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Объявляет out — данные out. */
uint16_t out[124];
/* Продолжает список аргументов, полей или выражение unsigned error, count;; порядок элементов сохраняется. */
unsigned error, count;
/* Цикл for (i = 0; i < 65536U; ++i); задаёт начальное значение, условие продолжения и шаг перебора. */
for (i = 0; i < 65536U; ++i)
/* Вызывает assert с аргументами (gas167_contains((uint16_t)i) == в текущей последовательности операций. */
assert(gas167_contains((uint16_t)i) ==
/* Продолжает список аргументов, полей или выражение ((i >= 0x5000U && i <= 0x507FU) || (i >= 0x5F00U && i <= 0x5F07U)));; порядок элементов сохраняется. */
((i >= 0x5000U && i <= 0x507FU) || (i >= 0x5F00U && i <= 0x5F07U)));
/* Вызывает assert с аргументами (gas167_prepare(3, 0x5000, 124, 0, out, &error) == 124 && !error) в текущей последовательности операций. */
assert(gas167_prepare(3, 0x5000, 124, 0, out, &error) == 124 && !error);
/* Вызывает assert с аргументами (out[1] == 0xFEDC && out[123] == 123) в текущей последовательности операций. */
assert(out[1] == 0xFEDC && out[123] == 123);
/* Записывает count значением gas167_prepare(3, 0x507F, 2, 0, out, &error); число. */
count = gas167_prepare(3, 0x507F, 2, 0, out, &error);
/* Вызывает assert с аргументами (count == 2 && error == 2 && modbus[128] == 0xD00D) в текущей последовательности операций. */
assert(count == 2 && error == 2 && modbus[128] == 0xD00D);
/* Вызывает assert с аргументами (gas167_prepare(3, 0x5000, 0, 0, out, &error) == 2 && error == 3) в текущей последовательности операций. */
assert(gas167_prepare(3, 0x5000, 0, 0, out, &error) == 2 && error == 3);
/* Вызывает assert с аргументами (gas167_prepare(3, 0x5000, 125, 0, out, &error) == 2 && error == 3) в текущей последовательности операций. */
assert(gas167_prepare(3, 0x5000, 125, 0, out, &error) == 2 && error == 3);
/* Вызывает assert с аргументами (gas167_prepare(3, 0x5000, 1, 1, out, &error) == 2 && error == 3) в текущей последовательности операций. */
assert(gas167_prepare(3, 0x5000, 1, 1, out, &error) == 2 && error == 3);
/* Вызывает assert с аргументами (gas167_prepare(3, 0xFFFF, 2, 0, out, &error) == 2 && error == 2) в текущей последовательности операций. */
assert(gas167_prepare(3, 0xFFFF, 2, 0, out, &error) == 2 && error == 2);
/* Вызывает assert с аргументами (gas167_prepare(16, 0x5000, 1, 0, out, &error) == 2 && error == 1) в текущей последовательности операций. */
assert(gas167_prepare(16, 0x5000, 1, 0, out, &error) == 2 && error == 1);
/* Вызывает assert с аргументами (gas167_prepare(6, 0x5080, 7, 0, out, &error) == 2 && error == 2) в текущей последовательности операций. */
assert(gas167_prepare(6, 0x5080, 7, 0, out, &error) == 2 && error == 2);
/* Вызывает assert с аргументами (gas167_prepare(6, 0x5052, 60001, 0, out, &error) == 2 && error == 3) в текущей последовательности операций. */
assert(gas167_prepare(6, 0x5052, 60001, 0, out, &error) == 2 && error == 3);
/* Вызывает assert с аргументами (gas167_prepare(6, 0x5052, 60000, 0, out, &error) == 2 && !error) в текущей последовательности операций. */
assert(gas167_prepare(6, 0x5052, 60000, 0, out, &error) == 2 && !error);
/* Вызывает assert с аргументами (modbus[0x52] == 60000) в текущей последовательности операций. */
assert(modbus[0x52] == 60000);
/* Вызывает assert с аргументами (gas167_prepare(3, 0x5000, 1, 0, 0, &error) == 0) в текущей последовательности операций. */
assert(gas167_prepare(3, 0x5000, 1, 0, 0, &error) == 0);
/* Вызывает assert с аргументами (gas167_prepare(6, 0x5000, 1, 0, out, 0) == 0 && modbus[0] == 0) в текущей последовательности операций. */
assert(gas167_prepare(6, 0x5000, 1, 0, out, 0) == 0 && modbus[0] == 0);
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Вызывает request с аргументами (&rs, 3, 0x5000, 2) в текущей последовательности операций. */
request(&rs, 3, 0x5000, 2);
/* Вызывает assert с аргументами (sent == 9 && rs.buffer[5] == 0xFE && rs.buffer[6] == 0xDC) в текущей последовательности операций. */
assert(sent == 9 && rs.buffer[5] == 0xFE && rs.buffer[6] == 0xDC);
/* Вызывает request с аргументами (&rs, 3, 0x5000, 124) в текущей последовательности операций. */
request(&rs, 3, 0x5000, 124);
/* Вызывает assert с аргументами (sent == 253 && rs.buffer[2] == 248) в текущей последовательности операций. */
assert(sent == 253 && rs.buffer[2] == 248);
/* Вызывает request с аргументами (&rs, 3, 0x5F00, 8) в текущей последовательности операций. */
request(&rs, 3, 0x5F00, 8);
/* Вызывает assert с аргументами (sent == 21 && rs.buffer[3] == 0x47 && rs.buffer[4] == 0x41) в текущей последовательности операций. */
assert(sent == 21 && rs.buffer[3] == 0x47 && rs.buffer[4] == 0x41);
/* Вызывает assert с аргументами (rs.buffer[5] == 0x53 && rs.buffer[6] == 0x31) в текущей последовательности операций. */
assert(rs.buffer[5] == 0x53 && rs.buffer[6] == 0x31);
/* Вызывает assert с аргументами (rs.buffer[10] == 167 && rs.buffer[18] == 1) в текущей последовательности операций. */
assert(rs.buffer[10] == 167 && rs.buffer[18] == 1);
/* Вызывает request с аргументами (&rs, 6, 0x5F00, 0) в текущей последовательности операций. */
request(&rs, 6, 0x5F00, 0);
/* Вызывает assert с аргументами (sent == 5 && rs.buffer[2] == 2) в текущей последовательности операций. */
assert(sent == 5 && rs.buffer[2] == 2);
/* Вызывает request с аргументами (&rs, 3, 0x5F07, 2) в текущей последовательности операций. */
request(&rs, 3, 0x5F07, 2);
/* Вызывает assert с аргументами (rs.buffer[2] == 2) в текущей последовательности операций. */
assert(rs.buffer[2] == 2);
/* Вызывает request с аргументами (&rs, 6, 0x5052, 0) в текущей последовательности операций. */
request(&rs, 6, 0x5052, 0);
/* Вызывает assert с аргументами (rs.buffer[2] == 3 && modbus[0x52] == 60000) в текущей последовательности операций. */
assert(rs.buffer[2] == 3 && modbus[0x52] == 60000);
/* Вызывает request с аргументами (&rs, 6, 0x507D, 9) в текущей последовательности операций. */
request(&rs, 6, 0x507D, 9);
/* Вызывает assert с аргументами (rs.buffer[2] == 2 && modbus[0x7D] == 0x7D) в текущей последовательности операций. */
assert(rs.buffer[2] == 2 && modbus[0x7D] == 0x7D);
/* Вызывает request с аргументами (&rs, 6, 0x507F, 0x80) в текущей последовательности операций. */
request(&rs, 6, 0x507F, 0x80);
/* Вызывает assert с аргументами (sent == 8 && rs.buffer[2] == 0x50 && rs.buffer[3] == 0x7F) в текущей последовательности операций. */
assert(sent == 8 && rs.buffer[2] == 0x50 && rs.buffer[3] == 0x7F);
/* Вызывает assert с аргументами (captures == 1 && modbus[127] == 0x80) в текущей последовательности операций. */
assert(captures == 1 && modbus[127] == 0x80);
/* Вызывает can_request с аргументами (6, 0x5001, 0xFEDC) в текущей последовательности операций. */
can_request(6, 0x5001, 0xFEDC);
/* Вызывает assert с аргументами (modbus[1] == 0xFEDC && ECanaMboxes.MBOX2.MDL.all == 0x5001FEDCUL) в текущей последовательности операций. */
assert(modbus[1] == 0xFEDC && ECanaMboxes.MBOX2.MDL.all == 0x5001FEDCUL);
/* Вызывает assert с аргументами (ECanaMboxes.MBOX2.MDH.all == 0x1F000100UL) в текущей последовательности операций. */
assert(ECanaMboxes.MBOX2.MDH.all == 0x1F000100UL);
/* Вызывает can_request с аргументами (3, 0x5001, 2) в текущей последовательности операций. */
can_request(3, 0x5001, 2);
/* Вызывает assert с аргументами (ECanaMboxes.MBOX2.MDL.all == 0xFEDC0002UL) в текущей последовательности операций. */
assert(ECanaMboxes.MBOX2.MDL.all == 0xFEDC0002UL);
/* Вызывает can_request с аргументами (3, 0x5000, 124) в текущей последовательности операций. */
can_request(3, 0x5000, 124);
/* Вызывает assert с аргументами (ump_can_length == 124 && ump_can_index == 2) в текущей последовательности операций. */
assert(ump_can_length == 124 && ump_can_index == 2);
modbus[2] = 777; /* All fragments must retain the original snapshot. */
modbus[2] = 777; /* All fragments must retain the original snapshot. */ /* Записывает modbus[2] значением 777; массив технологических регистров; слово int на C28x занимает 16 бит. */
/* Цикл for (i = 1; i < 62; ++i) ; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i = 1; i < 62; ++i) {
/* Записывает ECanaRegs.CANTA.all значением 4; представление регистра целым словом без разбиения на битовые поля. */
ECanaRegs.CANTA.all = 4;
/* Вызывает UMP_CAN_service. В главном цикле готовит замороженный ответ служебного CAN и отправляет его двухсловными фрагментами. */
UMP_CAN_service();
/* Вызывает assert с аргументами (ump_can_index == 2*(i+1)) в текущей последовательности операций. */
assert(ump_can_index == 2*(i+1));
/* Проверяет if (i == 1) assert(ECanaMboxes.MBOX2.MDL.all == 0x00020003UL); последующий оператор выполняется только при истинном условии. */
if (i == 1) assert(ECanaMboxes.MBOX2.MDL.all == 0x00020003UL);
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Записывает modbus[2] значением 2; массив технологических регистров; слово int на C28x занимает 16 бит. */
modbus[2] = 2;
/* Вызывает can_request с аргументами (3, 0x5000, 3) в текущей последовательности операций. */
can_request(3, 0x5000, 3);
/* Вызывает assert с аргументами (ECanaMboxes.MBOX2.MDH.all == 0x1F000103UL) в текущей последовательности операций. */
assert(ECanaMboxes.MBOX2.MDH.all == 0x1F000103UL);
/* Вызывает can_request с аргументами (6, 0x507C, 9) в текущей последовательности операций. */
can_request(6, 0x507C, 9);
/* Вызывает assert с аргументами ((ECanaMboxes.MBOX2.MDH.all & 255U) == 2 && modbus[0x7C] == 0x7C) в текущей последовательности операций. */
assert((ECanaMboxes.MBOX2.MDH.all & 255U) == 2 && modbus[0x7C] == 0x7C);
/* Вызывает can_request с аргументами (6, 0x507F, 0x40) в текущей последовательности операций. */
can_request(6, 0x507F, 0x40);
/* Вызывает assert с аргументами (captures == 2 && modbus[127] == 0x40) в текущей последовательности операций. */
assert(captures == 2 && modbus[127] == 0x40);
/* Вызывает can_request с аргументами (6, 0x5F00, 9) в текущей последовательности операций. */
can_request(6, 0x5F00, 9);
/* Вызывает assert с аргументами ((ECanaMboxes.MBOX2.MDH.all & 255U) == 2) в текущей последовательности операций. */
assert((ECanaMboxes.MBOX2.MDH.all & 255U) == 2);
/* Вызывает request с аргументами (&rs, 3, 0x8000, 0x8001) в текущей последовательности операций. */
request(&rs, 3, 0x8000, 0x8001);
/* Выбирает альтернативный блок текущего условия компиляции. */
#else
/* Вызывает request с аргументами (&rs, 3, 0x5000, 2) в текущей последовательности операций. */
request(&rs, 3, 0x5000, 2);
/* Вызывает assert с аргументами (sent == 5 && rs.buffer[2] == 2) в текущей последовательности операций. */
assert(sent == 5 && rs.buffer[2] == 2);
/* Вызывает request с аргументами (&rs, 6, 0x5001, 9) в текущей последовательности операций. */
request(&rs, 6, 0x5001, 9);
/* Вызывает assert с аргументами (rs.buffer[2] == 2 && modbus[1] == 0xFEDC) в текущей последовательности операций. */
assert(rs.buffer[2] == 2 && modbus[1] == 0xFEDC);
/* Вызывает request с аргументами (&rs, 3, 0x5000, 124) в текущей последовательности операций. */
request(&rs, 3, 0x5000, 124);
/* Вызывает assert с аргументами (sent == 5 && rs.buffer[2] == 2) в текущей последовательности операций. */
assert(sent == 5 && rs.buffer[2] == 2);
/* Вызывает request с аргументами (&rs, 3, 0x5F00, 8) в текущей последовательности операций. */
request(&rs, 3, 0x5F00, 8);
/* Вызывает assert с аргументами (rs.buffer[2] == 2) в текущей последовательности операций. */
assert(rs.buffer[2] == 2);
/* Вызывает can_request с аргументами (6, 0x5001, 9) в текущей последовательности операций. */
can_request(6, 0x5001, 9);
/* Вызывает assert с аргументами ((ECanaMboxes.MBOX2.MDH.all & 255U) == 2 && modbus[1] == 0xFEDC) в текущей последовательности операций. */
assert((ECanaMboxes.MBOX2.MDH.all & 255U) == 2 && modbus[1] == 0xFEDC);
/* Вызывает assert с аргументами (captures == 0) в текущей последовательности операций. */
assert(captures == 0);
/* Вызывает request с аргументами (&rs, 3, 0x8000, 1) в текущей последовательности операций. */
request(&rs, 3, 0x8000, 1);
/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */
#endif
/* Вызывает assert с аргументами (spi_reads == 1 && rs.buffer[3] == 0xBE && rs.buffer[4] == 0xEF) в текущей последовательности операций. */
assert(spi_reads == 1 && rs.buffer[3] == 0xBE && rs.buffer[4] == 0xEF);
/* Вызывает assert с аргументами (modbus[128] == 0xD00D) в текущей последовательности операций. */
assert(modbus[128] == 0xD00D);
/* Вызывает printf с аргументами ("PASS GAS167 profile %d: production RTU/CAN routes, guards, CRC and legacy services\n", EEPROM_M95M02) в текущей последовательности операций. */
printf("PASS GAS167 profile %d: production RTU/CAN routes, guards, CRC and legacy services\n", EEPROM_M95M02);
/* Завершает main и возвращает 0. */
return 0;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}

View File

@@ -1,51 +1,97 @@
# Проверка gas167 на модели пк. Комментарии и исходный текст в UTF-8.
# Продолжает текущий вызов, список или выражение: """Exercise the production GAS provider and extracted production RTU/CAN routes."""; порядок аргументов сохраняется.
"""Exercise the production GAS provider and extracted production RTU/CAN routes."""
# Подключает модуль os для этой проверки или подготовки сборки.
import os
# Импортирует необходимые имена: from pathlib import Path.
from pathlib import Path
# Подключает модуль re для этой проверки или подготовки сборки.
import re
# Подключает модуль shutil для этой проверки или подготовки сборки.
import shutil
# Подключает модуль subprocess для этой проверки или подготовки сборки.
import subprocess
# Подключает модуль tempfile для этой проверки или подготовки сборки.
import tempfile
# Задаёт root по выражению справа; значение используется последующими операциями.
root = Path(__file__).resolve().parents[2]
# Задаёт templates по выражению справа; значение используется последующими операциями.
templates = Path(os.environ.get("TEMPLATES_ROOT", root.parent / "newProject/SETGUI/third_party/templates"))
# Задаёт protocol по выражению справа; значение используется последующими операциями.
protocol = templates / "c/set-protocol"
# Задаёт compiler по выражению справа; значение используется последующими операциями.
compiler = os.environ.get("CC") or shutil.which("gcc") or "C:/msys64/mingw64/bin/gcc.exe"
# Задаёт os.environ["PATH"] по выражению справа; значение используется последующими операциями.
os.environ["PATH"] = str(Path(compiler).resolve().parent) + os.pathsep + os.environ["PATH"]
# Объявляет функцию function и её входные параметры.
def function(text, name):
# Задаёт match по выражению справа; значение используется последующими операциями.
match = re.search(r"^(?:static )?(?:void|int) " + name + r"\(", text, re.M)
# Проверяет условие if not match перед выполнением следующего блока.
if not match:
# Останавливает текущую операцию с исключением ValueError(f"Production function {name} missing").
raise ValueError(f"Production function {name} missing")
# Задаёт end по выражению справа; значение используется последующими операциями.
end = re.search(r"^}", text[match.start():], re.M)
# Проверяет условие if not end перед выполнением следующего блока.
if not end:
# Останавливает текущую операцию с исключением ValueError(f"Production function {name} incomplete").
raise ValueError(f"Production function {name} incomplete")
# Возвращает text[match.start():match.start() + end.end()] + "\n" вызывающему коду и завершает функцию.
return text[match.start():match.start() + end.end()] + "\n"
message = (root / "Source/Internal/message.c").read_text(encoding="cp1251")
ecan = (root / "Source/Internal/ecan.c").read_text(encoding="cp1251")
# Читает исходный файл или образ для последующей проверки и разбора.
message = (root / "Source/Internal/message.c").read_text(encoding="utf-8")
# Читает исходный файл или образ для последующей проверки и разбора.
ecan = (root / "Source/Internal/ecan.c").read_text(encoding="utf-8")
# Задаёт can_globals по выражению справа; значение используется последующими операциями.
can_globals = ecan[ecan.index("static volatile unsigned int ump_can_pending;"):
# Продолжает текущий вызов, список или выражение: ecan.index("static unsigned long ump_can_sent_at;") + len("static unsigned long ump_can_sent_at;")]; порядок аргументов сохраняется.
ecan.index("static unsigned long ump_can_sent_at;") + len("static unsigned long ump_can_sent_at;")]
# On C28x unsigned int is uint16_t. Preserve that target word layout on GCC.
# Задаёт can_globals по выражению справа; значение используется последующими операциями.
can_globals = can_globals.replace("static unsigned int ump_can_reply[",
# Продолжает текущий вызов, список или выражение: "static uint16_t ump_can_reply["); порядок аргументов сохраняется.
"static uint16_t ump_can_reply[")
# Задаёт routes по выражению справа; значение используется последующими операциями.
routes = can_globals + "\n" + "".join(function(message, name) for name in
# Продолжает текущий вызов, список или выражение: ("modbus_exception", "receive_ump", "ReceiveCommandModbus3", "ReceiveCommandModbus6")); порядок аргументов сохраняется.
("modbus_exception", "receive_ump", "ReceiveCommandModbus3", "ReceiveCommandModbus6"))
# Задаёт routes + по выражению справа; значение используется последующими операциями.
routes += function(ecan, "UMP_CAN_service")
# Открывает управляемый ресурс tempfile.TemporaryDirectory(prefix="gas167-test-") as tmp с автоматическим освобождением.
with tempfile.TemporaryDirectory(prefix="gas167-test-") as tmp:
# Задаёт directory по выражению справа; значение используется последующими операциями.
directory = Path(tmp)
# Сохраняет подготовленный файл в указанном формате для следующего шага.
(directory / "production_routes.inc").write_text(routes, encoding="utf-8")
# Перебирает profile in (0, 1) в указанном порядке.
for profile in (0, 1):
# Задаёт exe по выражению справа; значение используется последующими операциями.
exe = directory / f"gas167_{profile}.exe"
# Запускает внешний компилятор, генератор или тест; ненулевой результат проверяется параметрами вызова.
subprocess.run([compiler, "-std=c99", "-Wall", "-Wextra",
# Продолжает текущий вызов, список или выражение: "-Wno-unused-function", "-Wno-unused-parameter",; порядок аргументов сохраняется.
"-Wno-unused-function", "-Wno-unused-parameter",
# Задаёт f"-DEEPROM_M95M02 по выражению справа; значение используется последующими операциями.
f"-DEEPROM_M95M02={profile}", "-I" + str(directory),
# Продолжает текущий вызов, список или выражение: "-ISource/Internal/Include", "-I" + str(protocol),; порядок аргументов сохраняется.
"-ISource/Internal/Include", "-I" + str(protocol),
# Продолжает текущий вызов, список или выражение: "-I" + str(protocol / "include"),; порядок аргументов сохраняется.
"-I" + str(protocol / "include"),
# Продолжает текущий вызов, список или выражение: "-I" + str(protocol / "ports/tms320f28335"),; порядок аргументов сохраняется.
"-I" + str(protocol / "ports/tms320f28335"),
# Продолжает текущий вызов, список или выражение: "tests/gas167/gas167_test.c", "Source/Internal/gas167.c",; порядок аргументов сохраняется.
"tests/gas167/gas167_test.c", "Source/Internal/gas167.c",
# Продолжает текущий вызов, список или выражение: str(protocol / "src/ump_protocol.c"),; порядок аргументов сохраняется.
str(protocol / "src/ump_protocol.c"),
# Продолжает текущий вызов, список или выражение: str(protocol / "ports/tms320f28335/ump_tms28335.c"),; порядок аргументов сохраняется.
str(protocol / "ports/tms320f28335/ump_tms28335.c"),
# Задаёт "-o", str(exe)], cwd по выражению справа; значение используется последующими операциями.
"-o", str(exe)], cwd=root, check=True)
# Запускает внешний компилятор, генератор или тест; ненулевой результат проверяется параметрами вызова.
subprocess.run([str(exe)], check=True, timeout=10)

View File

@@ -1,103 +1,197 @@
/* Проверка load_control на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Подключает <stdio.h>: настройки и интерфейс stdio. */
#include <stdio.h>
/* Подключает <string.h>: настройки и интерфейс string. */
#include <string.h>
/* Подключает "../../Source/Internal/DAC.c": выход ЦАП и автомат защиты нагрузки с проверкой напряжения и свежести CAN. */
#include "../../Source/Internal/DAC.c"
/* Объявляет READY — данные READY; Desk — аппаратно определённый тип платы; Mode — рабочий адрес или режим платы, выбранный перемычками. Начальное значение задаётся справа от знака равенства. */
int READY = 1, Desk = 6, Mode = 5;
/* Объявляет modbus — массив технологических регистров; слово int на C28x занимает 16 бит. */
int modbus[128];
/* Объявляет test_start — данные test_start; test_stop — данные test_stop; test_permission — данные test_permission; test_tick — данные test_tick. */
unsigned int test_start, test_stop, test_permission, test_tick;
/* Объявляет test_starts — данные test_starts; test_last_stop_tick — данные test_last_stop_tick; test_last_start_tick — данные test_last_start_tick; test_init_dac — test init ЦАП. */
unsigned int test_starts, test_last_stop_tick, test_last_start_tick, test_init_dac;
/* Объявляет test_bad_order — данные test_bad_order. */
int test_bad_order;
/* Объявляет ump_dac_ramp — ump ЦАП ramp; ump_dac_duration — ump ЦАП duration; ump_dac_go10 — ump ЦАП go 10; ump_dac_stop10 — ump ЦАП stop 10; ump_dac_position — ump ЦАП position. */
unsigned int ump_dac_ramp, ump_dac_duration, ump_dac_go10, ump_dac_stop10, ump_dac_position;
/* Задаёт CHECK = do { if (!(x)) { printf("FAIL line %d: %s\n", __LINE__, #x); return 1; } } while (0); данные CHECK. */
#define CHECK(x) do { if (!(x)) { printf("FAIL line %d: %s\n", __LINE__, #x); return 1; } } while (0)
/* Начинает функцию setup; назначение модуля — проверка load_control на модели ПК. */
static void setup(int mode) {
/* Записывает Mode значением mode; READY = 1; рабочий адрес или режим платы, выбранный перемычками. */
memset(modbus, 0, sizeof(modbus)); Mode = mode; READY = 1;
/* Записывает test_start значением test_stop = test_permission = test_tick = test_starts = 0; данные test_start. */
test_start = test_stop = test_permission = test_tick = test_starts = 0;
/* Записывает test_bad_order значением test_init_dac = 0; данные test_bad_order. */
test_bad_order = test_init_dac = 0;
/* Записывает WAKEpowse значением 0; данные WAKEpowse. */
Load_control_init(); Setup_DAC_time(); WAKEpowse = 0;
/* Записывает DAC_go значением 4; DAC_stop = 16; DAC_min() = 100; DAC_max() = 3000; начальный ток нагрузки в мА, технологический регистр 0x50. */
DAC_go = 4; DAC_stop = 16; DAC_min() = 100; DAC_max() = 3000;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Начинает функцию tick; назначение модуля — проверка load_control на модели ПК. */
static void tick(unsigned int n, int exchange, unsigned int volts) {
/* Повторяет или ожидает, пока выполняется while (n--). */
while (n--) {
/* Проверяет if (exchange) Load_voltage_can(0x8000U | (Mode == 5 ? 305U : 8U), volts, 0, 0); последующий оператор выполняется только при истинном условии. */
if (exchange) Load_voltage_can(0x8000U | (Mode == 5 ? 305U : 8U), volts, 0, 0);
/* Изменяет счётчик в выражении test_tick++; Load_runner(); на один для следующего шага. */
test_tick++; Load_runner();
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Точка входа: настраивает периферию, загружает параметры и обслуживает команды в главном цикле. */
int main(void) {
/* Объявляет out — данные out; error — ошибка; count — число; ramp — данные ramp; code — данные code. */
unsigned int out[8], error, count, ramp, code, stopped_at;
/* Вызывает setup с аргументами (5) в текущей последовательности операций. */
setup(5);
/* Boot ISR before parameters: no divide-by-zero and no GPIO start. */
/* Записывает Commands значением 0x80; tick(10, 1, 0); CHECK(!test_starts); слово команд, технологический регистр 127. */
Load_control_init(); Commands = 0x80; tick(10, 1, 0); CHECK(!test_starts);
/* Записывает WAKEpowse значением 0; данные WAKEpowse. */
Setup_DAC_time(); WAKEpowse = 0;
/* Вызывает tick с аргументами (10, 0, 0); CHECK(test_starts == 1 && test_permission) в текущей последовательности операций. */
tick(10, 0, 0); CHECK(test_starts == 1 && test_permission);
/* Вызывает CHECK с аргументами (LOAD_CAN_TIMEOUT == 600) в текущей последовательности операций. */
CHECK(LOAD_CAN_TIMEOUT == 600);
/* Wrong ZPT and masked slots never confirm freshness. */
/* Записывает Commands значением 0x80; слово команд, технологический регистр 127. */
setup(5); Commands = 0x80;
/* Вызывает Load_voltage_can. Принимает напряжение выбранной нагрузки из достоверных слов CAN и сбрасывает возраст только нужного измерения. */
Load_voltage_can(0x8000U | 8U, 200, 0, 0);
/* Вызывает Load_voltage_can. Принимает напряжение выбранной нагрузки из достоверных слов CAN и сбрасывает возраст только нужного измерения. */
Load_voltage_can(305U, 200, 0, 0); tick(10, 0, 0);
/* Вызывает CHECK с аргументами (!test_starts && (LOAD_STATUS & 2)) в текущей последовательности операций. */
CHECK(!test_starts && (LOAD_STATUS & 2));
/* Вызывает Load_voltage_can. Принимает напряжение выбранной нагрузки из достоверных слов CAN и сбрасывает возраст только нужного измерения. */
Load_voltage_can(0x2000U | 303U, 0, 0, 30);
/* Вызывает tick с аргументами (1, 0, 0); CHECK(test_starts == 1) в текущей последовательности операций. */
tick(1, 0, 0); CHECK(test_starts == 1);
/* Freeze current and code at timeout; unrelated exchange cannot unfreeze. */
/* Вызывает tick с аргументами (1000, 1, 30); tick(600, 0, 0) в текущей последовательности операций. */
tick(1000, 1, 30); tick(600, 0, 0);
/* Записывает ramp значением ump_dac_ramp; code = modbus[123]; данные ramp. */
ramp = ump_dac_ramp; code = modbus[123];
/* Вызывает tick с аргументами (2000, 0, 0); CHECK(ump_dac_ramp == ramp && (unsigned int)modbus[123] == code) в текущей последовательности операций. */
tick(2000, 0, 0); CHECK(ump_dac_ramp == ramp && (unsigned int)modbus[123] == code);
/* Вызывает CHECK с аргументами (test_permission && !test_stop && (LOAD_STATUS & 2)) в текущей последовательности операций. */
CHECK(test_permission && !test_stop && (LOAD_STATUS & 2));
/* Вызывает Load_voltage_can. Принимает напряжение выбранной нагрузки из достоверных слов CAN и сбрасывает возраст только нужного измерения. */
Load_voltage_can(0x8000U | 8U, 200, 0, 0); tick(10, 0, 0);
/* Вызывает CHECK с аргументами (ump_dac_ramp == ramp) в текущей последовательности операций. */
CHECK(ump_dac_ramp == ramp);
/* Вызывает tick с аргументами (10, 1, 30); CHECK(ump_dac_ramp > ramp) в текущей последовательности операций. */
tick(10, 1, 30); CHECK(ump_dac_ramp > ramp);
/* Exactly 30 V permits growth; 29 V fails strictly above 6 mA. */
/* Записывает Commands значением 0x80; tick(10, 1, 30); слово команд, технологический регистр 127. */
setup(6); Commands = 0x80; tick(10, 1, 30);
/* Записывает load_count_ramp значением time_dac / 6; tick(5, 1, 30); load число ramp. */
load_count_ramp = time_dac / 6; tick(5, 1, 30);
/* Вызывает CHECK с аргументами (load_state == LOAD_RUN && modbus[0x1C] >= 60) в текущей последовательности операций. */
CHECK(load_state == LOAD_RUN && modbus[0x1C] >= 60);
/* Вызывает tick с аргументами (5, 1, 29); CHECK(load_state == LOAD_RELOAD && test_stop && !test_permission) в текущей последовательности операций. */
tick(5, 1, 29); CHECK(load_state == LOAD_RELOAD && test_stop && !test_permission);
/* Вызывает CHECK с аргументами (!test_start && ump_dac_ramp == 0 && modbus[0x1C] == 40) в текущей последовательности операций. */
CHECK(!test_start && ump_dac_ramp == 0 && modbus[0x1C] == 40);
/* Записывает stopped_at значением test_last_stop_tick; данные stopped_at. */
CHECK(modbus[123] == DAC_min()); stopped_at = test_last_stop_tick;
/* Вызывает tick с аргументами (999, 1, 0); CHECK(test_starts == 1 && test_stop) в текущей последовательности операций. */
tick(999, 1, 0); CHECK(test_starts == 1 && test_stop);
/* Вызывает tick с аргументами (1, 1, 0); CHECK(test_starts == 2 && test_last_start_tick-stopped_at == 1000) в текущей последовательности операций. */
tick(1, 1, 0); CHECK(test_starts == 2 && test_last_start_tick-stopped_at == 1000);
/* Вызывает CHECK с аргументами (!test_stop && test_permission && !test_bad_order) в текущей последовательности операций. */
CHECK(!test_stop && test_permission && !test_bad_order);
/* Five total attempts, then a persistent fault; no sixth start. */
/* Повторяет или ожидает, пока выполняется while (load_state != LOAD_FAULT). */
while (load_state != LOAD_FAULT) {
/* Записывает load_count_ramp значением time_dac / 6; tick(5, 1, 0); load число ramp. */
load_count_ramp = time_dac / 6; tick(5, 1, 0);
/* Проверяет if (load_state == LOAD_RELOAD) tick(1000, 1, 0); последующий оператор выполняется только при истинном условии. */
if (load_state == LOAD_RELOAD) tick(1000, 1, 0);
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Вызывает CHECK с аргументами (test_starts == 5 && LOAD_ATTEMPTS == 5 && (LOAD_STATUS & 1)) в текущей последовательности операций. */
CHECK(test_starts == 5 && LOAD_ATTEMPTS == 5 && (LOAD_STATUS & 1));
/* Вызывает tick с аргументами (3000, 1, 200); CHECK(test_starts == 5 && test_stop && !test_permission) в текущей последовательности операций. */
tick(3000, 1, 200); CHECK(test_starts == 5 && test_stop && !test_permission);
/* Записывает Commands значением 0xC0; tick(10, 1, 200); CHECK(load_state == LOAD_FAULT); слово команд, технологический регистр 127. */
Commands = 0xC0; tick(10, 1, 200); CHECK(load_state == LOAD_FAULT);
/* Записывает Commands значением 0; tick(1000, 1, 200); CHECK(!(LOAD_STATUS & 1)); слово команд, технологический регистр 127. */
Commands = 0; tick(1000, 1, 200); CHECK(!(LOAD_STATUS & 1));
/* Записывает Commands значением 0x80; test_starts = 0; tick(10, 1, 200); CHECK(LOAD_ATTEMPTS == 1); слово команд, технологический регистр 127. */
Commands = 0x80; test_starts = 0; tick(10, 1, 200); CHECK(LOAD_ATTEMPTS == 1);
/* Manual reset dominates START; releasing it alone cannot start again. */
/* Записывает Commands значением 0xC0; tick(1, 1, 200); CHECK(test_stop && !test_permission); слово команд, технологический регистр 127. */
Commands = 0xC0; tick(1, 1, 200); CHECK(test_stop && !test_permission);
/* Записывает Commands значением 0x80; tick(1500, 1, 200); CHECK(test_starts == 1); слово команд, технологический регистр 127. */
Commands = 0x80; tick(1500, 1, 200); CHECK(test_starts == 1);
/* Versioned simulation writes are bounded, read-only fields reject writes. */
/* Записывает count значением Load_protection_prepare(3, 0x1300, 8, out, &error); число. */
count = Load_protection_prepare(3, 0x1300, 8, out, &error);
/* Вызывает CHECK с аргументами (count == 8 && !error && out[0] == 0x5550 && out[1] == 1) в текущей последовательности операций. */
CHECK(count == 8 && !error && out[0] == 0x5550 && out[1] == 1);
/* Вызывает Load_protection_prepare. Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */
Load_protection_prepare(6, 0x1303, 0, out, &error); CHECK(error == 3);
/* Вызывает Load_protection_prepare. Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */
Load_protection_prepare(6, 0x1304, 0, out, &error); CHECK(error == 2);
/* Вызывает Load_protection_prepare. Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */
Load_protection_prepare(6, 0x1302, 4, out, &error); CHECK(error == 3);
/* Записывает Commands значением 0x80; tick(10, 1, 200); слово команд, технологический регистр 127. */
setup(5); Commands = 0x80; tick(10, 1, 200);
/* Вызывает Load_protection_prepare. Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */
Load_protection_prepare(6, 0x1303, 20, out, &error); CHECK(!error);
/* Вызывает Load_protection_prepare. Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */
Load_protection_prepare(6, 0x1302, 1, out, &error); CHECK(!error);
/* Вызывает tick с аргументами (30, 1, 200); CHECK(LOAD_STATUS & 2) в текущей последовательности операций. */
tick(30, 1, 200); CHECK(LOAD_STATUS & 2);
/* Записывает ramp значением ump_dac_ramp; tick(100, 1, 200); CHECK(ump_dac_ramp == ramp); данные ramp. */
ramp = ump_dac_ramp; tick(100, 1, 200); CHECK(ump_dac_ramp == ramp);
/* Вызывает Load_protection_prepare. Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */
Load_protection_prepare(6, 0x1302, 0, out, &error);
/* Вызывает tick с аргументами (10, 1, 200); CHECK(!(LOAD_STATUS & 2) && ump_dac_ramp > ramp) в текущей последовательности операций. */
tick(10, 1, 200); CHECK(!(LOAD_STATUS & 2) && ump_dac_ramp > ramp);
/* Вызывает Load_protection_prepare. Фиксирует управляющие входы перед выполнением автомата защиты нагрузки. */
Load_protection_prepare(6, 0x1302, 2, out, &error);
/* Записывает load_count_ramp значением time_dac / 6; tick(5, 1, 200); CHECK(load_state == LOAD_RELOAD); load число ramp. */
load_count_ramp = time_dac / 6; tick(5, 1, 200); CHECK(load_state == LOAD_RELOAD);
/* Calibration must not replace the forced 4 mA output during reload. */
/* Устанавливает биты Commands значением 0x200; DAC_cal() = 4095; tick(5, 1, 200); слово команд, технологический регистр 127. */
Commands |= 0x200; DAC_cal() = 4095; tick(5, 1, 200);
/* Вызывает CHECK с аргументами (modbus[123] == DAC_min() && modbus[0x1C] == 40) в текущей последовательности операций. */
CHECK(modbus[123] == DAC_min() && modbus[0x1C] == 40);
/* A calibration code preceding START must be replaced by 4 mA first. */
/* Записывает Commands значением 0x200; DAC_cal() = 4095; слово команд, технологический регистр 127. */
setup(5); Commands = 0x200; DAC_cal() = 4095;
/* Вызывает tick с аргументами (10, 1, 200); CHECK(modbus[123] == 4095 && !load_zero_sent) в текущей последовательности операций. */
tick(10, 1, 200); CHECK(modbus[123] == 4095 && !load_zero_sent);
/* Записывает Commands значением 0x280; tick(1, 1, 200); CHECK(!test_starts); слово команд, технологический регистр 127. */
Commands = 0x280; tick(1, 1, 200); CHECK(!test_starts);
/* Вызывает tick с аргументами (4, 1, 200); CHECK(!test_starts && modbus[123] == DAC_min()) в текущей последовательности операций. */
tick(4, 1, 200); CHECK(!test_starts && modbus[123] == DAC_min());
/* Вызывает tick с аргументами (1, 1, 200); CHECK(test_starts == 1) в текущей последовательности операций. */
tick(1, 1, 200); CHECK(test_starts == 1);
/* Timeout while STOP is held cannot initiate the pending retry. */
/* Записывает Commands значением 0x80; tick(10, 1, 0); слово команд, технологический регистр 127. */
setup(5); Commands = 0x80; tick(10, 1, 0);
/* Записывает load_count_ramp значением time_dac / 6; tick(5, 1, 0); load число ramp. */
load_count_ramp = time_dac / 6; tick(5, 1, 0);
/* Вызывает CHECK с аргументами (load_state == LOAD_RELOAD) в текущей последовательности операций. */
CHECK(load_state == LOAD_RELOAD);
/* Вызывает tick с аргументами (1500, 0, 0); CHECK(test_starts == 1 && test_stop) в текущей последовательности операций. */
tick(1500, 0, 0); CHECK(test_starts == 1 && test_stop);
/* Вызывает tick с аргументами (1, 1, 0); CHECK(test_starts == 2 && !test_stop) в текущей последовательности операций. */
tick(1, 1, 0); CHECK(test_starts == 2 && !test_stop);
/* Вызывает Load_control_init. Сбрасывает все переменные автомата нагрузки до разрешения прерываний; COFF не обнуляет всю .ebss. */
Load_control_init(); CHECK(!load_simulation);
/* Вызывает puts с аргументами ("PASS: production DAC control, timeout, CAN slots, STOP ordering, five attempts, simulation") в текущей последовательности операций. */
puts("PASS: production DAC control, timeout, CAN slots, STOP ordering, five attempts, simulation");
/* Завершает main и возвращает 0. */
return 0;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}

View File

@@ -1,16 +1,32 @@
# Проверка load_control на модели пк. Комментарии и исходный текст в UTF-8.
# Продолжает текущий вызов, список или выражение: """Compile the production DAC.c against GPIO/IRQ mocks; no hardware writes."""; порядок аргументов сохраняется.
"""Compile the production DAC.c against GPIO/IRQ mocks; no hardware writes."""
# Подключает модуль os для этой проверки или подготовки сборки.
import os
# Импортирует необходимые имена: from pathlib import Path.
from pathlib import Path
# Подключает модуль shutil для этой проверки или подготовки сборки.
import shutil
# Подключает модуль subprocess для этой проверки или подготовки сборки.
import subprocess
# Подключает модуль tempfile для этой проверки или подготовки сборки.
import tempfile
# Задаёт root по выражению справа; значение используется последующими операциями.
root = Path(__file__).resolve().parents[2]
# Задаёт compiler по выражению справа; значение используется последующими операциями.
compiler = os.environ.get('CC') or shutil.which('gcc') or 'C:/msys64/mingw64/bin/gcc.exe'
# Задаёт os.environ['PATH'] по выражению справа; значение используется последующими операциями.
os.environ['PATH'] = str(Path(compiler).resolve().parent) + os.pathsep + os.environ['PATH']
# Открывает управляемый ресурс tempfile.TemporaryDirectory(prefix='load-control-') as tmp с автоматическим освобождением.
with tempfile.TemporaryDirectory(prefix='load-control-') as tmp:
# Задаёт exe по выражению справа; значение используется последующими операциями.
exe = Path(tmp) / 'test.exe'
# Запускает внешний компилятор, генератор или тест; ненулевой результат проверяется параметрами вызова.
subprocess.run([compiler, '-Wall', '-Wextra', '-std=c99',
# Продолжает текущий вызов, список или выражение: '-Itests/load_control/stubs', '-ISource/Internal/Include',; порядок аргументов сохраняется.
'-Itests/load_control/stubs', '-ISource/Internal/Include',
# Задаёт 'tests/load_control/load_control_test.c', '-o', str(exe)], cwd по выражению справа; значение используется последующими операциями.
'tests/load_control/load_control_test.c', '-o', str(exe)], cwd=root, check=True)
# Запускает внешний компилятор, генератор или тест; ненулевой результат проверяется параметрами вызова.
subprocess.run([str(exe)], check=True, timeout=10)

View File

@@ -1,9 +1,19 @@
/* Проверка load_control/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Начинает условие: TEST_DEVICE_H ещё не определён; защищает повторное включение или задаёт значение сборки. */
#ifndef TEST_DEVICE_H
/* Определяет защитный символ или переключатель TEST_DEVICE_H для последующей компиляции. */
#define TEST_DEVICE_H
/* Описывает структуру bits; порядок полей определяет расположение данных. */
struct bits { unsigned int GPIO59, GPIO60, GPIO63; };
/* Описывает структуру reg; порядок полей определяет расположение данных. */
struct reg { struct bits bit; };
/* Продолжает список аргументов, полей или выражение static struct { struct reg GPBSET, GPBCLEAR; } GpioDataRegs;; порядок элементов сохраняется. */
static struct { struct reg GPBSET, GPBCLEAR; } GpioDataRegs;
/* Начинает функцию __disable_interrupts; назначение модуля — проверка load_control/stubs на модели ПК. */
static unsigned int __disable_interrupts(void) { return 0; }
/* Начинает функцию __restore_interrupts; назначение модуля — проверка load_control/stubs на модели ПК. */
static void __restore_interrupts(unsigned int saved) { (void)saved; }
/* Начинает функцию DSP28x_usDelay; назначение модуля — проверка load_control/stubs на модели ПК. */
static void DSP28x_usDelay(unsigned long n) { (void)n; }
/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */
#endif

View File

@@ -1 +1,2 @@
/* Проверка load_control/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* No IRQ registers needed in the host test. */

View File

@@ -1 +1,2 @@
/* Проверка load_control/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* No serial dependencies in the host test. */

View File

@@ -1 +1,2 @@
/* Проверка load_control/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* No filter dependencies in the host test. */

View File

@@ -1,4 +1,9 @@
/* Проверка load_control/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Задаёт READY_FREQ = 1000; частота основного такта Timer1 в герцах. */
#define READY_FREQ 1000
/* Задаёт DAC_FREQ = 200; частота обновления тока ЦАП в герцах. */
#define DAC_FREQ 200
/* Задаёт LOAD_TIME = 30; время нарастания тока нагрузки в секундах. */
#define LOAD_TIME 30
/* Объявляет READY — данные READY. Память определена в другом модуле. */
extern int READY;

View File

@@ -1 +1,3 @@
/* Проверка load_control/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Объявляет modbus — массив технологических регистров; слово int на C28x занимает 16 бит. Память определена в другом модуле. */
extern int modbus[128];

View File

@@ -1,17 +1,35 @@
/* Проверка load_control/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Задаёт dsk_LOAD = 6; код платы нагрузки. */
#define dsk_LOAD 6
/* Задаёт adr_LOA1 = 5; данные adr_LOA1. */
#define adr_LOA1 5
/* Задаёт adr_LOA2 = 6; данные adr_LOA2. */
#define adr_LOA2 6
/* Задаёт Commands = modbus[127]; слово команд, технологический регистр 127. */
#define Commands modbus[127]
/* Задаёт cUMPstart = (Commands & 0x80); данные cUMPstart. */
#define cUMPstart (Commands & 0x80)
/* Задаёт cUMPreset = (Commands & 0x40); данные cUMPreset. */
#define cUMPreset (Commands & 0x40)
/* Объявляет test_init_dac — test init ЦАП. Память определена в другом модуле. */
extern unsigned int test_init_dac;
/* Задаёт cInitDac = test_init_dac; c Init ЦАП. */
#define cInitDac test_init_dac
/* Задаёт cCalibrDac = (Commands & 0x200); c Calibr ЦАП. */
#define cCalibrDac (Commands & 0x200)
/* Задаёт DAC_go = modbus[0x50]; начальный ток нагрузки в мА, технологический регистр 0x50. */
#define DAC_go modbus[0x50]
/* Задаёт DAC_stop = modbus[0x51]; конечный ток нагрузки в мА, технологический регистр 0x51. */
#define DAC_stop modbus[0x51]
/* Задаёт LOAD_CAN_TIMEOUT = modbus[0x52]; сохраняемый тайм-аут свежести напряжения CAN в миллисекундах, регистр 0x52. */
#define LOAD_CAN_TIMEOUT modbus[0x52]
/* Задаёт LOAD_STATUS = modbus[0x7C]; слово состояния защиты нагрузки для чтения, регистр 0x7C. */
#define LOAD_STATUS modbus[0x7C]
/* Задаёт LOAD_ATTEMPTS = modbus[0x7D]; число попыток пуска для чтения, регистр 0x7D. */
#define LOAD_ATTEMPTS modbus[0x7D]
/* Задаёт DAC_min = modbus[0x79]; ЦАП min. */
#define DAC_min() modbus[0x79]
/* Задаёт DAC_max = modbus[0x78]; ЦАП max. */
#define DAC_max() modbus[0x78]
/* Задаёт DAC_cal = modbus[0x7A]; ЦАП cal. */
#define DAC_cal() modbus[0x7A]

View File

@@ -1,14 +1,29 @@
/* Проверка load_control/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Объявляет Desk — аппаратно определённый тип платы; Mode — рабочий адрес или режим платы, выбранный перемычками. Память определена в другом модуле. */
extern int Desk, Mode;
/* Объявляет test_start — данные test_start; test_stop — данные test_stop; test_permission — данные test_permission; test_tick — данные test_tick. Память определена в другом модуле. */
extern unsigned int test_start, test_stop, test_permission, test_tick;
/* Объявляет test_starts — данные test_starts; test_last_stop_tick — данные test_last_stop_tick; test_last_start_tick — данные test_last_start_tick. Память определена в другом модуле. */
extern unsigned int test_starts, test_last_stop_tick, test_last_start_tick;
/* Объявляет test_bad_order — данные test_bad_order. Память определена в другом модуле. */
extern int test_bad_order;
/* Начинает функцию clear_START_DPTB; назначение модуля — проверка load_control/stubs на модели ПК. */
static void clear_START_DPTB(void) { test_start = 0; }
/* Начинает функцию set_START_DPTB; назначение модуля — проверка load_control/stubs на модели ПК. */
static void set_START_DPTB(void) {
/* Проверяет if (test_stop или (test_starts и test_tick-test_last_stop_tick < 1000)) test_bad_order = 1; последующий оператор выполняется только при истинном условии. */
if (test_stop || (test_starts && test_tick-test_last_stop_tick < 1000)) test_bad_order = 1;
/* Записывает test_start значением 1; test_last_start_tick = test_tick; test_starts++; данные test_start. */
test_start = 1; test_last_start_tick = test_tick; test_starts++;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Начинает функцию set_STOP_DPTB; назначение модуля — проверка load_control/stubs на модели ПК. */
static void set_STOP_DPTB(void) { test_stop = 1; test_last_stop_tick = test_tick; }
/* Начинает функцию clear_STOP_DPTB; назначение модуля — проверка load_control/stubs на модели ПК. */
static void clear_STOP_DPTB(void) { test_stop = 0; }
/* Начинает функцию clear_RES_OUT_2; назначение модуля — проверка load_control/stubs на модели ПК. */
static void clear_RES_OUT_2(void) { test_permission = 0; }
/* Начинает функцию set_RES_OUT_2; назначение модуля — проверка load_control/stubs на модели ПК. */
static void set_RES_OUT_2(void) { if (!test_start || test_stop) test_bad_order = 1; test_permission = 1; }
/* Начинает функцию toggle_RES_OUT_1; назначение модуля — проверка load_control/stubs на модели ПК. */
static void toggle_RES_OUT_1(void) {}

View File

@@ -1 +1,2 @@
/* Проверка load_control/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Delay provided by the device stub. */

View File

@@ -1,118 +1,229 @@
/* Проверка rs232_fifo на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Продолжает список аргументов, полей или выражение volatile struct SCI_REGS SciaRegs,ScibRegs;; порядок элементов сохраняется. */
volatile struct SCI_REGS SciaRegs,ScibRegs;
/* Описывает структуру ; порядок полей определяет расположение данных. */
struct { struct { struct { unsigned ACK9; } bit; } PIEACK; } PieCtrlRegs;
/* Описывает структуру ; порядок полей определяет расположение данных. */
struct { struct { struct { unsigned GPIO34; } bit; } GPBDAT; } GpioDataRegs;
/* Объявляет rs_a — данные rs_a; rs_b — данные rs_b. */
RS_DATA rs_a,rs_b;
/* Объявляет RS_Len — таблица ожидаемых длин команд последовательного протокола; irq — данные irq. */
unsigned int RS_Len[70],irq;
/* Объявляет load_memory — данные load_memory. */
static unsigned int load_memory[4100];
/* Начинает функцию __disable_interrupts; назначение модуля — проверка rs232_fifo на модели ПК. */
static unsigned int __disable_interrupts(void) { unsigned old=irq;irq=1;return old; }
/* Начинает функцию __restore_interrupts; назначение модуля — проверка rs232_fifo на модели ПК. */
static void __restore_interrupts(unsigned state) { irq=state; }
/* Начинает функцию RS_SetLineMode; назначение модуля — проверка rs232_fifo на модели ПК. */
void RS_SetLineMode(RS_DATA *p,int bits,char parity,int stop)
/* Продолжает список аргументов, полей или выражение { (void)p;(void)bits;(void)parity;(void)stop; }; порядок элементов сохраняется. */
{ (void)p;(void)bits;(void)parity;(void)stop; }
/* Объявляет length — длина; wire_count — wire число. */
static unsigned int queue[2][16],length[2],wire[2][20000],wire_count[2];
/* Объявляет rx_count — rx число; rx_pos — данные rx_pos; shift_pending — данные shift_pending; shift_checks — данные shift_checks. */
static unsigned int rx[2][16],rx_count[2],rx_pos[2],shift_pending[2],shift_checks;
/* Начинает функцию port; назначение модуля — проверка rs232_fifo на модели ПК. */
static unsigned int port(RS_DATA *p) {return p->commnumber-1;}
/* Начинает функцию model_interrupts; назначение модуля — проверка rs232_fifo на модели ПК. */
static void model_interrupts(RS_DATA *p,unsigned tx)
/* Записывает p->SciRegs->SCICTL2.bit.TXINTENA значением tx;p->SciRegs->SCICTL2.bit.RXBKINTENA=!tx; }; данные TXINTENA. */
{ p->SciRegs->SCICTL2.bit.TXINTENA=tx;p->SciRegs->SCICTL2.bit.RXBKINTENA=!tx; }
/* Начинает функцию model_flush; назначение модуля — проверка rs232_fifo на модели ПК. */
static void model_flush(RS_DATA *p)
/* Записывает i значением port(p);rx_count[i]=rx_pos[i]=0;p->SciRegs->SCIFFRX.bit.RXFFST=0;p->SciRegs->SCIFFRX.bit.RXFFOVF=0; }; данные i. */
{ unsigned i=port(p);rx_count[i]=rx_pos[i]=0;p->SciRegs->SCIFFRX.bit.RXFFST=0;p->SciRegs->SCIFFRX.bit.RXFFOVF=0; }
/* Начинает функцию model_pop; назначение модуля — проверка rs232_fifo на модели ПК. */
static unsigned int model_pop(RS_DATA *p)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает i значением port(p),v;assert(rx_pos[i]<rx_count[i]);v=rx[i][rx_pos[i]++]; данные i. */
unsigned i=port(p),v;assert(rx_pos[i]<rx_count[i]);v=rx[i][rx_pos[i]++];
/* Записывает p->SciRegs->SCIFFRX.bit.RXFFST значением rx_count[i]-rx_pos[i]; данные RXFFST. */
p->SciRegs->SCIFFRX.bit.RXFFST=rx_count[i]-rx_pos[i];
/* Записывает p->SciRegs->SCIRXST.bit.RXRDY значением rx_pos[i]<rx_count[i];return v; данные RXRDY. */
p->SciRegs->SCIRXST.bit.RXRDY=rx_pos[i]<rx_count[i];return v;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Начинает функцию model_push; назначение модуля — проверка rs232_fifo на модели ПК. */
static void model_push(RS_DATA *p,unsigned v)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает i значением port(p);assert(length[i]<16);queue[i][length[i]++]=v&255; данные i. */
unsigned i=port(p);assert(length[i]<16);queue[i][length[i]++]=v&255;
/* Проверяет if(i==0)p->SciRegs->SCIFFTX.bit.TXFFST=length[i]; последующий оператор выполняется только при истинном условии. */
if(i==0)p->SciRegs->SCIFFTX.bit.TXFFST=length[i];
/* Записывает p->SciRegs->SCICTL2.bit.TXEMPTY значением 0; данные TXEMPTY. */
p->SciRegs->SCICTL2.bit.TXEMPTY=0;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Начинает функцию model_shift; назначение модуля — проверка rs232_fifo на модели ПК. */
static void model_shift(RS_DATA *p)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает i значением port(p);assert(length[i]==0); данные i. */
unsigned i=port(p);assert(length[i]==0);
if(i==0)assert(p->fifo_tx_active); /* last symbol cannot finish early */
if(i==0)assert(p->fifo_tx_active); /* last symbol cannot finish early */ /* Проверяет if(i==0)assert(p->fifo_tx_active); последующий оператор выполняется только при истинном условии. */
/* Записывает shift_pending[i] значением 0;p->SciRegs->SCICTL2.bit.TXEMPTY=1;shift_checks++; данные shift_pending. */
shift_pending[i]=0;p->SciRegs->SCICTL2.bit.TXEMPTY=1;shift_checks++;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Начинает функцию model_step; назначение модуля — проверка rs232_fifo на модели ПК. */
static void model_step(RS_DATA *p)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает i значением port(p),j; данные i. */
unsigned i=port(p),j;
/* Проверяет if(length[i]); последующий оператор выполняется только при истинном условии. */
if(length[i]) {
/* Изменяет счётчик в выражении wire[i][wire_count[i]++]=queue[i][0]; на один для следующего шага. */
wire[i][wire_count[i]++]=queue[i][0];
/* Цикл for(j=1;j<length[i];j++)queue[i][j-1]=queue[i][j];; задаёт начальное значение, условие продолжения и шаг перебора. */
for(j=1;j<length[i];j++)queue[i][j-1]=queue[i][j];
/* Записывает shift_pending[i] значением 1; данные shift_pending. */
length[i]--;shift_pending[i]=1;
/* Проверяет if(i==0)p->SciRegs->SCIFFTX.bit.TXFFST=length[i]; последующий оператор выполняется только при истинном условии. */
if(i==0)p->SciRegs->SCIFFTX.bit.TXFFST=length[i];
/* Проверяет else if(shift_pending[i]) model_shift(p); последующий оператор выполняется только при истинном условии. */
} else if(shift_pending[i]) model_shift(p);
/* Проверяет if(i==0 и p->SciRegs->SCIFFTX.bit.TXFFIENA и; последующий оператор выполняется только при истинном условии. */
if(i==0 && p->SciRegs->SCIFFTX.bit.TXFFIENA &&
/* Продолжает список аргументов, полей или выражение length[i]<=p->SciRegs->SCIFFTX.bit.TXFFIL) RS_TX_Handler(p);; порядок элементов сохраняется. */
length[i]<=p->SciRegs->SCIFFTX.bit.TXFFIL) RS_TX_Handler(p);
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Начинает функцию reset; назначение модуля — проверка rs232_fifo на модели ПК. */
static void reset(void)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Вызывает memset с аргументами (&rs_a,0,sizeof(rs_a));memset(&rs_b,0,sizeof(rs_b)) в текущей последовательности операций. */
memset(&rs_a,0,sizeof(rs_a));memset(&rs_b,0,sizeof(rs_b));
/* Вызывает memset с аргументами ((void *)&SciaRegs,0,sizeof(SciaRegs));memset((void *)&ScibRegs,0,sizeof(ScibRegs)) в текущей последовательности операций. */
memset((void *)&SciaRegs,0,sizeof(SciaRegs));memset((void *)&ScibRegs,0,sizeof(ScibRegs));
/* Вызывает memset с аргументами (length,0,sizeof(length));memset(wire_count,0,sizeof(wire_count)) в текущей последовательности операций. */
memset(length,0,sizeof(length));memset(wire_count,0,sizeof(wire_count));
/* Вызывает memset с аргументами (rx_count,0,sizeof(rx_count));memset(rx_pos,0,sizeof(rx_pos)) в текущей последовательности операций. */
memset(rx_count,0,sizeof(rx_count));memset(rx_pos,0,sizeof(rx_pos));
/* Вызывает memset с аргументами (shift_pending,0,sizeof(shift_pending)) в текущей последовательности операций. */
memset(shift_pending,0,sizeof(shift_pending));
/* Записывает rs_a.commnumber значением 1;rs_b.commnumber=2;rs_a.SciRegs=&SciaRegs;rs_b.SciRegs=&ScibRegs; данные commnumber. */
rs_a.commnumber=1;rs_b.commnumber=2;rs_a.SciRegs=&SciaRegs;rs_b.SciRegs=&ScibRegs;
/* Записывает SciaRegs.SCICTL2.bit.TXEMPTY значением ScibRegs.SCICTL2.bit.TXEMPTY=1; данные TXEMPTY. */
SciaRegs.SCICTL2.bit.TXEMPTY=ScibRegs.SCICTL2.bit.TXEMPTY=1;
/* Записывает rs_a.RS_Flag9bit значением rs_b.RS_Flag9bit=1; RS флаг 9 бит. */
rs_a.RS_Flag9bit=rs_b.RS_Flag9bit=1;
/* Записывает RS_Len[3] значением 8;RS_Len[6]=8;RS_Len[16]=13;RS_Len[51]=12; таблица ожидаемых длин команд последовательного протокола. */
RS_Len[3]=8;RS_Len[6]=8;RS_Len[16]=13;RS_Len[51]=12;
/* Записывает GpioDataRegs.GPBDAT.bit.GPIO34 значением 1;irq=0; аппаратная линия ввода/вывода GPIO34. */
GpioDataRegs.GPBDAT.bit.GPIO34=1;irq=0;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Начинает функцию feed; назначение модуля — проверка rs232_fifo на модели ПК. */
static void feed(RS_DATA *p,const unsigned *bytes,unsigned n)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Записывает i значением port(p),j;assert(n<=16);rx_pos[i]=0;rx_count[i]=n; данные i. */
unsigned i=port(p),j;assert(n<=16);rx_pos[i]=0;rx_count[i]=n;
/* Цикл for(j=0;j<n;j++)rx[i][j]=bytes[j];; задаёт начальное значение, условие продолжения и шаг перебора. */
for(j=0;j<n;j++)rx[i][j]=bytes[j];
/* Записывает p->SciRegs->SCIFFRX.bit.RXFFST значением n;p->SciRegs->SCIRXST.bit.RXRDY=n!=0; данные RXFFST. */
p->SciRegs->SCIFFRX.bit.RXFFST=n;p->SciRegs->SCIRXST.bit.RXRDY=n!=0;
/* Вызывает RS_RX_Handler. Разбирает приём SCI; для COM_1 читает FIFO и проверяет ошибки, для COM_2 сохраняет штатный обмен RS485. */
RS_RX_Handler(p);
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* HANDLERS */
/* Точка входа: настраивает периферию, загружает параметры и обслуживает команды в главном цикле. */
int main(void)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Продолжает список аргументов, полей или выражение unsigned data[4200],sizes[]={0,1,2,7,8,15,16,17,31,120,253,400,8194};; порядок элементов сохраняется. */
unsigned data[4200],sizes[]={0,1,2,7,8,15,16,17,31,120,253,400,8194};
/* Продолжает список аргументов, полей или выражение unsigned a,n,i,mode;unsigned request[]={16,3,0x10,0,0,16,0,0};; порядок элементов сохраняется. */
unsigned a,n,i,mode;unsigned request[]={16,3,0x10,0,0,16,0,0};
/* Цикл for(mode=0;mode<2;mode++)for(a=0;a<sizeof(sizes)/sizeof(sizes[0]);a++) ; задаёт начальное значение, условие продолжения и шаг перебора. */
for(mode=0;mode<2;mode++)for(a=0;a<sizeof(sizes)/sizeof(sizes[0]);a++) {
/* Записывает n значением sizes[a];for(i=0;i<4200;i++)data[i]=(i*131U+17U)&65535; данные n. */
reset();n=sizes[a];for(i=0;i<4200;i++)data[i]=(i*131U+17U)&65535;
/* Проверяет if(mode==0 и n>4200)continue; последующий оператор выполняется только при истинном условии. */
if(mode==0 && n>4200)continue;
/* Вызывает assert с аргументами ((mode ? RS_BSend(&rs_a,data,n):RS_Send(&rs_a,data,n))==0) в текущей последовательности операций. */
assert((mode ? RS_BSend(&rs_a,data,n):RS_Send(&rs_a,data,n))==0);
/* Проверяет if(n и rs_a.fifo_tx_active)assert(rs_a.RS_Flag9bit==0); последующий оператор выполняется только при истинном условии. */
if(n && rs_a.fifo_tx_active)assert(rs_a.RS_Flag9bit==0);
/* Вызывает RS_FifoWait. Ожидает завершения аппаратной передачи FIFO и сдвигового регистра SCI. */
RS_FifoWait(&rs_a);assert(!rs_a.fifo_tx_active && wire_count[0]==n);
/* Цикл for(i=0;i<n;i++)assert(wire[0][i]==(mode?((i&1)?LOBYTE(data[i/2]):HIBYTE(data[i/2])):LOBYTE(data[i])));; задаёт начальное значение, условие продолжения и шаг перебора. */
for(i=0;i<n;i++)assert(wire[0][i]==(mode?((i&1)?LOBYTE(data[i/2]):HIBYTE(data[i/2])):LOBYTE(data[i])));
assert(GpioDataRegs.GPBDAT.bit.GPIO34==1); /* RS232 never touches DE */
assert(GpioDataRegs.GPBDAT.bit.GPIO34==1); /* RS232 never touches DE */ /* Вызывает assert с аргументами (GpioDataRegs.GPBDAT.bit.GPIO34==1) в текущей последовательности операций. */
/* Вызывает assert с аргументами (!irq) в текущей последовательности операций. */
assert(!irq);
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Вызывает assert с аргументами (shift_checks>0) в текущей последовательности операций. */
assert(shift_checks>0);
/* Вызывает reset с аргументами ();feed(&rs_a,request,8);assert(rs_a.RS_DataReady && rs_a.RS_HeaderCnt==8) в текущей последовательности операций. */
reset();feed(&rs_a,request,8);assert(rs_a.RS_DataReady && rs_a.RS_HeaderCnt==8);
/* Вызывает reset с аргументами ();feed(&rs_a,request,3);feed(&rs_a,request+3,5);assert(rs_a.RS_DataReady) в текущей последовательности операций. */
reset();feed(&rs_a,request,3);feed(&rs_a,request+3,5);assert(rs_a.RS_DataReady);
/* LOAD payload, including a short final chunk: nothing waits for byte 8. */
/* Записывает rs_a.RS_PrevCmd значением CMD_INITLOAD;rs_a.RS_Length=8194; данные RS_PrevCmd. */
reset();rs_a.RS_PrevCmd=CMD_INITLOAD;rs_a.RS_Length=8194;
/* Записывает rs_a.pRS_RecvPtr значением rs_a.pRecvPtr=load_memory; данные pRS_RecvPtr. */
rs_a.pRS_RecvPtr=rs_a.pRecvPtr=load_memory;
/* Записывает data[0] значением 16;data[1]=CMD_LOAD;feed(&rs_a,data,2); данные. */
data[0]=16;data[1]=CMD_LOAD;feed(&rs_a,data,2);
/* Цикл for(a=0;a<8194;a+=n) ; задаёт начальное значение, условие продолжения и шаг перебора. */
for(a=0;a<8194;a+=n) {
/* Записывает n значением 8194-a;n=n<16?n:16; данные n. */
n=8194-a;n=n<16?n:16;
/* Цикл for(i=0;i<n;i++)data[i]=(a+i)&255;; задаёт начальное значение, условие продолжения и шаг перебора. */
for(i=0;i<n;i++)data[i]=(a+i)&255;
/* Вызывает feed с аргументами (&rs_a,data,n) в текущей последовательности операций. */
feed(&rs_a,data,n);
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Вызывает assert с аргументами (rs_a.RS_DataReady && rs_a.RS_RecvLen==8194) в текущей последовательности операций. */
assert(rs_a.RS_DataReady && rs_a.RS_RecvLen==8194);
/* Цикл for(i=0;i<4097;i++)assert(load_memory[i]==(((2*i)&255)<<8 | ((2*i+1)&255)));; задаёт начальное значение, условие продолжения и шаг перебора. */
for(i=0;i<4097;i++)assert(load_memory[i]==(((2*i)&255)<<8 | ((2*i+1)&255)));
/* Записывает data[0] значением 1;data[1]=2;RS_Send(&rs_a,data,2); данные. */
reset();data[0]=1;data[1]=2;RS_Send(&rs_a,data,2);
/* Вызывает feed с аргументами (&rs_b,request,8);assert(rs_b.RS_DataReady && rs_a.fifo_tx_active) в текущей последовательности операций. */
feed(&rs_b,request,8);assert(rs_b.RS_DataReady && rs_a.fifo_tx_active);
/* Вызывает RS_FifoWait. Ожидает завершения аппаратной передачи FIFO и сдвигового регистра SCI. */
RS_FifoWait(&rs_a);
/* Записывает request[3] значением 0xC000;feed(&rs_a,request,8); данные request. */
reset();request[3]=0xC000;feed(&rs_a,request,8);
/* Вызывает assert с аргументами (!rs_a.RS_DataReady && rs_a.fifo_rx_errors==1 && rs_a.fifo_rx_guard) в текущей последовательности операций. */
assert(!rs_a.RS_DataReady && rs_a.fifo_rx_errors==1 && rs_a.fifo_rx_guard);
/* Записывает request[3] значением 0;feed(&rs_a,request,8);assert(!rs_a.RS_DataReady); данные request. */
request[3]=0;feed(&rs_a,request,8);assert(!rs_a.RS_DataReady);
/* Цикл for(i=0;i<4;i++)RS_FifoTick1ms();; задаёт начальное значение, условие продолжения и шаг перебора. */
for(i=0;i<4;i++)RS_FifoTick1ms();
/* Вызывает feed с аргументами (&rs_a,request,8);assert(rs_a.RS_DataReady) в текущей последовательности операций. */
feed(&rs_a,request,8);assert(rs_a.RS_DataReady);
/* Записывает SciaRegs.SCIFFRX.bit.RXFFOVF значением 1;RS_RX_Handler(&rs_a); данные RXFFOVF. */
reset();SciaRegs.SCIFFRX.bit.RXFFOVF=1;RS_RX_Handler(&rs_a);
/* Вызывает assert с аргументами (rs_a.fifo_overflows==1 && !rs_a.BS_LoadOK) в текущей последовательности операций. */
assert(rs_a.fifo_overflows==1 && !rs_a.BS_LoadOK);
/* Цикл for(i=0;i<4;i++)RS_FifoTick1ms();feed(&rs_a,request,8);assert(rs_a.RS_DataReady);; задаёт начальное значение, условие продолжения и шаг перебора. */
for(i=0;i<4;i++)RS_FifoTick1ms();feed(&rs_a,request,8);assert(rs_a.RS_DataReady);
/* A spurious old threshold interrupt may not finish an occupied FIFO. */
/* Вызывает reset с аргументами ();RS_Send(&rs_a,data,8);RS_TX_Handler(&rs_a);assert(rs_a.fifo_tx_active) в текущей последовательности операций. */
reset();RS_Send(&rs_a,data,8);RS_TX_Handler(&rs_a);assert(rs_a.fifo_tx_active);
/* Вызывает RS_FifoWait. Ожидает завершения аппаратной передачи FIFO и сдвигового регистра SCI. */
RS_FifoWait(&rs_a);assert(wire_count[0]==8);
/* SCI-B keeps the original RX parser and IRQ/TX path, never FIFO state. */
/* Вызывает reset с аргументами ();feed(&rs_b,request,8);assert(rs_b.RS_DataReady) в текущей последовательности операций. */
reset();feed(&rs_b,request,8);assert(rs_b.RS_DataReady);
/* Вызывает reset с аргументами ();RS_Send(&rs_b,data,2);assert(!rs_b.fifo_tx_active && length[1]==1) в текущей последовательности операций. */
reset();RS_Send(&rs_b,data,2);assert(!rs_b.fifo_tx_active && length[1]==1);
model_step(&rs_b);RS_TX_Handler(&rs_b); /* legacy RS_Wait drains final char */
model_step(&rs_b);RS_TX_Handler(&rs_b); /* legacy RS_Wait drains final char */ /* Вызывает model_step с аргументами (&rs_b);RS_TX_Handler(&rs_b) в текущей последовательности операций. */
/* Вызывает assert с аргументами (GpioDataRegs.GPBDAT.bit.GPIO34==1) в текущей последовательности операций. */
assert(GpioDataRegs.GPBDAT.bit.GPIO34==1);
/* Вызывает puts с аргументами ("PM35 RS232 FIFO: PASS (TX/RX/errors/recovery/SCI-B isolation)");return 0 в текущей последовательности операций. */
puts("PM35 RS232 FIFO: PASS (TX/RX/errors/recovery/SCI-B isolation)");return 0;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}

View File

@@ -1,48 +1,93 @@
# Проверка rs232_fifo на модели пк. Комментарии и исходный текст в UTF-8.
# Продолжает текущий вызов, список или выражение: """Exercise production RS485.c functions with FIFO register side effects."""; порядок аргументов сохраняется.
"""Exercise production RS485.c functions with FIFO register side effects."""
# Подключает модуль argparse для этой проверки или подготовки сборки.
import argparse
# Подключает модуль os для этой проверки или подготовки сборки.
import os
# Импортирует необходимые имена: from pathlib import Path.
from pathlib import Path
# Подключает модуль re для этой проверки или подготовки сборки.
import re
# Подключает модуль subprocess для этой проверки или подготовки сборки.
import subprocess
# Подключает модуль tempfile для этой проверки или подготовки сборки.
import tempfile
# Задаёт root по выражению справа; значение используется последующими операциями.
root=Path(__file__).resolve().parents[2]
# Объявляет функцию read и её входные параметры.
def read(path):
return re.sub(r'/\*.*?\*/|//[^\n]*','',path.read_bytes().decode('cp1251').replace('\r\n','\n'),flags=re.S)
# Возвращает re.sub(r'/\*.*?\*/|//[^\n]*','',path.read_bytes().decode('utf-8').replace('\r\n','\n'),flags=re.S) вызывающему коду и завершает функцию.
return re.sub(r'/\*.*?\*/|//[^\n]*','',path.read_bytes().decode('utf-8').replace('\r\n','\n'),flags=re.S)
# Задаёт source по выражению справа; значение используется последующими операциями.
source=read(root/'Source/Internal/RS485.c')
# Задаёт names по выражению справа; значение используется последующими операциями.
names=['RS_RX_Handler','RS_TX_Handler','RS_Send','RS_BSend','RS_SetBitMode',
# Продолжает текущий вызов, список или выражение: 'RS_FifoWait','RS_FifoTx','RS_FifoStart','RS_FifoAbort','RS_FifoTick1ms']; порядок аргументов сохраняется.
'RS_FifoWait','RS_FifoTx','RS_FifoStart','RS_FifoAbort','RS_FifoTick1ms']
# Задаёт prototypes по выражению справа; значение используется последующими операциями.
prototypes=[];functions=[]
# Перебирает name in names в указанном порядке.
for name in names:
# Задаёт match по выражению справа; значение используется последующими операциями.
match=re.search(r'(?:static\s+)?(?:void|int)\s+'+name+r'\([^;{}]*\)\s*\{',source)
# Проверяет обязательное условие match,name; нарушение делает тест неуспешным.
assert match,name
# Задаёт begin по выражению справа; значение используется последующими операциями.
begin=source.index('{',match.start());end=begin+1;depth=1
# Повторяет блок при выполнении depth.
while depth:
# Задаёт depth+ по выражению справа; значение используется последующими операциями.
depth+=(source[end]=='{')-(source[end]=='}');end+=1
# Продолжает текущий вызов, список или выражение: prototypes.append(source[match.start():begin]+';'); порядок аргументов сохраняется.
prototypes.append(source[match.start():begin]+';')
# Продолжает текущий вызов, список или выражение: functions.append(source[match.start():end]); порядок аргументов сохраняется.
functions.append(source[match.start():end])
# Задаёт body по выражению справа; значение используется последующими операциями.
body='\n'.join(functions)
# TI C28x char is 16 bits: 0x80..0xFF remain positive before word packing.
# Задаёт body по выражению справа; значение используется последующими операциями.
body=re.sub(r'\bchar\s+Rc;', 'unsigned int Rc;', body)
# Задаёт body по выражению справа; значение используется последующими операциями.
body=body.replace('received=rs_arr->SciRegs->SCIRXBUF.all;', 'received=model_pop(rs_arr);')
# Задаёт body по выражению справа; значение используется последующими операциями.
body=body.replace('Rc = rs_arr->SciRegs->SCIRXBUF.bit.RXDT;', 'Rc=model_pop(rs_arr);')
# Задаёт body по выражению справа; значение используется последующими операциями.
body=body.replace('rs_arr->SciRegs->SCIFFRX.bit.RXFIFORESET=0;',
# Задаёт 'model_flush(rs_arr);rs_arr->SciRegs->SCIFFRX.bit.RXFIFORESET по выражению справа; значение используется последующими операциями.
'model_flush(rs_arr);rs_arr->SciRegs->SCIFFRX.bit.RXFIFORESET=0;')
# Задаёт body по выражению справа; значение используется последующими операциями.
body=body.replace('rs_arr->SciRegs->SCICTL1.bit.SWRESET=1;',
# Задаёт 'rs_arr->SciRegs->SCIRXST.all по выражению справа; значение используется последующими операциями.
'rs_arr->SciRegs->SCIRXST.all=0;rs_arr->SciRegs->SCICTL1.bit.SWRESET=1;')
# Задаёт body по выражению справа; значение используется последующими операциями.
body=body.replace('while (!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { }',
# Продолжает текущий вызов, список или выражение: 'while (!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { model_step(rs_arr); }',1); порядок аргументов сохраняется.
'while (!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { model_step(rs_arr); }',1)
# Задаёт body по выражению справа; значение используется последующими операциями.
body=body.replace('while (!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { }',
# Продолжает текущий вызов, список или выражение: 'while (!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { model_shift(rs_arr); }'); порядок аргументов сохраняется.
'while (!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { model_shift(rs_arr); }')
# Задаёт body по выражению справа; значение используется последующими операциями.
body=body.replace('!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { }',
# Продолжает текущий вызов, список или выражение: '!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { model_step(rs_arr); }'); порядок аргументов сохраняется.
'!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { model_step(rs_arr); }')
# Задаёт header по выражению справа; значение используется последующими операциями.
header=read(root/'Source/Internal/Include/RS485.h')
# Задаёт header по выражению справа; значение используется последующими операциями.
header=re.sub(r'#define SCI_send\(x,y\)[^\n]*', '#define SCI_send(x,y) model_push(x,y)',header)
# Задаёт header по выражению справа; значение используется последующими операциями.
header=re.sub(r'#define enableUARTInt\(x\)[^\n]*', '#define enableUARTInt(x) model_interrupts(x,0)',header)
# Задаёт header по выражению справа; значение используется последующими операциями.
header=re.sub(r'#define enableUARTIntW\(x\)[^\n]*', '#define enableUARTIntW(x) model_interrupts(x,1)',header)
# Задаёт header по выражению справа; значение используется последующими операциями.
header=re.sub(r'#define Rec_Bloc_Begin[^\n]*', '#define Rec_Bloc_Begin ((uintptr_t)load_memory)',header)
# Задаёт header по выражению справа; значение используется последующими операциями.
header=re.sub(r'#define Rec_Bloc_End[^\n]*', '#define Rec_Bloc_End ((uintptr_t)(load_memory+4100))',header)
# Задаёт registers по выражению справа; значение используется последующими операциями.
registers=read(root/'Source/External/v120/DSP2833x_headers/include/DSP2833x_Sci.h')
# Задаёт defines по выражению справа; значение используется последующими операциями.
defines='''
#include <assert.h>
#include <stdio.h>
@@ -62,12 +107,21 @@ typedef unsigned short Uint16;
enum {CMD_MODBUS_3=3,ANS_MODBUS_4=4,CMD_MODBUS_6=6,CMD_MODBUS_16=16,
CMD_LOAD=51,CMD_INITLOAD=58,CMD_STD_ANS=66};
'''
harness=(Path(__file__).with_name('model.inc')).read_text()
# Читает исходный файл или образ для последующей проверки и разбора.
harness=(Path(__file__).with_name('model.inc')).read_text(encoding="utf-8")
# Задаёт before,after по выражению справа; значение используется последующими операциями.
before,after=harness.split('/* HANDLERS */')
# Задаёт parser по выражению справа; значение используется последующими операциями.
parser=argparse.ArgumentParser();parser.add_argument('--cc',required=True);args=parser.parse_args()
# Задаёт env по выражению справа; значение используется последующими операциями.
env=dict(os.environ);env['PATH']=str(Path(args.cc).parent)+os.pathsep+env.get('PATH','')
# Открывает управляемый ресурс tempfile.TemporaryDirectory(prefix='pm35-fifo-') as directory с автоматическим освобождением.
with tempfile.TemporaryDirectory(prefix='pm35-fifo-') as directory:
# Задаёт path по выражению справа; значение используется последующими операциями.
path=Path(directory);c=path/'model.c';exe=path/'model.exe'
c.write_text(defines+registers+header+'\n'.join(prototypes)+before+body+after)
# Сохраняет подготовленный файл в указанном формате для следующего шага.
c.write_text(defines+registers+header+'\n'.join(prototypes)+before+body+after, encoding="utf-8")
# Запускает внешний компилятор, генератор или тест; ненулевой результат проверяется параметрами вызова.
subprocess.run([args.cc,'-std=c99','-O1','-Werror=implicit-function-declaration',str(c),'-o',str(exe)],check=True,env=env)
# Запускает внешний компилятор, генератор или тест; ненулевой результат проверяется параметрами вызова.
subprocess.run([str(exe)],check=True,env=env,timeout=20)

View File

@@ -1,56 +1,109 @@
/* Проверка ump_logger на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Подключает "../../Source/Internal/log_to_mem.c": двухбанковый регистратор событий нагрузки во внешней RAM. */
#include "../../Source/Internal/log_to_mem.c"
/* Описывает структуру mock_gpio GpioDataRegs;; порядок полей определяет расположение данных. */
struct mock_gpio GpioDataRegs;
/* Объявляет READY — данные READY; Desk — аппаратно определённый тип платы; Mode — рабочий адрес или режим платы, выбранный перемычками. Начальное значение задаётся справа от знака равенства. */
int READY = 1, Desk = 6, Mode = 5;
/* Объявляет modbus — массив технологических регистров; слово int на C28x занимает 16 бит; CanTimeOutErrorTR — CAN Time Out ошибка TR. */
int modbus[128], CanTimeOutErrorTR;
/* Объявляет IMPowse — данные IMPowse; WAKEpowse — данные WAKEpowse. */
unsigned long IMPowse, WAKEpowse;
/* Объявляет ADC_table — АЦП table. */
unsigned int ADC_table[4];
/* Задаёт CHECK = if (!(x)) return __LINE__; данные CHECK. */
#define CHECK(x) if (!(x)) return __LINE__
/* Точка входа: настраивает периферию, загружает параметры и обслуживает команды в главном цикле. */
int main(void)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Объявляет i — данные i. */
unsigned int i;
/* Simulate COFF boot with dirty RAM, including a stale active bank. */
/* Записывает ump_state значением ump_count = ump_cursor = ump_next = 0xA5A5; данные ump_state. */
ump_state = ump_count = ump_cursor = ump_next = 0xA5A5;
/* Записывает ump_period значением ump_divider = 0xA5A5; период записи регистратора в миллисекундных тактах. */
ump_period = ump_divider = 0xA5A5;
/* Записывает ump_time значением ump_sequence = 0xA5A5A5A5UL; миллисекундное время регистратора. */
ump_time = ump_sequence = 0xA5A5A5A5UL;
/* Записывает ump_bank значением ump_archive_bank = 0xA5A5; индекс активного банка регистратора. */
ump_bank = ump_archive_bank = 0xA5A5;
/* Записывает ump_archive_count значением ump_archive_next = ump_generation = 0xA5A5; ump archive число. */
ump_archive_count = ump_archive_next = ump_generation = 0xA5A5;
/* Записывает ump_source значением ump_post = 0xA5A5; данные ump_source. */
ump_source = ump_post = 0xA5A5;
/* Записывает ump_can_header значением ump_can_count = 0xA5A5; ump CAN header. */
ump_can_header = ump_can_count = 0xA5A5;
/* Цикл for (i = 0; i < 3; i++) ump_can_data[i] = 0xA5A5;; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i = 0; i < 3; i++) ump_can_data[i] = 0xA5A5;
/* Цикл for (i = 0; i < 2; i++) ump_pm67_voltage[i] = 0xA5A5;; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i = 0; i < 2; i++) ump_pm67_voltage[i] = 0xA5A5;
/* Записывает ump_prev_commands значением ump_prev_inputs = ump_prev_outputs = 0xA5A5; данные ump_prev_commands. */
ump_prev_commands = ump_prev_inputs = ump_prev_outputs = 0xA5A5;
/* Записывает ump_dac_ramp значением ump_dac_duration = ump_dac_go10 = 0xA5A5; ump ЦАП ramp. */
ump_dac_ramp = ump_dac_duration = ump_dac_go10 = 0xA5A5;
/* Записывает ump_dac_stop10 значением ump_dac_position = 0xA5A5; ump ЦАП stop 10. */
ump_dac_stop10 = ump_dac_position = 0xA5A5;
/* Вызывает ump_log_init. Явно инициализирует оба банка регистратора до включения IRQ; повторный старт записи архив не стирает. */
ump_log_init();
/* Вызывает CHECK с аргументами (ump_log_read(UMP_LOG_BASE) == 0x554D) в текущей последовательности операций. */
CHECK(ump_log_read(UMP_LOG_BASE) == 0x554D);
/* Вызывает CHECK с аргументами (ump_log_read(UMP_LOG_BASE+1) == 3) в текущей последовательности операций. */
CHECK(ump_log_read(UMP_LOG_BASE+1) == 3);
/* Вызывает CHECK с аргументами (ump_log_read(UMP_LOG_BASE+2) == 0) в текущей последовательности операций. */
CHECK(ump_log_read(UMP_LOG_BASE+2) == 0);
/* Вызывает CHECK с аргументами (ump_log_read(UMP_LOG_BASE+3) == 0) в текущей последовательности операций. */
CHECK(ump_log_read(UMP_LOG_BASE+3) == 0);
/* Вызывает CHECK с аргументами (ump_log_read(UMP_LOG_BASE+6) == 20) в текущей последовательности операций. */
CHECK(ump_log_read(UMP_LOG_BASE+6) == 20);
/* Цикл for (i = 7; i <= 8; i++) CHECK(ump_log_read(UMP_LOG_BASE+i) == 0);; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i = 7; i <= 8; i++) CHECK(ump_log_read(UMP_LOG_BASE+i) == 0);
/* Цикл for (i = 12; i <= 15; i++) CHECK(ump_log_read(UMP_LOG_BASE+i) == 0);; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i = 12; i <= 15; i++) CHECK(ump_log_read(UMP_LOG_BASE+i) == 0);
/* Вызывает CHECK с аргументами (ump_bank == 0 && ump_archive_bank == 1) в текущей последовательности операций. */
CHECK(ump_bank == 0 && ump_archive_bank == 1);
/* Вызывает CHECK с аргументами (ump_cursor == 0 && ump_next == 0 && ump_archive_next == 0) в текущей последовательности операций. */
CHECK(ump_cursor == 0 && ump_next == 0 && ump_archive_next == 0);
/* Вызывает CHECK с аргументами (ump_divider == 0 && ump_sequence == 0 && ump_post == 0) в текущей последовательности операций. */
CHECK(ump_divider == 0 && ump_sequence == 0 && ump_post == 0);
/* Вызывает CHECK с аргументами (ump_can_header == 0 && ump_can_count == 0) в текущей последовательности операций. */
CHECK(ump_can_header == 0 && ump_can_count == 0);
/* Цикл for (i = 0; i < 3; i++) CHECK(ump_can_data[i] == 0);; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i = 0; i < 3; i++) CHECK(ump_can_data[i] == 0);
/* Цикл for (i = 0; i < 2; i++) CHECK(ump_pm67_voltage[i] == 0);; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i = 0; i < 2; i++) CHECK(ump_pm67_voltage[i] == 0);
/* Вызывает CHECK с аргументами (ump_prev_commands == 0 && ump_prev_inputs == 0 && ump_prev_outputs == 0) в текущей последовательности операций. */
CHECK(ump_prev_commands == 0 && ump_prev_inputs == 0 && ump_prev_outputs == 0);
/* Вызывает CHECK с аргументами (ump_dac_ramp == 0 && ump_dac_duration == 0 && ump_dac_go10 == 0) в текущей последовательности операций. */
CHECK(ump_dac_ramp == 0 && ump_dac_duration == 0 && ump_dac_go10 == 0);
/* Вызывает CHECK с аргументами (ump_dac_stop10 == 0 && ump_dac_position == 0) в текущей последовательности операций. */
CHECK(ump_dac_stop10 == 0 && ump_dac_position == 0);
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE+1, 20)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE+1, 20));
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE, 1)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE, 1));
/* Вызывает CHECK с аргументами (ump_state == 1 && ump_count == 1) в текущей последовательности операций. */
CHECK(ump_state == 1 && ump_count == 1);
/* Вызывает ump_log_tick. Продвигает время регистратора в Timer1 и снимает записи с заданным периодом. */
ump_log_tick();
/* Вызывает CHECK с аргументами (ump_time == 1) в текущей последовательности операций. */
CHECK(ump_time == 1);
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE, 0)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE, 0));
/* Записывает ump_archive_count значением 7; ump_generation = 2; ump archive число. */
ump_archive_count = 7; ump_generation = 2;
/* Записывает ump_pm67_voltage[0] значением 123; данные ump_pm67_voltage. */
ump_pm67_voltage[0] = 123;
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE, 1)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE, 1));
/* Вызывает CHECK с аргументами (ump_time == 1 && ump_archive_count == 7 && ump_generation == 2) в текущей последовательности операций. */
CHECK(ump_time == 1 && ump_archive_count == 7 && ump_generation == 2);
/* Вызывает CHECK с аргументами (ump_word(0, 0, 40) == 123) в текущей последовательности операций. */
CHECK(ump_word(0, 0, 40) == 123);
/* Завершает main и возвращает 0. */
return 0;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}

View File

@@ -1,163 +1,311 @@
/* Проверка ump_logger на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Подключает "../../Source/Internal/log_to_mem.c": двухбанковый регистратор событий нагрузки во внешней RAM. */
#include "../../Source/Internal/log_to_mem.c"
/* Подключает "../../Source/Internal/Include/ump_can_protocol.h": настройки и интерфейс ump_can_protocol. */
#include "../../Source/Internal/Include/ump_can_protocol.h"
/* Описывает структуру mock_gpio GpioDataRegs;; порядок полей определяет расположение данных. */
struct mock_gpio GpioDataRegs;
/* Объявляет READY — данные READY; Desk — аппаратно определённый тип платы; Mode — рабочий адрес или режим платы, выбранный перемычками. Начальное значение задаётся справа от знака равенства. */
int READY = 1, Desk = 6, Mode = 5;
/* Объявляет modbus — массив технологических регистров; слово int на C28x занимает 16 бит. */
int modbus[128];
/* Объявляет CanTimeOutErrorTR — CAN Time Out ошибка TR. */
int CanTimeOutErrorTR;
/* Объявляет IMPowse — данные IMPowse; WAKEpowse — данные WAKEpowse. */
unsigned long IMPowse, WAKEpowse;
/* Объявляет ADC_table — АЦП table. */
unsigned int ADC_table[4];
/* Задаёт CHECK = if (!(x)) return __LINE__; данные CHECK. */
#define CHECK(x) if (!(x)) return __LINE__
/* Возвращаем номер строки при ошибке, ноль при успехе; CRT не требуется. */
/* Вызывает __declspec с аргументами (dllexport) int run_tests(void) в текущей последовательности операций. */
__declspec(dllexport) int run_tests(void)
/* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */
{
/* Объявляет i — данные i; generation — данные generation; archived — данные archived; error — ошибка; length — длина. */
unsigned int i, generation, archived, error, length;
/* Объявляет reply — данные reply. */
uint16_t reply[UMP_CAN_MAX_WORDS];
/* Объявляет sequence — последовательность. */
unsigned long sequence;
/* Вызывает ump_log_init. Явно инициализирует оба банка регистратора до включения IRQ; повторный старт записи архив не стирает. */
ump_log_init();
/* Вызывает CHECK с аргументами (!ump_log_write(UMP_LOG_BASE+1, 0)) в текущей последовательности операций. */
CHECK(!ump_log_write(UMP_LOG_BASE+1, 0));
/* Вызывает CHECK с аргументами (!ump_log_write(UMP_LOG_BASE+1, 1001)) в текущей последовательности операций. */
CHECK(!ump_log_write(UMP_LOG_BASE+1, 1001));
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE+1, 1)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE+1, 1));
/* Записывает modbus[127] значением 0x80; массив технологических регистров; слово int на C28x занимает 16 бит. */
modbus[127] = 0x80;
/* Записывает modbus[0x50] значением 6; modbus[0x51] = 16; массив технологических регистров; слово int на C28x занимает 16 бит. */
modbus[0x50] = 6; modbus[0x51] = 16;
/* Записывает modbus[0x7B] значением 1234; modbus[0x1C] = 160; массив технологических регистров; слово int на C28x занимает 16 бит. */
modbus[0x7B] = 1234; modbus[0x1C] = 160;
/* PM67 reception is independent of recording; all three CAN slots work. */
/* Вызывает ump_log_can. Обновляет последние CAN-данные и напряжения для следующего снимка регистратора. */
ump_log_can(0x8000U | 305U, 0xFEDCU, 0, 0);
/* Вызывает ump_log_can. Обновляет последние CAN-данные и напряжения для следующего снимка регистратора. */
ump_log_can(0x4000U | 7U, 0, 456, 0);
/* Вызывает CHECK с аргументами (ump_pm67_voltage[0] == 0xFEDCU && ump_pm67_voltage[1] == 456) в текущей последовательности операций. */
CHECK(ump_pm67_voltage[0] == 0xFEDCU && ump_pm67_voltage[1] == 456);
ump_log_can(305U, 1, 2, 3); /* Masked-out word must not overwrite. */
ump_log_can(305U, 1, 2, 3); /* Masked-out word must not overwrite. */ /* Вызывает ump_log_can. Обновляет последние CAN-данные и напряжения для следующего снимка регистратора. */
/* Вызывает ump_log_can. Обновляет последние CAN-данные и напряжения для следующего снимка регистратора. */
ump_log_can(0x2000U | 303U, 0, 0, 123);
/* Вызывает ump_log_can. Обновляет последние CAN-данные и напряжения для следующего снимка регистратора. */
ump_log_can(0x2000U | 6U, 0, 0, 789);
/* Вызывает CHECK с аргументами (ump_pm67_voltage[0] == 123 && ump_pm67_voltage[1] == 789) в текущей последовательности операций. */
CHECK(ump_pm67_voltage[0] == 123 && ump_pm67_voltage[1] == 789);
ump_log_can(0x8000U | 306U, 999, 0, 0); /* Not a one-based CAN address. */
ump_log_can(0x8000U | 306U, 999, 0, 0); /* Not a one-based CAN address. */ /* Вызывает ump_log_can. Обновляет последние CAN-данные и напряжения для следующего снимка регистратора. */
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE, 1)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE, 1));
/* Вызывает CHECK с аргументами (ump_word(0, 0, 40) == 123 && ump_word(0, 0, 41) == 789) в текущей последовательности операций. */
CHECK(ump_word(0, 0, 40) == 123 && ump_word(0, 0, 41) == 789);
/* Вызывает CHECK с аргументами (2UL * UMP_LOG_CAPACITY * UMP_LOG_WORDS <= LOG_PAGE_LEN) в текущей последовательности операций. */
CHECK(2UL * UMP_LOG_CAPACITY * UMP_LOG_WORDS <= LOG_PAGE_LEN);
/* Вызывает CHECK с аргументами (!ump_log_write(UMP_LOG_BASE, 1)) в текущей последовательности операций. */
CHECK(!ump_log_write(UMP_LOG_BASE, 1));
/* Вызывает CHECK с аргументами (!ump_log_write(UMP_LOG_BASE+1, 20)) в текущей последовательности операций. */
CHECK(!ump_log_write(UMP_LOG_BASE+1, 20));
/* Цикл for (i=0; i<900; i++) ump_log_tick();; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i=0; i<900; i++) ump_log_tick();
/* Вызывает CHECK с аргументами (ump_count == UMP_LOG_CAPACITY) в текущей последовательности операций. */
CHECK(ump_count == UMP_LOG_CAPACITY);
/* Вызывает CHECK с аргументами (ump_word(0, 0, 0) == 901-UMP_LOG_CAPACITY) в текущей последовательности операций. */
CHECK(ump_word(0, 0, 0) == 901-UMP_LOG_CAPACITY);
/* Вызывает CHECK с аргументами (ump_word(0, UMP_LOG_CAPACITY-1, 0) == 900) в текущей последовательности операций. */
CHECK(ump_word(0, UMP_LOG_CAPACITY-1, 0) == 900);
/* Вызывает CHECK с аргументами (ump_word(0, 0, 8) == 1234) в текущей последовательности операций. */
CHECK(ump_word(0, 0, 8) == 1234);
/* Вызывает CHECK с аргументами (ump_word(0, 0, 24) == 6) в текущей последовательности операций. */
CHECK(ump_word(0, 0, 24) == 6);
/* Короткая CAN-команда должна остаться отдельным событием. */
/* Записывает modbus[127] значением 0x40; массив технологических регистров; слово int на C28x занимает 16 бит. */
modbus[127] = 0x40;
/* Вызывает ump_log_can. Обновляет последние CAN-данные и напряжения для следующего снимка регистратора. */
ump_log_can(0x807F, 0x40, 0, 0);
CHECK(ump_post == 0); /* A command alone is not an output transition. */
CHECK(ump_post == 0); /* A command alone is not an output transition. */ /* Вызывает CHECK с аргументами (ump_post == 0) в текущей последовательности операций. */
/* Записывает GpioDataRegs.GPBDAT.bit.GPIO58 значением 1; аппаратная линия ввода/вывода GPIO58. */
GpioDataRegs.GPBDAT.bit.GPIO58 = 1;
ump_log_io(); /* STOP may be sampled before RES_OUT_2 is cleared. */
ump_log_io(); /* STOP may be sampled before RES_OUT_2 is cleared. */ /* Вызывает ump_log_io. Обслуживает изменения дискретных входов и выходов из главного цикла. */
/* Вызывает CHECK с аргументами (ump_post == 0) в текущей последовательности операций. */
CHECK(ump_post == 0);
/* Записывает GpioDataRegs.GPADAT.bit.GPIO3 значением 1; аппаратная линия ввода/вывода GPIO3. */
GpioDataRegs.GPADAT.bit.GPIO3 = 1;
/* Вызывает ump_log_io. Обслуживает изменения дискретных входов и выходов из главного цикла. */
ump_log_io();
/* Вызывает CHECK с аргументами (ump_post == UMP_POST_POINTS) в текущей последовательности операций. */
CHECK(ump_post == UMP_POST_POINTS);
/* Вызывает CHECK с аргументами (ump_word(0, ump_count-1, 2) == 0x103) в текущей последовательности операций. */
CHECK(ump_word(0, ump_count-1, 2) == 0x103);
/* Вызывает CHECK с аргументами (ump_word(0, ump_count-1, 18) == 0x807F) в текущей последовательности операций. */
CHECK(ump_word(0, ump_count-1, 18) == 0x807F);
/* Цикл for (i=0; i<UMP_POST_POINTS-1; i++) ump_log_tick();; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i=0; i<UMP_POST_POINTS-1; i++) ump_log_tick();
/* Вызывает CHECK с аргументами (ump_generation == 0) в текущей последовательности операций. */
CHECK(ump_generation == 0);
/* Вызывает ump_log_tick. Продвигает время регистратора в Timer1 и снимает записи с заданным периодом. */
ump_log_tick();
/* Вызывает CHECK с аргументами (ump_generation == 1) в текущей последовательности операций. */
CHECK(ump_generation == 1);
/* Вызывает CHECK с аргументами (ump_archive_count == UMP_LOG_CAPACITY) в текущей последовательности операций. */
CHECK(ump_archive_count == UMP_LOG_CAPACITY);
/* Вызывает CHECK с аргументами (ump_word(1, UMP_LOG_CAPACITY-UMP_POST_POINTS-1, 2) == 0x103) в текущей последовательности операций. */
CHECK(ump_word(1, UMP_LOG_CAPACITY-UMP_POST_POINTS-1, 2) == 0x103);
/* Вызывает CHECK с аргументами (ump_word(1, UMP_LOG_CAPACITY-1, 2) == 5) в текущей последовательности операций. */
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 2) == 5);
/* Вызывает CHECK с аргументами (ump_count == 0 && ump_state == 1) в текущей последовательности операций. */
CHECK(ump_count == 0 && ump_state == 1);
/* Вызывает CHECK с аргументами (ump_word(1, UMP_LOG_CAPACITY-1, 40) == 123) в текущей последовательности операций. */
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 40) == 123);
/* Вызывает CHECK с аргументами (ump_word(1, UMP_LOG_CAPACITY-1, 41) == 789) в текущей последовательности операций. */
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 41) == 789);
/* Вызывает ump_log_can. Обновляет последние CAN-данные и напряжения для следующего снимка регистратора. */
ump_log_can(0x8000U | 305U, 999, 0, 0);
/* Вызывает CHECK с аргументами (ump_word(0, ump_count-1, 40) == 999) в текущей последовательности операций. */
CHECK(ump_word(0, ump_count-1, 40) == 999);
/* Вызывает CHECK с аргументами (ump_word(1, UMP_LOG_CAPACITY-1, 40) == 123) в текущей последовательности операций. */
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 40) == 123);
/* Записывает generation значением ump_generation; данные generation. */
generation = ump_generation;
/* Записывает archived значением ump_word(1, UMP_LOG_CAPACITY-1, 0); данные archived. */
archived = ump_word(1, UMP_LOG_CAPACITY-1, 0);
/* Записывает sequence значением ump_sequence; последовательность. */
sequence = ump_sequence;
/* Цикл for (i=0; i<200; i++) ump_log_tick();; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i=0; i<200; i++) ump_log_tick();
/* Вызывает CHECK с аргументами (ump_word(1, UMP_LOG_CAPACITY-1, 0) == archived) в текущей последовательности операций. */
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 0) == archived);
/* Вызывает CHECK с аргументами (ump_generation == generation) в текущей последовательности операций. */
CHECK(ump_generation == generation);
/* Вызывает CHECK с аргументами (ump_sequence == sequence + 200) в текущей последовательности операций. */
CHECK(ump_sequence == sequence + 200);
/* Вызывает CHECK с аргументами (ump_log_read(UMP_LOG_LIVE+2) == UMP_LOG_LIVE_RECORDS) в текущей последовательности операций. */
CHECK(ump_log_read(UMP_LOG_LIVE+2) == UMP_LOG_LIVE_RECORDS);
/* Вызывает CHECK с аргументами (ump_log_read(UMP_LOG_LIVE+4) == ump_time-(UMP_LOG_LIVE_RECORDS-1)) в текущей последовательности операций. */
CHECK(ump_log_read(UMP_LOG_LIVE+4) == ump_time-(UMP_LOG_LIVE_RECORDS-1));
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE+3, 1)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE+3, 1));
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE+2, UMP_LOG_CAPACITY-1)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE+2, UMP_LOG_CAPACITY-1));
/* Вызывает CHECK с аргументами (ump_log_read(UMP_LOG_DATA) == archived) в текущей последовательности операций. */
CHECK(ump_log_read(UMP_LOG_DATA) == archived);
/* Вызывает CHECK с аргументами (ump_log_read(UMP_LOG_DATA+UMP_LOG_WORDS) == 0) в текущей последовательности операций. */
CHECK(ump_log_read(UMP_LOG_DATA+UMP_LOG_WORDS) == 0);
/* Вызывает CHECK с аргументами (!ump_log_write(UMP_LOG_BASE+2, UMP_LOG_CAPACITY)) в текущей последовательности операций. */
CHECK(!ump_log_write(UMP_LOG_BASE+2, UMP_LOG_CAPACITY));
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE, 0)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE, 0));
/* Записывает sequence значением ump_sequence; последовательность. */
sequence = ump_sequence;
/* Вызывает ump_log_tick. Продвигает время регистратора в Timer1 и снимает записи с заданным периодом. */
ump_log_tick(); ump_log_io(); ump_log_can(1,2,3,4);
/* Вызывает CHECK с аргументами (sequence == ump_sequence) в текущей последовательности операций. */
CHECK(sequence == ump_sequence);
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE, 1)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE, 1));
/* Вызывает CHECK с аргументами (ump_word(1, UMP_LOG_CAPACITY-1, 0) == archived) в текущей последовательности операций. */
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 0) == archived);
/* Repeated reset/STOP pulses beyond the post interval preserve archive. */
/* Цикл for (i=0; i<3; i++) ; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i=0; i<3; i++) {
/* Записывает modbus[127] значением 0; GpioDataRegs.GPBDAT.bit.GPIO58 = 0; ump_log_io(); массив технологических регистров; слово int на C28x занимает 16 бит. */
modbus[127] = 0; GpioDataRegs.GPBDAT.bit.GPIO58 = 0; ump_log_io();
/* Записывает modbus[127] значением 0x40; ump_log_can(0x807F, 0x40, 0, 0); массив технологических регистров; слово int на C28x занимает 16 бит. */
modbus[127] = 0x40; ump_log_can(0x807F, 0x40, 0, 0);
/* Записывает GpioDataRegs.GPBDAT.bit.GPIO58 значением 1; ump_log_io(); аппаратная линия ввода/вывода GPIO58. */
GpioDataRegs.GPBDAT.bit.GPIO58 = 1; ump_log_io();
/* Вызывает CHECK с аргументами (ump_post == 0) в текущей последовательности операций. */
CHECK(ump_post == 0);
/* Записывает tick значением 0; tick<1100; tick++) ump_log_tick(); }; данные tick. */
{ unsigned int tick; for (tick=0; tick<1100; tick++) ump_log_tick(); }
/* Вызывает CHECK с аргументами (ump_generation == generation) в текущей последовательности операций. */
CHECK(ump_generation == generation);
/* Вызывает CHECK с аргументами (ump_word(1, UMP_LOG_CAPACITY-1, 0) == archived) в текущей последовательности операций. */
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 0) == archived);
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}
/* Falling start alone does not freeze; a new real cycle does. */
/* Записывает modbus[127] значением 0x80; ump_log_rs(); массив технологических регистров; слово int на C28x занимает 16 бит. */
modbus[127] = 0x80; ump_log_rs();
/* Записывает GpioDataRegs.GPBDAT.bit.GPIO58 значением 0; аппаратная линия ввода/вывода GPIO58. */
GpioDataRegs.GPBDAT.bit.GPIO58 = 0;
/* Записывает GpioDataRegs.GPADAT.bit.GPIO3 значением 0; ump_log_io(); аппаратная линия ввода/вывода GPIO3. */
GpioDataRegs.GPADAT.bit.GPIO3 = 0; ump_log_io();
/* Записывает modbus[127] значением 0; ump_log_rs(); массив технологических регистров; слово int на C28x занимает 16 бит. */
modbus[127] = 0; ump_log_rs();
/* Вызывает CHECK с аргументами (ump_post == 0) в текущей последовательности операций. */
CHECK(ump_post == 0);
/* Записывает GpioDataRegs.GPBDAT.bit.GPIO58 значением 1; аппаратная линия ввода/вывода GPIO58. */
GpioDataRegs.GPBDAT.bit.GPIO58 = 1;
/* Записывает GpioDataRegs.GPADAT.bit.GPIO3 значением 1; ump_log_io(); аппаратная линия ввода/вывода GPIO3. */
GpioDataRegs.GPADAT.bit.GPIO3 = 1; ump_log_io();
/* Вызывает CHECK с аргументами (ump_post == UMP_POST_POINTS) в текущей последовательности операций. */
CHECK(ump_post == UMP_POST_POINTS);
/* Цикл for (i=0; i<UMP_POST_POINTS; i++) ump_log_tick();; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i=0; i<UMP_POST_POINTS; i++) ump_log_tick();
/* Вызывает CHECK с аргументами (ump_generation == generation+1) в текущей последовательности операций. */
CHECK(ump_generation == generation+1);
/* A RES_OUT_2 fall without STOP is not a shutdown trigger. */
/* Записывает generation значением ump_generation; данные generation. */
generation = ump_generation;
/* Записывает GpioDataRegs.GPBDAT.bit.GPIO58 значением 0; аппаратная линия ввода/вывода GPIO58. */
GpioDataRegs.GPBDAT.bit.GPIO58 = 0;
/* Записывает GpioDataRegs.GPADAT.bit.GPIO3 значением 0; ump_log_io(); аппаратная линия ввода/вывода GPIO3. */
GpioDataRegs.GPADAT.bit.GPIO3 = 0; ump_log_io();
/* Записывает GpioDataRegs.GPADAT.bit.GPIO3 значением 1; ump_log_io(); аппаратная линия ввода/вывода GPIO3. */
GpioDataRegs.GPADAT.bit.GPIO3 = 1; ump_log_io();
/* Вызывает CHECK с аргументами (ump_post == 0) в текущей последовательности операций. */
CHECK(ump_post == 0);
/* Starting the recorder with stopped outputs must not invent an edge. */
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE, 0)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE, 0));
/* Записывает GpioDataRegs.GPBDAT.bit.GPIO58 значением 1; аппаратная линия ввода/вывода GPIO58. */
GpioDataRegs.GPBDAT.bit.GPIO58 = 1;
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE, 1)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE, 1));
/* Вызывает CHECK с аргументами (ump_post == 0 && ump_generation == generation) в текущей последовательности операций. */
CHECK(ump_post == 0 && ump_generation == generation);
/* At a slow sample period time alone cannot finish the point budget.
* CAN and RS records count, and repeated edges do not restart it. */
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE, 0)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE, 0));
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE+1, 1000)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE+1, 1000));
/* Вызывает CHECK с аргументами (ump_log_write(UMP_LOG_BASE, 1)) в текущей последовательности операций. */
CHECK(ump_log_write(UMP_LOG_BASE, 1));
/* Записывает GpioDataRegs.GPADAT.bit.GPIO3 значением 0; ump_log_io(); аппаратная линия ввода/вывода GPIO3. */
GpioDataRegs.GPADAT.bit.GPIO3 = 0; ump_log_io();
/* Записывает GpioDataRegs.GPADAT.bit.GPIO3 значением 1; ump_log_io(); аппаратная линия ввода/вывода GPIO3. */
GpioDataRegs.GPADAT.bit.GPIO3 = 1; ump_log_io();
/* Вызывает CHECK с аргументами (ump_post == UMP_POST_POINTS) в текущей последовательности операций. */
CHECK(ump_post == UMP_POST_POINTS);
/* Цикл for (i=0; i<1000; i++) ump_log_tick();; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i=0; i<1000; i++) ump_log_tick();
/* Вызывает CHECK с аргументами (ump_post == UMP_POST_POINTS-1 && ump_generation == generation) в текущей последовательности операций. */
CHECK(ump_post == UMP_POST_POINTS-1 && ump_generation == generation);
/* Записывает GpioDataRegs.GPADAT.bit.GPIO3 значением 0; ump_log_io(); аппаратная линия ввода/вывода GPIO3. */
GpioDataRegs.GPADAT.bit.GPIO3 = 0; ump_log_io();
/* Записывает GpioDataRegs.GPADAT.bit.GPIO3 значением 1; ump_log_io(); аппаратная линия ввода/вывода GPIO3. */
GpioDataRegs.GPADAT.bit.GPIO3 = 1; ump_log_io();
/* Вызывает CHECK с аргументами (ump_post == UMP_POST_POINTS-3) в текущей последовательности операций. */
CHECK(ump_post == UMP_POST_POINTS-3);
/* Цикл for (i=0; i<UMP_POST_POINTS-4; i++) ump_log_can(0x807F, 0, 0, 0);; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i=0; i<UMP_POST_POINTS-4; i++) ump_log_can(0x807F, 0, 0, 0);
/* Вызывает CHECK с аргументами (ump_post == 1 && ump_generation == generation) в текущей последовательности операций. */
CHECK(ump_post == 1 && ump_generation == generation);
/* Вызывает ump_log_rs. Регистрирует изменение слова команд после записи по последовательному интерфейсу. */
ump_log_rs();
/* Вызывает CHECK с аргументами (ump_post == 0 && ump_generation == generation+1) в текущей последовательности операций. */
CHECK(ump_post == 0 && ump_generation == generation+1);
/* Вызывает CHECK с аргументами (ump_archive_count == UMP_POST_POINTS+3) в текущей последовательности операций. */
CHECK(ump_archive_count == UMP_POST_POINTS+3);
/* CAN читает те же регистры и формирует цельный снимок из 124 слов.
* Запись по старым технологическим адресам через сервис запрещена. */
/* Записывает length значением ump_can_prepare(3, UMP_LOG_BASE, 16, reply, &error); длина. */
length = ump_can_prepare(3, UMP_LOG_BASE, 16, reply, &error);
/* Вызывает CHECK с аргументами (!error && length == 16 && reply[0] == 0x554D && reply[1] == 3) в текущей последовательности операций. */
CHECK(!error && length == 16 && reply[0] == 0x554D && reply[1] == 3);
/* Записывает length значением ump_can_prepare(3, UMP_LOG_LIVE, 124, reply, &error); длина. */
length = ump_can_prepare(3, UMP_LOG_LIVE, 124, reply, &error);
/* Вызывает CHECK с аргументами (!error && length == 124) в текущей последовательности операций. */
CHECK(!error && length == 124);
/* Вызывает CHECK с аргументами (reply[2] <= UMP_LOG_LIVE_RECORDS) в текущей последовательности операций. */
CHECK(reply[2] <= UMP_LOG_LIVE_RECORDS);
/* Цикл for (i=4+reply[2]*UMP_LOG_WORDS; i<124; i++) CHECK(reply[i] == 0);; задаёт начальное значение, условие продолжения и шаг перебора. */
for (i=4+reply[2]*UMP_LOG_WORDS; i<124; i++) CHECK(reply[i] == 0);
/* Записывает length значением ump_can_prepare(3, UMP_LOG_DATA, 84, reply, &error); длина. */
length = ump_can_prepare(3, UMP_LOG_DATA, 84, reply, &error);
/* Вызывает CHECK с аргументами (!error && length == 84) в текущей последовательности операций. */
CHECK(!error && length == 84);
/* Записывает length значением ump_can_prepare(3, UMP_LOG_DATA, 42, reply, &error); длина. */
length = ump_can_prepare(3, UMP_LOG_DATA, 42, reply, &error);
/* Вызывает CHECK с аргументами (!error && length == 42) в текущей последовательности операций. */
CHECK(!error && length == 42);
/* Вызывает ump_can_prepare с аргументами (3, UMP_LOG_LIVE, 126, reply, &error) в текущей последовательности операций. */
ump_can_prepare(3, UMP_LOG_LIVE, 126, reply, &error);
/* Вызывает CHECK с аргументами (error == 2) в текущей последовательности операций. */
CHECK(error == 2);
/* Вызывает ump_can_prepare с аргументами (6, 127, 0x80, reply, &error) в текущей последовательности операций. */
ump_can_prepare(6, 127, 0x80, reply, &error);
/* Вызывает CHECK с аргументами (error == 2 && modbus[127] == 0) в текущей последовательности операций. */
CHECK(error == 2 && modbus[127] == 0);
/* Записывает length значением ump_can_prepare(6, UMP_LOG_BASE, 0, reply, &error); длина. */
length = ump_can_prepare(6, UMP_LOG_BASE, 0, reply, &error);
/* Вызывает CHECK с аргументами (!error && length == 2 && reply[0] == UMP_LOG_BASE && reply[1] == 0) в текущей последовательности операций. */
CHECK(!error && length == 2 && reply[0] == UMP_LOG_BASE && reply[1] == 0);
/* Вызывает CHECK с аргументами (ump_state == 3) в текущей последовательности операций. */
CHECK(ump_state == 3);
/* Вызывает ump_can_prepare с аргументами (6, UMP_LOG_BASE+1, 0, reply, &error) в текущей последовательности операций. */
ump_can_prepare(6, UMP_LOG_BASE+1, 0, reply, &error);
/* Вызывает CHECK с аргументами (error == 3) в текущей последовательности операций. */
CHECK(error == 3);
/* Вызывает ump_can_prepare с аргументами (99, UMP_LOG_BASE, 16, reply, &error) в текущей последовательности операций. */
ump_can_prepare(99, UMP_LOG_BASE, 16, reply, &error);
/* Вызывает CHECK с аргументами (error == 1) в текущей последовательности операций. */
CHECK(error == 1);
/* Завершает функцию и возвращает 0. */
return 0;
/* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */
}

View File

@@ -1,35 +1,66 @@
# Проверка ump_logger на модели пк. Комментарии и исходный текст в UTF-8.
# Продолжает текущий вызов, список или выражение: """Boot regression independent of the external shared protocol checkout.; порядок аргументов сохраняется.
"""Boot regression independent of the external shared protocol checkout.
Run with GCC in PATH: python tests/ump_logger/run_init_test.py
The negative control must fail without the boot initialization call.
"""
# Подключает модуль os для этой проверки или подготовки сборки.
import os
# Импортирует необходимые имена: from pathlib import Path.
from pathlib import Path
# Подключает модуль subprocess для этой проверки или подготовки сборки.
import subprocess
# Подключает модуль tempfile для этой проверки или подготовки сборки.
import tempfile
# Задаёт root по выражению справа; значение используется последующими операциями.
root = Path(__file__).resolve().parents[2]
# Задаёт source по выражению справа; значение используется последующими операциями.
source = root / 'tests/ump_logger/init_test.c'
# Задаёт compiler по выражению справа; значение используется последующими операциями.
compiler = os.environ.get('CC', 'gcc')
# Открывает управляемый ресурс tempfile.TemporaryDirectory(prefix='ump-init-') as directory с автоматическим освобождением.
with tempfile.TemporaryDirectory(prefix='ump-init-') as directory:
# Задаёт directory по выражению справа; значение используется последующими операциями.
directory = Path(directory)
text = source.read_text().replace(
# Читает исходный файл или образ для последующей проверки и разбора.
text = source.read_text(encoding="utf-8").replace(
# Продолжает текущий вызов, список или выражение: '../../Source/Internal/log_to_mem.c',; порядок аргументов сохраняется.
'../../Source/Internal/log_to_mem.c',
# Продолжает текущий вызов, список или выражение: (root / 'Source/Internal/log_to_mem.c').as_posix(),; порядок аргументов сохраняется.
(root / 'Source/Internal/log_to_mem.c').as_posix(),
# Продолжает текущий вызов, список или выражение: ); порядок аргументов сохраняется.
)
# Перебирает initialize in (False, True) в указанном порядке.
for initialize in (False, True):
# Задаёт case по выражению справа; значение используется последующими операциями.
case = directory / 'init_test.c'
case.write_text(text if initialize else text.replace('ump_log_init();', ';'))
# Сохраняет подготовленный файл в указанном формате для следующего шага.
case.write_text(text if initialize else text.replace('ump_log_init();', ';'), encoding="utf-8")
# Задаёт executable по выражению справа; значение используется последующими операциями.
executable = directory / 'init_test.exe'
# Запускает внешний компилятор, генератор или тест; ненулевой результат проверяется параметрами вызова.
subprocess.run([
# Продолжает текущий вызов, список или выражение: compiler, '-Wno-unknown-pragmas', '-Wno-int-to-pointer-cast',; порядок аргументов сохраняется.
compiler, '-Wno-unknown-pragmas', '-Wno-int-to-pointer-cast',
# Продолжает текущий вызов, список или выражение: '-I' + str(root / 'tests/ump_logger/stubs'),; порядок аргументов сохраняется.
'-I' + str(root / 'tests/ump_logger/stubs'),
# Продолжает текущий вызов, список или выражение: '-I' + str(root / 'Source/Internal/Include'),; порядок аргументов сохраняется.
'-I' + str(root / 'Source/Internal/Include'),
# Продолжает текущий вызов, список или выражение: str(case), '-o', str(executable),; порядок аргументов сохраняется.
str(case), '-o', str(executable),
# Задаёт ], check по выражению справа; значение используется последующими операциями.
], check=True)
# Запускает внешний компилятор, генератор или тест; ненулевой результат проверяется параметрами вызова.
result = subprocess.run([str(executable)])
# Проверяет условие if initialize перед выполнением следующего блока.
if initialize:
# Проверяет обязательное условие result.returncode == 0, f'Initialization failed: {result.returncode}'; нарушение делает тест неуспешным.
assert result.returncode == 0, f'Initialization failed: {result.returncode}'
# Обрабатывает альтернативу предыдущего условия.
else:
# Проверяет обязательное условие result.returncode != 0, 'Negative control unexpectedly passed'; нарушение делает тест неуспешным.
assert result.returncode != 0, 'Negative control unexpectedly passed'
# Продолжает текущий вызов, список или выражение: print(f'{"Initialized boot" if initialize else "Dirty RAM negative control"}: PASS'); порядок аргументов сохраняется.
print(f'{"Initialized boot" if initialize else "Dirty RAM negative control"}: PASS')

View File

@@ -1,41 +1,76 @@
# Проверка ump_logger на модели пк. Комментарии и исходный текст в UTF-8.
# Продолжает текущий вызов, список или выражение: """Сборка и запуск исходного регистратора с подменой GPIO/IRQ на Windows.; порядок аргументов сохраняется.
"""Сборка и запуск исходного регистратора с подменой GPIO/IRQ на Windows.
Нужны GCC либо Clang и lld-link в PATH. TEMPLATES_ROOT задаёт библиотеку. Проверяется алгоритм, но не ABI и тайминги TI.
DLL создаётся во временной папке; исходные .out/.hex прошивки не затрагиваются.
"""
# Подключает модуль ctypes для этой проверки или подготовки сборки.
import ctypes
# Подключает модуль os для этой проверки или подготовки сборки.
import os
# Импортирует необходимые имена: from pathlib import Path.
from pathlib import Path
# Подключает модуль subprocess для этой проверки или подготовки сборки.
import subprocess
# Подключает модуль shutil для этой проверки или подготовки сборки.
import shutil
# Подключает модуль tempfile для этой проверки или подготовки сборки.
import tempfile
# Задаёт root по выражению справа; значение используется последующими операциями.
root = Path(__file__).resolve().parents[2]
# Задаёт templates по выражению справа; значение используется последующими операциями.
templates = Path(os.environ.get('TEMPLATES_ROOT', root.parent / 'newProject/SETGUI/third_party/templates'))
# Задаёт protocol по выражению справа; значение используется последующими операциями.
protocol = templates / 'c/set-protocol'
# Задаёт compiler по выражению справа; значение используется последующими операциями.
compiler = os.environ.get('CC') or shutil.which('clang') or shutil.which('gcc')
# Проверяет условие if not compiler перед выполнением следующего блока.
if not compiler:
# Останавливает текущую операцию с исключением SystemExit('Clang or GCC is required in PATH').
raise SystemExit('Clang or GCC is required in PATH')
# Задаёт link_flags по выражению справа; значение используется последующими операциями.
link_flags = [] if 'gcc' in Path(compiler).name else ['-nostdlib', '-fuse-ld=lld', '-Wl,/noentry,/nodefaultlib']
# Открывает управляемый ресурс tempfile.TemporaryDirectory(prefix='ump-recorder-') as directory с автоматическим освобождением.
with tempfile.TemporaryDirectory(prefix='ump-recorder-') as directory:
# Exercise the production identity binding too, using a build-local header.
# Запускает внешний компилятор, генератор или тест; ненулевой результат проверяется параметрами вызова.
subprocess.run([
# Продолжает текущий вызов, список или выражение: os.sys.executable, str(root / 'UKSSTMS320F28335/prepare_identity.py'),; порядок аргументов сохраняется.
os.sys.executable, str(root / 'UKSSTMS320F28335/prepare_identity.py'),
# Продолжает текущий вызов, список или выражение: '--project', str(root / 'UKSSTMS320F28335'), '--templates', str(templates),; порядок аргументов сохраняется.
'--project', str(root / 'UKSSTMS320F28335'), '--templates', str(templates),
# Продолжает текущий вызов, список или выражение: '--output', directory,; порядок аргументов сохраняется.
'--output', directory,
# Задаёт ], check по выражению справа; значение используется последующими операциями.
], check=True)
# Задаёт library по выражению справа; значение используется последующими операциями.
library = Path(directory) / 'recorder_test.dll'
# Запускает внешний компилятор, генератор или тест; ненулевой результат проверяется параметрами вызова.
subprocess.run([
# Продолжает текущий вызов, список или выражение: compiler, '-shared', *link_flags, '-Wno-unknown-pragmas', '-Wno-int-to-pointer-cast',; порядок аргументов сохраняется.
compiler, '-shared', *link_flags, '-Wno-unknown-pragmas', '-Wno-int-to-pointer-cast',
# Продолжает текущий вызов, список или выражение: '-Itests/ump_logger/stubs', '-ISource/Internal/Include',; порядок аргументов сохраняется.
'-Itests/ump_logger/stubs', '-ISource/Internal/Include',
# Продолжает текущий вызов, список или выражение: '-I' + str(protocol), '-I' + str(protocol / 'ports/tms320f28335'),; порядок аргументов сохраняется.
'-I' + str(protocol), '-I' + str(protocol / 'ports/tms320f28335'),
# Продолжает текущий вызов, список или выражение: '-I' + str(templates / 'c/firmware-info/include'), '-I' + directory,; порядок аргументов сохраняется.
'-I' + str(templates / 'c/firmware-info/include'), '-I' + directory,
# Продолжает текущий вызов, список или выражение: 'tests/ump_logger/recorder_test.c', 'Source/Internal/shared_ump.c', '-o', str(library),; порядок аргументов сохраняется.
'tests/ump_logger/recorder_test.c', 'Source/Internal/shared_ump.c', '-o', str(library),
# Задаёт ], cwd по выражению справа; значение используется последующими операциями.
], cwd=root, check=True)
# Отдельный процесс освобождает DLL до удаления временной папки Windows.
# Запускает внешний компилятор, генератор или тест; ненулевой результат проверяется параметрами вызова.
subprocess.run([
# Продолжает текущий вызов, список или выражение: os.sys.executable, '-c',; порядок аргументов сохраняется.
os.sys.executable, '-c',
# Задаёт 'import ctypes,sys; r по выражению справа; значение используется последующими операциями.
'import ctypes,sys; r=ctypes.CDLL(sys.argv[1]).run_tests(); '
# Задаёт 'print("PASS" if r по выражению справа; значение используется последующими операциями.
'print("PASS" if r==0 else f"FAIL: C line {r}"); sys.exit(bool(r))',
# Продолжает текущий вызов, список или выражение: str(library),; порядок аргументов сохраняется.
str(library),
# Задаёт ], check по выражению справа; значение используется последующими операциями.
], check=True)

View File

@@ -1 +1,3 @@
/* Проверка ump_logger/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Объявляет ADC_table — АЦП table. Память определена в другом модуле. */
extern unsigned int ADC_table[4];

View File

@@ -1 +1,3 @@
/* Проверка ump_logger/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Объявляет IMPowse — данные IMPowse; WAKEpowse — данные WAKEpowse. Память определена в другом модуле. */
extern unsigned long IMPowse, WAKEpowse;

View File

@@ -1,9 +1,19 @@
/* Проверка ump_logger/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Начинает условие: UMP_TEST_DEVICE_H ещё не определён; защищает повторное включение или задаёт значение сборки. */
#ifndef UMP_TEST_DEVICE_H
/* Определяет защитный символ или переключатель UMP_TEST_DEVICE_H для последующей компиляции. */
#define UMP_TEST_DEVICE_H
/* Описывает структуру mock_bits; порядок полей определяет расположение данных. */
struct mock_bits { unsigned int GPIO3, GPIO6, GPIO8, GPIO11, GPIO58, GPIO62; };
/* Описывает структуру mock_reg; порядок полей определяет расположение данных. */
struct mock_reg { struct mock_bits bit; };
/* Описывает структуру mock_gpio; порядок полей определяет расположение данных. */
struct mock_gpio { struct mock_reg GPADAT, GPBDAT; };
/* Продолжает список аргументов, полей или выражение extern struct mock_gpio GpioDataRegs;; порядок элементов сохраняется. */
extern struct mock_gpio GpioDataRegs;
/* Начинает функцию __disable_interrupts; назначение модуля — проверка ump_logger/stubs на модели ПК. */
static unsigned int __disable_interrupts(void) { return 0; }
/* Начинает функцию __restore_interrupts; назначение модуля — проверка ump_logger/stubs на модели ПК. */
static void __restore_interrupts(unsigned int saved) { (void)saved; }
/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */
#endif

View File

@@ -1 +1,2 @@
/* Проверка ump_logger/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Подмена зависимостей для проверки регистратора без платы. */

View File

@@ -1 +1,2 @@
/* Проверка ump_logger/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Подмена зависимостей для проверки регистратора без платы. */

View File

@@ -1,2 +1,5 @@
/* Проверка ump_logger/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Объявляет READY — данные READY; Desk — аппаратно определённый тип платы; Mode — рабочий адрес или режим платы, выбранный перемычками. Память определена в другом модуле. */
extern int READY, Desk, Mode;
/* Задаёт READY_FREQ = 1000; частота основного такта Timer1 в герцах. */
#define READY_FREQ 1000

View File

@@ -1 +1,2 @@
/* Проверка ump_logger/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Подмена зависимостей для проверки регистратора без платы. */

View File

@@ -1,11 +1,23 @@
/* Проверка ump_logger/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Объявляет modbus — массив технологических регистров; слово int на C28x занимает 16 бит. Память определена в другом модуле. */
extern int modbus[128];
/* Задаёт dsk_LOAD = 6; код платы нагрузки. */
#define dsk_LOAD 6
/* Задаёт Commands = modbus[127]; слово команд, технологический регистр 127. */
#define Commands modbus[127]
/* Задаёт sens_data = (modbus+24); sens данные. */
#define sens_data (modbus+24)
/* Задаёт DAC_go = modbus[0x50]; начальный ток нагрузки в мА, технологический регистр 0x50. */
#define DAC_go modbus[0x50]
/* Задаёт DAC_stop = modbus[0x51]; конечный ток нагрузки в мА, технологический регистр 0x51. */
#define DAC_stop modbus[0x51]
/* Задаёт DAC_min = modbus[0x79]; ЦАП min. */
#define DAC_min() modbus[0x79]
/* Задаёт DAC_max = modbus[0x78]; ЦАП max. */
#define DAC_max() modbus[0x78]
/* Задаёт DAC_cal = modbus[0x7A]; ЦАП cal. */
#define DAC_cal() modbus[0x7A]
/* Задаёт DAC_04 = modbus[0x6F]; ЦАП 04. */
#define DAC_04 modbus[0x6F]
/* Задаёт DAC_20 = modbus[0x6E]; ЦАП 20. */
#define DAC_20 modbus[0x6E]

View File

@@ -1 +1,2 @@
/* Проверка ump_logger/stubs на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Подмена зависимостей для проверки регистратора без платы. */

View File

@@ -1,65 +1,117 @@
# Проверка ump_logger на модели пк. Комментарии и исходный текст в UTF-8.
# Продолжает текущий вызов, список или выражение: """Exercise the current board-specific SCI8 gate without TI tools or hardware."""; порядок аргументов сохраняется.
"""Exercise the current board-specific SCI8 gate without TI tools or hardware."""
# Импортирует необходимые имена: from pathlib import Path.
from pathlib import Path
# Подключает модуль struct для этой проверки или подготовки сборки.
import struct
# Подключает модуль subprocess для этой проверки или подготовки сборки.
import subprocess
# Подключает модуль sys для этой проверки или подготовки сборки.
import sys
# Подключает модуль tempfile для этой проверки или подготовки сборки.
import tempfile
# Подключает модуль unittest для этой проверки или подготовки сборки.
import unittest
# Задаёт ROOT по выражению справа; значение используется последующими операциями.
ROOT = Path(__file__).resolve().parents[2]
# Задаёт LIMIT по выражению справа; значение используется последующими операциями.
LIMIT = (0x3FFF - (128 + 1)) * 2
# Объявляет функцию image и её входные параметры.
def image(size):
# Задаёт header по выражению справа; значение используется последующими операциями.
header = struct.pack('<H', 0x08AA) + bytes(16) + struct.pack('<HH', 0, 0x8000)
# Задаёт blocks по выражению справа; значение используется последующими операциями.
blocks = max(1, (size-24+131075)//131076)
# Задаёт remaining по выражению справа; значение используется последующими операциями.
remaining = (size-24-blocks*6)//2
# Задаёт result по выражению справа; значение используется последующими операциями.
result = bytearray(header)
# Перебирает _ in range(blocks) в указанном порядке.
for _ in range(blocks):
# Задаёт words по выражению справа; значение используется последующими операциями.
words = min(65535, remaining)
# Задаёт result + по выражению справа; значение используется последующими операциями.
result += struct.pack('<HHH', words, 0, 0x8000) + bytes(words*2)
# Задаёт remaining - по выражению справа; значение используется последующими операциями.
remaining -= words
# Возвращает bytes(result)+bytes(2) вызывающему коду и завершает функцию.
return bytes(result)+bytes(2)
# Объявляет класс FirmwareGateTest для группировки проверок.
class FirmwareGateTest(unittest.TestCase):
# Объявляет функцию check_image и её входные параметры.
def check_image(self, data, success, profile="AT25256B"):
# Открывает управляемый ресурс tempfile.TemporaryDirectory() as directory с автоматическим освобождением.
with tempfile.TemporaryDirectory() as directory:
# Задаёт source по выражению справа; значение используется последующими операциями.
source = Path(directory) / 'candidate.bin'
# Сохраняет подготовленный файл в указанном формате для следующего шага.
source.write_bytes(data)
# Запускает внешний компилятор, генератор или тест; ненулевой результат проверяется параметрами вызова.
result = subprocess.run([
# Продолжает текущий вызов, список или выражение: sys.executable, str(ROOT / 'tests/gas167/check_image.py'),; порядок аргументов сохраняется.
sys.executable, str(ROOT / 'tests/gas167/check_image.py'),
# Продолжает текущий вызов, список или выражение: str(source), '--eeprom', profile,; порядок аргументов сохраняется.
str(source), '--eeprom', profile,
# Задаёт ], capture_output по выражению справа; значение используется последующими операциями.
], capture_output=True)
# Задаёт self.assertEqual(result.returncode по выражению справа; значение используется последующими операциями.
self.assertEqual(result.returncode == 0, success,
# Задаёт result.stderr.decode(errors по выражению справа; значение используется последующими операциями.
result.stderr.decode(errors='replace'))
# Читает исходный файл или образ для последующей проверки и разбора.
self.assertEqual(source.read_bytes(), data)
# Возвращает result.stdout + result.stderr вызывающему коду и завершает функцию.
return result.stdout + result.stderr
# Объявляет функцию test_exact_boundary_is_accepted и её входные параметры.
def test_exact_boundary_is_accepted(self):
# Продолжает текущий вызов, список или выражение: self.check_image(image(LIMIT), True); порядок аргументов сохраняется.
self.check_image(image(LIMIT), True)
# Объявляет функцию test_34a95bc5_size_is_rejected и её входные параметры.
def test_34a95bc5_size_is_rejected(self):
# Продолжает текущий вызов, список или выражение: self.check_image(image(32518), False); порядок аргументов сохраняется.
self.check_image(image(32518), False)
# Объявляет функцию test_missing_boot_terminator_is_rejected и её входные параметры.
def test_missing_boot_terminator_is_rejected(self):
# Продолжает текущий вызов, список или выражение: self.check_image(image(100)[:-2], False); порядок аргументов сохраняется.
self.check_image(image(100)[:-2], False)
# Объявляет функцию test_partial_block_is_rejected и её входные параметры.
def test_partial_block_is_rejected(self):
# Продолжает текущий вызов, список или выражение: self.check_image(image(100)[:-10], False); порядок аргументов сохраняется.
self.check_image(image(100)[:-10], False)
# Объявляет функцию test_m95_capacity_does_not_expand_code_ram и её входные параметры.
def test_m95_capacity_does_not_expand_code_ram(self):
# Задаёт diagnostic по выражению справа; значение используется последующими операциями.
diagnostic = self.check_image(image(261884), False, "M95M02")
# Продолжает текущий вызов, список или выражение: self.assertIn(b'outside code RAM', diagnostic); порядок аргументов сохраняется.
self.assertIn(b'outside code RAM', diagnostic)
# Продолжает текущий вызов, список или выражение: self.check_image(image(261886), False, "M95M02"); порядок аргументов сохраняется.
self.check_image(image(261886), False, "M95M02")
# Объявляет функцию test_m95_image_rejected_for_small_part и её входные параметры.
def test_m95_image_rejected_for_small_part(self):
# Продолжает текущий вызов, список или выражение: self.check_image(image(32734), True, "M95M02"); порядок аргументов сохраняется.
self.check_image(image(32734), True, "M95M02")
# Продолжает текущий вызов, список или выражение: self.check_image(image(32734), False, "AT25256B"); порядок аргументов сохраняется.
self.check_image(image(32734), False, "AT25256B")
# Объявляет функцию test_wrong_format_is_rejected и её входные параметры.
def test_wrong_format_is_rejected(self):
# Продолжает текущий вызов, список или выражение: self.check_image(bytes(100), False); порядок аргументов сохраняется.
self.check_image(bytes(100), False)
# Проверяет условие if __name__ == '__main__' перед выполнением следующего блока.
if __name__ == '__main__':
# Продолжает текущий вызов, список или выражение: unittest.main(); порядок аргументов сохраняется.
unittest.main()

View File

@@ -1,3 +1,6 @@
/* Проверка ump_logger на модели ПК. Русские пояснения сохранены в UTF-8. */
/* Декларации TI-интринсиков только для проверки синтаксиса на компьютере. */
/* Объявляет интерфейс функции __disable_interrupts; реализация вызывается через этот прототип. */
unsigned int __disable_interrupts(void);
/* Объявляет интерфейс функции __restore_interrupts; реализация вызывается через этот прототип. */
void __restore_interrupts(unsigned int saved);