Skip to content

Commit c2a8f73

Browse files
committed
fix(esp_ulp): Add support for multiple ULP program embedding without name collision
1 parent f420609 commit c2a8f73

File tree

4 files changed

+79
-40
lines changed

4 files changed

+79
-40
lines changed

components/ulp/cmake/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ include(IDFULPProject)
88

99
ulp_apply_default_options(${ULP_APP_NAME})
1010
ulp_apply_default_sources(${ULP_APP_NAME})
11-
ulp_add_build_binary_targets(${ULP_APP_NAME})
11+
ulp_add_build_binary_targets(${ULP_APP_NAME} ${ULP_VAR_PREFIX})

components/ulp/cmake/IDFULPProject.cmake

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ function(ulp_apply_default_sources ulp_app_name)
178178
endif()
179179
endfunction()
180180

181-
function(ulp_add_build_binary_targets ulp_app_name)
181+
function(ulp_add_build_binary_targets ulp_app_name prefix)
182182

183183
if(CONFIG_ULP_COPROC_TYPE_LP_CORE)
184184
set(ULP_BASE_ADDR "0x0")
@@ -190,7 +190,7 @@ function(ulp_add_build_binary_targets ulp_app_name)
190190

191191
# Dump the list of global symbols in a convenient format
192192
add_custom_command(OUTPUT ${ULP_APP_NAME}.sym
193-
COMMAND ${CMAKE_NM} -f posix -g $<TARGET_FILE:${ulp_app_name}> > ${ulp_app_name}.sym
193+
COMMAND ${CMAKE_READELF} -sW $<TARGET_FILE:${ulp_app_name}> > ${ulp_app_name}.sym
194194
DEPENDS ${ulp_app_name}
195195
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
196196

@@ -201,7 +201,8 @@ function(ulp_add_build_binary_targets ulp_app_name)
201201
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
202202

203203
add_custom_command(OUTPUT ${ulp_app_name}.ld ${ulp_app_name}.h
204-
COMMAND ${ULP_MAP_GEN} -s ${ulp_app_name}.sym -o ${ulp_app_name} --base ${ULP_BASE_ADDR}
204+
COMMAND ${ULP_MAP_GEN} -s ${ulp_app_name}.sym -o ${ulp_app_name}
205+
--base ${ULP_BASE_ADDR} --prefix ${prefix}
205206
DEPENDS ${ulp_app_name}.sym
206207
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
207208

components/ulp/esp32ulp_mapgen.py

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,71 +2,103 @@
22
# esp32ulp_mapgen utility converts a symbol list provided by nm into an export script
33
# for the linker and a header file.
44
#
5-
# SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
5+
# SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD
66
# SPDX-License-Identifier: Apache-2.0
7-
8-
from __future__ import print_function
9-
107
import argparse
118
import os
9+
import re
1210
import textwrap
1311
import typing
1412

1513
UTIL = os.path.basename(__file__)
1614

1715

18-
def gen_ld_h_from_sym(f_sym: typing.TextIO, f_ld: typing.TextIO, f_h: typing.TextIO, base_addr: int) -> None:
16+
def name_mangling(name: str) -> str:
17+
# Simple and dumb name mangling for namespaced name following GCC algorithm
18+
ns, n = name.split('::')
19+
return '_ZN{0}{1}{2}{3}E'.format(len(ns), ns, len(n), n)
20+
21+
22+
def gen_ld_h_from_sym(f_sym: typing.TextIO, f_ld: typing.TextIO, f_h: typing.TextIO, base_addr: int, prefix: str) -> None:
1923
f_ld.write(textwrap.dedent(
2024
f"""
2125
/* ULP variable definitions for the linker.
2226
* This file is generated automatically by {UTIL} utility.
2327
*/
24-
"""
25-
))
26-
f_h.write(textwrap.dedent(
27-
f"""
28-
/* ULP variable definitions for the compiler.
29-
* This file is generated automatically by {UTIL} utility.
30-
*/
31-
#pragma once
32-
#ifdef __cplusplus
33-
extern "C" {{
34-
#endif
35-
"""
28+
""" # noqa: E222
3629
))
30+
cpp_mode = False
31+
var_prefix = prefix
32+
namespace = ''
33+
if '::' in prefix:
34+
# C++ mode, let's avoid the extern "C" type and instead use namespace
35+
f_h.write(textwrap.dedent(
36+
f"""
37+
/* ULP variable definitions for the compiler.
38+
* This file is generated automatically by {UTIL} utility.
39+
*/
40+
#pragma once
41+
""" # noqa: E222
42+
))
43+
namespace, var_prefix = prefix.split('::')
44+
f_h.write('namespace {0} {{\n'.format(namespace))
45+
cpp_mode = True
46+
else:
47+
f_h.write(textwrap.dedent(
48+
f"""
49+
/* ULP variable definitions for the compiler.
50+
* This file is generated automatically by {UTIL} utility.
51+
*/
52+
#pragma once
53+
#ifdef __cplusplus
54+
extern "C" {{
55+
#endif
56+
""" # noqa: E222
57+
))
3758

59+
expr = re.compile('^\\s*\\d+: ([a-f0-9]{8})\\s+(\\d+) OBJECT\\s+GLOBAL\\s+DEFAULT\\s+[^ ]+ (.*)$')
60+
already_defined = 'this_symbol_is_already_defined_please_use_prefix_in_ulp_embed_binary'
3861
for line in f_sym:
39-
# NM "posix" format output has the following structure:
40-
# symbol_name symbol_type addr_hex [size_hex]
41-
parts = line.split()
42-
name = parts[0]
43-
addr = int(parts[2], 16) + base_addr
44-
f_h.write('extern uint32_t ulp_{0};\n'.format(name))
45-
f_ld.write('PROVIDE ( ulp_{0} = 0x{1:08x} );\n'.format(name, addr))
62+
# readelf format output has the following structure:
63+
# index: addr_hex size TYPE SCOPE DEFAULT junk symbol_name
64+
# So match the line with a regular expression to parse it first
65+
groups = expr.match(line)
66+
if groups is None: # Ignore non global or non object
67+
continue
68+
addr = int(groups.group(1), 16) + base_addr
69+
size = int(groups.group(2))
70+
name = var_prefix + groups.group(3)
71+
f_h.write('extern uint32_t {0}{1};\n'.format(name, '[{0}]'.format(int(size / 4)) if size > 4 else ''))
72+
f_ld.write('{0} = DEFINED({0}) ? {2} : 0x{1:08x};\n'.format(
73+
name_mangling(namespace + '::' + name) if cpp_mode else name, addr, already_defined))
4674

47-
f_h.write(textwrap.dedent(
48-
"""
49-
#ifdef __cplusplus
50-
}
51-
#endif
52-
"""
53-
))
75+
if cpp_mode:
76+
f_h.write('}\n')
77+
else:
78+
f_h.write(textwrap.dedent(
79+
"""
80+
#ifdef __cplusplus
81+
}
82+
#endif
83+
"""
84+
))
5485

5586

5687
def main() -> None:
5788
description = ('This application generates .h and .ld files for symbols defined in input file. '
5889
'The input symbols file can be generated using nm utility like this: '
59-
'<PREFIX>nm -g -f posix <elf_file> > <symbols_file>')
90+
'<PREFIX>readelf -sW <elf_file> > <symbols_file>')
6091

6192
parser = argparse.ArgumentParser(description=description)
6293
parser.add_argument('-s', '--symfile', required=True, help='symbols file name', metavar='SYMFILE', type=argparse.FileType('r'))
6394
parser.add_argument('-o', '--outputfile', required=True, help='destination .h and .ld files name prefix', metavar='OUTFILE')
6495
parser.add_argument('--base-addr', required=True, help='base address of the ULP memory, to be added to each symbol')
96+
parser.add_argument('-p', '--prefix', required=False, help='prefix for generated header file', default='ulp_')
6597

6698
args = parser.parse_args()
6799

68100
with open(args.outputfile + '.h', 'w') as f_h, open(args.outputfile + '.ld', 'w') as f_ld:
69-
gen_ld_h_from_sym(args.symfile, f_ld, f_h, int(args.base_addr, 0))
101+
gen_ld_h_from_sym(args.symfile, f_ld, f_h, int(args.base_addr, 0), args.prefix)
70102

71103

72104
if __name__ == '__main__':

components/ulp/project_include.cmake

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# Create ULP binary and embed into the application.
44

5-
function(__setup_ulp_project app_name project_path s_sources exp_dep_srcs)
5+
function(__setup_ulp_project app_name project_path prefix s_sources exp_dep_srcs)
66

77
if(NOT CMAKE_BUILD_EARLY_EXPANSION)
88
spaces2list(s_sources)
@@ -60,6 +60,7 @@ function(__setup_ulp_project app_name project_path s_sources exp_dep_srcs)
6060
-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FLAG}
6161
-DULP_S_SOURCES=$<TARGET_PROPERTY:${app_name},ULP_SOURCES>
6262
-DULP_APP_NAME=${app_name}
63+
-DULP_VAR_PREFIX=${prefix}
6364
-DCOMPONENT_DIR=${COMPONENT_DIR}
6465
-DCOMPONENT_INCLUDES=$<TARGET_PROPERTY:${COMPONENT_TARGET},INTERFACE_INCLUDE_DIRECTORIES>
6566
-DIDF_TARGET=${idf_target}
@@ -92,9 +93,14 @@ function(__setup_ulp_project app_name project_path s_sources exp_dep_srcs)
9293
endfunction()
9394

9495
function(ulp_embed_binary app_name s_sources exp_dep_srcs)
95-
__setup_ulp_project("${app_name}" "${idf_path}/components/ulp/cmake" "${s_sources}" "${exp_dep_srcs}")
96+
cmake_parse_arguments(ULP "" "PREFIX" "" ${ARGN})
97+
if(NOT ULP_PREFIX)
98+
set(ULP_PREFIX "ulp_")
99+
endif()
100+
__setup_ulp_project("${app_name}" "${idf_path}/components/ulp/cmake"
101+
"${ULP_PREFIX}" "${s_sources}" "${exp_dep_srcs}")
96102
endfunction()
97103

98104
function(ulp_add_project app_name project_path)
99-
__setup_ulp_project("${app_name}" "${project_path}" "" "")
105+
__setup_ulp_project("${app_name}" "${project_path}" "ulp_" "" "")
100106
endfunction()

0 commit comments

Comments
 (0)