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.
This commit is contained in:
Lucas Saavedra Vaz 2023-05-10 09:28:00 -03:00 committed by Alan Carvalho de Assis
parent 53d0d04e8e
commit 274a79fd34
6 changed files with 480 additions and 26 deletions

View File

@ -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)

View File

@ -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;
}

View File

@ -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();

View File

@ -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
****************************************************************************/

View File

@ -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 */

View File

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