if(CONFIG_BUILD_OUTPUT_ADJUST_LMA)
math(EXPR adjustment "${CONFIG_BUILD_OUTPUT_ADJUST_LMA}" OUTPUT_FORMAT DECIMAL)
# 1. Вместо жестко зашитой маски мы объявляем кастомную команду (скрипт на Python или inline bash),
# которая выполнится в момент сборки, отфильтрует секции на 0x8 и сама вызовет objcopy.
# Формируем inline-скрипт для Python (он гарантированно кроссплатформенный и есть в Zephyr SDK)
set(PY_LMA_FILTER "
import sys, subprocess
elf_file = sys.argv[1]
offset = sys.argv[2]
objcopy_bin = sys.argv[3]
# Запускаем readelf, чтобы получить список всех секций и их VMA адресов
res = subprocess.run(['arm-zeabi-readelf', '-S', elf_file], capture_output=True, text=True, alpha=True)
if res.returncode != 0:
res = subprocess.run(['arm-zephyr-eabi-readelf', '-S', elf_file], capture_output=True, text=True)
# Ищем секции, чей VMA-адрес начинается на '8' (область SDRAM/FLASH)
lma_args = []
for line in res.stdout.splitlines():
parts = line.split()
if len(parts) >= 4 and parts[3].startswith('8'):
sec_name = parts[1].replace('[', '').replace(']', '')
# Пропускаем маркеры bss и noinit внутри SDRAM на всякий случай
if 'bss' not in sec_name and 'noinit' not in sec_name:
lma_args.extend(['--change-section-lma', f'{sec_name}+{offset}'])
# Вызываем финальный objcopy только для нужных секций
if lma_args:
cmd = [objcopy_bin] + lma_args + [elf_file, elf_file]
subprocess.run(cmd, check=True)
")
# 2. Интегрируем наш умный фильтр в конвейер сборки post_build_commands
list(APPEND
post_build_commands
# Сначала выполняем наш Python-скрипт, который точечно и безопасно сдвинет LMA только у секций на 0x8
COMMAND ${PYTHON_EXECUTABLE} -c "${PY_LMA_FILTER}"
${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}
${adjustment}
$<TARGET_PROPERTY:bintools,elfconvert_command>
)
endif()