Skip to content

Commit

Permalink
Add WASI support for esp-idf platform (#3348)
Browse files Browse the repository at this point in the history
Add WASI support for esp-idf platform:

1. add Kconfig and cmake scripts
2. add API "openat" when using littlefs
3. add clock/rwlock/file/socket OS adapter
  • Loading branch information
donghengqaz authored Apr 24, 2024
1 parent 0aeef69 commit 6aa7cb8
Show file tree
Hide file tree
Showing 7 changed files with 2,192 additions and 78 deletions.
130 changes: 88 additions & 42 deletions build-scripts/esp-idf/wamr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,102 @@
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

# Set WAMR's build options
if("${IDF_TARGET}" STREQUAL "esp32c3" OR "${IDF_TARGET}" STREQUAL "esp32c6")
set(WAMR_BUILD_TARGET "RISCV32")
else()
set(WAMR_BUILD_TARGET "XTENSA")
endif()
if (NOT CMAKE_BUILD_EARLY_EXPANSION)

set(WAMR_BUILD_PLATFORM "esp-idf")
if (CONFIG_IDF_TARGET_ARCH_RISCV)
set (WAMR_BUILD_TARGET "RISCV32")
elseif (CONFIG_IDF_TARGET_ARCH_XTENSA)
set (WAMR_BUILD_TARGET "XTENSA")
else ()
message (FATAL_ERROR "Arch ${CONFIG_IDF_TARGET_ARCH} is not supported")
endif ()

if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif ()
set (WAMR_BUILD_PLATFORM "esp-idf")

if (NOT DEFINED WAMR_BUILD_INTERP)
set (WAMR_BUILD_INTERP 1)
endif ()
if (CONFIG_WAMR_BUILD_DEBUG)
set (CMAKE_BUILD_TYPE Debug)
else ()
set (CMAKE_BUILD_TYPE Release)
endif ()

if (NOT DEFINED WAMR_BUILD_FAST_INTERP)
set (WAMR_BUILD_FAST_INTERP 1)
endif ()
if (CONFIG_WAMR_ENABLE_INTERP)
set (WAMR_BUILD_INTERP 1)
endif ()

if (NOT DEFINED WAMR_BUILD_AOT)
set (WAMR_BUILD_AOT 1)
endif ()
if (CONFIG_WAMR_INTERP_FAST)
set (WAMR_BUILD_FAST_INTERP 1)
endif ()

if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN)
set (WAMR_BUILD_LIBC_BUILTIN 1)
endif ()
if (CONFIG_WAMR_ENABLE_AOT)
set (WAMR_BUILD_AOT 1)
endif ()

if (CONFIG_WAMR_ENABLE_LIBC_BUILTIN)
set (WAMR_BUILD_LIBC_BUILTIN 1)
endif ()

if (CONFIG_WAMR_INTERP_LOADER_MINI)
set (WAMR_BUILD_MINI_LOADER 1)
endif ()

if (CONFIG_WAMR_ENABLE_MULTI_MODULE)
set (WAMR_BUILD_MULTI_MODULE 1)
endif ()

if (CONFIG_WAMR_ENABLE_SHARED_MEMORY)
set (WAMR_BUILD_SHARED_MEMORY 1)
endif ()

if (CONFIG_WAMR_ENABLE_MEMORY_PROFILING)
set (WAMR_BUILD_MEMORY_PROFILING 1)
endif ()

if (CONFIG_WAMR_ENABLE_PERF_PROFILING)
set (WAMR_BUILD_PERF_PROFILING 1)
endif ()

if (NOT DEFINED WAMR_BUILD_APP_FRAMEWORK)
set (WAMR_BUILD_APP_FRAMEWORK 0)
if (CONFIG_WAMR_ENABLE_REF_TYPES)
set (WAMR_BUILD_REF_TYPES 1)
endif ()

if (CONFIG_WAMR_ENABLE_LIBC_WASI)
set (WAMR_BUILD_LIBC_WASI 1)
endif ()

if (CONFIG_WAMR_ENABLE_LIB_PTHREAD)
set (WAMR_BUILD_LIB_PTHREAD 1)
endif ()

set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..)
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)

list (APPEND srcs "${WAMR_RUNTIME_LIB_SOURCE}"
"${PLATFORM_SHARED_SOURCE}")

set (include_dirs "${IWASM_DIR}/include"
"${UTILS_SHARED_DIR}"
"${PLATFORM_SHARED_DIR}"
"${PLATFORM_SHARED_DIR}/../include"
"${IWASM_COMMON_DIR}")
endif ()

if (NOT CMAKE_BUILD_EARLY_EXPANSION)
if (WAMR_BUILD_TARGET STREQUAL "XTENSA")
idf_build_set_property(COMPILE_DEFINITIONS "-DBUILD_TARGET_XTENSA=1" APPEND)
endif ()
if (WAMR_BUILD_INTERP)
idf_build_set_property(COMPILE_DEFINITIONS "-DWASM_ENABLE_INTERP=1" APPEND)
endif ()
if (WAMR_BUILD_AOT)
idf_build_set_property(COMPILE_DEFINITIONS "-DWASM_ENABLE_AOT=1" APPEND)
endif ()

set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..)
include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
endif()

idf_component_register(SRCS ${WAMR_RUNTIME_LIB_SOURCE} ${PLATFORM_SHARED_SOURCE}
INCLUDE_DIRS ${IWASM_DIR}/include ${UTILS_SHARED_DIR} ${PLATFORM_SHARED_DIR} ${PLATFORM_SHARED_DIR}/../include
REQUIRES pthread lwip esp_timer
)
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${include_dirs}
REQUIRES pthread lwip esp_timer
KCONFIG ${CMAKE_CURRENT_LIST_DIR}/Kconfig)

target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")

if (CONFIG_IDF_TARGET_ARCH_RISCV)
target_compile_definitions(${COMPONENT_LIB} PUBLIC -DBUILD_TARGET_RISCV32_ILP32=1)
elseif (CONFIG_IDF_TARGET_ARCH_XTENSA)
target_compile_definitions(${COMPONENT_LIB} PUBLIC -DBUILD_TARGET_XTENSA=1)
endif ()

if (CONFIG_WAMR_ENABLE_AOT)
target_compile_definitions(${COMPONENT_LIB} PUBLIC -DWASM_ENABLE_AOT=1)
endif ()

if (CONFIG_WAMR_ENABLE_INTERP)
target_compile_definitions(${COMPONENT_LIB} PUBLIC -DWASM_ENABLE_INTERP=1)
endif ()
77 changes: 77 additions & 0 deletions build-scripts/esp-idf/wamr/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
menu "WASM Micro Runtime"
choice WAMR_BUILD_TYPE
prompt "Build type"
default WAMR_BUILD_RELEASE

config WAMR_BUILD_RELEASE
bool "Release"

config WAMR_BUILD_DEBUG
bool "Debug"
endchoice

config WAMR_ENABLE_AOT
bool "AOT"
default y

menuconfig WAMR_ENABLE_INTERP
bool "Interpreter"
default y

if WAMR_ENABLE_INTERP

choice WAMR_INTERP_MODE
prompt "Interpreter mode"
default WAMR_INTERP_FAST

config WAMR_INTERP_CLASSIC
bool "Classic"

config WAMR_INTERP_FAST
bool "Fast"
endchoice

choice WAMR_INTERP_LOADER_MODE
prompt "Loader mode"
default WAMR_INTERP_LOADER_NORMAL

config WAMR_INTERP_LOADER_NORMAL
bool "Normal"

config WAMR_INTERP_LOADER_MINI
bool "Mini"
endchoice
endif

config WAMR_ENABLE_LIB_PTHREAD
bool "Lib pthread"
default y

config WAMR_ENABLE_LIBC_BUILTIN
bool "Libc builtin"
default y

config WAMR_ENABLE_LIBC_WASI
bool "Libc WASI"
default y

config WAMR_ENABLE_MEMORY_PROFILING
bool "Memory profiling"
default n

config WAMR_ENABLE_MULTI_MODULE
bool "Multi module"
default n

config WAMR_ENABLE_PERF_PROFILING
bool "Performance profiling"
default n

config WAMR_ENABLE_REF_TYPES
bool "Reference types"
default n

config WAMR_ENABLE_SHARED_MEMORY
bool "Shared memory"
default n
endmenu
88 changes: 88 additions & 0 deletions core/shared/platform/esp-idf/espidf_clock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright (C) 2023 Amazon Inc. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/

#include "libc_errno.h"
#include "platform_api_extension.h"

#define NANOSECONDS_PER_SECOND 1000000000ULL

static __wasi_errno_t
wasi_clockid_to_clockid(__wasi_clockid_t in, clockid_t *out)
{
switch (in) {
case __WASI_CLOCK_MONOTONIC:
*out = CLOCK_MONOTONIC;
return __WASI_ESUCCESS;
case __WASI_CLOCK_REALTIME:
*out = CLOCK_REALTIME;
return __WASI_ESUCCESS;
case __WASI_CLOCK_PROCESS_CPUTIME_ID:
#if defined(CLOCK_PROCESS_CPUTIME_ID)
*out = CLOCK_PROCESS_CPUTIME_ID;
return __WASI_ESUCCESS;
#else
return __WASI_ENOTSUP;
#endif
case __WASI_CLOCK_THREAD_CPUTIME_ID:
#if defined(CLOCK_THREAD_CPUTIME_ID)
*out = CLOCK_THREAD_CPUTIME_ID;
return __WASI_ESUCCESS;
#else
return __WASI_ENOTSUP;
#endif
default:
return __WASI_EINVAL;
}
}

static __wasi_timestamp_t
timespec_to_nanoseconds(const struct timespec *ts)
{
if (ts->tv_sec < 0)
return 0;
if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / NANOSECONDS_PER_SECOND)
return UINT64_MAX;
return (__wasi_timestamp_t)ts->tv_sec * NANOSECONDS_PER_SECOND
+ (__wasi_timestamp_t)ts->tv_nsec;
}

__wasi_errno_t
os_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution)
{
clockid_t nclock_id;
__wasi_errno_t error = wasi_clockid_to_clockid(clock_id, &nclock_id);

if (error != __WASI_ESUCCESS)
return error;

struct timespec ts;
if (clock_getres(nclock_id, &ts) < 0)
return convert_errno(errno);

*resolution = timespec_to_nanoseconds(&ts);

return error;
}

__wasi_errno_t
os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision,
__wasi_timestamp_t *time)
{
clockid_t nclock_id;
__wasi_errno_t error = wasi_clockid_to_clockid(clock_id, &nclock_id);

(void)precision;

if (error != __WASI_ESUCCESS)
return error;

struct timespec ts;
if (clock_gettime(nclock_id, &ts) < 0)
return convert_errno(errno);

*time = timespec_to_nanoseconds(&ts);

return error;
}
Loading

0 comments on commit 6aa7cb8

Please sign in to comment.