Skip to content

Commit

Permalink
Merge branch 'feature/esp_system_linux' into 'master'
Browse files Browse the repository at this point in the history
esp_system partially buildable on Linux

Closes IDF-5983

See merge request espressif/esp-idf!21055
  • Loading branch information
0xjakob committed Nov 16, 2022
2 parents fbef416 + 5b3a645 commit c381fee
Show file tree
Hide file tree
Showing 19 changed files with 305 additions and 60 deletions.
8 changes: 8 additions & 0 deletions .gitlab/ci/host-test.yml
Expand Up @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions components/esp_system/.build-test-rules.yml
@@ -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
Expand Down
10 changes: 10 additions & 0 deletions components/esp_system/CMakeLists.txt
@@ -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)
Expand Down
51 changes: 0 additions & 51 deletions components/esp_system/esp_system.c
Expand Up @@ -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"
Expand All @@ -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++) {
Expand Down Expand Up @@ -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);
}
@@ -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)
2 changes: 2 additions & 0 deletions components/esp_system/host_test/test_esp_system/README.md
@@ -0,0 +1,2 @@
| Supported Targets | Linux |
| ----------------- | ----- |
@@ -0,0 +1,3 @@
idf_component_register(SRCS "esp_system_test.c"
INCLUDE_DIRS "."
PRIV_REQUIRES unity esp_system)
120 changes: 120 additions & 0 deletions components/esp_system/host_test/test_esp_system/main/esp_system_test.c
@@ -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();
}
@@ -0,0 +1,2 @@
CONFIG_IDF_TARGET="linux"
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n
2 changes: 1 addition & 1 deletion components/esp_system/linker.lf
Expand Up @@ -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:
Expand Down
3 changes: 2 additions & 1 deletion components/esp_system/port/CMakeLists.txt
Expand Up @@ -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})
Expand Down
60 changes: 60 additions & 0 deletions components/esp_system/port/esp_system_chip.c
@@ -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);
}
47 changes: 47 additions & 0 deletions components/esp_system/port/esp_system_linux.c
@@ -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);
}
1 change: 1 addition & 0 deletions components/esp_system/port/soc/linux/Kconfig.cpu
@@ -0,0 +1 @@
# The CPU frequency is never really used, except in some xtensa timer headers, so it's empty for Linux.
1 change: 1 addition & 0 deletions components/esp_system/port/soc/linux/Kconfig.system
@@ -0,0 +1 @@
# Original Kconfig has settings related to brownout, rom and cache. All non-existent on Linux.

0 comments on commit c381fee

Please sign in to comment.