From 980b1c64f2d2612158cb99060e26ba89a416931a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 7 Dec 2023 17:53:43 +0100 Subject: [PATCH] smart-amp-test: make a loadable module Convert the smart-amp-test in its IPC4 version to a loadable LLEXT module. Use an overlay configuration to select between monolithic and modular builds. Signed-off-by: Guennadi Liakhovetski --- app/overlays/mtl/module_overlay.conf | 1 + scripts/llext_link_helper.py | 56 ++++++++++++++ src/samples/audio/Kconfig | 2 +- .../audio/smart_amp_llext/CMakeLists.txt | 75 +++++++++++++++++++ .../audio/smart_amp_llext/llext.toml.h | 5 ++ src/samples/audio/smart_amp_test_ipc4.c | 60 ++++++++++++--- zephyr/CMakeLists.txt | 12 ++- 7 files changed, 198 insertions(+), 13 deletions(-) create mode 100644 app/overlays/mtl/module_overlay.conf create mode 100755 scripts/llext_link_helper.py create mode 100644 src/samples/audio/smart_amp_llext/CMakeLists.txt create mode 100644 src/samples/audio/smart_amp_llext/llext.toml.h diff --git a/app/overlays/mtl/module_overlay.conf b/app/overlays/mtl/module_overlay.conf new file mode 100644 index 000000000000..172a8ea28e82 --- /dev/null +++ b/app/overlays/mtl/module_overlay.conf @@ -0,0 +1 @@ +CONFIG_SAMPLE_SMART_AMP=m diff --git a/scripts/llext_link_helper.py b/scripts/llext_link_helper.py new file mode 100755 index 000000000000..1b8ad8c86221 --- /dev/null +++ b/scripts/llext_link_helper.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause + +# We need to calculate ELF section addresses of an LLEXT module and use them to +# run the linker. We could just use Python to calculate addresses and pass them +# back to cmake to have it call the linker. However, there doesn't seem to be a +# portable way to do that. Therefore we pass the linker path and all the command +# line parameters to this script and call the linker directly. + +import argparse +import subprocess +from elftools.elf.elffile import ELFFile + +args = None +def parse_args(): + global args + + parser = argparse.ArgumentParser(description='Helper utility to run a linker command ' + 'with calculated ELF section addresses') + + parser.add_argument('command', type=str, help='Linker command to execute') + parser.add_argument('params', nargs='+', help='Additional linker parameters') + parser.add_argument("-f", "--file", required=True, type=str, + help='Object file name') + parser.add_argument("-t", "--text-addr", required=True, type=str, + help='.text section address') + + args = parser.parse_args() + +def main(): + parse_args() + + elf = ELFFile(open(args.file, 'rb')) + + text_addr = int(args.text_addr, 0) + + text_offset = elf.get_section_by_name('.text').header.sh_offset + rodata_offset = elf.get_section_by_name('.rodata').header.sh_offset + data_offset = elf.get_section_by_name('.data').header.sh_offset + + upper = rodata_offset - text_offset + text_addr + 0xfff + rodata_addr = upper - (upper % 0x1000) + + upper = data_offset - rodata_offset + rodata_addr + 0xf + data_addr = upper - (upper % 0x10) + + command = [args.command, + f'-Wl,-Ttext=0x{text_addr:x}', + f'-Wl,--section-start=.rodata=0x{rodata_addr:x}', + f'-Wl,-Tdata=0x{data_addr:x}'] + command.extend(args.params) + + subprocess.run(command) + +if __name__ == "__main__": + main() diff --git a/src/samples/audio/Kconfig b/src/samples/audio/Kconfig index a427f0b3172f..e853b0668f1a 100644 --- a/src/samples/audio/Kconfig +++ b/src/samples/audio/Kconfig @@ -3,7 +3,7 @@ menu "Audio component samples" config SAMPLE_SMART_AMP - bool "Smart amplifier test component" + tristate "Smart amplifier test component" default y help Select for test smart amplifier component diff --git a/src/samples/audio/smart_amp_llext/CMakeLists.txt b/src/samples/audio/smart_amp_llext/CMakeLists.txt new file mode 100644 index 000000000000..006e53b79f66 --- /dev/null +++ b/src/samples/audio/smart_amp_llext/CMakeLists.txt @@ -0,0 +1,75 @@ +# Copyright (c) 2023 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(smart_amp_test) + +SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE) + +set(MODULE "smart_amp_test") +cmake_path(SET SOF_BASE NORMALIZE ${PROJECT_SOURCE_DIR}/../../../..) + +add_library(${MODULE} SHARED) + +target_sources(${MODULE} PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/../smart_amp_test_ipc4.c +) + +sof_append_relative_path_definitions(${MODULE}) + +target_include_directories(${MODULE} PRIVATE + "${ZEPHYR_BASE}/include" + "${ZEPHYR_BASE}/soc/xtensa/intel_adsp/common/include" + "${ZEPHYR_BASE}/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm" + "${ZEPHYR_BASE}/../modules/hal/xtensa/include" + "${ZEPHYR_BASE}/../modules/hal/xtensa/zephyr/soc/intel_ace15_mtpm" + "${SOF_BASE}/src/include" + "${SOF_BASE}/src/arch/xtensa/include" + "${SOF_BASE}/src/platform/meteorlake/include" + "${SOF_BASE}/src/platform/intel/ace/include" + "${SOF_BASE}/src/include/sof/audio/module_adapter/iadk" + "${SOF_BASE}/zephyr/include" + "${SOF_BASE}/xtos/include" + "${SOF_BASE}/tools/rimage/src/include" + "${PROJECT_BINARY_DIR}/../include/generated" +) + +set(MODULE_PROPERTIES HPSRAM_ADDR "0xa06c1000") +set_target_properties(${MODULE} PROPERTIES ${MODULE_PROPERTIES}) + +set(MODULE_COMPILE_DEF + __ZEPHYR__=1 + __XTENSA__ + KERNEL + MAJOR_IADSP_API_VERSION=5 + MIDDLE_IADSP_API_VERSION=0 + MINOR_IADSP_API_VERSION=0 +) +target_compile_definitions(${MODULE} PRIVATE ${MODULE_COMPILE_DEF}) + +target_compile_options(${MODULE} PRIVATE + -imacros${PROJECT_BINARY_DIR}/../include/generated/autoconf.h + -save-temps -O2 +) + +set(MODULE_LINKER_PARAMS -nostdlib -nodefaultlibs) +target_link_options(${MODULE} PRIVATE + ${MODULE_LINKER_PARAMS} +) + +add_custom_command(OUTPUT lib${MODULE}_out.so + DEPENDS ${MODULE} + COMMAND ${SOF_BASE}scripts/llext_link_helper.py + -f lib${MODULE}.so -t "0xa06ca000" ${CMAKE_C_COMPILER} -- + ${MODULE_LINKER_PARAMS} -shared -fPIC + -o lib${MODULE}_llext.so $ + COMMAND ${CMAKE_STRIP} -R .xt.* -o lib${MODULE}_out.so lib${MODULE}_llext.so + COMMAND_EXPAND_LISTS +) + +add_custom_target(${MODULE}_llext ALL + DEPENDS lib${MODULE}_out.so +) + +add_dependencies(${MODULE} zephyr_interface) diff --git a/src/samples/audio/smart_amp_llext/llext.toml.h b/src/samples/audio/smart_amp_llext/llext.toml.h new file mode 100644 index 000000000000..350cdc076e06 --- /dev/null +++ b/src/samples/audio/smart_amp_llext/llext.toml.h @@ -0,0 +1,5 @@ +#include +#include "../smart_amp_test.toml" + +[module] +count = __COUNTER__ diff --git a/src/samples/audio/smart_amp_test_ipc4.c b/src/samples/audio/smart_amp_test_ipc4.c index f6ffd6dae115..13f5f866e9a9 100644 --- a/src/samples/audio/smart_amp_test_ipc4.c +++ b/src/samples/audio/smart_amp_test_ipc4.c @@ -33,16 +33,16 @@ DECLARE_TR_CTX(smart_amp_test_comp_tr, SOF_UUID(smart_amp_test_comp_uuid), #include #include -#include #include #include -#include #include