Перейти на компактные 12-словные записи v4 и сохранять 10 процентов банка после отключения. Добавить трёхсекундное ожидание роста ЗПТ и настраиваемый лимит пусков. Явно инициализировать состояние UART и гарантировать публикацию параметров EEPROM перед запуском Timer2. Сохранить воспроизводимые сборки, регрессионные проверки, документацию и обновлённые результаты сборки; исключить временные артефакты.
42 lines
7.4 KiB
Python
42 lines
7.4 KiB
Python
from pathlib import Path # Формирует абсолютные пути сборки и установленных инструментов TI.
|
||
import subprocess # Выполняет компиляцию и проверку без shell-подстановок.
|
||
import json # Читает фактический идентификатор текущей сборки из её паспорта.
|
||
import sys # Использует текущий Python для подготовки паспорта и образа.
|
||
root = Path.cwd().resolve() # Фиксирует разрешённый корень проекта.
|
||
out = root / 'Bin/UartColdStart' # Изолирует результаты исправления холодного запуска UART от прежней прошивки.
|
||
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_uart_init' # Различает прошивку с явной инициализацией UART при холодном запуске.
|
||
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', '-O2', '--opt_for_speed=0', '--define=_DEBUG', '--define=LARGE_MODEL', '-g', '--diag_warning=225', '--display_error_number', '--gen_func_subsections=on', '--abi=coffabi'] # Сохраняет ABI, FPU и существующую оптимизацию размера проекта.
|
||
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) # Указывает пользователю точный готовый результат.
|