From ece79c3767b9f69952db024ddfe3ad93427ae6e3 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 21 May 2023 20:54:45 +0200 Subject: [PATCH] device: Add device subsystem enumeration script The device enumeration feature requires all devices to place their API implementation in linker sections by api type. This commit adds a script which uses the tag __subsystem to identify all existing driver API types and generate iterable sections for them. The script is invoked from the top CMakeLists.txt Signed-off-by: Bjarki Arge Andreasen Co-authored-by: Pieter De Gendt Signed-off-by: Pieter De Gendt --- CMakeLists.txt | 24 ++++++++++ .../common-rom/common-rom-kernel-devices.ld | 2 + scripts/build/gen_iter_sections.py | 48 +++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 scripts/build/gen_iter_sections.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 59d91526bd1..2015626637c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,6 +88,7 @@ set(SYSCALL_LIST_H_TARGET syscall_list_h_target) set(DRIVER_VALIDATION_H_TARGET driver_validation_h_target) set(KOBJ_TYPES_H_TARGET kobj_types_h_target) set(PARSE_SYSCALLS_TARGET parse_syscalls_target) +set(DEVICE_API_LD_TARGET device_api_ld_target) define_property(GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT BRIEF_DOCS " " FULL_DOCS " ") set_property( GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT elf32-little${ARCH}) # BFD format @@ -882,6 +883,28 @@ add_custom_target(${DRIVER_VALIDATION_H_TARGET} DEPENDS ${DRV_VALIDATION}) include(${ZEPHYR_BASE}/cmake/kobj.cmake) gen_kobj(KOBJ_INCLUDE_PATH) +# Generate sections for kernel device subsystems +set( + DEVICE_API_LD_SECTIONS + ${CMAKE_CURRENT_BINARY_DIR}/include/generated/device-api-sections.ld + ) + +add_custom_command( + OUTPUT ${DEVICE_API_LD_SECTIONS} + COMMAND + ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/build/gen_iter_sections.py + --input ${struct_tags_json} + --tag __subsystem + --ld-output ${DEVICE_API_LD_SECTIONS} + DEPENDS + ${ZEPHYR_BASE}/scripts/build/gen_iter_sections.py + ${struct_tags_json} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + +add_custom_target(${DEVICE_API_LD_TARGET} DEPENDS ${DEVICE_API_LD_SECTIONS}) + # Add a pseudo-target that is up-to-date when all generated headers # are up-to-date. @@ -912,6 +935,7 @@ add_dependencies(zephyr_interface ${SYSCALL_LIST_H_TARGET} ${DRIVER_VALIDATION_H_TARGET} ${KOBJ_TYPES_H_TARGET} + ${DEVICE_API_LD_TARGET} ) add_custom_command( diff --git a/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld b/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld index b073fcdab85..c6920b5bec0 100644 --- a/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld +++ b/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld @@ -102,3 +102,5 @@ #include } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) #endif /* !CONFIG_DEVICE_DEPS_DYNAMIC */ + +#include diff --git a/scripts/build/gen_iter_sections.py b/scripts/build/gen_iter_sections.py new file mode 100644 index 00000000000..98ce5c72d1e --- /dev/null +++ b/scripts/build/gen_iter_sections.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2023 Bjarki Arge Andreasen +# +# SPDX-License-Identifier: Apache-2.0 +""" +Script to generate iterable sections from JSON encoded dictionary containing lists of items. +""" + +import argparse +import json + + +def get_tagged_items(filepath: str, tag: str) -> list: + with open(filepath) as fp: + return json.load(fp)[tag] + + +def gen_ld(filepath: str, items: list): + with open(filepath, "w") as fp: + for item in items: + fp.write(f"ITERABLE_SECTION_ROM({item}, Z_LINK_ITERABLE_SUBALIGN)\n") + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + allow_abbrev=False, + ) + + parser.add_argument("-i", "--input", required=True, help="Path to input list of tags") + parser.add_argument("-t", "--tag", required=True, help="Tag to generate iterable sections for") + parser.add_argument("-l", "--ld-output", required=True, help="Path to output linker file") + + return parser.parse_args() + + +def main(): + args = parse_args() + + items = get_tagged_items(args.input, args.tag) + + gen_ld(args.ld_output, items) + + +if __name__ == "__main__": + main()