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/app/prj.conf b/app/prj.conf index cd182e5be16c..5a681ac5b74b 100644 --- a/app/prj.conf +++ b/app/prj.conf @@ -53,3 +53,7 @@ CONFIG_SCHED_CPU_MASK_PIN_ONLY=y CONFIG_SYS_CLOCK_TICKS_PER_SEC=15000 CONFIG_DAI=y CONFIG_HEAP_MEM_POOL_SIZE=2048 + +CONFIG_LLEXT=y +CONFIG_LLEXT_STORAGE_WRITABLE=y +CONFIG_MODULES=y 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/audio/module_adapter/module/modules.c b/src/audio/module_adapter/module/modules.c index 773811550af0..04b8a27e0c50 100644 --- a/src/audio/module_adapter/module/modules.c +++ b/src/audio/module_adapter/module/modules.c @@ -14,6 +14,7 @@ #include #include #include +#include /* Intel module adapter is an extension to SOF module adapter component that allows to integrate * modules developed under IADK (Intel Audio Development Kit) Framework. IADK modules uses uniform @@ -49,6 +50,67 @@ DECLARE_SOF_RT_UUID("modules", intel_uuid, 0xee2585f2, 0xe7d8, 0x43dc, 0x90, 0xab, 0x42, 0x24, 0xe0, 0x0c, 0x3e, 0x84); DECLARE_TR_CTX(intel_codec_tr, SOF_UUID(intel_uuid), LOG_LEVEL_INFO); +static const struct module_interface interface; + +static int modules_new(struct processing_module *mod, const void *buildinfo, + uintptr_t module_entry_point) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + uint32_t module_id = IPC4_MOD_ID(dev->ipc_config.id); + uint32_t instance_id = IPC4_INST_ID(dev->ipc_config.id); + uint32_t log_handle = (uint32_t) dev->drv->tctx; + /* Connect loadable module interfaces with module adapter entity. */ + /* Check if native Zephyr lib is loaded */ + struct sof_man_fw_desc *desc = lib_manager_get_library_module_desc(module_id); + + if (!desc) { + comp_err(dev, "modules_init(): Failed to load manifest"); + return -ENOMEM; + } + + const struct sof_module_api_build_info *mod_buildinfo; + + if (buildinfo) { + mod_buildinfo = buildinfo; + } else { + struct sof_man_module *module_entry = + (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(0)); + + mod_buildinfo = + (struct sof_module_api_build_info *) + (module_entry->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr); + } + + byte_array_t mod_cfg = { + .data = (uint8_t *)md->cfg.init_data, + /* Intel modules expects DW size here */ + .size = md->cfg.size >> 2, + }; + + /* Check if module is FDK */ + if (mod_buildinfo->format == IADK_MODULE_API_BUILD_INFO_FORMAT && + mod_buildinfo->api_version_number.full == IADK_MODULE_API_CURRENT_VERSION) { + md->module_adapter = (void *)system_agent_start(module_entry_point, + module_id, instance_id, + 0, log_handle, &mod_cfg); + } else if (mod_buildinfo->format == SOF_MODULE_API_BUILD_INFO_FORMAT && + mod_buildinfo->api_version_number.full == SOF_MODULE_API_CURRENT_VERSION) { + /* The module is native: start agent for sof loadable */ + mod->is_native_sof = true; + md->ops = native_system_agent_start(mod->sys_service, module_entry_point, + module_id, instance_id, + 0, log_handle, &mod_cfg); + } else { + return -ENOEXEC; + } + + md->module_entry_point = module_entry_point; + md->private = mod; + + return 0; +} + /** * \brief modules_init. * \param[in] mod - processing module pointer. @@ -58,64 +120,28 @@ DECLARE_TR_CTX(intel_codec_tr, SOF_UUID(intel_uuid), LOG_LEVEL_INFO); */ static int modules_init(struct processing_module *mod) { - uint32_t module_entry_point; struct module_data *md = &mod->priv; struct comp_dev *dev = mod->dev; const struct ipc4_base_module_cfg *src_cfg = &md->cfg.base_cfg; - byte_array_t mod_cfg; - - mod_cfg.data = (uint8_t *)md->cfg.init_data; - /* Intel modules expects DW size here */ - mod_cfg.size = md->cfg.size >> 2; - md->private = mod; - struct comp_ipc_config *config = &(dev->ipc_config); - /* At this point module resources are allocated and it is moved to L2 memory. */ - module_entry_point = lib_manager_allocate_module(dev->drv, config, src_cfg); + const void *buildinfo = NULL; + int ret; + uintptr_t module_entry_point = lib_manager_allocate_module(mod, config, src_cfg, + &buildinfo); + if (module_entry_point == 0) { comp_err(dev, "modules_init(), lib_manager_allocate_module() failed!"); return -EINVAL; } - md->module_entry_point = module_entry_point; comp_info(dev, "modules_init() start"); - uint32_t module_id = IPC4_MOD_ID(dev->ipc_config.id); - uint32_t instance_id = IPC4_INST_ID(dev->ipc_config.id); - uint32_t log_handle = (uint32_t) dev->drv->tctx; - /* Connect loadable module interfaces with module adapter entity. */ - /* Check if native Zephyr lib is loaded */ - struct sof_man_fw_desc *desc; - - desc = lib_manager_get_library_module_desc(module_id); - if (!desc) { - comp_err(dev, "modules_init(): Failed to load manifest"); - return -ENOMEM; + if (!md->module_adapter && md->ops == &interface) { + /* First load */ + ret = modules_new(mod, buildinfo, module_entry_point); + if (ret < 0) + return ret; } - struct sof_man_module *module_entry = - (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(0)); - - struct sof_module_api_build_info *mod_buildinfo = - (struct sof_module_api_build_info *) - (module_entry->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr); - - /* Check if module is FDK */ - if (mod_buildinfo->format == IADK_MODULE_API_BUILD_INFO_FORMAT && - mod_buildinfo->api_version_number.full == IADK_MODULE_API_CURRENT_VERSION) { - md->module_adapter = (void *)system_agent_start(md->module_entry_point, module_id, - instance_id, 0, log_handle, - &mod_cfg); - } else - /* Check if module is native */ - if (mod_buildinfo->format == SOF_MODULE_API_BUILD_INFO_FORMAT && - mod_buildinfo->api_version_number.full == SOF_MODULE_API_CURRENT_VERSION) { - /* If start agent for sof loadable */ - mod->is_native_sof = true; - md->ops = native_system_agent_start(mod->sys_service, md->module_entry_point, - module_id, instance_id, 0, log_handle, - &mod_cfg); - } else - return -ENOEXEC; /* Allocate module buffers */ md->mpd.in_buff = rballoc(0, SOF_MEM_CAPS_RAM, src_cfg->ibs); @@ -133,8 +159,6 @@ static int modules_init(struct processing_module *mod) } md->mpd.out_buff_size = src_cfg->obs; - int ret; - /* Call module specific init function if exists. */ if (mod->is_native_sof) { const struct module_interface *mod_in = md->ops; @@ -271,7 +295,7 @@ static int modules_free(struct processing_module *mod) struct comp_dev *dev = mod->dev; struct module_data *md = &mod->priv; struct comp_ipc_config *config = &(mod->dev->ipc_config); - int ret = 0; + int ret; comp_info(dev, "modules_free()"); if (mod->is_native_sof) { @@ -281,13 +305,19 @@ static int modules_free(struct processing_module *mod) } else { ret = iadk_wrapper_free(mod->priv.module_adapter); } + + if (ret < 0) + comp_err(dev, "Failed to free a module: %d", ret); + rfree(md->mpd.in_buff); rfree(md->mpd.out_buff); - /* Free module resources allocated in L2 memory. */ - ret = lib_manager_free_module(dev->drv, config); - if (ret < 0) - comp_err(dev, "modules_free(), lib_manager_free_module() failed!"); + if (!md->llext || !llext_unload(&md->llext)) { + /* Free module resources allocated in L2 memory. */ + ret = lib_manager_free_module(mod, config); + if (ret < 0) + comp_err(dev, "modules_free(), lib_manager_free_module() failed!"); + } return ret; } diff --git a/src/include/module/module/base.h b/src/include/module/module/base.h index 323599b055f2..69e216435033 100644 --- a/src/include/module/module/base.h +++ b/src/include/module/module/base.h @@ -37,6 +37,8 @@ struct module_config { #endif }; +struct llext; + /* * A structure containing a module's private data, intended for its exclusive use. * @@ -60,7 +62,8 @@ struct module_data { struct module_memory memory; /**< memory allocated by module */ struct module_processing_data mpd; /**< shared data comp <-> module */ void *module_adapter; /**desc); + const uintptr_t load_offset = POINTER_TO_UINT(ctx->base_addr); void *src; void __sparse_cache *va_base; size_t size; @@ -342,9 +342,9 @@ static bool module_is_llext(struct sof_man_module *mod) return mod->type.load_type == SOF_MAN_MOD_TYPE_LLEXT; } -uint32_t lib_manager_allocate_module(const struct comp_driver *drv, - struct comp_ipc_config *ipc_config, - const void *ipc_specific_config) +uintptr_t lib_manager_allocate_module(struct processing_module *proc, + struct comp_ipc_config *ipc_config, + const void *ipc_specific_config, const void **buildinfo) { struct sof_man_fw_desc *desc; struct sof_man_module *mod; @@ -366,7 +366,8 @@ uint32_t lib_manager_allocate_module(const struct comp_driver *drv, mod = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); if (module_is_llext(mod)) - return llext_manager_allocate_module(drv, ipc_config, ipc_specific_config); + return llext_manager_allocate_module(proc, ipc_config, ipc_specific_config, + buildinfo); ret = lib_manager_load_module(module_id, mod); if (ret < 0) @@ -395,7 +396,7 @@ uint32_t lib_manager_allocate_module(const struct comp_driver *drv, return 0; } -int lib_manager_free_module(const struct comp_driver *drv, +int lib_manager_free_module(struct processing_module *proc, struct comp_ipc_config *ipc_config) { struct sof_man_fw_desc *desc; @@ -410,7 +411,7 @@ int lib_manager_free_module(const struct comp_driver *drv, mod = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); if (module_is_llext(mod)) - return llext_manager_free_module(drv, ipc_config); + return llext_manager_free_module(proc, ipc_config); ret = lib_manager_unload_module(mod); if (ret < 0) @@ -435,16 +436,16 @@ int lib_manager_free_module(const struct comp_driver *drv, #define PAGE_SZ 4096 /* equals to MAN_PAGE_SIZE used by rimage */ -uint32_t lib_manager_allocate_module(const struct comp_driver *drv, - struct comp_ipc_config *ipc_config, - const void *ipc_specific_config) +uintptr_t lib_manager_allocate_module(struct processing_module *proc, + struct comp_ipc_config *ipc_config, + const void *ipc_specific_config, const void **buildinfo) { tr_err(&lib_manager_tr, "lib_manager_allocate_module(): Dynamic module allocation is not supported"); return 0; } -int lib_manager_free_module(const struct comp_driver *drv, +int lib_manager_free_module(struct processing_module *proc, struct comp_ipc_config *ipc_config) { /* Since we cannot allocate the freeing is not considered to be an error */ @@ -465,21 +466,21 @@ void lib_manager_init(void) struct sof_man_fw_desc *lib_manager_get_library_module_desc(int module_id) { struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); - uint8_t *buffptr = (uint8_t *)(ctx ? ctx->desc : NULL); + uint8_t *buffptr = ctx ? ctx->base_addr : NULL; if (!buffptr) return NULL; return (struct sof_man_fw_desc *)(buffptr + SOF_MAN_ELF_TEXT_OFFSET); } -static void lib_manager_update_sof_ctx(struct sof_man_fw_desc *desc, uint32_t lib_id) +static void lib_manager_update_sof_ctx(void *base_addr, uint32_t lib_id) { struct ext_library *_ext_lib = ext_lib_get(); /* Never freed, will panic if fails */ struct lib_manager_mod_ctx *ctx = rmalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, sizeof(*ctx)); - ctx->desc = desc; + ctx->base_addr = base_addr; _ext_lib->desc[lib_id] = ctx; /* TODO: maybe need to call dcache_writeback here? */ @@ -697,7 +698,10 @@ static int lib_manager_store_library(struct lib_manager_dma_ext *dma_ext, uint32_t preload_size = man_desc->header.preload_page_count * PAGE_SZ; int ret; - /* Prepare storage memory, note: it is never freed, library unloading is unsupported */ + /* + * Prepare storage memory, note: it is never freed, it is assumed, that this + * memory is abundant, so we store all loaded modules there permanently + */ library_base_address = lib_manager_allocate_store_mem(preload_size, 0); if (!library_base_address) return -ENOMEM; diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index a0503117bd95..23ded81f9a10 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -25,6 +25,11 @@ #include #include +#include +#include +#include + +#include #include #include @@ -72,7 +77,7 @@ static int llext_manager_load_module(uint32_t module_id, struct sof_man_module * struct sof_man_fw_desc *desc) { struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); - uint8_t *load_base = (uint8_t *)ctx->desc; + uint8_t *load_base = (uint8_t *)ctx->base_addr; void __sparse_cache *va_base_text = (void __sparse_cache *) mod->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr; void *src_txt = (void *)(load_base + mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset); @@ -137,19 +142,12 @@ static void __sparse_cache *llext_manager_get_bss_address(uint32_t module_id, } static int llext_manager_allocate_module_bss(uint32_t module_id, - uint32_t is_pages, struct sof_man_module *mod) + struct sof_man_module *mod) { struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); size_t bss_size = ctx->segment_size[SOF_MAN_SEGMENT_BSS]; void __sparse_cache *va_base = llext_manager_get_bss_address(module_id, mod); - if (is_pages * PAGE_SZ > bss_size) { - tr_err(&lib_manager_tr, - "llext_manager_allocate_module_bss(): invalid is_pages: %u, required: %u", - is_pages, bss_size / PAGE_SZ); - return -ENOMEM; - } - /* Map bss memory and clear it. */ if (llext_manager_align_map(va_base, bss_size, SYS_MM_MEM_PERM_RW) < 0) return -ENOMEM; @@ -170,17 +168,78 @@ static int llext_manager_free_module_bss(uint32_t module_id, return llext_manager_align_unmap(va_base, bss_size); } -uint32_t llext_manager_allocate_module(const struct comp_driver *drv, - struct comp_ipc_config *ipc_config, - const void *ipc_specific_config) +static int llext_manager_link(struct sof_man_fw_desc *desc, struct sof_man_module *mod, + uint32_t module_id, struct module_data *md, const void **buildinfo, + const struct sof_man_module_manifest **mod_manifest) +{ + size_t mod_size = desc->header.preload_page_count * PAGE_SZ; + /* FIXME: where does the module begin?? */ + struct llext_buf_loader ebl = LLEXT_BUF_LOADER((uint8_t *)desc - + SOF_MAN_ELF_TEXT_OFFSET + 0x8000, + mod_size); + struct llext_load_param ldr_parm = {false}; + struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); + int ret = llext_load(&ebl.loader, mod->name, &md->llext, &ldr_parm); + + if (ret < 0) + return ret; + + mod->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr = ebl.loader.sects[LLEXT_MEM_TEXT].sh_addr; + mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset = + (uintptr_t)md->llext->mem[LLEXT_MEM_TEXT] - + (uintptr_t)desc + SOF_MAN_ELF_TEXT_OFFSET; + ctx->segment_size[SOF_MAN_SEGMENT_TEXT] = ebl.loader.sects[LLEXT_MEM_TEXT].sh_size; + + tr_dbg(&lib_manager_tr, ".text: start: %#x size %#x offset %#x", + mod->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr, + ctx->segment_size[SOF_MAN_SEGMENT_TEXT], + mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset); + + /* This contains all other sections, except .text, it might contain .bss too */ + mod->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr = + ebl.loader.sects[LLEXT_MEM_RODATA].sh_addr; + mod->segment[SOF_MAN_SEGMENT_RODATA].file_offset = + (uintptr_t)md->llext->mem[LLEXT_MEM_RODATA] - + (uintptr_t)desc + SOF_MAN_ELF_TEXT_OFFSET; + ctx->segment_size[SOF_MAN_SEGMENT_RODATA] = mod_size - + ebl.loader.sects[LLEXT_MEM_TEXT].sh_size; + + tr_dbg(&lib_manager_tr, ".data: start: %#x size %#x offset %#x", + mod->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr, + ctx->segment_size[SOF_MAN_SEGMENT_RODATA], + mod->segment[SOF_MAN_SEGMENT_RODATA].file_offset); + + mod->segment[SOF_MAN_SEGMENT_BSS].v_base_addr = ebl.loader.sects[LLEXT_MEM_BSS].sh_addr; + ctx->segment_size[SOF_MAN_SEGMENT_BSS] = ebl.loader.sects[LLEXT_MEM_BSS].sh_size; + + tr_dbg(&lib_manager_tr, ".bss: start: %#x size %#x", + mod->segment[SOF_MAN_SEGMENT_BSS].v_base_addr, + ctx->segment_size[SOF_MAN_SEGMENT_BSS]); + + ssize_t binfo_o = llext_find_section(&ebl.loader, ".mod_buildinfo"); + + if (binfo_o) + *buildinfo = llext_peek(&ebl.loader, binfo_o); + + ssize_t mod_o = llext_find_section(&ebl.loader, ".module"); + + if (mod_o) + *mod_manifest = llext_peek(&ebl.loader, mod_o); + + return 0; +} + +uintptr_t llext_manager_allocate_module(struct processing_module *proc, + struct comp_ipc_config *ipc_config, + const void *ipc_specific_config, const void **buildinfo) { struct sof_man_fw_desc *desc; struct sof_man_module *mod; - const struct ipc4_base_module_cfg *base_cfg = ipc_specific_config; int ret; uint32_t module_id = IPC4_MOD_ID(ipc_config->id); uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(module_id); struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); + const struct sof_man_module_manifest *mod_manifest; tr_dbg(&lib_manager_tr, "llext_manager_allocate_module(): mod_id: %#x", ipc_config->id); @@ -194,23 +253,26 @@ uint32_t llext_manager_allocate_module(const struct comp_driver *drv, mod = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); - for (unsigned int i = 0; i < ARRAY_SIZE(ctx->segment_size); i++) - ctx->segment_size[i] = mod->segment[i].flags.r.length * PAGE_SZ; + ret = llext_manager_link(desc, mod, module_id, &proc->priv, buildinfo, &mod_manifest); + if (ret < 0) + return 0; + /* Map .text and the rest as .data */ ret = llext_manager_load_module(module_id, mod, desc); if (ret < 0) return 0; - ret = llext_manager_allocate_module_bss(module_id, base_cfg->is_pages, mod); + ret = llext_manager_allocate_module_bss(module_id, mod); if (ret < 0) { tr_err(&lib_manager_tr, "llext_manager_allocate_module(): module allocation failed: %d", ret); return 0; } - return mod->entry_point; + + return mod_manifest->module.entry_point; } -int llext_manager_free_module(const struct comp_driver *drv, +int llext_manager_free_module(struct processing_module *proc, struct comp_ipc_config *ipc_config) { struct sof_man_fw_desc *desc; 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