Загрузка данных
import sys
import subprocess
import os
import re
def main():
# Ensure the path to the real objcopy tool is provided
if len(sys.argv) < 2:
print("[LMA Filter] Error: No real objcopy path provided.")
sys.exit(1)
real_objcopy = sys.argv[1]
args = sys.argv[2:]
elf_path = "zephyr.elf"
# Extract the elf path from the arguments if present
for arg in args:
if arg.endswith("zephyr.elf"):
elf_path = arg
break
# Skip processing if this is an internal ELF-to-ELF LMA adjustment step by Zephyr
is_elf_to_elf_adjust = any("--change-section-lma" in arg for arg in args) and ("zephyr.elf" in elf_path) and not any(fmt in " ".join(args) for fmt in ["ihex", "binary"])
if is_elf_to_elf_adjust:
sys.exit(0)
# Detect if the current command is generating the final .hex or .bin file
is_hex_or_bin_generation = any("--output-target=" in arg for arg in args) or any(fmt in " ".join(args) for fmt in ["ihex", "binary"])
if is_hex_or_bin_generation:
# Shift LMA down by 0x20000000 to map SDRAM execution addresses (0x80000000)
# to the physical FlexSPI Flash base addresses (0x60000000)
shift_value = 0x20000000
global_offset = ["--change-addresses", f"-{hex(shift_value)}"]
# Execute objcopy with the applied global address shift
final_cmd = [real_objcopy] + global_offset + args
subprocess.run(final_cmd, check=True)
# Try to locate the corresponding readelf utility to print the final memory map
sdk_bin_dir = os.path.dirname(real_objcopy)
readelf_bin = os.path.join(sdk_bin_dir, "arm-zephyr-eabi-readelf")
if not os.path.exists(readelf_bin):
for file in os.listdir(sdk_bin_dir):
if file.endswith("readelf"):
readelf_bin = os.path.join(sdk_bin_dir, file)
break
# If readelf is found, parse the ELF sections and print a clean memory map summary
if os.path.exists(readelf_bin):
res = subprocess.run([readelf_bin, "-SW", elf_path], capture_output=True, text=True)
if res.returncode == 0:
print(f"\n[LMA Filter] === FINAL MEMORY MAP FOR FLASH ===")
print(f"{'Section Name':<28} | {'Original VMA':<12} | {'Resulting LMA (Flash)':<22}")
print("-" * 72)
section_regex = re.compile(r'^\s*\[\s*\d+\]\s+([\.\w\-_]+)\s+(\w+)\s+([0-9a-fA-F]{8,16})')
for line in res.stdout.splitlines():
match = section_regex.match(line)
if not match:
continue
sec_name, sec_type, vma_str = match.groups()
# Ignore debug, symbol, and comment sections
if sec_name in [".comment", ".symtab", ".strtab", ".shstrtab"] or sec_name.startswith(".debug"):
continue
vma_val = int(vma_str, 16)
vma_formatted = f"0x{vma_val:08X}"
# Fix: Handle NOBITS sections (like BSS/noinit) safely.
# They are RAM-only and do not occupy space inside the physical Flash binary.
if sec_type == "NOBITS":
lma_formatted = "--------"
marker = "[RAM-only / Ignored in Flash]"
else:
resulting_lma = vma_val - shift_value
if resulting_lma < 0:
resulting_lma &= 0xFFFFFFFF
lma_formatted = f"0x{resulting_lma:08X}"
# Validate if the calculated LMA fits within the valid i.MX RT1024 4MB Flash boundary (0x60000000 - 0x603FFFFF)
if 0x60000000 <= resulting_lma <= 0x603FFFFF:
marker = "-> OK (Flash)"
else:
marker = "[WARNING: Out of Flash Bounds!]"
print(f"{sec_name:<28} | {vma_formatted:<12} | {lma_formatted:<22} {marker}")
print("=" * 72 + "\n")
else:
print("[LMA Filter] Applied global LMA shift, but readelf log helper could not find readelf binary.")
else:
# Pass-through for any other objcopy calls without modifications
subprocess.run([real_objcopy] + args, check=True)
if __name__ == "__main__":
main()