This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 274a79fd348f52c9ed6d046ad55bbbb4f58b1e61 Author: Lucas Saavedra Vaz <[email protected]> AuthorDate: Wed May 10 09:28:00 2023 -0300 arch/xtensa/esp32: Define syscall table to enable using ROM functions This commit aims to enable the use of ROM functions on ESP32. This is done by creating the required syscall stubs table and adding the missing symbols to the linker script. --- arch/xtensa/src/esp32/Make.defs | 2 +- arch/xtensa/src/esp32/esp32_libc_stubs.c | 337 ++++++++++++++++++++++++ arch/xtensa/src/esp32/esp32_start.c | 5 + arch/xtensa/src/esp32/esp32_wifi_adapter.c | 25 -- arch/xtensa/src/esp32/rom/esp32_libc_stubs.h | 133 ++++++++++ boards/xtensa/esp32/common/scripts/esp32_rom.ld | 4 + 6 files changed, 480 insertions(+), 26 deletions(-) diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs index 27f55b52e2..9ddcab35d1 100644 --- a/arch/xtensa/src/esp32/Make.defs +++ b/arch/xtensa/src/esp32/Make.defs @@ -34,7 +34,7 @@ endif CHIP_CSRCS = esp32_allocateheap.c esp32_clockconfig.c esp32_gpio.c CHIP_CSRCS += esp32_systemreset.c esp32_resetcause.c CHIP_CSRCS += esp32_irq.c esp32_region.c esp32_rtc_gpio.c -CHIP_CSRCS += esp32_user.c +CHIP_CSRCS += esp32_user.c esp32_libc_stubs.c CHIP_CSRCS += esp32_dma.c ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y) diff --git a/arch/xtensa/src/esp32/esp32_libc_stubs.c b/arch/xtensa/src/esp32/esp32_libc_stubs.c new file mode 100644 index 0000000000..f65a865318 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_libc_stubs.c @@ -0,0 +1,337 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_libc_stubs.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <assert.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <sys/times.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <nuttx/mutex.h> +#include "rom/esp32_libc_stubs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define _lock_t int + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +static mutex_t g_nxlock_common; +static mutex_t g_nxlock_recursive; + +/* Forward declaration */ + +struct _reent; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int _close_r(struct _reent *r, int fd) +{ + return close(fd); +} + +int _fstat_r(struct _reent *r, int fd, struct stat *statbuf) +{ + return fstat(fd, statbuf); +} + +int _getpid_r(struct _reent *r) +{ + return getpid(); +} + +int _kill_r(struct _reent *r, int pid, int sig) +{ + return kill(pid, sig); +} + +int _link_r(struct _reent *r, const char *oldpath, const char *newpath) +{ + /* TODO */ + + return 0; +} + +int lseek_r(struct _reent *r, int fd, int offset, int whence) +{ + return lseek(fd, offset, whence); +} + +int _open_r(struct _reent *r, const char *pathname, int flags, int mode) +{ + return open(pathname, flags, mode); +} + +int read_r(struct _reent *r, int fd, void *buf, int count) +{ + return read(fd, buf, count); +} + +int _rename_r(struct _reent *r, const char *oldpath, const char *newpath) +{ + return rename(oldpath, newpath); +} + +void *_sbrk_r(struct _reent *r, ptrdiff_t increment) +{ + /* TODO: sbrk is only supported on Kernel mode */ + + errno = -ENOMEM; + return (void *) -1; +} + +int _stat_r(struct _reent *r, const char *pathname, struct stat *statbuf) +{ + return stat(pathname, statbuf); +} + +clock_t _times_r(struct _reent *r, struct tms *buf) +{ + return times(buf); +} + +int _unlink_r(struct _reent *r, const char *pathname) +{ + return unlink(pathname); +} + +int write_r(struct _reent *r, int fd, const void *buf, int count) +{ + return write(fd, buf, count); +} + +int _gettimeofday_r(struct _reent *r, struct timeval *tv, void *tz) +{ + return gettimeofday(tv, tz); +} + +void *_malloc_r(struct _reent *r, size_t size) +{ + return malloc(size); +} + +void *_realloc_r(struct _reent *r, void *ptr, size_t size) +{ + return realloc(ptr, size); +} + +void *_calloc_r(struct _reent *r, size_t nmemb, size_t size) +{ + return calloc(nmemb, size); +} + +void _free_r(struct _reent *r, void *ptr) +{ + free(ptr); +} + +void _abort(void) +{ + abort(); +} + +void _raise_r(struct _reent *r) +{ + /* FIXME */ +} + +void _lock_init(_lock_t *lock) +{ + nxmutex_init(&g_nxlock_common); + nxsem_get_value(&g_nxlock_common.sem, lock); +} + +void _lock_init_recursive(_lock_t *lock) +{ + nxmutex_init(&g_nxlock_recursive); + nxsem_get_value(&g_nxlock_recursive.sem, lock); +} + +void _lock_close(_lock_t *lock) +{ + nxmutex_destroy(&g_nxlock_common); + *lock = 0; +} + +void _lock_close_recursive(_lock_t *lock) +{ + nxmutex_destroy(&g_nxlock_recursive); + *lock = 0; +} + +void _lock_acquire(_lock_t *lock) +{ + nxmutex_lock(&g_nxlock_common); + nxsem_get_value(&g_nxlock_common.sem, lock); +} + +void _lock_acquire_recursive(_lock_t *lock) +{ + nxmutex_lock(&g_nxlock_recursive); + nxsem_get_value(&g_nxlock_recursive.sem, lock); +} + +int _lock_try_acquire(_lock_t *lock) +{ + nxmutex_trylock(&g_nxlock_common); + nxsem_get_value(&g_nxlock_common.sem, lock); + return 0; +} + +int _lock_try_acquire_recursive(_lock_t *lock) +{ + nxmutex_trylock(&g_nxlock_recursive); + nxsem_get_value(&g_nxlock_recursive.sem, lock); + return 0; +} + +void _lock_release(_lock_t *lock) +{ + nxmutex_unlock(&g_nxlock_common); + nxsem_get_value(&g_nxlock_common.sem, lock); +} + +void _lock_release_recursive(_lock_t *lock) +{ + nxmutex_unlock(&g_nxlock_recursive); + nxsem_get_value(&g_nxlock_recursive.sem, lock); +} + +struct _reent *__getreent(void) +{ + /* TODO */ + + return (struct _reent *) NULL; +} + +int _system_r(struct _reent *r, const char *command) +{ + /* TODO: Implement system() */ + + return 0; +} + +void noreturn_function __assert_func(const char *file, int line, + const char *func, const char *expr) +{ + __assert(file, line, expr); +} + +void _cleanup_r(struct _reent *r) +{ +} + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct syscall_stub_table g_stub_table = +{ + .__getreent = &__getreent, + ._malloc_r = &_malloc_r, + ._free_r = &_free_r, + ._realloc_r = &_realloc_r, + ._calloc_r = &_calloc_r, + ._abort = &_abort, + ._system_r = &_system_r, + ._rename_r = &_rename_r, + ._times_r = &_times_r, + ._gettimeofday_r = &_gettimeofday_r, + ._raise_r = &_raise_r, + ._unlink_r = &_unlink_r, + ._link_r = &_link_r, + ._stat_r = &_stat_r, + ._fstat_r = &_fstat_r, + ._sbrk_r = &_sbrk_r, + ._getpid_r = &_getpid_r, + ._kill_r = &_kill_r, + ._exit_r = NULL, + ._close_r = &_close_r, + ._open_r = &_open_r, + ._write_r = &write_r, + ._lseek_r = &lseek_r, + ._read_r = &read_r, + ._lock_init = &_lock_init, + ._lock_init_recursive = &_lock_init_recursive, + ._lock_close = &_lock_close, + ._lock_close_recursive = &_lock_close_recursive, + ._lock_acquire = &_lock_acquire, + ._lock_acquire_recursive = &_lock_acquire_recursive, + ._lock_try_acquire = &_lock_try_acquire, + ._lock_try_acquire_recursive = &_lock_try_acquire_recursive, + ._lock_release = &_lock_release, + ._lock_release_recursive = &_lock_release_recursive, + ._printf_float = NULL, + ._scanf_float = NULL +}; + +/**************************************************************************** + * Name: esp_setup_syscall_table + * + * Description: + * Configure the syscall table used by the ROM code for calling C library + * functions. + * ROM code from Espressif's chips contains implementations of some of C + * library functions. Whenever a function in ROM needs to use a syscall, + * it calls a pointer to the corresponding syscall implementation defined + * in the syscall_stub_table struct. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_setup_syscall_table(void) +{ + syscall_table_ptr_pro = (struct syscall_stub_table *)&g_stub_table; + syscall_table_ptr_app = (struct syscall_stub_table *)&g_stub_table; + + /* Newlib 2.2.0 is used in ROM, the following lock symbols are defined: */ + + extern _lock_t __sfp_lock; + __sfp_lock = (_lock_t) &g_nxlock_recursive; + + extern _lock_t __sinit_lock; + __sinit_lock = (_lock_t) &g_nxlock_recursive; + + extern _lock_t __env_lock_object; + __env_lock_object = (_lock_t) &g_nxlock_recursive; + + extern _lock_t __tz_lock_object; + __tz_lock_object = (_lock_t) &g_nxlock_common; +} diff --git a/arch/xtensa/src/esp32/esp32_start.c b/arch/xtensa/src/esp32/esp32_start.c index 8aeab7f271..bde7ef8624 100644 --- a/arch/xtensa/src/esp32/esp32_start.c +++ b/arch/xtensa/src/esp32/esp32_start.c @@ -44,6 +44,7 @@ #endif #include "hardware/esp32_dport.h" #include "hardware/esp32_rtccntl.h" +#include "rom/esp32_libc_stubs.h" /**************************************************************************** * Pre-processor Definitions @@ -243,6 +244,10 @@ static noreturn_function void __esp32_start(void) #endif + /* Setup the syscall table needed by the ROM code */ + + esp_setup_syscall_table(); + /* Initialize onboard resources */ esp32_board_initialize(); diff --git a/arch/xtensa/src/esp32/esp32_wifi_adapter.c b/arch/xtensa/src/esp32/esp32_wifi_adapter.c index 21dad51c16..1a1a1dad65 100644 --- a/arch/xtensa/src/esp32/esp32_wifi_adapter.c +++ b/arch/xtensa/src/esp32/esp32_wifi_adapter.c @@ -4504,31 +4504,6 @@ int32_t esp_timer_delete(esp_timer_handle_t timer) return 0; } -/**************************************************************************** - * Name: __assert_func - * - * Description: - * Delete timer and free resource - * - * Input Parameters: - * file - assert file - * line - assert line - * func - assert function - * expr - assert condition - * - * Returned Value: - * None - * - ****************************************************************************/ - -void __assert_func(const char *file, int line, - const char *func, const char *expr) -{ - wlerr("Assert failed in %s, %s:%d (%s)", - func, file, line, expr); - abort(); -} - /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/arch/xtensa/src/esp32/rom/esp32_libc_stubs.h b/arch/xtensa/src/esp32/rom/esp32_libc_stubs.h new file mode 100644 index 0000000000..e63e1004cf --- /dev/null +++ b/arch/xtensa/src/esp32/rom/esp32_libc_stubs.h @@ -0,0 +1,133 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/rom/esp32_libc_stubs.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32_ROM_ESP32_LIBC_STUBS_H +#define __ARCH_XTENSA_SRC_ESP32_ROM_ESP32_LIBC_STUBS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <stdio.h> + +#include <sys/time.h> +#include <sys/times.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <signal.h> + +#include <nuttx/mutex.h> + +#define _lock_t int + +/* Forward declaration */ + +struct _reent; + +/** + * @brief ESP32 ROM code contains implementations of some of C + * library functions. + * Whenever a function in ROM needs to use a syscall, it calls a + * pointer to the corresponding syscall implementation defined in + * the following struct. + * + * The table itself, by default, is not allocated in RAM. There are + * two pointers, `syscall_table_ptr_pro` and `syscall_table_ptr_app`, + * which can be set to point to the locations of syscall tables of + * CPU 0 (aka PRO CPU) and CPU 1 (aka APP CPU). Location of these + * pointers in .bss segment of ROM code is defined in linker script. + * + * So, before using any of the C library functions (except for pure + * functions and memcpy/memset functions), application must allocate + * syscall table structure for each CPU being used, and populate it + * with pointers to actual implementations of corresponding syscalls. + */ + +struct syscall_stub_table +{ + struct _reent *(* __getreent)(void); + void *(* _malloc_r)(struct _reent *r, size_t); + void (* _free_r)(struct _reent *r, void *); + void *(* _realloc_r)(struct _reent *r, void *, size_t); + void *(* _calloc_r)(struct _reent *r, size_t, size_t); + void (* _abort)(void); + int (* _system_r)(struct _reent *r, const char *); + int (* _rename_r)(struct _reent *r, const char *, const char *); + clock_t (* _times_r)(struct _reent *r, struct tms *); + int (* _gettimeofday_r) (struct _reent *r, struct timeval *, void *); + void (* _raise_r)(struct _reent *r); + int (* _unlink_r)(struct _reent *r, const char *); + int (* _link_r)(struct _reent *r, const char *, const char *); + int (* _stat_r)(struct _reent *r, const char *, struct stat *); + int (* _fstat_r)(struct _reent *r, int, struct stat *); + void *(* _sbrk_r)(struct _reent *r, ptrdiff_t); + int (* _getpid_r)(struct _reent *r); + int (* _kill_r)(struct _reent *r, int, int); + void (* _exit_r)(struct _reent *r, int); + int (* _close_r)(struct _reent *r, int); + int (* _open_r)(struct _reent *r, const char *, int, int); + int (* _write_r)(struct _reent *r, int, const void *, int); + int (* _lseek_r)(struct _reent *r, int, int, int); + int (* _read_r)(struct _reent *r, int, void *, int); + void (*_lock_init)(_lock_t *lock); + void (*_lock_init_recursive)(_lock_t *lock); + void (*_lock_close)(_lock_t *lock); + void (*_lock_close_recursive)(_lock_t *lock); + void (*_lock_acquire)(_lock_t *lock); + void (*_lock_acquire_recursive)(_lock_t *lock); + int (*_lock_try_acquire)(_lock_t *lock); + int (*_lock_try_acquire_recursive)(_lock_t *lock); + void (*_lock_release)(_lock_t *lock); + void (*_lock_release_recursive)(_lock_t *lock); + int (*_printf_float)(struct _reent *data, void *pdata, FILE * fp, + int (*pfunc) (struct _reent *, FILE *, + const char *, size_t len), va_list * ap); + int (*_scanf_float)(struct _reent *rptr, void *pdata, FILE *fp, + va_list *ap); +}; + +extern struct syscall_stub_table *syscall_table_ptr_pro; +extern struct syscall_stub_table *syscall_table_ptr_app; + +/**************************************************************************** + * Name: esp_setup_syscall_table + * + * Description: + * Configure the syscall table used by the ROM code for calling C library + * functions. + * ROM code from Espressif's chips contains implementations of some of C + * library functions. Whenever a function in ROM needs to use a syscall, + * it calls a pointer to the corresponding syscall implementation defined + * in the syscall_stub_table struct. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_setup_syscall_table(void); + +#endif /* __ARCH_XTENSA_SRC_ESP32_ROM_ESP32_LIBC_STUBS_H */ diff --git a/boards/xtensa/esp32/common/scripts/esp32_rom.ld b/boards/xtensa/esp32/common/scripts/esp32_rom.ld index ff0bd51e11..efc1275f6e 100644 --- a/boards/xtensa/esp32/common/scripts/esp32_rom.ld +++ b/boards/xtensa/esp32/common/scripts/esp32_rom.ld @@ -234,6 +234,7 @@ PROVIDE ( ecc_Jacobian_InfinityPoint256 = 0x3ff972e8 ); PROVIDE ( em_buf_env = 0x3ffb8d74 ); PROVIDE ( environ = 0x3ffae0b4 ); PROVIDE ( __env_lock = 0x40001fd4 ); +PROVIDE ( __env_lock_object = 0x3ffae0b8 ); PROVIDE ( __env_unlock = 0x40001fe0 ); PROVIDE ( esp_crc8 = 0x4005d144 ); PROVIDE ( _etext = 0x4000d66c ); @@ -1708,6 +1709,7 @@ PROVIDE ( __sf_fake_stdout = 0x3ff96478 ); PROVIDE ( __sflush_r = 0x400591e0 ); PROVIDE ( __sfmoreglue = 0x40001dc8 ); PROVIDE ( __sfp = 0x40001e90 ); +PROVIDE ( __sfp_lock = 0x3ffae0ac ); PROVIDE ( __sfp_lock_acquire = 0x40001e08 ); PROVIDE ( __sfp_lock_release = 0x40001e14 ); PROVIDE ( __sfputs_r = 0x40057790 ); @@ -1721,6 +1723,7 @@ PROVIDE ( sha_blk_bits_bytes = 0x3ff99288 ); PROVIDE ( sha_blk_hash_bytes = 0x3ff9928c ); PROVIDE ( sig_matrix = 0x3ffae293 ); PROVIDE ( __sinit = 0x40001e38 ); +PROVIDE ( __sinit_lock = 0x3ffae0a8 ); PROVIDE ( __sinit_lock_acquire = 0x40001e20 ); PROVIDE ( __sinit_lock_release = 0x40001e2c ); PROVIDE ( sip_after_tx_complete = 0x4000b358 ); @@ -1892,6 +1895,7 @@ PROVIDE ( __tz_lock = 0x40001a04 ); PROVIDE ( _tzname = 0x3ffae030 ); PROVIDE ( tzset = 0x40001a1c ); PROVIDE ( _tzset_r = 0x40001a28 ); +PROVIDE ( __tz_lock_object = 0x3ffae080 ); PROVIDE ( __tz_unlock = 0x40001a10 ); PROVIDE ( uartAttach = 0x40008fd0 ); PROVIDE ( uart_baudrate_detect = 0x40009034 );
