diff --git a/arch/xtensa/src/esp32s3/Make.defs b/arch/xtensa/src/esp32s3/Make.defs index 32b8a48a7b..e0f8c11626 100644 --- a/arch/xtensa/src/esp32s3/Make.defs +++ b/arch/xtensa/src/esp32s3/Make.defs @@ -30,7 +30,7 @@ HEAD_CSRC = esp32s3_start.c CHIP_CSRCS = esp32s3_irq.c esp32s3_clockconfig.c esp32s3_region.c CHIP_CSRCS += esp32s3_systemreset.c esp32s3_user.c esp32s3_allocateheap.c CHIP_CSRCS += esp32s3_wdt.c esp32s3_gpio.c esp32s3_lowputc.c esp32s3_serial.c -CHIP_CSRCS += esp32s3_rtc_gpio.c +CHIP_CSRCS += esp32s3_rtc_gpio.c esp32s3_libc_stubs.c # Configuration-dependent ESP32-S3 files diff --git a/arch/xtensa/src/esp32s3/esp32s3_libc_stubs.c b/arch/xtensa/src/esp32s3/esp32s3_libc_stubs.c new file mode 100644 index 0000000000..c6c722f8a6 --- /dev/null +++ b/arch/xtensa/src/esp32s3/esp32s3_libc_stubs.c @@ -0,0 +1,394 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s3/esp32s3_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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "rom/esp32s3_libc_stubs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define _lock_t int + +#define ROM_MUTEX_MAGIC 0xbb10c433 + +/**************************************************************************** + * 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); +} + +void __retarget_lock_init(_lock_t *lock) +{ + _lock_init(lock); +} + +void __retarget_lock_init_recursive(_lock_t *lock) +{ + _lock_init_recursive(lock); +} + +void __retarget_lock_close(_lock_t lock) +{ + _lock_close(&lock); +} + +void __retarget_lock_close_recursive(_lock_t lock) +{ + _lock_close_recursive(&lock); +} + +void __retarget_lock_acquire(_lock_t lock) +{ + _lock_acquire(&lock); +} + +void __retarget_lock_acquire_recursive(_lock_t lock) +{ + _lock_acquire_recursive(&lock); +} + +int __retarget_lock_try_acquire(_lock_t lock) +{ + return _lock_try_acquire(&lock); +} + +int __retarget_lock_try_acquire_recursive(_lock_t lock) +{ + return _lock_try_acquire_recursive(&lock); +} + +void __retarget_lock_release(_lock_t lock) +{ + _lock_release(&lock); +} + +void __retarget_lock_release_recursive(_lock_t lock) +{ + _lock_release_recursive(&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, + ._retarget_lock_init = &__retarget_lock_init, + ._retarget_lock_init_recursive = &__retarget_lock_init_recursive, + ._retarget_lock_close = &__retarget_lock_close, + ._retarget_lock_close_recursive = &__retarget_lock_close_recursive, + ._retarget_lock_acquire = &__retarget_lock_acquire, + ._retarget_lock_acquire_recursive = &__retarget_lock_acquire_recursive, + ._retarget_lock_try_acquire = &__retarget_lock_try_acquire, + ._retarget_lock_try_acquire_recursive = + &__retarget_lock_try_acquire_recursive, + ._retarget_lock_release = &__retarget_lock_release, + ._retarget_lock_release_recursive = &__retarget_lock_release_recursive, + ._printf_float = NULL, + ._scanf_float = NULL, + .__assert_func = &__assert_func, + .__sinit = (void *)abort, + ._cleanup_r = &_cleanup_r +}; + +/**************************************************************************** + * 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 = (struct syscall_stub_table *)&g_stub_table; + + /* Newlib 3.3.0 is used in ROM, built with _RETARGETABLE_LOCKING. + * No access to lock variables for the purpose of ECO forward + * compatibility, however we have an API to initialize lock variables used + * in the ROM. + */ + + extern void esp_rom_newlib_init_common_mutexes(_lock_t, _lock_t); + + int magic_val = ROM_MUTEX_MAGIC; + _lock_t magic_mutex = (_lock_t) &magic_val; + esp_rom_newlib_init_common_mutexes(magic_mutex, magic_mutex); +} diff --git a/arch/xtensa/src/esp32s3/esp32s3_start.c b/arch/xtensa/src/esp32s3/esp32s3_start.c index 22fbdb1a99..49cac473d5 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_start.c +++ b/arch/xtensa/src/esp32s3/esp32s3_start.c @@ -45,6 +45,7 @@ #include "hardware/esp32s3_cache_memory.h" #include "hardware/esp32s3_system.h" #include "hardware/esp32s3_extmem.h" +#include "rom/esp32s3_libc_stubs.h" /**************************************************************************** * Pre-processor Definitions @@ -351,6 +352,10 @@ void noreturn_function IRAM_ATTR __esp32s3_start(void) } #endif + /* Setup the syscall table needed by the ROM code */ + + esp_setup_syscall_table(); + /* Initialize onboard resources */ esp32s3_board_initialize(); diff --git a/arch/xtensa/src/esp32s3/rom/esp32s3_libc_stubs.h b/arch/xtensa/src/esp32s3/rom/esp32s3_libc_stubs.h new file mode 100644 index 0000000000..6740807433 --- /dev/null +++ b/arch/xtensa/src/esp32s3/rom/esp32s3_libc_stubs.h @@ -0,0 +1,139 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s3/rom/esp32s3_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_ESP32S3_ROM_ESP32S3_LIBC_STUBS_H +#define __ARCH_XTENSA_SRC_ESP32S3_ROM_ESP32S3_LIBC_STUBS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define _lock_t int + +/* Forward declaration */ + +struct _reent; + +/** + * @brief ESP32-S3 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 (* _retarget_lock_init)(_lock_t *lock); + void (* _retarget_lock_init_recursive)(_lock_t *lock); + void (* _retarget_lock_close)(_lock_t lock); + void (* _retarget_lock_close_recursive)(_lock_t lock); + void (* _retarget_lock_acquire)(_lock_t lock); + void (* _retarget_lock_acquire_recursive)(_lock_t lock); + int (* _retarget_lock_try_acquire)(_lock_t lock); + int (* _retarget_lock_try_acquire_recursive)(_lock_t lock); + void (* _retarget_lock_release)(_lock_t lock); + void (* _retarget_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); + void (* __assert_func) (const char *file, int line, + const char *func, const char *failedexpr) + __attribute__((noreturn)); + void (* __sinit) (struct _reent *r); + void (* _cleanup_r) (struct _reent *r); +}; + +extern const struct syscall_stub_table *syscall_table_ptr; +#define syscall_table_ptr_pro syscall_table_ptr +#define syscall_table_ptr_app syscall_table_ptr + +/**************************************************************************** + * 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_ESP32S3_ROM_ESP32S3_LIBC_STUBS_H */