diff --git a/Documentation/ideas.md b/Documentation/ideas.md index 6cab31f1..2e240fff 100644 --- a/Documentation/ideas.md +++ b/Documentation/ideas.md @@ -15,6 +15,16 @@ Write the user choice to a file on the card. File contains 3 statuses: ignore, data, .. initdata? The latter is used for auto-selecting it as data partition. +- Support direct installation of an `.app` file with `tactility.py install helloworld.app ` +- Support `tactility.py target ` to remember the device IP address. +- External app error code 22 should warn that the user might've forgotten a `main()` entry point +- Bug: `Buildscript/release-sdk-current.sh` should delete the currently released SDK. It should probably also output it with versioning and target platform naming so it can be referred to as if it is a real release. +- Tactility docs: external app dev guide should explain [debugging](https://docs.zephyrproject.org/latest/services/llext/debug.html) +- elf_loader changes/suggestions: + - Make entry-point optional (so we can build libraries, or have the `manifest` as a global symbol) + - Implement support for alternative symbol lists. e.g. a function pointer that resolves a single symbol. +- Implement the entire list of [soft-float library functions](https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html) to `tt_init.cpp` +- `tactility.py` should stop running applications when it is: uninstalling, installing, or running an application that is already running. ## Medium Priority @@ -29,6 +39,7 @@ - Bug: Turn on WiFi (when testing it wasn't connected/connecting - just active). Open chat. Observe crash. - Bug: Crash handling app cannot be exited with an EncoderDevice. (current work-around is to manually reset the device) - I2C app should show error when I2C port is disabled when the scan button was manually pressed +- TactilitySDK: Support automatic scanning of header files so that we can generate the `tt_init.cpp` symbols list. ## Lower Priority diff --git a/Libraries/elf_loader/CHANGELOG.md b/Libraries/elf_loader/CHANGELOG.md index 3a0651b8..d10f8d5f 100644 --- a/Libraries/elf_loader/CHANGELOG.md +++ b/Libraries/elf_loader/CHANGELOG.md @@ -1,5 +1,16 @@ # ChangeLog +## v1.1.1 - 2025-06-26 + +* Added support for ESP32-C61 + +## v1.1.0 - 2025-05-06 + +* Added fast build for ELF application +* Added a script to generate the symbol table for the ELF APP: + * Supports generating symbols table based on ELF file + * Supports generating symbols table based on static libraries + ## v1.0.0 - 2024-12-09 * Added support for the following RISC-V chips: ESP32-P4 and ESP32-C6 diff --git a/Libraries/elf_loader/CMakeLists.txt b/Libraries/elf_loader/CMakeLists.txt index a6d4edba..4a8ddb63 100644 --- a/Libraries/elf_loader/CMakeLists.txt +++ b/Libraries/elf_loader/CMakeLists.txt @@ -4,6 +4,10 @@ if(CONFIG_ELF_LOADER) "src/esp_elf.c" "src/esp_elf_adapter.c") + if(CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS) + list(APPEND srcs "src/esp_all_symbol.c") + endif() + if(CONFIG_IDF_TARGET_ARCH_XTENSA) list(APPEND srcs "src/arch/esp_elf_xtensa.c") diff --git a/Libraries/elf_loader/Kconfig b/Libraries/elf_loader/Kconfig index 673df38d..be8f32b7 100644 --- a/Libraries/elf_loader/Kconfig +++ b/Libraries/elf_loader/Kconfig @@ -1,15 +1,15 @@ menu "Espressif ELF Loader Configuration" - visible if (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4) + visible if (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4 || IDF_TARGET_ESP32C61) config ELF_LOADER_BUS_ADDRESS_MIRROR bool default y if (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) - default n if (IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4) + default n if (IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4 || IDF_TARGET_ESP32C61) config ELF_LOADER bool "Enable Espressif ELF Loader" default y - depends on (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4) + depends on (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4 || IDF_TARGET_ESP32C61) help Select this option to enable ELF Loader and show the submenu with ELF Loader configuration choices. @@ -29,7 +29,7 @@ menu "Espressif ELF Loader Configuration" config ELF_LOADER_LOAD_PSRAM bool "Load ELF to PSRAM" default y - depends on (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM + depends on (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4 || IDF_TARGET_ESP32C61) && SPIRAM select ELF_LOADER_CACHE_OFFSET if (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) select ELF_LOADER_SET_MMU if IDF_TARGET_ESP32S2 help diff --git a/Libraries/elf_loader/README.md b/Libraries/elf_loader/README.md index 749ebd93..1e6090c7 100644 --- a/Libraries/elf_loader/README.md +++ b/Libraries/elf_loader/README.md @@ -13,6 +13,7 @@ This ELF loader supports following SoCs: - ESP32-S3, support running ELF in PSRAM - ESP32-P4, support running ELF in PSRAM - ESP32-C6 +- ESP32-C61, support running ELF in PSRAM ### Usage @@ -62,6 +63,29 @@ project_elf(XXXX) Build the project as an ordinary ESP-IDF project, and then the ELF file named `XXXX.app.elf` is in the build directory. +### ELF APP Fast Build + +Users can enable ELF fast build functionality by configuring CMAKE's generator as Unit Makefile. The reference command is as follows: + +```bash +idf.py -G 'Unix Makefiles' set-target +``` + +Then input the ELF APP build command as follows: + +``` +idf.py elf +``` + +The build system will only build ELF target components and show the following logs: + +``` +Building C object esp-idf/main/CMakeFiles/__idf_main.dir/main.c.obj +Linking C static library libmain.a +Build ELF: hello_world.app.elf +Built target elf +``` + ### Adding the Component to Your Project Please use the component manager command add-dependency to add the elf_loader component as a dependency in your project. During the CMake step, the component will be downloaded automatically. diff --git a/Libraries/elf_loader/elf_loader.cmake b/Libraries/elf_loader/elf_loader.cmake index 1880311a..dc14cf5e 100644 --- a/Libraries/elf_loader/elf_loader.cmake +++ b/Libraries/elf_loader/elf_loader.cmake @@ -52,7 +52,16 @@ macro(project_elf project_name) if(ELF_COMPONENTS) foreach(c ${ELF_COMPONENTS}) list(APPEND elf_libs "esp-idf/${c}/lib${c}.a") - list(APPEND elf_dependeces "idf::${c}") + + if(${CMAKE_GENERATOR} STREQUAL "Unix Makefiles") + add_custom_command(OUTPUT elf_${c}_app + COMMAND +${CMAKE_MAKE_PROGRAM} "__idf_${c}/fast" + COMMENT "Build Component: ${c}" + ) + list(APPEND elf_dependeces "elf_${c}_app") + else() + list(APPEND elf_dependeces "idf::${c}") + endif() endforeach() endif() if (ELF_LIBS) diff --git a/Libraries/elf_loader/idf_component.yml b/Libraries/elf_loader/idf_component.yml index c5b4e8a6..65795807 100644 --- a/Libraries/elf_loader/idf_component.yml +++ b/Libraries/elf_loader/idf_component.yml @@ -1,4 +1,11 @@ -version: "1.0.0" +version: "1.1.1" +targets: + - esp32 + - esp32s2 + - esp32s3 + - esp32c6 + - esp32c61 + - esp32p4 description: Espressif ELF(Executable and Linkable Format) Loader url: https://github.com/espressif/esp-iot-solution/tree/master/components/elf_loader dependencies: diff --git a/Libraries/elf_loader/include/private/elf_symbol.h b/Libraries/elf_loader/include/private/elf_symbol.h index 447756a4..3b58e021 100644 --- a/Libraries/elf_loader/include/private/elf_symbol.h +++ b/Libraries/elf_loader/include/private/elf_symbol.h @@ -12,9 +12,7 @@ extern "C" { #endif -// Tactility custom --> -#define ESP_ELFSYM_EXPORT(_sym) { #_sym, (const void*)&_sym } -// <-- Tactility custom +#define ESP_ELFSYM_EXPORT(_sym) { #_sym, (void*)&_sym } #define ESP_ELFSYM_END { NULL, NULL } /** @brief Function symbol description */ @@ -33,9 +31,23 @@ struct esp_elfsym { */ uintptr_t elf_find_sym(const char *sym_name); -// Tactility custom --> -void elf_set_custom_symbols(const struct esp_elfsym* symbols); -// <-- Tactility custom + +/** + * @brief Resolves a symbol name (e.g. function name) to its address. + * + * @param sym_name - Symbol name + * @return Symbol address if success or 0 if failed. + */ +typedef uintptr_t (*symbol_resolver)(const char *sym_name); + +/** + * @brief Override the internal symbol resolver. + * The default resolver is based on static lists that are determined by KConfig. + * This override allows for an arbitrary implementation. + * + * @param resolver the resolver function + */ +void elf_set_symbol_resolver(symbol_resolver resolver); #ifdef __cplusplus } diff --git a/Libraries/elf_loader/src/esp_all_symbol.c b/Libraries/elf_loader/src/esp_all_symbol.c new file mode 100644 index 00000000..b30bc62c --- /dev/null +++ b/Libraries/elf_loader/src/esp_all_symbol.c @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "private/elf_symbol.h" + +/* Extern declarations from ELF symbol table */ + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch" +#pragma GCC diagnostic pop + +/* Available ELF symbols table: g_customer_elfsyms */ + +const struct esp_elfsym g_customer_elfsyms[] = { + ESP_ELFSYM_END +}; diff --git a/Libraries/elf_loader/src/esp_elf.c b/Libraries/elf_loader/src/esp_elf.c index 385cefa3..6139be3c 100644 --- a/Libraries/elf_loader/src/esp_elf.c +++ b/Libraries/elf_loader/src/esp_elf.c @@ -19,12 +19,27 @@ #include "private/elf_symbol.h" #include "private/elf_platform.h" +#include "esp_elf.h" #define stype(_s, _t) ((_s)->type == (_t)) #define sflags(_s, _f) (((_s)->flags & (_f)) == (_f)) #define ADDR_OFFSET (0x400) +uintptr_t elf_find_sym_default(const char *sym_name); + static const char *TAG = "ELF"; +static symbol_resolver current_resolver = elf_find_sym_default; + +/** + * @brief Find symbol address by name. + * + * @param sym_name - Symbol name + * + * @return Symbol address if success or 0 if failed. + */ +uintptr_t elf_find_sym(const char *sym_name) { + return current_resolver(sym_name); +} #if CONFIG_ELF_LOADER_BUS_ADDRESS_MIRROR @@ -306,6 +321,18 @@ static int esp_elf_load_segment(esp_elf_t *elf, const uint8_t *pbuf) } #endif +/** + * @brief Override the internal symbol resolver. + * The default resolver is based on static lists that are determined by KConfig. + * This override allows for an arbitrary implementation. + * + * @param resolver the resolver function + */ +void elf_set_symbol_resolver(symbol_resolver resolver) { + current_resolver = resolver; +} + + /** * @brief Map symbol's address of ELF to physic space. * diff --git a/Libraries/elf_loader/src/esp_elf_symbol.c b/Libraries/elf_loader/src/esp_elf_symbol.c index 66e4862c..5bddcfd7 100644 --- a/Libraries/elf_loader/src/esp_elf_symbol.c +++ b/Libraries/elf_loader/src/esp_elf_symbol.c @@ -27,13 +27,6 @@ extern int __gtdf2(double a, double b); extern double __floatunsidf(unsigned int i); extern double __divdf3(double a, double b); -// Tactility custom --> -static const struct esp_elfsym* custom_symbols = NULL; -void elf_set_custom_symbols(const struct esp_elfsym* symbols) { - custom_symbols = symbols; -} -// <-- Tactility custom - /** @brief Libc public functions symbols look-up table */ static const struct esp_elfsym g_esp_libc_elfsyms[] = { @@ -163,7 +156,7 @@ static const struct esp_elfsym g_esp_espidf_elfsyms[] = { * * @return Symbol address if success or 0 if failed. */ -uintptr_t elf_find_sym(const char *sym_name) +uintptr_t elf_find_sym_default(const char *sym_name) { const struct esp_elfsym *syms; @@ -208,16 +201,5 @@ uintptr_t elf_find_sym(const char *sym_name) } #endif -// Tactility custom --> - syms = custom_symbols; - while (syms->name) { - if (!strcmp(syms->name, sym_name)) { - return (uintptr_t)syms->sym; - } - - syms++; - } -// <-- Tactility custom - return 0; } diff --git a/Libraries/elf_loader/tool/symbols.py b/Libraries/elf_loader/tool/symbols.py new file mode 100755 index 00000000..79dc7582 --- /dev/null +++ b/Libraries/elf_loader/tool/symbols.py @@ -0,0 +1,268 @@ +#!/usr/bin/env python +# +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: Apache-2.0 + +import logging +import os +import argparse +import sys +import re +import subprocess + +def get_global_symbols(lines, type, undefined=False, symbol_types=None): + """ + Extract global symbols from the given lines of a symbol table. + + :param lines: List of lines from the symbol table, each representing a symbol. + :param type: Type of the input file ('e' for ELF files, 'l' for static libraries). + :param undefined: If True, only extract undefined (UND) symbols; otherwise, extract all GLOBAL symbols. + :param symbol_types: A list of symbol types to filter by (e.g., ['FUNC', 'OBJECT']). If None, no filtering by type. + :return: List of symbol names if any match the criteria; otherwise, returns an empty list. + """ + symbols = [] + + if type == 'e': + # Pattern for ELF files + if not undefined: + pattern = re.compile( + r'^\s*\d+:\s+(\S+)\s+(\d+)\s+(FUNC|OBJECT)\s+GLOBAL\s+DEFAULT\s+(?:\d+|ABS|UND|COM|DEBUG)\s+(\S+)', + re.MULTILINE + ) + else: + pattern = re.compile( + r'^\s*\d*:\s*\w*\s*\d*\s*NOTYPE\s*GLOBAL\s*DEFAULT\s*UND\s+(\S*)', + re.MULTILINE + ) + + for line in lines: + match = pattern.match(line) + if match: + if not undefined: + address, size, symbol_type, symbol_name = match.groups() + + # Filter by symbol type if specified + if symbol_types and symbol_type not in symbol_types: + continue + + symbols.append(symbol_name) + else: + symbol_name = match.group(1) + symbols.append(symbol_name) + + elif type == 'l': + # Patterns for static libraries + func_pattern = re.compile(r'^\s*[0-9a-fA-F]+\s+[TD]\s+(\S+)$') + var_pattern = re.compile(r'^\s*[0-9a-fA-F]+\s+[BD]\s+(\S+)$') + + for line in lines: + if not undefined: + func_match = func_pattern.match(line) + var_match = var_pattern.match(line) + + if func_match: + symbols.append(func_match.group(1)) + elif var_match: + symbols.append(var_match.group(1)) + + return symbols + +def save_c_file(symbols, output, symbol_table, exclude_symbols=None): + """ + Write extern declarations and ESP_ELFSYM structure to a C file, excluding specified symbols. + + :param symbols: List of symbol names. + :param output: Path to the output C file. + :param exclude_symbols: List of symbol names to exclude; defaults to ['elf_find_sym']. + """ + if exclude_symbols is None: + exclude_symbols = ['elf_find_sym'] # Set default excluded symbols + + # Filter out excluded symbols + filtered_symbols = [name for name in symbols if name not in exclude_symbols] + + # Build the content of the C file + buf = '/*\n' + buf += ' * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD\n' + buf += ' *\n' + buf += ' * SPDX-License-Identifier: Apache-2.0\n' + buf += ' */\n\n' + + # Add standard library headers + libc_headers = ['stddef'] # Add more headers as needed + buf += '\n'.join([f'#include <{h}.h>' for h in libc_headers]) + '\n\n' + + # Add custom header + buf += '#include "private/elf_symbol.h"\n\n' + + # Generate extern declarations if there are symbols + if filtered_symbols: + buf += '/* Extern declarations from ELF symbol table */\n\n' + buf += '#pragma GCC diagnostic push\n' + buf += '#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch"\n' + for symbol_name in filtered_symbols: + buf += f'extern int {symbol_name};\n' + buf += '#pragma GCC diagnostic pop\n\n' + + # Define the symbol table structure with dynamic variable name + symbol_table_var = f'g_{symbol_table}_elfsyms' + buf += f'/* Available ELF symbols table: {symbol_table_var} */\n' + buf += f'\nconst struct esp_elfsym {symbol_table_var}[] = {{\n' + + # Generate ESP_ELFSYM_EXPORT entries + if filtered_symbols: + for symbol_name in filtered_symbols: + buf += f' ESP_ELFSYM_EXPORT({symbol_name}),\n' + + # End the symbol table + buf += ' ESP_ELFSYM_END\n' + buf += '};\n' + + # Write to the file + with open(output, 'w+') as f: + f.write(buf) + +def main(): + """ + Main function to parse command-line arguments and process the input file's symbol table. + """ + parser = argparse.ArgumentParser(description='Extract all public functions from an application project', prog='symbols') + + parser.add_argument( + '--output-file', '-of', + help='Custom output file path with filename (overrides --output)', + default=None + ) + + parser.add_argument( + '--input', '-i', + help='Input file name with full path', + required=True + ) + + parser.add_argument( + '--undefined', '-u', + action='store_true', + help='If set, only extract undefined (UND) symbols; otherwise, extract all GLOBAL symbols.', + default=False + ) + + parser.add_argument( + '--exclude', '-e', + nargs='+', + help='Symbols to exclude from the generated C file (e.g., memcpy __ltdf2). Default: elf_find_sym', + default=[] # User can extend this list + ) + + parser.add_argument( + '--type', '-t', + choices=['e', 'l'], + required=True, + help='Type of the input file: "elf" for ELF file, "lib" for static library (.a)' + ) + + parser.add_argument( + '--debug', '-d', + help='Debug level(option is \'debug\')', + default='no', + type=str) + + args = parser.parse_args() + + # Configure logging + if args.debug == 'debug': + logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') + else: + logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + + # Get the absolute path of the current file + cur_dir = os.path.dirname(os.path.abspath(__file__)) + + if args.type == 'e': + extracted_part = 'customer' + elif args.type == 'l': + # Convert relative path to absolute path + input_abs_path = os.path.abspath(args.input) + + # Get the base name of the input file (without extension) + input_basename = os.path.basename(input_abs_path) + + # Use a regular expression to extract the middle part + match = re.search(r'^lib(.+)\.a$', input_basename) + if match: + extracted_part = match.group(1) + else: + logging.error('Invalid input file name format. Expected format: lib.a') + sys.exit(1) + + # Determine the output file path + if args.output_file: + # Use the custom file path provided by the user + elfsym_file_dir = os.path.abspath(args.output_file) + output_dir = os.path.dirname(elfsym_file_dir) + output_abs_path = os.path.abspath(args.output_file) + output_basename = os.path.basename(output_abs_path) + extracted_part = os.path.splitext(output_basename)[0] + else: + # Use the default behavior: generate the file in the parent directory's 'src' folder + parent_dir = os.path.dirname(cur_dir) + output_dir = os.path.join(parent_dir, 'src') # Default directory is 'src' under the parent directory + output_file_name = f'esp_all_symbol.c' + elfsym_file_dir = os.path.join(output_dir, output_file_name) + + # Ensure the output directory exists + os.makedirs(output_dir, exist_ok=True) + + # Set default excluded symbols and allow user to extend the list + exclude_symbols = ['elf_find_sym', 'g_customer_elfsyms'] + args.exclude + + if args.type == 'e': + cmd = ['readelf', '-s', '-W', args.input] + elif args.type == 'l': + cmd = ['nm', '--defined-only', '-g', args.input] + + # Execute the readelf or nm command for static libraries + try: + result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True) + lines = result.stdout.splitlines() + except subprocess.CalledProcessError as e: + logging.error(f'Error executing command: {e.stderr}') + sys.exit(1) + except FileNotFoundError: + logging.error('nm command not found. Please ensure it is installed and available in your PATH.') + sys.exit(1) + + # Extract global symbols from ELF file or static library + symbols = get_global_symbols(lines, type=args.type, undefined=args.undefined, symbol_types=['FUNC', 'OBJECT']) + + if not symbols: + logging.warning('No global symbols found in the input file.') + sys.exit(0) + + logging.debug('symbols: %s'%(cmd)) + logging.debug('symbols: %s'%(symbols)) + logging.debug('elfsym_file_dir: %s'%(elfsym_file_dir)) + logging.debug('extracted_part: %s'%(extracted_part)) + logging.debug('exclude_symbols: %s'%(exclude_symbols)) + + # Save the C file + try: + save_c_file(symbols, elfsym_file_dir, extracted_part, exclude_symbols=exclude_symbols) + logging.info(f"C file with extern declarations and symbol table has been saved to '{elfsym_file_dir}'.") + except Exception as e: + logging.error(f'Error writing C file: {e}') + sys.exit(1) + +def _main(): + """ + Wrapper for the main function to catch and handle runtime errors. + """ + try: + main() + except RuntimeError as e: + logging.error(f'A fatal error occurred: {e}') + sys.exit(2) + +if __name__ == '__main__': + _main() diff --git a/TactilityC/CMakeLists.txt b/TactilityC/CMakeLists.txt index c3d239b3..97c81c4a 100644 --- a/TactilityC/CMakeLists.txt +++ b/TactilityC/CMakeLists.txt @@ -9,6 +9,7 @@ if (DEFINED ENV{ESP_IDF_VERSION}) idf_component_register( SRCS ${SOURCE_FILES} INCLUDE_DIRS "Include/" + PRIV_INCLUDE_DIRS "Private/" REQUIRES lvgl PRIV_REQUIRES Tactility TactilityCore elf_loader ) @@ -21,16 +22,12 @@ else() add_library(TactilityC OBJECT) - target_sources(TactilityC - PRIVATE ${SOURCES} - ) - - target_include_directories(TactilityC - PUBLIC Include/ - ) - add_definitions(-D_Nullable=) add_definitions(-D_Nonnull=) + + target_sources(TactilityC PRIVATE ${SOURCES}) + include_directories(TactilityC PRIVATE Private/) + target_include_directories(TactilityC PUBLIC Include/) target_link_libraries(TactilityC PRIVATE Tactility PRIVATE TactilityCore diff --git a/TactilityC/Private/symbols/gcc_soft_float.h b/TactilityC/Private/symbols/gcc_soft_float.h new file mode 100644 index 00000000..120e9ef6 --- /dev/null +++ b/TactilityC/Private/symbols/gcc_soft_float.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern const esp_elfsym gcc_soft_float_symbols[]; + +#ifdef __cplusplus +} +#endif diff --git a/TactilityC/Source/symbols/gcc_soft_float.cpp b/TactilityC/Source/symbols/gcc_soft_float.cpp new file mode 100644 index 00000000..45dd9cfd --- /dev/null +++ b/TactilityC/Source/symbols/gcc_soft_float.cpp @@ -0,0 +1,280 @@ +#include +#include + +extern "C" { + +// Reference: https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html + +extern float __addsf3(float a, float b); +extern double __adddf3(double a, double b); +// extern long double __addtf3(long double a, long double b); +// extern long double __addxf3(long double a, long double b); + +extern float __subsf3(float a, float b); +extern double __subdf3(double a, double b); +// extern long double __subtf3(long double a, long double b); +// extern long double __subxf3(long double a, long double b); + +extern float __mulsf3(float a, float b); +extern double __muldf3(double a, double b); +// extern long double __multf3(long double a, long double b); +// extern long double __mulxf3(long double a, long double b); + +extern float __divsf3(float a, float b); +extern double __divdf3(double a, double b); +// extern long double __divtf3(long double a, long double b); +// extern long double __divxf3(long double a, long double b); + +extern float __negsf2(float a); +extern double __negdf2(double a); +// extern long double __negtf2(long double a); +// extern long double __negxf2(long double a); + +extern double __extendsfdf2(float a); +// extern long double __extendsftf2(float a); +// extern long double __extendsfxf2(float a); +// extern long double __extenddftf2(double a); +// extern long double __extenddfxf2(double a); + +// extern double __truncxfdf2(long double a); +// extern double __trunctfdf2(long double a); +// extern float __truncxfsf2(long double a); +// extern float __trunctfsf2(long double a); +extern float __truncdfsf2(double a); + +extern int __fixsfsi(float a); +extern int __fixdfsi(double a); +// extern int __fixtfsi(long double a); +// extern int __fixxfsi(long double a); + +extern long __fixsfdi(float a); +extern long __fixdfdi(double a); +// extern long __fixtfdi(long double a); +// extern long __fixxfdi(long double a); + +// extern long long __fixsfti(float a); +// extern long long __fixdfti(double a); +// extern long long __fixtfti(long double a); +// extern long long __fixxfti(long double a); + +// extern unsigned int __fixunssfsi(float a); +// extern unsigned int __fixunsdfsi(double a); +// extern unsigned int __fixunstfsi(long double a); +// extern unsigned int __fixunsxfsi(long double a); + +extern unsigned long __fixunssfdi(float a); +extern unsigned long __fixunsdfdi(double a); +// extern unsigned long __fixunstfdi(long double a); +// extern unsigned long __fixunsxfdi(long double a); + +// extern unsigned long long __fixunssfti(float a); +// extern unsigned long long __fixunsdfti(double a); +// extern unsigned long long __fixunstfti(long double a); +// extern unsigned long long __fixunsxfti(long double a); + +// extern float __floatsisf(int i); +// extern double __floatsidf(int i); +// extern long double __floatsitf(int i); +// extern long double __floatsixf(int i); + +extern float __floatdisf(long i); +extern double __floatdidf(long i); +// extern long double __floatditf(long i); +// extern long double __floatdixf(long i); + +// extern float __floattisf(long long i); +// extern double __floattidf(long long i); +// extern long double __floattitf(long long i); +// extern long double __floattixf(long long i); + +extern float __floatunsisf(unsigned int i); +extern double __floatunsidf(unsigned int i); +// extern long double __floatunsitf(unsigned int i); +// extern long double __floatunsixf(unsigned int i); + +extern float __floatundisf(unsigned long i); +extern double __floatundidf(unsigned long i); +// extern long double __floatunditf(unsigned long i); +// extern long double __floatundixf(unsigned long i); + +// extern float __floatuntisf(unsigned long long i); +// extern double __floatuntidf(unsigned long long i); +// extern long double __floatuntitf(unsigned long long i); +// extern long double __floatuntixf(unsigned long long i); + +float __powisf2(float a, int b); +double __powidf2(double a, int b); +// long double __powitf2(long double a, int b); +// long double __powixf2(long double a, int b); + +// int __cmpsf2(float a, float b); +int __cmpdf2(double a, double b); +// int __cmptf2(long double a, long double b); + +int __unordsf2(float a, float b); +int __unorddf2(double a, double b); +// int __unordtf2(long double a, long double b); + +int __eqsf2(float a, float b); +int __eqdf2(double a, double b); +// int __eqtf2(long double a, long double b); + +int __nesf2(float a, float b); +int __nedf2(double a, double b); +// int __netf2(long double a, long double b); + +int __gesf2(float a, float b); +int __gedf2(double a, double b); +// int __getf2(long double a, long double b); + +int __ltsf2(float a, float b); +int __ltdf2(double a, double b); +// int __lttf2(long double a, long double b); + +int __lesf2(float a, float b); +int __ledf2(double a, double b); +// int __letf2(long double a, long double b); + +int __gtsf2(float a, float b); +int __gtdf2(double a, double b); +// int __gttf2(long double a, long double b); + +const esp_elfsym gcc_soft_float_symbols[] = { + ESP_ELFSYM_EXPORT(__addsf3), + ESP_ELFSYM_EXPORT(__adddf3), + // ESP_ELFSYM_EXPORT(__addtf3), + // ESP_ELFSYM_EXPORT(__addxf3), + + ESP_ELFSYM_EXPORT(__subsf3), + ESP_ELFSYM_EXPORT(__subdf3), + // ESP_ELFSYM_EXPORT(__subtf3), + // ESP_ELFSYM_EXPORT(__subxf3), + + ESP_ELFSYM_EXPORT(__mulsf3), + ESP_ELFSYM_EXPORT(__muldf3), + // ESP_ELFSYM_EXPORT(__multf3), + // ESP_ELFSYM_EXPORT(__mulxf3), + + ESP_ELFSYM_EXPORT(__divsf3), + ESP_ELFSYM_EXPORT(__divdf3), + // ESP_ELFSYM_EXPORT(__divtf3), + // ESP_ELFSYM_EXPORT(__divxf3), + + ESP_ELFSYM_EXPORT(__negsf2), + ESP_ELFSYM_EXPORT(__negdf2), + // ESP_ELFSYM_EXPORT(__negtf2), + // ESP_ELFSYM_EXPORT(__negxf2), + + ESP_ELFSYM_EXPORT(__extendsfdf2), + // ESP_ELFSYM_EXPORT(__extendsftf2), + // ESP_ELFSYM_EXPORT(__extendsfxf2), + // ESP_ELFSYM_EXPORT(__extenddftf2), + // ESP_ELFSYM_EXPORT(__extenddfxf2), + + // ESP_ELFSYM_EXPORT(__truncxfdf2), + // ESP_ELFSYM_EXPORT(__trunctfdf2), + // ESP_ELFSYM_EXPORT(__truncxfsf2), + // ESP_ELFSYM_EXPORT(__trunctfsf2), + ESP_ELFSYM_EXPORT(__truncdfsf2), + + ESP_ELFSYM_EXPORT(__fixsfsi), + ESP_ELFSYM_EXPORT(__fixdfsi), + // ESP_ELFSYM_EXPORT(__fixtfsi), + // ESP_ELFSYM_EXPORT(__fixxfsi), + + ESP_ELFSYM_EXPORT(__fixsfdi), + ESP_ELFSYM_EXPORT(__fixdfdi), + // ESP_ELFSYM_EXPORT(__fixtfdi), + // ESP_ELFSYM_EXPORT(__fixxfdi), + + // ESP_ELFSYM_EXPORT(__fixsfti), + // ESP_ELFSYM_EXPORT(__fixdfti), + // ESP_ELFSYM_EXPORT(__fixtfti), + // ESP_ELFSYM_EXPORT(__fixxfti), + + // ESP_ELFSYM_EXPORT(__fixunssfsi), + // ESP_ELFSYM_EXPORT(__fixunsdfsi), + // ESP_ELFSYM_EXPORT(__fixunstfsi), + // ESP_ELFSYM_EXPORT(__fixunsxfsi), + + ESP_ELFSYM_EXPORT(__fixunssfdi), + ESP_ELFSYM_EXPORT(__fixunsdfdi), + // ESP_ELFSYM_EXPORT(__fixunstfdi), + // ESP_ELFSYM_EXPORT(__fixunsxfdi), + + // ESP_ELFSYM_EXPORT(__fixunssfti), + // ESP_ELFSYM_EXPORT(__fixunsdfti), + // ESP_ELFSYM_EXPORT(__fixunstfti), + // ESP_ELFSYM_EXPORT(__fixunsxfti), + + // ESP_ELFSYM_EXPORT(__floatsisf), + // ESP_ELFSYM_EXPORT(__floatsidf), + // ESP_ELFSYM_EXPORT(__floatsitf), + // ESP_ELFSYM_EXPORT(__floatsixf), + + ESP_ELFSYM_EXPORT(__floatdisf), + ESP_ELFSYM_EXPORT(__floatdidf), + // ESP_ELFSYM_EXPORT(__floatditf), + // ESP_ELFSYM_EXPORT(__floatdixf), + + // ESP_ELFSYM_EXPORT(__floattisf), + // ESP_ELFSYM_EXPORT(__floattidf), + // ESP_ELFSYM_EXPORT(__floattitf), + // ESP_ELFSYM_EXPORT(__floattixf), + + ESP_ELFSYM_EXPORT(__floatunsisf), + ESP_ELFSYM_EXPORT(__floatunsidf), + // ESP_ELFSYM_EXPORT(__floatunsitf), + // ESP_ELFSYM_EXPORT(__floatunsixf), + + ESP_ELFSYM_EXPORT(__floatundisf), + ESP_ELFSYM_EXPORT(__floatundidf), + // ESP_ELFSYM_EXPORT(__floatunditf), + // ESP_ELFSYM_EXPORT(__floatundixf), + + // ESP_ELFSYM_EXPORT(__floatuntisf), + // ESP_ELFSYM_EXPORT(__floatuntidf), + // ESP_ELFSYM_EXPORT(__floatuntitf), + // ESP_ELFSYM_EXPORT(__floatuntixf), + + ESP_ELFSYM_EXPORT(__powisf2), + ESP_ELFSYM_EXPORT(__powidf2), + // ESP_ELFSYM_EXPORT(__powitf2), + // ESP_ELFSYM_EXPORT(__powixf2), + + // ESP_ELFSYM_EXPORT(__cmpsf2), + // ESP_ELFSYM_EXPORT(__cmpdf2), + // ESP_ELFSYM_EXPORT(__cmptf2), + + ESP_ELFSYM_EXPORT(__unordsf2), + ESP_ELFSYM_EXPORT(__unorddf2), + // ESP_ELFSYM_EXPORT(__unordtf2), + + ESP_ELFSYM_EXPORT(__eqsf2), + ESP_ELFSYM_EXPORT(__eqdf2), + // ESP_ELFSYM_EXPORT(__eqtf2), + + ESP_ELFSYM_EXPORT(__nesf2), + ESP_ELFSYM_EXPORT(__nedf2), + // ESP_ELFSYM_EXPORT(__netf2), + + ESP_ELFSYM_EXPORT(__gesf2), + ESP_ELFSYM_EXPORT(__gedf2), + // ESP_ELFSYM_EXPORT(__getf2), + + ESP_ELFSYM_EXPORT(__ltsf2), + ESP_ELFSYM_EXPORT(__ltdf2), + // ESP_ELFSYM_EXPORT(__lttf2), + + ESP_ELFSYM_EXPORT(__lesf2), + ESP_ELFSYM_EXPORT(__ledf2), + // ESP_ELFSYM_EXPORT(__letf2), + + ESP_ELFSYM_EXPORT(__gtsf2), + ESP_ELFSYM_EXPORT(__gtdf2), + // ESP_ELFSYM_EXPORT(__gttf2), + + ESP_ELFSYM_END +}; + +} \ No newline at end of file diff --git a/TactilityC/Source/tt_init.cpp b/TactilityC/Source/tt_init.cpp index e3e374b1..1a74e772 100644 --- a/TactilityC/Source/tt_init.cpp +++ b/TactilityC/Source/tt_init.cpp @@ -25,38 +25,72 @@ #include "tt_timer.h" #include "tt_wifi.h" +#include +#include "symbols/gcc_soft_float.h" + #include #include -#include #include #include #include +#include #include +#include +#include extern "C" { -// Hidden functions work-around +// GCC internal new and delete extern void* _Znwj(uint32_t size); extern void _ZdlPvj(void* p, uint64_t size); -extern double __adddf3(double a, double b); -extern double __subdf3(double a, double b); -extern double __muldf3 (double a, double b); -extern double __divdf3 (double a, double b); -extern int __nedf2 (double a, double b); const esp_elfsym elf_symbols[] { - // Hidden functions work-around - ESP_ELFSYM_EXPORT(_ZdlPvj), // new? - ESP_ELFSYM_EXPORT(_Znwj), // delete? - ESP_ELFSYM_EXPORT(__adddf3), // Routines for floating point emulation: - ESP_ELFSYM_EXPORT(__subdf3), // See https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html - ESP_ELFSYM_EXPORT(__muldf3), - ESP_ELFSYM_EXPORT(__nedf2), - ESP_ELFSYM_EXPORT(__divdf3), - // + // GCC internal + ESP_ELFSYM_EXPORT(_Znwj), // new + ESP_ELFSYM_EXPORT(_ZdlPvj), // delete + // stdlib.h + ESP_ELFSYM_EXPORT(malloc), + ESP_ELFSYM_EXPORT(calloc), + ESP_ELFSYM_EXPORT(realloc), + ESP_ELFSYM_EXPORT(free), + // unistd.h + ESP_ELFSYM_EXPORT(usleep), + ESP_ELFSYM_EXPORT(sleep), + ESP_ELFSYM_EXPORT(exit), + ESP_ELFSYM_EXPORT(close), + // time.h + ESP_ELFSYM_EXPORT(clock_gettime), + ESP_ELFSYM_EXPORT(strftime), + // pthread + ESP_ELFSYM_EXPORT(pthread_create), + ESP_ELFSYM_EXPORT(pthread_attr_init), + ESP_ELFSYM_EXPORT(pthread_attr_setstacksize), + ESP_ELFSYM_EXPORT(pthread_detach), + ESP_ELFSYM_EXPORT(pthread_join), + ESP_ELFSYM_EXPORT(pthread_exit), + // sys/errno.h + ESP_ELFSYM_EXPORT(__errno), + // freertos_tasks_c_additions.h + ESP_ELFSYM_EXPORT(__getreent), +#ifdef __HAVE_LOCALE_INFO__ + // ctype.h + ESP_ELFSYM_EXPORT(__locale_ctype_ptr), +#else + ESP_ELFSYM_EXPORT(_ctype_), +#endif + // getopt.h + ESP_ELFSYM_EXPORT(getopt_long), + ESP_ELFSYM_EXPORT(optind), + ESP_ELFSYM_EXPORT(opterr), + ESP_ELFSYM_EXPORT(optarg), + ESP_ELFSYM_EXPORT(optopt), + // setjmp.h + ESP_ELFSYM_EXPORT(longjmp), + ESP_ELFSYM_EXPORT(setjmp), + // cassert ESP_ELFSYM_EXPORT(__assert_func), - // + // cstdio ESP_ELFSYM_EXPORT(fclose), ESP_ELFSYM_EXPORT(feof), ESP_ELFSYM_EXPORT(ferror), @@ -90,6 +124,12 @@ const esp_elfsym elf_symbols[] { ESP_ELFSYM_EXPORT(strcat), ESP_ELFSYM_EXPORT(strchr), ESP_ELFSYM_EXPORT(strstr), + ESP_ELFSYM_EXPORT(strerror), + ESP_ELFSYM_EXPORT(strtod), + ESP_ELFSYM_EXPORT(strrchr), + ESP_ELFSYM_EXPORT(strtol), + ESP_ELFSYM_EXPORT(strcspn), + ESP_ELFSYM_EXPORT(strncat), ESP_ELFSYM_EXPORT(memset), ESP_ELFSYM_EXPORT(memcpy), ESP_ELFSYM_EXPORT(memcmp), @@ -490,8 +530,27 @@ const esp_elfsym elf_symbols[] { ESP_ELFSYM_END }; +uintptr_t resolve_symbol(const esp_elfsym* source, const char* symbolName) { + const esp_elfsym* symbol_iterator = source; + while (symbol_iterator->name) { + if (!strcmp(symbol_iterator->name, symbolName)) { + return reinterpret_cast(symbol_iterator->sym); + } + symbol_iterator++; + } + return 0; +} + +uintptr_t tt_symbol_resolver(const char* symbolName) { + uintptr_t address = resolve_symbol(elf_symbols, symbolName); + if (address != 0) { + return address; + } + return resolve_symbol(gcc_soft_float_symbols, symbolName); +} + void tt_init_tactility_c() { - elf_set_custom_symbols(elf_symbols); + elf_set_symbol_resolver(tt_symbol_resolver); } }