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 a895cd4854634813472656ae890dfcad2fa350e1
Author: Lucas Saavedra Vaz <[email protected]>
AuthorDate: Wed May 10 09:28:13 2023 -0300

    arch/xtensa/esp32s2: Define syscall table to enable using ROM functions
    
    This commit aims to enable the use of ROM functions on ESP32-S2.
    This is done by creating the required syscall stubs table and adding the 
missing symbols to the linker script.
---
 arch/xtensa/src/esp32s2/Make.defs                  |   2 +-
 arch/xtensa/src/esp32s2/esp32s2_libc_stubs.c       | 330 +++++++++++++++++++++
 arch/xtensa/src/esp32s2/esp32s2_start.c            |   5 +
 arch/xtensa/src/esp32s2/rom/esp32s2_libc_stubs.h   | 132 +++++++++
 .../xtensa/esp32s2/common/scripts/esp32s2_rom.ld   |   2 +
 5 files changed, 470 insertions(+), 1 deletion(-)

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 <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/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 <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-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 );

Reply via email to