Files
Balsam_167/Bin/EepromPublishFix/rebuild.py
T
Andrey 1e911e5250 Обновить логгер УМП и исправить запуск UART и EEPROM
Перейти на компактные 12-словные записи v4 и сохранять 10 процентов банка после отключения. Добавить трёхсекундное ожидание роста ЗПТ и настраиваемый лимит пусков. Явно инициализировать состояние UART и гарантировать публикацию параметров EEPROM перед запуском Timer2. Сохранить воспроизводимые сборки, регрессионные проверки, документацию и обновлённые результаты сборки; исключить временные артефакты.
2026-10-12 12:25:41 +03:00

42 lines
7.5 KiB
Python

from pathlib import Path # Формирует абсолютные пути сборки и установленных инструментов TI.
import subprocess # Выполняет компиляцию и проверку без shell-подстановок.
import json # Читает фактический идентификатор текущей сборки из её паспорта.
import sys # Использует текущий Python для подготовки паспорта и образа.
root = Path.cwd().resolve() # Фиксирует разрешённый корень проекта.
out = root / 'Bin/EepromPublishFix' # Изолирует исправление публикации задания EEPROM от предыдущих образов.
obj = out / 'obj' # Хранит объекты полной текущей пересборки.
gen = out / 'generated' # Хранит паспорт текущих исходников.
for directory in (out, obj, gen): # Создаёт только подкаталоги этой сборки.
directory.mkdir(parents=True, exist_ok=True) # Не удаляет старые файлы проекта.
ti = Path('C:/ti/ccs1230/ccs/tools/compiler/ti-cgt-c2000_22.6.0.LTS') # Повторяет установленный компилятор CCS.
templates = root.parent / 'newProject/templates' # Использует штатную общую библиотеку проекта.
protocol = templates / 'c/set-protocol' # Задаёт интерфейсы и карту памяти УМП.
name = 'UKSSTMS320F28335_eeprom_fix' # Обозначает исправление обмена заданием EEPROM между главным циклом и Timer2.
log = (out / 'build.log').open('w', encoding='utf-8') # Записывает диагностику в UTF-8.
def run(args): # Останавливает сборку при ошибке любого шага.
result = subprocess.run([str(arg) for arg in args], cwd=root, capture_output=True) # Передаёт параметры инструменту напрямую.
output = (result.stdout + result.stderr).decode('utf-8', errors='replace') # Декодирует диагностический вывод.
log.write(output); log.flush() # Сохраняет текущий результат до следующего шага.
if result.returncode: # Запрещает формирование готового BIN после ошибки.
print(output); raise SystemExit(result.returncode) # Показывает причину незавершённой сборки.
return output # Возвращает отчёт успешно выполненного шага.
run([sys.executable, root / 'UKSSTMS320F28335/prepare_identity.py', '--project', root / 'UKSSTMS320F28335', '--templates', templates, '--output', gen]) # Обновляет паспорт перед полной компиляцией.
includes = [root / 'UKSSTMS320F28335', root / 'Source/Internal/Include', root / 'Source/External/v120/DSP2833x_headers/include', root / 'Source/External/v120/DSP2833x_common/include', protocol, protocol / 'ports/tms320f28335', templates / 'c/firmware-info/include', gen, ti / 'include'] # Повторяет каталоги CCS с локальным паспортом сборки.
flags = ['-v28', '-ml', '-mt', '--float_support=fpu32', '-O3', '--opt_for_speed=0', '--define=EEPROM_M95M02=0', '--define=_DEBUG', '--define=LARGE_MODEL', '-g', '--diag_warning=225', '--display_error_number', '--gen_func_subsections=on', '--abi=coffabi'] # Проверяет исправление при оптимизации O3 проекта CCS; EEPROM_M95M02=0 явно выбирает AT25256B.
flags += ['--include_path=' + str(path) for path in includes] # Передаёт каждый каталог отдельным аргументом.
common = root / 'Source/External/v120/DSP2833x_common/source' # Задаёт уже используемый комплект TI.
external = ['DSP2833x_ADC_cal.asm', 'DSP2833x_Adc.c', 'DSP2833x_CpuTimers.c', 'DSP2833x_PieCtrl.c', 'DSP2833x_SWPrioritizedDefaultIsr.c', 'DSP2833x_SWPrioritizedPieVect.c', 'DSP2833x_SysCtrl.c', 'DSP2833x_Xintf.c', 'DSP2833x_usDelay.asm'] # Повторяет штатный список внешних исходников.
sources = [common / item for item in external] + [root / 'Source/External/v120/DSP2833x_headers/source/DSP2833x_GlobalVariableDefs.c'] + sorted((root / 'Source/Internal').glob('*.c')) # Пересобирает все модули после окончательной правки.
for source in sources: # Последовательно компилирует каждый модуль.
run([ti / 'bin/cl2000.exe', *flags, '--obj_directory=' + str(obj), source]) # Проверяет настоящий C28x-код и создаёт новый объект.
objects = [obj / (source.stem + '.obj') for source in sources] # Использует только объекты завершённой текущей компиляции.
run([ti / 'bin/cl2000.exe', '-v28', '-ml', '-mt', '--float_support=fpu32', '--abi=coffabi', '-z', '--map_file=' + str(out / (name + '.map')), '--stack_size=0x3f0', '--warn_sections', '-i' + str(ti / 'lib'), '-i' + str(root), '-i' + str(protocol), '-i' + str(ti / 'include'), '--reread_libs', '--display_error_number', '--entry_point=_c_int00', '--rom_model', '--output_file=' + str(out / (name + '.out')), root / 'F28335.cmd', root / 'Source/External/v120/DSP2833x_headers/cmd/DSP2833x_Headers_nonBIOS.cmd', *objects, root / 'Libraries/rts2800_fpu32.lib', '-lrts2800_fpu32.lib', '-llibc.a']) # Линкует со штатной картой памяти и библиотеками времени выполнения.
run([ti / 'bin/hex2000.exe', '--diag_wrap=off', '--boot', '--sci8', '--binary', '-o', out / (name + '.candidate'), out / (name + '.out')]) # Создаёт кандидат загрузочного образа для обязательной проверки размера.
print(run([sys.executable, root / 'tests/gas167/check_image.py', out / (name + '.candidate'), '--eeprom', 'AT25256B']).strip()) # Проверяет EEPROM, RAM-блоки и точку входа до выдачи прошивки.
print(run([sys.executable, templates / 'c/firmware-info/tools/c2000_postbuild.py', '--compiler', ti, '--build-dir', out, '--artifact', name, '--metadata', gen / 'firmware_identity.json', '--output', out]).strip()) # Создаёт штатный BIN, манифест и SHA-256 без экспорта в другие проекты.
bin_path = out / (name + '_' + json.loads((gen / 'firmware_identity.json').read_text(encoding='utf-8'))['build_id'] + '.bin') # Выбирает именно текущую сборку, даже если в каталоге остаются прежние BIN.
print(run([sys.executable, root / 'tests/gas167/check_image.py', bin_path, '--eeprom', 'AT25256B']).strip()) # Повторяет проверку на самом выдаваемом BIN после штатной упаковки.
assert bin_path.read_bytes() == (out / (name + '.candidate')).read_bytes() # Подтверждает совпадение проверенного кандидата и итоговой прошивки.
log.close() # Завершает полный лог успешно проверенной сборки.
print('READY:', bin_path) # Указывает пользователю точный готовый результат.