Merge branch 'feature/esp_system_linux' into 'master'

esp_system partially buildable on Linux

Closes IDF-5983

See merge request espressif/esp-idf!21055
This commit is contained in:
Jakob Hasse 2022-11-16 22:38:48 +08:00
commit c381fee319
19 changed files with 305 additions and 60 deletions

View File

@ -370,6 +370,14 @@ test_hello_world_linux_compatible_example:
- timeout 15 build/hello_world.elf | tee test.txt
- grep "Hello world!" test.txt
test_esp_system:
extends: .host_test_template
script:
- cd ${IDF_PATH}/components/esp_system/host_test/test_esp_system/
- idf.py build
- timeout 5 build/test_esp_system.elf | tee log.txt || true
- grep "6 Tests 0 Failures 0 Ignored" log.txt
test_esp_timer_cxx:
extends: .host_test_template
script:

View File

@ -1,5 +1,8 @@
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
components/esp_system/host_test/esp_system:
enable:
- if: IDF_TARGET == "linux"
components/esp_system/test_apps/rtc_8md256:
disable:
- if: SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256 != 1

View File

@ -1,5 +1,15 @@
idf_build_get_property(target IDF_TARGET)
# On Linux, we only support a few features, hence this simple component registration
if(${target} STREQUAL "linux")
idf_component_register(SRCS "esp_system.c"
"port/soc/linux/reset_reason.c"
"port/soc/linux/system_internal.c"
"port/esp_system_linux.c"
INCLUDE_DIRS "include")
return()
endif()
set(srcs "esp_err.c")
if(CONFIG_IDF_ENV_FPGA)

View File

@ -6,14 +6,8 @@
#include "esp_system.h"
#include "esp_private/system_internal.h"
#include "esp_heap_caps.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_cpu.h"
#include "soc/rtc.h"
#include "esp_private/panic_internal.h"
#include "esp_rom_uart.h"
#include "esp_rom_sys.h"
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/memprot.h"
@ -28,26 +22,6 @@
static shutdown_handler_t shutdown_handlers[SHUTDOWN_HANDLERS_NO];
void IRAM_ATTR esp_restart_noos_dig(void)
{
// make sure all the panic handler output is sent from UART FIFO
if (CONFIG_ESP_CONSOLE_UART_NUM >= 0) {
esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
}
// switch to XTAL (otherwise we will keep running from the PLL)
rtc_clk_cpu_freq_set_xtal();
#if CONFIG_IDF_TARGET_ESP32
esp_cpu_unstall(PRO_CPU_NUM);
#endif
// reset the digital part
esp_rom_software_reset_system();
while (true) {
;
}
}
esp_err_t esp_register_shutdown_handler(shutdown_handler_t handler)
{
for (int i = 0; i < SHUTDOWN_HANDLERS_NO; i++) {
@ -109,28 +83,3 @@ void IRAM_ATTR esp_restart(void)
}
esp_restart_noos();
}
uint32_t esp_get_free_heap_size( void )
{
return heap_caps_get_free_size( MALLOC_CAP_DEFAULT );
}
uint32_t esp_get_free_internal_heap_size( void )
{
return heap_caps_get_free_size( MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL );
}
uint32_t esp_get_minimum_free_heap_size( void )
{
return heap_caps_get_minimum_free_size( MALLOC_CAP_DEFAULT );
}
const char *esp_get_idf_version(void)
{
return IDF_VER;
}
void __attribute__((noreturn)) esp_system_abort(const char *details)
{
panic_abort(details);
}

View File

@ -0,0 +1,9 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five 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.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main)
project(test_esp_system)

View File

@ -0,0 +1,2 @@
| Supported Targets | Linux |
| ----------------- | ----- |

View File

@ -0,0 +1,3 @@
idf_component_register(SRCS "esp_system_test.c"
INCLUDE_DIRS "."
PRIV_REQUIRES unity esp_system)

View File

@ -0,0 +1,120 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include "unity.h"
#include "esp_system.h"
static jmp_buf env;
static uint32_t token;
static void jump_back_shutdown_handler(void)
{
longjmp(env, 1);
}
static void dummy_shutdown_handler_0(void) { }
static void dummy_shutdown_handler_1(void) { }
static void dummy_shutdown_handler_2(void) { }
static void dummy_shutdown_handler_3(void) { }
static void dummy_shutdown_handler_4(void) { }
static void action(void)
{
token++;
}
static void cleanup(void)
{
esp_unregister_shutdown_handler(jump_back_shutdown_handler);
esp_unregister_shutdown_handler(dummy_shutdown_handler_0);
esp_unregister_shutdown_handler(dummy_shutdown_handler_1);
esp_unregister_shutdown_handler(dummy_shutdown_handler_2);
esp_unregister_shutdown_handler(dummy_shutdown_handler_3);
esp_unregister_shutdown_handler(dummy_shutdown_handler_4);
esp_unregister_shutdown_handler(action);
}
void test_reset_reason(void)
{
TEST_ASSERT_EQUAL(ESP_RST_POWERON, esp_reset_reason());
}
void test_unregister_handler_works(void)
{
token = 0;
// for some reason, the handlers are executed in reverse order of adding handlers, so we always
// register the jumping handler at first to make it execute last
TEST_ASSERT_EQUAL(ESP_OK, esp_register_shutdown_handler(jump_back_shutdown_handler));
TEST_ASSERT_EQUAL(ESP_OK, esp_register_shutdown_handler(action));
TEST_ASSERT_EQUAL(ESP_OK, esp_unregister_shutdown_handler(action));
if (setjmp(env) == 0) {
esp_restart();
}
// fist unregister before any assert to avoid skipping by assert's longjmp
cleanup();
TEST_ASSERT_EQUAL(0, token);
}
void test_register_shutdown_handler_twice_fails(void)
{
TEST_ASSERT_EQUAL(ESP_OK, esp_register_shutdown_handler(jump_back_shutdown_handler));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, esp_register_shutdown_handler(jump_back_shutdown_handler));
cleanup();
}
void test_register_shutdown_handler_works(void)
{
token = 0;
TEST_ASSERT_EQUAL(esp_register_shutdown_handler(jump_back_shutdown_handler), ESP_OK);
TEST_ASSERT_EQUAL(esp_register_shutdown_handler(action), ESP_OK);
if (setjmp(env) == 0) {
esp_restart();
}
cleanup();
TEST_ASSERT_EQUAL(1, token);
}
void test_register_too_many_shutdown_handler_fails(void)
{
TEST_ASSERT_EQUAL(ESP_OK, esp_register_shutdown_handler(dummy_shutdown_handler_0));
TEST_ASSERT_EQUAL(ESP_OK, esp_register_shutdown_handler(dummy_shutdown_handler_1));
TEST_ASSERT_EQUAL(ESP_OK, esp_register_shutdown_handler(dummy_shutdown_handler_2));
TEST_ASSERT_EQUAL(ESP_OK, esp_register_shutdown_handler(dummy_shutdown_handler_3));
TEST_ASSERT_EQUAL(ESP_OK, esp_register_shutdown_handler(dummy_shutdown_handler_4));
TEST_ASSERT_EQUAL(esp_register_shutdown_handler(jump_back_shutdown_handler), ESP_ERR_NO_MEM);
cleanup();
}
void test_heap_size_stubs(void)
{
TEST_ASSERT_EQUAL(47000, esp_get_free_heap_size());
TEST_ASSERT_EQUAL(47000, esp_get_free_internal_heap_size());
TEST_ASSERT_EQUAL(47000, esp_get_minimum_free_heap_size());
}
void app_main(void)
{
UNITY_BEGIN();
RUN_TEST(test_reset_reason);
RUN_TEST(test_unregister_handler_works);
RUN_TEST(test_register_shutdown_handler_twice_fails);
RUN_TEST(test_register_shutdown_handler_works);
RUN_TEST(test_register_too_many_shutdown_handler_fails);
RUN_TEST(test_heap_size_stubs);
UNITY_END();
}

View File

@ -0,0 +1,2 @@
CONFIG_IDF_TARGET="linux"
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n

View File

@ -7,7 +7,7 @@ entries:
panic_arch (noflash)
esp_err (noflash)
esp_system:esp_system_abort (noflash)
esp_system_chip:esp_system_abort (noflash)
ubsan (noflash)
if ESP_CONSOLE_USB_CDC_SUPPORT_ETS_PRINTF:

View File

@ -6,7 +6,8 @@ endif()
target_include_directories(${COMPONENT_LIB} PRIVATE ${INCLUDE_FILES} include/private)
set(srcs "cpu_start.c" "panic_handler.c" "brownout.c")
set(srcs "cpu_start.c" "panic_handler.c" "brownout.c" "esp_system_chip.c")
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})
target_sources(${COMPONENT_LIB} PRIVATE ${srcs})

View File

@ -0,0 +1,60 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "esp_cpu.h"
#include "soc/rtc.h"
#include "esp_private/panic_internal.h"
#include "esp_private/system_internal.h"
#include "esp_heap_caps.h"
#include "esp_rom_uart.h"
#include "esp_rom_sys.h"
#include "sdkconfig.h"
void IRAM_ATTR esp_restart_noos_dig(void)
{
// make sure all the panic handler output is sent from UART FIFO
if (CONFIG_ESP_CONSOLE_UART_NUM >= 0) {
esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
}
// switch to XTAL (otherwise we will keep running from the PLL)
rtc_clk_cpu_freq_set_xtal();
#if CONFIG_IDF_TARGET_ESP32
esp_cpu_unstall(PRO_CPU_NUM);
#endif
// reset the digital part
esp_rom_software_reset_system();
while (true) {
;
}
}
uint32_t esp_get_free_heap_size( void )
{
return heap_caps_get_free_size( MALLOC_CAP_DEFAULT );
}
uint32_t esp_get_free_internal_heap_size( void )
{
return heap_caps_get_free_size( MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL );
}
uint32_t esp_get_minimum_free_heap_size( void )
{
return heap_caps_get_minimum_free_size( MALLOC_CAP_DEFAULT );
}
const char *esp_get_idf_version(void)
{
return IDF_VER;
}
void __attribute__((noreturn)) esp_system_abort(const char *details)
{
panic_abort(details);
}

View File

@ -0,0 +1,47 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* All functions presented here are stubs for the POSIX/Linux implementation of FReeRTOS.
* They are meant to allow to compile, but they DO NOT return any meaningful value.
*/
#include <stdlib.h>
#include <stdint.h>
#include "esp_private/system_internal.h"
static const uint32_t MAGIC_HEAP_SIZE = 47000;
// dummy, we should never get here on Linux
void esp_restart_noos_dig(void)
{
abort();
}
uint32_t esp_get_free_heap_size( void )
{
return MAGIC_HEAP_SIZE;
}
uint32_t esp_get_free_internal_heap_size( void )
{
return MAGIC_HEAP_SIZE;
}
uint32_t esp_get_minimum_free_heap_size( void )
{
return MAGIC_HEAP_SIZE;
}
const char *esp_get_idf_version(void)
{
return IDF_VER;
}
void __attribute__((noreturn)) esp_system_abort(const char *details)
{
exit(1);
}

View File

@ -0,0 +1 @@
# The CPU frequency is never really used, except in some xtensa timer headers, so it's empty for Linux.

View File

@ -0,0 +1 @@
# Original Kconfig has settings related to brownout, rom and cache. All non-existent on Linux.

View File

@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* All functions presented here are stubs for the POSIX/Linux implementation of FreeRTOS.
* They are meant to allow to compile, but they DO NOT return any meaningful value.
*/
#include "esp_system.h"
// On Linux, this is just a meaningful value to make applications build and run
esp_reset_reason_t esp_reset_reason(void)
{
return ESP_RST_POWERON;
}

View File

@ -0,0 +1,17 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdlib.h>
/*
* "inner" restart function on POSIX/Linux just exits.
*/
void esp_restart_noos(void)
{
printf("restart triggered on Linux, hence exiting\n");
exit(0); // TODO: other exit value?
}

View File

@ -22,12 +22,6 @@
extern "C" {
#endif
// TODO: IDF-5983 From esp_task.h, should later be used from there
// or be refactored in IDF (e.g. move esp_task.h to freertos)
// See also configMINIMAL_STACK_SIZE for more information.
#define CONFIG_ESP_MAIN_TASK_STACK_SIZE ( ( unsigned short ) (0x4000 + 40) / sizeof(portSTACK_TYPE) ) // should be in Kconfig again
#define CONFIG_ESP_MAIN_TASK_AFFINITY 0
#define ESP_TASK_PRIO_MAX (configMAX_PRIORITIES)
#define ESP_TASK_PRIO_MIN (0)
#define ESP_TASK_MAIN_PRIO (ESP_TASK_PRIO_MIN + 1)

View File

@ -225,7 +225,7 @@ function(__build_init idf_path)
endforeach()
if("${target}" STREQUAL "linux")
set(requires_common freertos log esp_rom esp_common linux)
set(requires_common freertos log esp_rom esp_common esp_system linux)
idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${requires_common}")
else()
# Set components required by all other components in the build