diff --git a/arch/xtensa/src/esp32s2/Make.defs b/arch/xtensa/src/esp32s2/Make.defs index 0bf9659b44..12fea11818 100644 --- a/arch/xtensa/src/esp32s2/Make.defs +++ b/arch/xtensa/src/esp32s2/Make.defs @@ -30,7 +30,7 @@ HEAD_CSRC = esp32s2_start.c esp32s2_wdt.c CHIP_CSRCS = esp32s2_allocateheap.c esp32s2_clockconfig.c esp32s2_irq.c CHIP_CSRCS += esp32s2_gpio.c esp32s2_rtc_gpio.c esp32s2_region.c esp32s2_user.c CHIP_CSRCS += esp32s2_timerisr.c esp32s2_lowputc.c esp32s2_systemreset.c -CHIP_CSRCS += esp32s2_dma.c +CHIP_CSRCS += esp32s2_dma.c esp32s2_libc_stubs.c # Configuration-dependent ESP32-S2 files diff --git a/arch/xtensa/src/esp32s2/esp32s2_libc_stubs.c b/arch/xtensa/src/esp32s2/esp32s2_libc_stubs.c new file mode 100644 index 0000000000..3ce1294043 --- /dev/null +++ b/arch/xtensa/src/esp32s2/esp32s2_libc_stubs.c @@ -0,0 +1,330 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s2/esp32s2_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/esp32s2_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; + + /* Newlib 3.0.0 is used in ROM, the following lock symbols are defined: */ + + extern _lock_t __sinit_recursive_mutex; + __sinit_recursive_mutex = (_lock_t) &g_nxlock_recursive; + + extern _lock_t __sfp_recursive_mutex; + __sfp_recursive_mutex = (_lock_t) &g_nxlock_recursive; +} diff --git a/arch/xtensa/src/esp32s2/esp32s2_start.c b/arch/xtensa/src/esp32s2/esp32s2_start.c index 891efbeaef..22a0b368ea 100644 --- a/arch/xtensa/src/esp32s2/esp32s2_start.c +++ b/arch/xtensa/src/esp32s2/esp32s2_start.c @@ -35,6 +35,7 @@ #include "hardware/esp32s2_cache_memory.h" #include "hardware/esp32s2_extmem.h" +#include "rom/esp32s2_libc_stubs.h" #include "esp32s2_clockconfig.h" #include "esp32s2_region.h" #include "esp32s2_spiram.h" @@ -371,6 +372,10 @@ static void noreturn_function IRAM_ATTR __esp32s2_start(void) } #endif + /* Setup the syscall table needed by the ROM code */ + + esp_setup_syscall_table(); + /* Initialize onboard resources */ esp32s2_board_initialize(); diff --git a/arch/xtensa/src/esp32s2/rom/esp32s2_libc_stubs.h b/arch/xtensa/src/esp32s2/rom/esp32s2_libc_stubs.h new file mode 100644 index 0000000000..9101775437 --- /dev/null +++ b/arch/xtensa/src/esp32s2/rom/esp32s2_libc_stubs.h @@ -0,0 +1,132 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s2/rom/esp32s2_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_ESP32S2_ROM_ESP32S2_LIBC_STUBS_H +#define __ARCH_XTENSA_SRC_ESP32S2_ROM_ESP32S2_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-S2 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 is + * a pointer, `syscall_table_ptr_pro`, + * which can be set to point to the locations of syscall tables of + * CPU 0 (aka PRO 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; + +/**************************************************************************** + * 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_ESP32S2_ROM_ESP32S2_LIBC_STUBS_H */ diff --git a/boards/xtensa/esp32s2/common/scripts/esp32s2_rom.ld b/boards/xtensa/esp32s2/common/scripts/esp32s2_rom.ld index 07608a43ec..51fba7b788 100644 --- a/boards/xtensa/esp32s2/common/scripts/esp32s2_rom.ld +++ b/boards/xtensa/esp32s2/common/scripts/esp32s2_rom.ld @@ -618,7 +618,9 @@ PROVIDE ( SendMsg = 0x40012d0c ); PROVIDE ( send_packet = 0x40012cc8 ); PROVIDE ( set_rtc_memory_crc = 0x40010010 ); PROVIDE ( SetSpiDrvs = 0x40015c18 ); +PROVIDE ( __sfp_recursive_mutex = 0x3ffffd88 ); PROVIDE ( sig_matrix = 0x3ffffd57 ); +PROVIDE ( __sinit_recursive_mutex = 0x3ffffd84 ); PROVIDE ( software_reset = 0x40010068 ); PROVIDE ( software_reset_cpu = 0x40010080 ); PROVIDE ( SPI_block_erase = 0x4001623c );