mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 09:09:10 -04:00
fix(ulp): Add support for multiple ULP program embedding without name collision
Merges: https://github.com/espressif/esp-idf/pull/14954
This commit is contained in:
parent
33c340a328
commit
5dea6adbef
@ -8,4 +8,4 @@ include(IDFULPProject)
|
||||
|
||||
ulp_apply_default_options(${ULP_APP_NAME})
|
||||
ulp_apply_default_sources(${ULP_APP_NAME})
|
||||
ulp_add_build_binary_targets(${ULP_APP_NAME})
|
||||
ulp_add_build_binary_targets(${ULP_APP_NAME} ${ULP_VAR_PREFIX})
|
||||
|
@ -178,7 +178,7 @@ function(ulp_apply_default_sources ulp_app_name)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(ulp_add_build_binary_targets ulp_app_name)
|
||||
function(ulp_add_build_binary_targets ulp_app_name prefix)
|
||||
|
||||
if(ADD_PICOLIBC_SPECS)
|
||||
target_compile_options(${ulp_app_name} PRIVATE $<$<COMPILE_LANG_AND_ID:C,GNU>:-specs=picolibc.specs>)
|
||||
@ -195,7 +195,7 @@ function(ulp_add_build_binary_targets ulp_app_name)
|
||||
|
||||
# Dump the list of global symbols in a convenient format
|
||||
add_custom_command(OUTPUT ${ULP_APP_NAME}.sym
|
||||
COMMAND ${CMAKE_NM} -f posix -g $<TARGET_FILE:${ulp_app_name}> > ${ulp_app_name}.sym
|
||||
COMMAND ${CMAKE_READELF} -sW $<TARGET_FILE:${ulp_app_name}> > ${ulp_app_name}.sym
|
||||
DEPENDS ${ulp_app_name}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
@ -206,7 +206,8 @@ function(ulp_add_build_binary_targets ulp_app_name)
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_custom_command(OUTPUT ${ulp_app_name}.ld ${ulp_app_name}.h
|
||||
COMMAND ${ULP_MAP_GEN} -s ${ulp_app_name}.sym -o ${ulp_app_name} --base ${ULP_BASE_ADDR}
|
||||
COMMAND ${ULP_MAP_GEN} -s ${ulp_app_name}.sym -o ${ulp_app_name}
|
||||
--base ${ULP_BASE_ADDR} --prefix ${prefix}
|
||||
DEPENDS ${ulp_app_name}.sym
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
|
@ -6,13 +6,20 @@
|
||||
# for the linker and a header file.
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import textwrap
|
||||
import typing
|
||||
|
||||
UTIL = os.path.basename(__file__)
|
||||
|
||||
|
||||
def gen_ld_h_from_sym(f_sym: typing.TextIO, f_ld: typing.TextIO, f_h: typing.TextIO, base_addr: int) -> None:
|
||||
def name_mangling(name: str) -> str:
|
||||
# Simple and dumb name mangling for namespaced name following GCC algorithm
|
||||
ns, n = name.split('::')
|
||||
return '_ZN{0}{1}{2}{3}E'.format(len(ns), ns, len(n), n)
|
||||
|
||||
|
||||
def gen_ld_h_from_sym(f_sym: typing.TextIO, f_ld: typing.TextIO, f_h: typing.TextIO, base_addr: int, prefix: str) -> None:
|
||||
f_ld.write(textwrap.dedent(
|
||||
f"""
|
||||
/* ULP variable definitions for the linker.
|
||||
@ -20,52 +27,80 @@ def gen_ld_h_from_sym(f_sym: typing.TextIO, f_ld: typing.TextIO, f_h: typing.Tex
|
||||
*/
|
||||
""" # noqa: E222
|
||||
))
|
||||
f_h.write(textwrap.dedent(
|
||||
f"""
|
||||
/* ULP variable definitions for the compiler.
|
||||
* This file is generated automatically by {UTIL} utility.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
extern "C" {{
|
||||
#endif
|
||||
""" # noqa: E222
|
||||
))
|
||||
cpp_mode = False
|
||||
var_prefix = prefix
|
||||
namespace = ''
|
||||
if '::' in prefix:
|
||||
# C++ mode, let's avoid the extern "C" type and instead use namespace
|
||||
f_h.write(textwrap.dedent(
|
||||
f"""
|
||||
/* ULP variable definitions for the compiler.
|
||||
* This file is generated automatically by {UTIL} utility.
|
||||
*/
|
||||
#pragma once
|
||||
""" # noqa: E222
|
||||
))
|
||||
tmp = prefix.split('::')
|
||||
namespace = tmp[0]
|
||||
var_prefix = '_'.join(tmp[1:]) # Limit to a single namespace here to avoid complex mangling rules
|
||||
f_h.write('namespace {0} {{\n'.format(namespace))
|
||||
cpp_mode = True
|
||||
else:
|
||||
f_h.write(textwrap.dedent(
|
||||
f"""
|
||||
/* ULP variable definitions for the compiler.
|
||||
* This file is generated automatically by {UTIL} utility.
|
||||
*/
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
extern "C" {{
|
||||
#endif
|
||||
""" # noqa: E222
|
||||
))
|
||||
|
||||
expr = re.compile('^\\s*\\d+: ([a-f0-9]{8})\\s+(\\d+) OBJECT\\s+GLOBAL\\s+DEFAULT\\s+[^ ]+ (.*)$')
|
||||
already_defined = 'this_symbol_is_already_defined_please_use_prefix_in_ulp_embed_binary'
|
||||
for line in f_sym:
|
||||
# NM "posix" format output has the following structure:
|
||||
# symbol_name symbol_type addr_hex [size_hex]
|
||||
parts = line.split()
|
||||
name = parts[0]
|
||||
addr = int(parts[2], 16) + base_addr
|
||||
f_h.write('extern uint32_t ulp_{0};\n'.format(name))
|
||||
f_ld.write('PROVIDE ( ulp_{0} = 0x{1:08x} );\n'.format(name, addr))
|
||||
# readelf format output has the following structure:
|
||||
# index: addr_hex size TYPE SCOPE DEFAULT junk symbol_name
|
||||
# So match the line with a regular expression to parse it first
|
||||
groups = expr.match(line)
|
||||
if groups is None: # Ignore non global or non object
|
||||
continue
|
||||
addr = int(groups.group(1), 16) + base_addr
|
||||
size = int(groups.group(2))
|
||||
name = var_prefix + groups.group(3)
|
||||
f_h.write('extern uint32_t {0}{1};\n'.format(name, '[{0}]'.format(int(size / 4)) if size > 4 else ''))
|
||||
f_ld.write('{0} = DEFINED({0}) ? {2} : 0x{1:08x};\n'.format(
|
||||
name_mangling(namespace + '::' + name) if cpp_mode else name, addr, already_defined))
|
||||
|
||||
f_h.write(textwrap.dedent(
|
||||
"""
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
"""
|
||||
))
|
||||
if cpp_mode:
|
||||
f_h.write('}\n')
|
||||
else:
|
||||
f_h.write(textwrap.dedent(
|
||||
"""
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
"""
|
||||
))
|
||||
|
||||
|
||||
def main() -> None:
|
||||
description = ('This application generates .h and .ld files for symbols defined in input file. '
|
||||
'The input symbols file can be generated using nm utility like this: '
|
||||
'<PREFIX>nm -g -f posix <elf_file> > <symbols_file>')
|
||||
'The input symbols file can be generated using readelf utility like this: '
|
||||
'<PREFIX>readelf -sW <elf_file> > <symbols_file>')
|
||||
|
||||
parser = argparse.ArgumentParser(description=description)
|
||||
parser.add_argument('-s', '--symfile', required=True, help='symbols file name', metavar='SYMFILE', type=argparse.FileType('r'))
|
||||
parser.add_argument('-o', '--outputfile', required=True, help='destination .h and .ld files name prefix', metavar='OUTFILE')
|
||||
parser.add_argument('--base-addr', required=True, help='base address of the ULP memory, to be added to each symbol')
|
||||
parser.add_argument('-p', '--prefix', required=False, help='prefix for generated header file', default='ulp_')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.outputfile + '.h', 'w', encoding='utf-8') as f_h, open(args.outputfile + '.ld', 'w', encoding='utf-8') as f_ld:
|
||||
gen_ld_h_from_sym(args.symfile, f_ld, f_h, int(args.base_addr, 0))
|
||||
with open(args.outputfile + '.h', 'w') as f_h, open(args.outputfile + '.ld', 'w') as f_ld:
|
||||
gen_ld_h_from_sym(args.symfile, f_ld, f_h, int(args.base_addr, 0), args.prefix)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -2,7 +2,7 @@
|
||||
#
|
||||
# Create ULP binary and embed into the application.
|
||||
|
||||
function(__setup_ulp_project app_name project_path s_sources exp_dep_srcs)
|
||||
function(__setup_ulp_project app_name project_path prefix s_sources exp_dep_srcs)
|
||||
|
||||
if(NOT CMAKE_BUILD_EARLY_EXPANSION)
|
||||
spaces2list(s_sources)
|
||||
@ -61,6 +61,7 @@ function(__setup_ulp_project app_name project_path s_sources exp_dep_srcs)
|
||||
-DULP_S_SOURCES=$<TARGET_PROPERTY:${app_name},ULP_SOURCES>
|
||||
-DULP_APP_NAME=${app_name}
|
||||
-DADD_PICOLIBC_SPECS=${CONFIG_LIBC_PICOLIBC}
|
||||
-DULP_VAR_PREFIX=${prefix}
|
||||
-DCOMPONENT_DIR=${COMPONENT_DIR}
|
||||
-DCOMPONENT_INCLUDES=$<TARGET_PROPERTY:${COMPONENT_TARGET},INTERFACE_INCLUDE_DIRECTORIES>
|
||||
-DIDF_TARGET=${idf_target}
|
||||
@ -93,9 +94,14 @@ function(__setup_ulp_project app_name project_path s_sources exp_dep_srcs)
|
||||
endfunction()
|
||||
|
||||
function(ulp_embed_binary app_name s_sources exp_dep_srcs)
|
||||
__setup_ulp_project("${app_name}" "${idf_path}/components/ulp/cmake" "${s_sources}" "${exp_dep_srcs}")
|
||||
cmake_parse_arguments(ULP "" "PREFIX" "" ${ARGN})
|
||||
if(NOT ULP_PREFIX)
|
||||
set(ULP_PREFIX "ulp_")
|
||||
endif()
|
||||
__setup_ulp_project("${app_name}" "${idf_path}/components/ulp/cmake"
|
||||
"${ULP_PREFIX}" "${s_sources}" "${exp_dep_srcs}")
|
||||
endfunction()
|
||||
|
||||
function(ulp_add_project app_name project_path)
|
||||
__setup_ulp_project("${app_name}" "${project_path}" "" "")
|
||||
__setup_ulp_project("${app_name}" "${project_path}" "ulp_" "" "")
|
||||
endfunction()
|
||||
|
Loading…
x
Reference in New Issue
Block a user