diff --git a/core/config.h b/core/config.h index 7ab1d2fec..234b43e3e 100644 --- a/core/config.h +++ b/core/config.h @@ -225,7 +225,8 @@ #endif /* Default/min/max stack size of each app thread */ -#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) +#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) \ + && !defined(BH_PLATFORM_FREERTOS) #define APP_THREAD_STACK_SIZE_DEFAULT (32 * 1024) #define APP_THREAD_STACK_SIZE_MIN (24 * 1024) #else diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index ad9ebae01..de252c2e5 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -7,7 +7,8 @@ #include "wasm_runtime_common.h" #include "bh_log.h" -#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) +#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) \ + && !defined(BH_PLATFORM_FREERTOS) #define ENABLE_QUICKSORT 1 #else #define ENABLE_QUICKSORT 0 diff --git a/core/shared/platform/freertos/freertos_platform.c b/core/shared/platform/freertos/freertos_platform.c new file mode 100644 index 000000000..4a47a4989 --- /dev/null +++ b/core/shared/platform/freertos/freertos_platform.c @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" + + +int errno = 0; + +int +os_thread_sys_init(); + +void +os_thread_sys_destroy(); + +int +bh_platform_init() +{ + return os_thread_sys_init(); +} + +void +bh_platform_destroy() +{ + os_thread_sys_destroy(); +} + +void * +os_malloc(unsigned size) +{ + return NULL; +} + +void * +os_realloc(void *ptr, unsigned size) +{ + return NULL; +} + +void +os_free(void *ptr) +{ +} + +int os_printf(const char *format, ...) +{ + /* TODO: implement os_printf */ + return 0; +} + +int +os_vprintf(const char *format, va_list ap) +{ + /* TODO: implement os_vprintf */ + return 1; +} + +void * +os_mmap(void *hint, size_t size, int prot, int flags) +{ + + return BH_MALLOC(size); +} + +void +os_munmap(void *addr, size_t size) +{ + BH_FREE(addr); +} + +int +os_mprotect(void *addr, size_t size, int prot) +{ + return 0; +} + +void +os_dcache_flush() +{ +} + +int atoi(const char *nptr) +{ + bool is_negative = false; + int total = 0; + const char *p = nptr; + char temp = '0'; + + if (NULL == p) { + os_printf("invlaid atoi input\n"); + return 0; + } + + if (*p == '-') { + is_negative = true; + p++; + } + + while ((temp = *p++) != '\0') { + if (temp > '9' || temp < '0') { + continue; + } + + total = total * 10 + (int)(temp - '0'); + } + + if (is_negative) + total = 0 - total; + + return total; +} + +/** + * TODO: implement these APIs which are needed by libc_builtin_wrapper.c + * and wasm_runtime_common.c + */ +int strncasecmp(const char *s1, const char *s2, size_t n) +{ + os_printf("### unimplemented function strncasecmp called!\n"); + return 0; +} + +long int strtol(const char *str, char **endptr, int base) +{ + os_printf("### unimplemented function strtol called!\n"); + return 0; +} + +unsigned long int strtoul(const char *str, char **endptr, int base) +{ + os_printf("### unimplemented function strtoul called!\n"); + return 0; +} + +unsigned long long int strtoull(const char *nptr, char **endptr, int base) +{ + os_printf("### unimplemented function strtoull called!\n"); + return 0; +} + +double strtod(const char *nptr, char **endptr) +{ + os_printf("### unimplemented function strtod called!\n"); + return 0; +} + +float strtof(const char *nptr, char **endptr) +{ + os_printf("### unimplemented function strtof called!\n"); + return 0; +} + +char *strstr(const char *haystack, const char *needle) +{ + os_printf("### unimplemented function strstr called!\n"); + return NULL; +} + +size_t strspn(const char *s, const char *accept) +{ + os_printf("### unimplemented function strspn called!\n"); + return 0; +} + +size_t strcspn(const char *s, const char *reject) +{ + os_printf("### unimplemented function strcspn called!\n"); + return 0; +} + +void *memchr(const void *s, int c, size_t n) +{ + os_printf("### unimplemented function memchr called!\n"); + return NULL; +} + +int isalnum(int c) +{ + os_printf("### unimplemented function isalnum called!\n"); + return 0; +} + +int isxdigit(int c) +{ + os_printf("### unimplemented function isxdigit called!\n"); + return 0; +} + +int isdigit(int c) +{ + os_printf("### unimplemented function isdigit called!\n"); + return 0; +} + +int isprint(int c) +{ + os_printf("### unimplemented function isprint called!\n"); + return 0; +} + +int isgraph(int c) +{ + os_printf("### unimplemented function isgraph called!\n"); + return 0; +} + +int isspace(int c) +{ + os_printf("### unimplemented function isspace called!\n"); + return 0; +} + +int isalpha(int c) +{ + os_printf("### unimplemented function isalpha called!\n"); + return 0; +} + +int isupper(int c) +{ + os_printf("### unimplemented function isupper called!\n"); + return 0; +} + +int toupper(int c) +{ + os_printf("### unimplemented function toupper called!\n"); + return 0; +} + +int tolower(int c) +{ + os_printf("### unimplemented function tolower called!\n"); + return 0; +} + +void *memmove(void *dest, const void *src, size_t n) +{ + char *d = dest; + const char *s = src; + + if (d < s) { + while (n--) + *d++ = *s++; + } + else { + const char *lasts = s + (n-1); + char *lastd = d + (n-1); + while (n--) + *lastd-- = *lasts--; + } + return dest; +} + +static union { + int a; + char b; +} __ue = { .a = 1 }; + +#define is_little_endian() (__ue.b == 1) + +static void swap32(uint8_t* pData) +{ + uint8_t value = *pData; + *pData = *(pData + 3); + *(pData + 3) = value; + + value = *(pData + 1); + *(pData + 1) = *(pData + 2); + *(pData + 2) = value; +} + +static void swap16(uint8_t* pData) +{ + uint8_t value = *pData; + *(pData) = *(pData + 1); + *(pData + 1) = value; +} + +uint32_t htonl(uint32_t value) +{ + uint32_t ret; + if (is_little_endian()) { + ret = value; + swap32((uint8*) &ret); + return ret; + } + + return value; +} + +uint32_t ntohl(uint32_t value) +{ + return htonl(value); +} + +uint16_t htons(uint16_t value) +{ + uint16_t ret; + if (is_little_endian()) { + ret = value; + swap16((uint8_t *)&ret); + return ret; + } + + return value; +} + +uint16_t ntohs(uint16_t value) +{ + return htons(value); +} + diff --git a/core/shared/platform/freertos/freertos_thread.c b/core/shared/platform/freertos/freertos_thread.c new file mode 100644 index 000000000..b0b2d2af6 --- /dev/null +++ b/core/shared/platform/freertos/freertos_thread.c @@ -0,0 +1,426 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" + +#define bh_assert(v) do { \ + if (!(v)) { \ + os_printf("\nASSERTION FAILED: %s, at %s, line %d\n",\ + #v, __FILE__, __LINE__); \ + abort(); \ + } \ + } while (0) + +struct os_thread_data; +typedef struct os_thread_wait_node { + /* Binary semaphore */ + SemaphoreHandle_t sem; + os_thread_wait_list next; +} os_thread_wait_node; + +typedef struct os_thread_data { + /* Next thread data */ + struct os_thread_data *next; + /* Thread handle */ + TaskHandle_t handle; + /* Thread start routine */ + thread_start_routine_t start_routine; + /* Thread start routine argument */ + void *arg; + /* Thread local root */ + void *tlr; + /* Wait node of current thread */ + os_thread_wait_node wait_node; + /* Lock for waiting list */ + SemaphoreHandle_t wait_list_lock; + /* Waiting list of other threads who are joining this thread */ + os_thread_wait_list thread_wait_list; +} os_thread_data; + +static bool is_thread_sys_inited = false; + +/* Lock for thread data list */ +static SemaphoreHandle_t thread_data_lock; + +/* Thread data list */ +static os_thread_data *thread_data_list = NULL; +/* Thread data of supervisor thread */ +static os_thread_data supervisor_thread_data; + +/* Thread name index */ +static int thread_name_index; + +static void thread_data_list_add(os_thread_data *thread_data) +{ + xSemaphoreTake(thread_data_lock, portMAX_DELAY); + if (!thread_data_list) + thread_data_list = thread_data; + else { + /* If already in list, just return */ + os_thread_data *p = thread_data_list; + while (p) { + if (p == thread_data) { + xSemaphoreGive(thread_data_lock); + return; + } + p = p->next; + } + + /* Set as head of list */ + thread_data->next = thread_data_list; + thread_data_list = thread_data; + } + xSemaphoreGive(thread_data_lock); +} + +static void thread_data_list_remove(os_thread_data *thread_data) +{ + xSemaphoreTake(thread_data_lock, portMAX_DELAY); + if (thread_data_list) { + if (thread_data_list == thread_data) + thread_data_list = thread_data_list->next; + else { + /* Search and remove it from list */ + os_thread_data *p = thread_data_list; + while (p && p->next != thread_data) + p = p->next; + if (p && p->next == thread_data) + p->next = p->next->next; + } + } + xSemaphoreGive(thread_data_lock); +} + +static os_thread_data * +thread_data_list_lookup(TaskHandle_t handle) +{ + xSemaphoreTake(thread_data_lock, portMAX_DELAY); + if (thread_data_list) { + os_thread_data *p = thread_data_list; + while (p) { + if (p->handle == handle) { + /* Found */ + xSemaphoreGive(thread_data_lock); + return p; + } + p = p->next; + } + } + xSemaphoreGive(thread_data_lock); + return NULL; +} + +int +os_thread_sys_init() +{ + if (is_thread_sys_inited) + return BHT_OK; + + if (!(thread_data_lock = xSemaphoreCreateMutex())) + return BHT_ERROR; + + /* Initialize supervisor thread data */ + memset(&supervisor_thread_data, 0, sizeof(supervisor_thread_data)); + + if (!(supervisor_thread_data.wait_node.sem = xSemaphoreCreateBinary())) { + vSemaphoreDelete(thread_data_lock); + return BHT_ERROR; + } + + supervisor_thread_data.handle = xTaskGetCurrentTaskHandle(); + /* Set as head of thread data list */ + thread_data_list = &supervisor_thread_data; + + is_thread_sys_inited = true; + return BHT_OK; +} + +void +os_thread_sys_destroy() +{ + if (is_thread_sys_inited) { + vSemaphoreDelete(supervisor_thread_data.wait_node.sem); + vSemaphoreDelete(thread_data_lock); + is_thread_sys_inited = false; + } +} + +static os_thread_data * +thread_data_current() +{ + TaskHandle_t handle = xTaskGetCurrentTaskHandle(); + return thread_data_list_lookup(handle); +} + +static void +os_thread_cleanup(void) +{ + os_thread_data *thread_data = thread_data_current(); + os_thread_wait_list thread_wait_list; + SemaphoreHandle_t wait_list_lock; + SemaphoreHandle_t wait_node_sem; + + bh_assert(thread_data != NULL); + wait_list_lock = thread_data->wait_list_lock; + thread_wait_list = thread_data->thread_wait_list; + wait_node_sem = thread_data->wait_node.sem; + + xSemaphoreTake(wait_list_lock, portMAX_DELAY); + if (thread_wait_list) { + /* Signal each joining thread */ + os_thread_wait_list head = thread_wait_list; + while (head) { + os_thread_wait_list next = head->next; + xSemaphoreGive(head->sem); + head = next; + } + } + xSemaphoreGive(wait_list_lock); + + /* Free sem and lock */ + vSemaphoreDelete(wait_node_sem); + vSemaphoreDelete(wait_list_lock); + + thread_data_list_remove(thread_data); + BH_FREE(thread_data); +} + +static void +os_thread_wrapper(void *arg) +{ + os_thread_data *thread_data = arg; + + thread_data->handle = xTaskGetCurrentTaskHandle(); + thread_data_list_add(thread_data); + + thread_data->start_routine(thread_data->arg); + os_thread_cleanup(); + vTaskDelete(NULL); +} + +int os_thread_create(korp_tid *p_tid, thread_start_routine_t start, void *arg, + unsigned int stack_size) +{ + return os_thread_create_with_prio(p_tid, start, arg, stack_size, + BH_THREAD_DEFAULT_PRIORITY); +} + +int os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, + void *arg, unsigned int stack_size, int prio) +{ + os_thread_data *thread_data; + char thread_name[32]; + + if (!p_tid || !stack_size) + return BHT_ERROR; + + /* Create and initialize thread data */ + if (!(thread_data = BH_MALLOC(sizeof(os_thread_data)))) + return BHT_ERROR; + + memset(thread_data, 0, sizeof(os_thread_data)); + + thread_data->start_routine = start; + thread_data->arg = arg; + + if (!(thread_data->wait_node.sem = xSemaphoreCreateBinary())) + goto fail1; + + if (!(thread_data->wait_list_lock = xSemaphoreCreateMutex())) + goto fail2; + + snprintf(thread_name, sizeof(thread_name), "%s%d", + "wasm-thread-", ++thread_name_index); + + /* Create the thread */ + if (pdPASS != xTaskCreate(os_thread_wrapper, thread_name, + stack_size / 4, thread_data, + prio, &thread_data->handle)) + goto fail3; + + thread_data_list_add(thread_data); + *p_tid = thread_data->handle; + return BHT_OK; + +fail3: + vSemaphoreDelete(thread_data->wait_list_lock); +fail2: + vSemaphoreDelete(thread_data->wait_node.sem); +fail1: + BH_FREE(thread_data); + return BHT_ERROR; +} + +korp_tid os_self_thread() +{ + return xTaskGetCurrentTaskHandle(); +} + +int os_thread_join(korp_tid thread, void **value_ptr) +{ + os_thread_data *thread_data, *curr_thread_data; + TaskHandle_t handle = thread; + + (void)value_ptr; + + /* Get thread data of current thread */ + curr_thread_data = thread_data_current(); + curr_thread_data->wait_node.next = NULL; + + /* Get thread data */ + thread_data = thread_data_list_lookup(handle); + + xSemaphoreTake(thread_data->wait_list_lock, portMAX_DELAY); + if (!thread_data->thread_wait_list) + thread_data->thread_wait_list = &curr_thread_data->wait_node; + else { + /* Add to end of waiting list */ + os_thread_wait_node *p = thread_data->thread_wait_list; + while (p->next) + p = p->next; + p->next = &curr_thread_data->wait_node; + } + xSemaphoreGive(thread_data->wait_list_lock); + + /* Wait the sem */ + xSemaphoreTake(curr_thread_data->wait_node.sem, portMAX_DELAY); + return BHT_OK; +} + +int os_mutex_init(korp_mutex *mutex) +{ + SemaphoreHandle_t semaphore; + if (!(semaphore = xSemaphoreCreateMutex())) + return BHT_ERROR; + mutex->sem = semaphore; + mutex->is_recursive = false; + return BHT_OK; +} + +int os_recursive_mutex_init(korp_mutex *mutex) +{ + SemaphoreHandle_t semaphore; + if (!(semaphore = xSemaphoreCreateRecursiveMutex())) + return BHT_ERROR; + mutex->sem = semaphore; + mutex->is_recursive = true; + return BHT_OK; +} + +int os_mutex_destroy(korp_mutex *mutex) +{ + vSemaphoreDelete(mutex->sem); + return BHT_OK; +} + +int os_mutex_lock(korp_mutex *mutex) +{ + int ret = -1; + + if (!mutex->is_recursive) + ret = xSemaphoreTake(mutex->sem, portMAX_DELAY); + else + ret = xSemaphoreTakeRecursive(mutex->sem, portMAX_DELAY); + return ret == pdPASS ? BHT_OK : BHT_ERROR; +} + +int os_mutex_unlock(korp_mutex *mutex) +{ + int ret = -1; + + if (!mutex->is_recursive) + ret = xSemaphoreGive(mutex->sem); + else + ret = xSemaphoreGiveRecursive(mutex->sem); + return ret == pdPASS ? BHT_OK : BHT_ERROR; +} + +int os_cond_init(korp_cond *cond) +{ + if (!(cond->wait_list_lock = xSemaphoreCreateMutex())) + return BHT_ERROR; + + cond->thread_wait_list = NULL; + return BHT_OK; +} + +int os_cond_destroy(korp_cond *cond) +{ + vSemaphoreDelete(cond->wait_list_lock); + return BHT_OK; +} + +static int +os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, + bool timed, int mills) +{ + os_thread_wait_node *node = &thread_data_current()->wait_node; + + node->next = NULL; + + xSemaphoreTake(cond->wait_list_lock, portMAX_DELAY); + if (!cond->thread_wait_list) + cond->thread_wait_list = node; + else { + /* Add to end of wait list */ + os_thread_wait_node *p = cond->thread_wait_list; + while (p->next) + p = p->next; + p->next = node; + } + xSemaphoreGive(cond->wait_list_lock); + + /* Unlock mutex, wait sem and lock mutex again */ + os_mutex_unlock(mutex); + xSemaphoreTake(node->sem, timed ? mills / portTICK_RATE_MS : portMAX_DELAY); + os_mutex_lock(mutex); + + /* Remove wait node from wait list */ + xSemaphoreTake(cond->wait_list_lock, portMAX_DELAY); + if (cond->thread_wait_list == node) + cond->thread_wait_list = node->next; + else { + /* Remove from the wait list */ + os_thread_wait_node *p = cond->thread_wait_list; + while (p->next != node) + p = p->next; + p->next = node->next; + } + xSemaphoreGive(cond->wait_list_lock); + + return BHT_OK; +} + +int os_cond_wait(korp_cond *cond, korp_mutex *mutex) +{ + return os_cond_wait_internal(cond, mutex, false, 0); +} + +int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds) +{ + if (useconds == BHT_WAIT_FOREVER) + return os_cond_wait_internal(cond, mutex, false, 0); + else + return os_cond_wait_internal(cond, mutex, true, useconds / 1000); +} + +int os_cond_signal(korp_cond *cond) +{ + /* Signal the head wait node of wait list */ + xSemaphoreTake(cond->wait_list_lock, portMAX_DELAY); + if (cond->thread_wait_list) + xSemaphoreGive(cond->thread_wait_list->sem); + xSemaphoreGive(cond->wait_list_lock); + + return BHT_OK; +} + +uint8 *os_thread_get_stack_boundary() +{ + /* TODO: implement os_thread_get_stack_boundary */ + return NULL; +} + diff --git a/core/shared/platform/freertos/freertos_time.c b/core/shared/platform/freertos/freertos_time.c new file mode 100644 index 000000000..72b1b5842 --- /dev/null +++ b/core/shared/platform/freertos/freertos_time.c @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +uint64 +os_time_get_boot_microsecond() +{ + TickType_t ticks = xTaskGetTickCount(); + return (uint64)1000 * 1000 / configTICK_RATE_HZ * ticks; +} + diff --git a/core/shared/platform/freertos/platform_internal.h b/core/shared/platform/freertos/platform_internal.h new file mode 100644 index 000000000..baa9e069f --- /dev/null +++ b/core/shared/platform/freertos/platform_internal.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef BH_PLATFORM_FREERTOS +#define BH_PLATFORM_FREERTOS +#endif + +#define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB) + +/* Default thread priority */ +#define BH_THREAD_DEFAULT_PRIORITY 5 + +extern int errno; + +typedef TaskHandle_t korp_thread; +typedef korp_thread korp_tid; +typedef struct { + bool is_recursive; + SemaphoreHandle_t sem; +} korp_mutex; + +struct os_thread_wait_node; +typedef struct os_thread_wait_node *os_thread_wait_list; +typedef struct korp_cond { + SemaphoreHandle_t wait_list_lock; + os_thread_wait_list thread_wait_list; +} korp_cond; + +int os_printf(const char *format, ...); +int os_vprintf(const char *format, va_list ap); + +/* math functions which are not provided by os */ +double sqrt(double x); +double floor(double x); +double ceil(double x); +double fmin(double x, double y); +double fmax(double x, double y); +double rint(double x); +double fabs(double x); +double trunc(double x); +float floorf(float x); +float ceilf(float x); +float fminf(float x, float y); +float fmaxf(float x, float y); +float rintf(float x); +float truncf(float x); +int signbit(double x); +int isnan(double x); + +int atoi(const char *s); +int strncasecmp(const char *s1, const char *s2, size_t n); +long int strtol(const char *str, char **endptr, int base); +unsigned long int strtoul(const char *str, char **endptr, int base); +unsigned long long int strtoull(const char *nptr, char **endptr, int base); +double strtod(const char *nptr, char **endptr); +float strtof(const char *nptr, char **endptr); +char *strstr(const char *haystack, const char *needle); +size_t strspn(const char *s, const char *accept); +size_t strcspn(const char *s, const char *reject); +void *memchr(const void *s, int c, size_t n); +int isalnum(int c); +int isxdigit(int c); +int isdigit(int c); +int isprint(int c); +int isgraph(int c); +int isspace(int c); +int isalpha(int c); +int isupper(int c); +int toupper(int c); +int tolower(int c); +void *memmove(void *dest, const void *src, size_t n); + +uint32_t htonl(uint32_t hostlong); +uint16_t htons(uint16_t hostshort); +uint32_t ntohl(uint32_t netlong); +uint16_t ntohs(uint16_t netshort); + +#endif diff --git a/core/shared/platform/freertos/shared_platform.cmake b/core/shared/platform/freertos/shared_platform.cmake new file mode 100644 index 000000000..1938acfd9 --- /dev/null +++ b/core/shared/platform/freertos/shared_platform.cmake @@ -0,0 +1,16 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions(-DBH_PLATFORM_FREERTOS) + +include_directories(${PLATFORM_SHARED_DIR}) +include_directories(${PLATFORM_SHARED_DIR}/../include) + +include (${CMAKE_CURRENT_LIST_DIR}/../common/math/platform_api_math.cmake) + +file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) + +set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE}) + diff --git a/product-mini/platforms/freertos/simple/iwasm_main.c b/product-mini/platforms/freertos/simple/iwasm_main.c new file mode 100644 index 000000000..fd0d0a9a7 --- /dev/null +++ b/product-mini/platforms/freertos/simple/iwasm_main.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" +#include "wasm_export.h" +#include "test_wasm.h" + +#define CONFIG_GLOBAL_HEAP_BUF_SIZE 131072 +#define CONFIG_APP_STACK_SIZE 8192 +#define CONFIG_APP_HEAP_SIZE 8192 + +static int app_argc; +static char **app_argv; + +static void* +app_instance_main(wasm_module_inst_t module_inst) +{ + const char *exception; + + wasm_application_execute_main(module_inst, app_argc, app_argv); + if ((exception = wasm_runtime_get_exception(module_inst))) + os_printf("%s\n", exception); + return NULL; +} + +static char global_heap_buf[CONFIG_GLOBAL_HEAP_BUF_SIZE] = { 0 }; + +void iwasm_main(void) +{ + uint8 *wasm_file_buf = NULL; + uint32 wasm_file_size; + wasm_module_t wasm_module = NULL; + wasm_module_inst_t wasm_module_inst = NULL; + RuntimeInitArgs init_args; + char error_buf[128]; +#if WASM_ENABLE_LOG != 0 + int log_verbose_level = 2; +#endif + + os_printf("### iwasm main begin\n"); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + /* initialize runtime environment */ + if (!wasm_runtime_full_init(&init_args)) { + os_printf("Init runtime environment failed.\n"); + return; + } + + os_printf("### wasm runtime initialized.\n"); + +#if WASM_ENABLE_LOG != 0 + bh_log_set_verbose_level(log_verbose_level); +#endif + + /* load WASM byte buffer from byte buffer of include file */ + wasm_file_buf = (uint8*)wasm_test_file; + wasm_file_size = sizeof(wasm_test_file); + + /* load WASM module */ + if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + os_printf("%s\n", error_buf); + goto fail1; + } + + os_printf("### wasm runtime load module success.\n"); + + /* instantiate the module */ + if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, + CONFIG_APP_STACK_SIZE, + CONFIG_APP_HEAP_SIZE, + error_buf, + sizeof(error_buf)))) { + os_printf("%s\n", error_buf); + goto fail2; + } + + os_printf("### wasm runtime instantiate module success.\n"); + + /* invoke the main function */ + app_instance_main(wasm_module_inst); + + os_printf("### wasm runtime execute app's main function success.\n"); + + /* destroy the module instance */ + wasm_runtime_deinstantiate(wasm_module_inst); + + os_printf("### wasm runtime deinstantiate module success.\n"); + +fail2: + /* unload the module */ + wasm_runtime_unload(wasm_module); + + os_printf("### wasm runtime unload module success.\n"); +fail1: + /* destroy runtime environment */ + wasm_runtime_destroy(); + os_printf("### wasm runtime destroy success.\n"); +} diff --git a/product-mini/platforms/freertos/simple/main.c b/product-mini/platforms/freertos/simple/main.c new file mode 100644 index 000000000..520754818 --- /dev/null +++ b/product-mini/platforms/freertos/simple/main.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" + +extern void +iwasm_main(void); + +static void +wamr_task(void *param) +{ + os_printf("WAMR task started\n"); + + iwasm_main(); + + while (1) { + task_sleep(1000); + /*os_printf("Hello WAMR\n");*/ + } + (void)param; +} + +static bool +app_init(uint32_t id) +{ + os_printf("WAMR init, id: %d\n", id); + task_start("wamr_task", 8192, 4, wamr_task, NULL); + return true; +} + +static void +app_exit(uint32_t id) +{ + os_printf("WAMR exit, id: %d\n", id); +} + +INTERNAL_APP_DEFINE("WAMR", APP_VERSION(0, 0, 0, 1), 0, app_init, app_exit); diff --git a/product-mini/platforms/freertos/simple/sources.mk b/product-mini/platforms/freertos/simple/sources.mk new file mode 100644 index 000000000..466769ee4 --- /dev/null +++ b/product-mini/platforms/freertos/simple/sources.mk @@ -0,0 +1,54 @@ +# TODO: set WAMR root dir +WAMR_ROOT := ../../../../ + +override PROJECT_CFLAGS := $(PROJECT_CFLAGS) -Wno-unused-parameter -Wno-pedantic + +override PROJECT_CFLAGS := $(PROJECT_CFLAGS) -I$(PROJECTS_SRC_ROOT)/include + +override PROJECT_CFLAGS := $(PROJECT_CFLAGS) \ + -I$(WAMR_INC_ROOT)/core \ + -I$(WAMR_INC_ROOT)/core/iwasm/include \ + -I$(WAMR_INC_ROOT)/core/iwasm/common \ + -I$(WAMR_INC_ROOT)/core/shared/utils \ + -I$(WAMR_INC_ROOT)/core/shared/mem-alloc \ + -I$(WAMR_INC_ROOT)/core/shared/platform/include \ + -I$(WAMR_INC_ROOT)/core/shared/platform/freertos \ + -I$(WAMR_INC_ROOT)/core/iwasm/interpreter + +override PROJECT_CFLAGS := $(PROJECT_CFLAGS) \ + -DBH_PLATFORM_FREERTOS \ + -DBH_MALLOC=wasm_runtime_malloc \ + -DBH_FREE=wasm_runtime_free \ + -DBUILD_TARGET_X86_32 \ + -DWASM_ENABLE_INTERP=1 \ + -DWASM_ENABLE_FAST_INTERP=0 \ + -DWASM_ENABLE_LIBC_BUILTIN=1 + +override PROJECT_CSRC := $(PROJECT_CSRC) \ + $(WAMR_SRC_ROOT)/core/shared/platform/freertos/freertos_platform.c \ + $(WAMR_SRC_ROOT)/core/shared/platform/freertos/freertos_thread.c \ + $(WAMR_SRC_ROOT)/core/shared/platform/freertos/freertos_time.c \ + $(WAMR_SRC_ROOT)/core/shared/platform/common/math/math.c \ + $(WAMR_SRC_ROOT)/core/shared/mem-alloc/mem_alloc.c \ + $(WAMR_SRC_ROOT)/core/shared/mem-alloc/ems/ems_kfc.c \ + $(WAMR_SRC_ROOT)/core/shared/mem-alloc/ems/ems_hmu.c \ + $(WAMR_SRC_ROOT)/core/shared/mem-alloc/ems/ems_alloc.c \ + $(WAMR_SRC_ROOT)/core/shared/utils/bh_assert.c \ + $(WAMR_SRC_ROOT)/core/shared/utils/bh_common.c \ + $(WAMR_SRC_ROOT)/core/shared/utils/bh_hashmap.c \ + $(WAMR_SRC_ROOT)/core/shared/utils/bh_list.c \ + $(WAMR_SRC_ROOT)/core/shared/utils/bh_log.c \ + $(WAMR_SRC_ROOT)/core/shared/utils/bh_vector.c \ + $(WAMR_SRC_ROOT)/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c \ + $(WAMR_SRC_ROOT)/core/iwasm/common/wasm_runtime_common.c \ + $(WAMR_SRC_ROOT)/core/iwasm/common/wasm_exec_env.c \ + $(WAMR_SRC_ROOT)/core/iwasm/common/wasm_native.c \ + $(WAMR_SRC_ROOT)/core/iwasm/common/wasm_memory.c \ + $(WAMR_SRC_ROOT)/core/iwasm/common/wasm_shared_memory.c \ + $(WAMR_SRC_ROOT)/core/iwasm/common/wasm_c_api.c \ + $(WAMR_SRC_ROOT)/core/iwasm/common/arch/invokeNative_ia32.s \ + $(WAMR_SRC_ROOT)/core/iwasm/interpreter/wasm_interp_classic.c \ + $(WAMR_SRC_ROOT)/core/iwasm/interpreter/wasm_loader.c \ + $(WAMR_SRC_ROOT)/core/iwasm/interpreter/wasm_runtime.c \ + $(WAMR_SRC_ROOT)/product-mini/platforms/freertos/simple/iwasm_main.c \ + $(WAMR_SRC_ROOT)/product-mini/platforms/freertos/simple/main.c diff --git a/product-mini/platforms/freertos/simple/test_wasm.h b/product-mini/platforms/freertos/simple/test_wasm.h new file mode 100644 index 000000000..a729cadef --- /dev/null +++ b/product-mini/platforms/freertos/simple/test_wasm.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +/** + * The byte array buffer is the file content of a test wasm binary file, + * which is compiled by wasi-sdk toolchain from C source file of: + * product-mini/app-samples/hello-world/main.c. + */ +unsigned char __aligned(4) wasm_test_file[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, + 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x01, + 0x7F, 0x00, 0x02, 0x31, 0x04, 0x03, 0x65, 0x6E, 0x76, 0x04, 0x70, 0x75, + 0x74, 0x73, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x61, 0x6C, + 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x70, 0x72, + 0x69, 0x6E, 0x74, 0x66, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x04, 0x66, + 0x72, 0x65, 0x65, 0x00, 0x02, 0x03, 0x02, 0x01, 0x01, 0x04, 0x05, 0x01, + 0x70, 0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x13, 0x03, + 0x7F, 0x01, 0x41, 0xC0, 0x28, 0x0B, 0x7F, 0x00, 0x41, 0xBA, 0x08, 0x0B, + 0x7F, 0x00, 0x41, 0xC0, 0x28, 0x0B, 0x07, 0x2C, 0x04, 0x06, 0x6D, 0x65, + 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x0A, 0x5F, 0x5F, 0x64, 0x61, 0x74, + 0x61, 0x5F, 0x65, 0x6E, 0x64, 0x03, 0x01, 0x0B, 0x5F, 0x5F, 0x68, 0x65, + 0x61, 0x70, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x02, 0x04, 0x6D, 0x61, + 0x69, 0x6E, 0x00, 0x04, 0x0A, 0xB2, 0x01, 0x01, 0xAF, 0x01, 0x01, 0x03, + 0x7F, 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x20, 0x6B, 0x22, 0x02, + 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x9B, 0x88, 0x80, 0x80, 0x00, + 0x10, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1A, 0x02, 0x40, 0x02, 0x40, 0x41, + 0x80, 0x08, 0x10, 0x81, 0x80, 0x80, 0x80, 0x00, 0x22, 0x03, 0x0D, 0x00, + 0x41, 0xA8, 0x88, 0x80, 0x80, 0x00, 0x10, 0x80, 0x80, 0x80, 0x80, 0x00, + 0x1A, 0x41, 0x7F, 0x21, 0x04, 0x0C, 0x01, 0x0B, 0x20, 0x02, 0x20, 0x03, + 0x36, 0x02, 0x10, 0x41, 0x80, 0x88, 0x80, 0x80, 0x00, 0x20, 0x02, 0x41, + 0x10, 0x6A, 0x10, 0x82, 0x80, 0x80, 0x80, 0x00, 0x1A, 0x41, 0x00, 0x21, + 0x04, 0x20, 0x03, 0x41, 0x04, 0x6A, 0x41, 0x00, 0x2F, 0x00, 0x91, 0x88, + 0x80, 0x80, 0x00, 0x3B, 0x00, 0x00, 0x20, 0x03, 0x41, 0x00, 0x28, 0x00, + 0x8D, 0x88, 0x80, 0x80, 0x00, 0x36, 0x00, 0x00, 0x20, 0x02, 0x20, 0x03, + 0x36, 0x02, 0x00, 0x41, 0x93, 0x88, 0x80, 0x80, 0x00, 0x20, 0x02, 0x10, + 0x82, 0x80, 0x80, 0x80, 0x00, 0x1A, 0x20, 0x03, 0x10, 0x83, 0x80, 0x80, + 0x80, 0x00, 0x0B, 0x20, 0x02, 0x41, 0x20, 0x6A, 0x24, 0x80, 0x80, 0x80, + 0x80, 0x00, 0x20, 0x04, 0x0B, 0x0B, 0x41, 0x01, 0x00, 0x41, 0x80, 0x08, + 0x0B, 0x3A, 0x62, 0x75, 0x66, 0x20, 0x70, 0x74, 0x72, 0x3A, 0x20, 0x25, + 0x70, 0x0A, 0x00, 0x31, 0x32, 0x33, 0x34, 0x0A, 0x00, 0x62, 0x75, 0x66, + 0x3A, 0x20, 0x25, 0x73, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, + 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x00, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, + 0x20, 0x62, 0x75, 0x66, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x00 +};