Support for building and running external apps (#112)

This commit is contained in:
Ken Van Hoeylandt
2024-12-08 16:46:19 +01:00
committed by GitHub
parent 42e843b463
commit 415442e410
74 changed files with 2901 additions and 126 deletions
@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(elf-loader)
@@ -0,0 +1,50 @@
## ELF Loader Example
This example shows how to use ELF loader to run ELF file.
## How to Use Example
Before project configuration and build, be sure to set the correct chip target using `idf.py set-target <chip_name>`.
* Note: Only ESP32, ESP32-S2 and ESP32-S3 are supported
### Hardware Required
* A development board based on espressif ESP32/ESP32-S2/ESP32-S3 SoC
* A USB cable for power supply and programming
### Configure the Project
Open the project configuration menu (`idf.py menuconfig`).
In the `Example Configuration` menu:
* Enable ELF input arguments in the `Support arguments for ELF main` option if necessary.
* Set the arguments in the `Arguments of ELF main` option.
### Build and Flash
Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
(To exit the serial monitor, type ``Ctrl-]``.)
## Example Output
As you run the example, you will see the following log:
```
I (0) cpu_start: Starting scheduler on APP CPU.
I (382) elf_loader: Start to relocate ELF
I (392) elf_loader: Start to run ELF
hello world 0
hello world 1
hello world 2
hello world 3
hello world 4
hello world 5
hello world 6
hello world 7
hello world 8
hello world 9
I (10392) elf_loader: Success to exit from APP of ELF
```
@@ -0,0 +1,3 @@
idf_component_register(SRCS "elf_loader_example_main.c"
INCLUDE_DIRS ""
EMBED_TXTFILES "test.elf")
@@ -0,0 +1,12 @@
menu "ELF Loader Example Configuration"
config ELF_LOADER_MAIN_ARGS
bool "Support arguments for ELF main"
default n
config ELF_LOADER_MAIN_ARGS_STRING
string "Arguments of ELF main"
default "main"
depends on ELF_LOADER_MAIN_ARGS
endmenu
@@ -0,0 +1,119 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdlib.h>
#include <sys/errno.h>
#include "esp_log.h"
#include "esp_elf.h"
static const char *TAG = "elf_loader";
extern const uint8_t test_elf_start[] asm("_binary_test_elf_start");
extern const uint8_t test_elf_end[] asm("_binary_test_elf_end");
#ifdef CONFIG_ELF_LOADER_MAIN_ARGS
static int elf_args_decode(const char *str, int *argc, char ***argv)
{
int n;
char **argv_buf;
char *s;
char *pbuf;
int len;
s = (char *)str;
n = 1;
len = 1;
while (*s) {
if (*s++ == ' ') {
n++;
}
len++;
}
pbuf = malloc(n * sizeof(char *) + len);
if (!pbuf) {
return -ENOMEM;
}
argv_buf = (char **)pbuf;
s = pbuf + n * sizeof(char *);
memcpy(s, str, len);
for (int i = 0; i < n; i++) {
argv_buf[i] = s;
while (*s != ' ' || *s == 0) {
s++;
}
*s++ = 0;
}
*argc = n;
*argv = argv_buf;
return 0;
}
#endif
int app_main(void)
{
int ret;
int argc;
char **argv;
esp_elf_t elf;
const uint8_t *buffer = test_elf_start;
ESP_LOGI(TAG, "Start to relocate ELF file");
#ifdef CONFIG_ELF_LOADER_MAIN_ARGS
if (strlen(CONFIG_ELF_LOADER_MAIN_ARGS_STRING) <= 0) {
ESP_LOGE(TAG, "Failed to check arguments %s",
CONFIG_ELF_LOADER_MAIN_ARGS_STRING);
return -1;
}
ret = elf_args_decode(CONFIG_ELF_LOADER_MAIN_ARGS_STRING, &argc, &argv);
if (ret < 0) {
ESP_LOGE(TAG, "Failed to decode arguments %s errno=%d",
CONFIG_ELF_LOADER_MAIN_ARGS_STRING, ret);
return ret;
}
#else
argc = 0;
argv = NULL;
#endif
ret = esp_elf_init(&elf);
if (ret < 0) {
ESP_LOGE(TAG, "Failed to initialize ELF file errno=%d", ret);
return ret;
}
ret = esp_elf_relocate(&elf, buffer);
if (ret < 0) {
ESP_LOGE(TAG, "Failed to relocate ELF file errno=%d", ret);
return ret;
}
ESP_LOGI(TAG, "Start to run ELF file");
esp_elf_request(&elf, 0, argc, argv);
ESP_LOGI(TAG, "Success to exit from ELF file");
esp_elf_deinit(&elf);
#ifdef CONFIG_ELF_LOADER_MAIN_ARGS
if (argv) {
free(argv);
}
#endif
return 0;
}
@@ -0,0 +1,5 @@
dependencies:
elf_loader:
version: "0.*"
override_path: "../../../../components/elf_loader"
@@ -0,0 +1,2 @@
CONFIG_SPIRAM=y
CONFIG_ELF_LOADER_LOAD_PSRAM=y
@@ -0,0 +1 @@
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n
@@ -0,0 +1 @@
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n