zephyr/scripts/gen_app_partitions.py
Ioannis Glaropoulos 62c5894bc1 arch: arm: properly enforce MPU-aware linker section alignment
This commit standardizes and simplifies the way we enforce
linker section alignment, to comply with minimum alignment
requirement for MPU, if we build Zephyr with MPU support:
- it enforces alignment with the minimum MPU granularity at
  the beginning and end of linker sections that require to
  be protected by MPU,
- it enforces alignment with size if required by the MPU
  architecture.

Particularly for the Application Memory section, the commit
simplifies how the proper alignment is enforced, removing
the need of calculating the alignment with a post-linker
python script. It also removes the need for an additional
section for padding.

For the Application Shared Memory section(s), the commit
enforces minimum alignment besides the requirement for
alignment with size (for the respective MPUs) and fixes
a bug where the app_data_align was erronously used in the
scipts for auto-generating the linker scripts.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2018-11-30 15:22:58 +01:00

112 lines
3.6 KiB
Python

#!/usr/bin/env python3
import sys
import argparse
import os
import re
import string
from elf_helper import ElfHelper
from elftools.elf.elffile import ELFFile
# This script will create linker comands for power of two aligned MPU
# when APP_SHARED_MEM is enabled.
print_template = """
/* Auto generated code do not modify */
MPU_ALIGN(data_smem_{0}b_end - data_smem_{0});
data_smem_{0} = .;
KEEP(*(SORT(data_smem_{0}*)))
MPU_ALIGN(data_smem_{0}b_end - data_smem_{0});
data_smem_{0}b_end = .;
"""
linker_start_seq = """
SECTION_PROLOGUE(_APP_SMEM_SECTION_NAME, (OPTIONAL),)
{
APP_SHARED_ALIGN;
_image_ram_start = .;
_app_smem_start = .;
"""
linker_end_seq = """
_app_smem_end = .;
APP_SHARED_ALIGN;
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
"""
size_cal_string = """
data_smem_{0}_size = data_smem_{0}b_end - data_smem_{0};
"""
def find_partitions(filename, full_list_of_partitions, partitions_source_file):
with open(filename, 'rb') as f:
full_lib = ELFFile( f)
if (not full_lib):
print("Error parsing file: ",filename)
os.exit(1)
sections = [ x for x in full_lib.iter_sections()]
for section in sections:
if ("smem" in section.name and not ".rel" in section.name):
partition_name = section.name.split("data_smem_")[1]
if partition_name not in full_list_of_partitions:
full_list_of_partitions.append(partition_name)
if args.verbose:
partitions_source_file.update({partition_name: filename})
return( full_list_of_partitions, partitions_source_file)
def cleanup_remove_bss_regions(full_list_of_partitions):
for partition in full_list_of_partitions:
if (partition+"b" in full_list_of_partitions):
full_list_of_partitions.remove(partition+"b")
return full_list_of_partitions
def generate_final_linker(linker_file, full_list_of_partitions):
string = linker_start_seq
size_string = ''
for partition in full_list_of_partitions:
string += print_template.format(partition)
size_string += size_cal_string.format(partition)
string += linker_end_seq
string += size_string
with open(linker_file, "w") as fw:
fw.write(string)
def parse_args():
global args
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("-d", "--directory", required=True,
help="Root build directory")
parser.add_argument("-o", "--output", required=False,
help="Output ld file")
parser.add_argument("-v", "--verbose", action="count", default =0,
help="Verbose Output")
args = parser.parse_args()
def main():
parse_args()
root_directory = args.directory
linker_file = args.output
full_list_of_partitions = []
partitions_source_file= {}
for dirpath, dirs, files in os.walk(root_directory):
for filename in files:
if re.match(".*\.obj$",filename):
fullname = os.path.join(dirpath, filename)
full_list_of_partitions, partitions_source_file = find_partitions(fullname, full_list_of_partitions, partitions_source_file)
full_list_of_partitions = cleanup_remove_bss_regions(full_list_of_partitions)
generate_final_linker(linker_file, full_list_of_partitions)
if args.verbose:
print("Partitions retrieved: PARTITION, FILENAME")
print([key + " "+ partitions_source_file[key] for key in full_list_of_partitions])
if __name__ == '__main__':
main()