Merge branch 'feature/vfs_optional' into 'master'
vfs: add option to disable VFS layer, saving some RAM and code size See merge request espressif/esp-idf!7950
This commit is contained in:
commit
55c3c2b73d
27 changed files with 602 additions and 418 deletions
|
@ -354,18 +354,21 @@ void start_cpu0_default(void)
|
||||||
esp_efuse_disable_basic_rom_console();
|
esp_efuse_disable_basic_rom_console();
|
||||||
#endif
|
#endif
|
||||||
rtc_gpio_force_hold_dis_all();
|
rtc_gpio_force_hold_dis_all();
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_IO
|
||||||
esp_vfs_dev_uart_register();
|
esp_vfs_dev_uart_register();
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_IO
|
||||||
|
|
||||||
|
#if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||||
esp_reent_init(_GLOBAL_REENT);
|
esp_reent_init(_GLOBAL_REENT);
|
||||||
#ifndef CONFIG_ESP_CONSOLE_UART_NONE
|
|
||||||
const char* default_uart_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
|
const char* default_uart_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||||
_GLOBAL_REENT->_stdin = fopen(default_uart_dev, "r");
|
_GLOBAL_REENT->_stdin = fopen(default_uart_dev, "r");
|
||||||
_GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w");
|
_GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w");
|
||||||
_GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w");
|
_GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w");
|
||||||
#else
|
#else // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||||
_GLOBAL_REENT->_stdin = (FILE*) &__sf_fake_stdin;
|
_REENT_SMALL_CHECK_INIT(_GLOBAL_REENT);
|
||||||
_GLOBAL_REENT->_stdout = (FILE*) &__sf_fake_stdout;
|
#endif // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||||
_GLOBAL_REENT->_stderr = (FILE*) &__sf_fake_stderr;
|
|
||||||
#endif
|
|
||||||
esp_timer_init();
|
esp_timer_init();
|
||||||
esp_set_time_from_rtc();
|
esp_set_time_from_rtc();
|
||||||
#if CONFIG_APPTRACE_ENABLE
|
#if CONFIG_APPTRACE_ENABLE
|
||||||
|
|
|
@ -284,18 +284,21 @@ void start_cpu0_default(void)
|
||||||
esp_efuse_disable_basic_rom_console();
|
esp_efuse_disable_basic_rom_console();
|
||||||
#endif
|
#endif
|
||||||
rtc_gpio_force_hold_dis_all();
|
rtc_gpio_force_hold_dis_all();
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_IO
|
||||||
esp_vfs_dev_uart_register();
|
esp_vfs_dev_uart_register();
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_IO
|
||||||
|
|
||||||
|
#if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||||
esp_reent_init(_GLOBAL_REENT);
|
esp_reent_init(_GLOBAL_REENT);
|
||||||
#ifndef CONFIG_ESP_CONSOLE_UART_NONE
|
|
||||||
const char *default_uart_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
|
const char *default_uart_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||||
_GLOBAL_REENT->_stdin = fopen(default_uart_dev, "r");
|
_GLOBAL_REENT->_stdin = fopen(default_uart_dev, "r");
|
||||||
_GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w");
|
_GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w");
|
||||||
_GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w");
|
_GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w");
|
||||||
#else
|
#else // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||||
_GLOBAL_REENT->_stdin = (FILE *) &__sf_fake_stdin;
|
_REENT_SMALL_CHECK_INIT(_GLOBAL_REENT);
|
||||||
_GLOBAL_REENT->_stdout = (FILE *) &__sf_fake_stdout;
|
#endif // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||||
_GLOBAL_REENT->_stderr = (FILE *) &__sf_fake_stderr;
|
|
||||||
#endif
|
|
||||||
esp_timer_init();
|
esp_timer_init();
|
||||||
esp_set_time_from_rtc();
|
esp_set_time_from_rtc();
|
||||||
#if CONFIG_APPTRACE_ENABLE
|
#if CONFIG_APPTRACE_ENABLE
|
||||||
|
|
|
@ -73,8 +73,9 @@ static ssize_t vfs_fat_pwrite(void *ctx, int fd, const void *src, size_t size, o
|
||||||
static int vfs_fat_open(void* ctx, const char * path, int flags, int mode);
|
static int vfs_fat_open(void* ctx, const char * path, int flags, int mode);
|
||||||
static int vfs_fat_close(void* ctx, int fd);
|
static int vfs_fat_close(void* ctx, int fd);
|
||||||
static int vfs_fat_fstat(void* ctx, int fd, struct stat * st);
|
static int vfs_fat_fstat(void* ctx, int fd, struct stat * st);
|
||||||
static int vfs_fat_stat(void* ctx, const char * path, struct stat * st);
|
|
||||||
static int vfs_fat_fsync(void* ctx, int fd);
|
static int vfs_fat_fsync(void* ctx, int fd);
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
|
static int vfs_fat_stat(void* ctx, const char * path, struct stat * st);
|
||||||
static int vfs_fat_link(void* ctx, const char* n1, const char* n2);
|
static int vfs_fat_link(void* ctx, const char* n1, const char* n2);
|
||||||
static int vfs_fat_unlink(void* ctx, const char *path);
|
static int vfs_fat_unlink(void* ctx, const char *path);
|
||||||
static int vfs_fat_rename(void* ctx, const char *src, const char *dst);
|
static int vfs_fat_rename(void* ctx, const char *src, const char *dst);
|
||||||
|
@ -89,6 +90,7 @@ static int vfs_fat_rmdir(void* ctx, const char* name);
|
||||||
static int vfs_fat_access(void* ctx, const char *path, int amode);
|
static int vfs_fat_access(void* ctx, const char *path, int amode);
|
||||||
static int vfs_fat_truncate(void* ctx, const char *path, off_t length);
|
static int vfs_fat_truncate(void* ctx, const char *path, off_t length);
|
||||||
static int vfs_fat_utime(void* ctx, const char *path, const struct utimbuf *times);
|
static int vfs_fat_utime(void* ctx, const char *path, const struct utimbuf *times);
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
|
|
||||||
static vfs_fat_ctx_t* s_fat_ctxs[FF_VOLUMES] = { NULL, NULL };
|
static vfs_fat_ctx_t* s_fat_ctxs[FF_VOLUMES] = { NULL, NULL };
|
||||||
//backwards-compatibility with esp_vfs_fat_unregister()
|
//backwards-compatibility with esp_vfs_fat_unregister()
|
||||||
|
@ -136,8 +138,9 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, siz
|
||||||
.open_p = &vfs_fat_open,
|
.open_p = &vfs_fat_open,
|
||||||
.close_p = &vfs_fat_close,
|
.close_p = &vfs_fat_close,
|
||||||
.fstat_p = &vfs_fat_fstat,
|
.fstat_p = &vfs_fat_fstat,
|
||||||
.stat_p = &vfs_fat_stat,
|
|
||||||
.fsync_p = &vfs_fat_fsync,
|
.fsync_p = &vfs_fat_fsync,
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
|
.stat_p = &vfs_fat_stat,
|
||||||
.link_p = &vfs_fat_link,
|
.link_p = &vfs_fat_link,
|
||||||
.unlink_p = &vfs_fat_unlink,
|
.unlink_p = &vfs_fat_unlink,
|
||||||
.rename_p = &vfs_fat_rename,
|
.rename_p = &vfs_fat_rename,
|
||||||
|
@ -152,6 +155,7 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, siz
|
||||||
.access_p = &vfs_fat_access,
|
.access_p = &vfs_fat_access,
|
||||||
.truncate_p = &vfs_fat_truncate,
|
.truncate_p = &vfs_fat_truncate,
|
||||||
.utime_p = &vfs_fat_utime,
|
.utime_p = &vfs_fat_utime,
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
};
|
};
|
||||||
size_t ctx_size = sizeof(vfs_fat_ctx_t) + max_files * sizeof(FIL);
|
size_t ctx_size = sizeof(vfs_fat_ctx_t) + max_files * sizeof(FIL);
|
||||||
vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ff_memalloc(ctx_size);
|
vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ff_memalloc(ctx_size);
|
||||||
|
@ -511,6 +515,8 @@ static int vfs_fat_fstat(void* ctx, int fd, struct stat * st)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
|
|
||||||
static inline mode_t get_stat_mode(bool is_dir)
|
static inline mode_t get_stat_mode(bool is_dir)
|
||||||
{
|
{
|
||||||
return S_IRWXU | S_IRWXG | S_IRWXO |
|
return S_IRWXU | S_IRWXG | S_IRWXO |
|
||||||
|
@ -954,3 +960,5 @@ static int vfs_fat_utime(void *ctx, const char *path, const struct utimbuf *time
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
|
|
|
@ -85,7 +85,6 @@ set(srcs
|
||||||
"lwip/src/netif/ppp/upap.c"
|
"lwip/src/netif/ppp/upap.c"
|
||||||
"lwip/src/netif/ppp/utils.c"
|
"lwip/src/netif/ppp/utils.c"
|
||||||
"lwip/src/netif/ppp/vj.c"
|
"lwip/src/netif/ppp/vj.c"
|
||||||
"port/esp32/vfs_lwip.c"
|
|
||||||
"port/esp32/debug/lwip_debug.c"
|
"port/esp32/debug/lwip_debug.c"
|
||||||
"port/esp32/freertos/sys_arch.c"
|
"port/esp32/freertos/sys_arch.c"
|
||||||
"port/esp32/netif/dhcp_state.c"
|
"port/esp32/netif/dhcp_state.c"
|
||||||
|
@ -129,6 +128,12 @@ if(CONFIG_ETH_ENABLED)
|
||||||
list(APPEND srcs "port/esp32/netif/ethernetif.c")
|
list(APPEND srcs "port/esp32/netif/ethernetif.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_VFS_SUPPORT_IO)
|
||||||
|
list(APPEND srcs "port/esp32/vfs_lwip.c")
|
||||||
|
else()
|
||||||
|
list(APPEND srcs "port/esp32/no_vfs_syscalls.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS "${srcs}"
|
idf_component_register(SRCS "${srcs}"
|
||||||
INCLUDE_DIRS "${include_dirs}"
|
INCLUDE_DIRS "${include_dirs}"
|
||||||
LDFRAGMENTS linker.lf
|
LDFRAGMENTS linker.lf
|
||||||
|
|
|
@ -63,9 +63,12 @@ menu "LWIP"
|
||||||
to 16.
|
to 16.
|
||||||
|
|
||||||
config LWIP_USE_ONLY_LWIP_SELECT
|
config LWIP_USE_ONLY_LWIP_SELECT
|
||||||
bool "Support LWIP socket select() only"
|
bool "Support LWIP socket select() only (DEPRECATED)"
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
|
This option is deprecated. Use VFS_SUPPORT_SELECT instead, which is
|
||||||
|
the inverse of this option.
|
||||||
|
|
||||||
The virtual filesystem layer of select() redirects sockets to
|
The virtual filesystem layer of select() redirects sockets to
|
||||||
lwip_select() and non-socket file descriptors to their respective driver
|
lwip_select() and non-socket file descriptors to their respective driver
|
||||||
implementations. If this option is enabled then all calls of select()
|
implementations. If this option is enabled then all calls of select()
|
||||||
|
|
|
@ -29,6 +29,11 @@ COMPONENT_SRCDIRS := \
|
||||||
ifndef CONFIG_IDF_TARGET_ESP32
|
ifndef CONFIG_IDF_TARGET_ESP32
|
||||||
COMPONENT_OBJEXCLUDE := port/esp32/netif/ethernetif.o
|
COMPONENT_OBJEXCLUDE := port/esp32/netif/ethernetif.o
|
||||||
endif
|
endif
|
||||||
|
ifndef CONFIG_VFS_SUPPORT_IO
|
||||||
|
COMPONENT_OBJEXCLUDE += port/esp32/vfs_lwip.o
|
||||||
|
else
|
||||||
|
COMPONENT_OBJEXCLUDE += port/esp32/no_vfs_syscalls.o
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_LWIP_PPP_SUPPORT
|
ifdef CONFIG_LWIP_PPP_SUPPORT
|
||||||
COMPONENT_SRCDIRS += lwip/src/netif/ppp lwip/src/netif/ppp/polarssl
|
COMPONENT_SRCDIRS += lwip/src/netif/ppp lwip/src/netif/ppp/polarssl
|
||||||
|
|
83
components/lwip/port/esp32/no_vfs_syscalls.c
Normal file
83
components/lwip/port/esp32/no_vfs_syscalls.c
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed 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.
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <sys/lock.h>
|
||||||
|
#include <sys/fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "lwip/sockets.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_IO
|
||||||
|
#error This file should only be built when CONFIG_VFS_SUPPORT_IO=n
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Default implementations of read/write provided in newlib component,
|
||||||
|
* used as a fallback for console I/O.
|
||||||
|
*/
|
||||||
|
extern ssize_t _write_r_console(struct _reent *r, int fd, const void * data, size_t size);
|
||||||
|
extern ssize_t _read_r_console(struct _reent *r, int fd, const void * data, size_t size);
|
||||||
|
|
||||||
|
ssize_t _write_r(struct _reent *r, int fd, const void * data, size_t size)
|
||||||
|
{
|
||||||
|
if (fd < LWIP_SOCKET_OFFSET) {
|
||||||
|
return _write_r_console(r, fd, data, size);
|
||||||
|
}
|
||||||
|
return lwip_write(fd, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t _read_r(struct _reent *r, int fd, void * dst, size_t size)
|
||||||
|
{
|
||||||
|
if (fd < LWIP_SOCKET_OFFSET) {
|
||||||
|
return _read_r_console(r, fd, dst, size);
|
||||||
|
}
|
||||||
|
return lwip_read(fd, dst, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _close_r(struct _reent *r, int fd)
|
||||||
|
{
|
||||||
|
if (fd < LWIP_SOCKET_OFFSET) {
|
||||||
|
errno = ENOSYS;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return lwip_close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _fcntl_r(struct _reent *r, int fd, int cmd, int arg)
|
||||||
|
{
|
||||||
|
return lwip_fcntl(fd, cmd, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ioctl(int fd, int cmd, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, cmd);
|
||||||
|
int res = lwip_ioctl(fd, cmd, va_arg(args, void*));
|
||||||
|
va_end(args);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)
|
||||||
|
{
|
||||||
|
return lwip_select(nfds, readfds, writefds, errorfds, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_vfs_lwip_sockets_register(void)
|
||||||
|
{
|
||||||
|
/* Doesn't register anything, just a hook to force linking this file */
|
||||||
|
}
|
|
@ -18,15 +18,20 @@
|
||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include <sys/fcntl.h>
|
#include <sys/fcntl.h>
|
||||||
#include "esp_vfs.h"
|
|
||||||
#include "esp_vfs_dev.h"
|
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "lwip/sockets.h"
|
#include "esp_vfs.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
#include "lwip/sockets.h"
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
|
#ifndef CONFIG_VFS_SUPPORT_IO
|
||||||
|
#error This file should only be built when CONFIG_VFS_SUPPORT_IO=y
|
||||||
|
#endif
|
||||||
|
|
||||||
_Static_assert(MAX_FDS >= CONFIG_LWIP_MAX_SOCKETS, "MAX_FDS < CONFIG_LWIP_MAX_SOCKETS");
|
_Static_assert(MAX_FDS >= CONFIG_LWIP_MAX_SOCKETS, "MAX_FDS < CONFIG_LWIP_MAX_SOCKETS");
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
static void lwip_stop_socket_select(void *sem)
|
static void lwip_stop_socket_select(void *sem)
|
||||||
{
|
{
|
||||||
sys_sem_signal(sem); //socket_select will return
|
sys_sem_signal(sem); //socket_select will return
|
||||||
|
@ -46,6 +51,14 @@ static void *lwip_get_socket_select_semaphore(void)
|
||||||
*/
|
*/
|
||||||
return (void *) sys_thread_sem_get();
|
return (void *) sys_thread_sem_get();
|
||||||
}
|
}
|
||||||
|
#else // CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
|
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)
|
||||||
|
{
|
||||||
|
return lwip_select(nfds, readfds, writefds, errorfds, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
static int lwip_fcntl_r_wrapper(int fd, int cmd, int arg)
|
static int lwip_fcntl_r_wrapper(int fd, int cmd, int arg)
|
||||||
{
|
{
|
||||||
|
@ -68,10 +81,12 @@ void esp_vfs_lwip_sockets_register(void)
|
||||||
.read = &lwip_read,
|
.read = &lwip_read,
|
||||||
.fcntl = &lwip_fcntl_r_wrapper,
|
.fcntl = &lwip_fcntl_r_wrapper,
|
||||||
.ioctl = &lwip_ioctl_r_wrapper,
|
.ioctl = &lwip_ioctl_r_wrapper,
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||||
.socket_select = &lwip_select,
|
.socket_select = &lwip_select,
|
||||||
.get_socket_select_semaphore = &lwip_get_socket_select_semaphore,
|
.get_socket_select_semaphore = &lwip_get_socket_select_semaphore,
|
||||||
.stop_socket_select = &lwip_stop_socket_select,
|
.stop_socket_select = &lwip_stop_socket_select,
|
||||||
.stop_socket_select_isr = &lwip_stop_socket_select_isr,
|
.stop_socket_select_isr = &lwip_stop_socket_select_isr,
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||||
};
|
};
|
||||||
/* Non-LWIP file descriptors are from 0 to (LWIP_SOCKET_OFFSET-1). LWIP
|
/* Non-LWIP file descriptors are from 0 to (LWIP_SOCKET_OFFSET-1). LWIP
|
||||||
* file descriptors are registered from LWIP_SOCKET_OFFSET to
|
* file descriptors are registered from LWIP_SOCKET_OFFSET to
|
||||||
|
|
|
@ -3,17 +3,13 @@ set(srcs
|
||||||
"heap.c"
|
"heap.c"
|
||||||
"locks.c"
|
"locks.c"
|
||||||
"poll.c"
|
"poll.c"
|
||||||
"pread.c"
|
|
||||||
"pwrite.c"
|
|
||||||
"pthread.c"
|
"pthread.c"
|
||||||
"random.c"
|
"random.c"
|
||||||
"reent_init.c"
|
"reent_init.c"
|
||||||
"select.c"
|
|
||||||
"syscall_table.c"
|
"syscall_table.c"
|
||||||
"syscalls.c"
|
"syscalls.c"
|
||||||
"termios.c"
|
"termios.c"
|
||||||
"time.c"
|
"time.c")
|
||||||
"utime.c")
|
|
||||||
set(include_dirs platform_include)
|
set(include_dirs platform_include)
|
||||||
|
|
||||||
if(CONFIG_SPIRAM_CACHE_WORKAROUND)
|
if(CONFIG_SPIRAM_CACHE_WORKAROUND)
|
||||||
|
@ -24,7 +20,6 @@ list(APPEND ldfragments newlib.lf)
|
||||||
|
|
||||||
idf_component_register(SRCS "${srcs}"
|
idf_component_register(SRCS "${srcs}"
|
||||||
INCLUDE_DIRS "${include_dirs}"
|
INCLUDE_DIRS "${include_dirs}"
|
||||||
REQUIRES vfs
|
|
||||||
PRIV_REQUIRES soc esp_timer
|
PRIV_REQUIRES soc esp_timer
|
||||||
LDFRAGMENTS "${ldfragments}")
|
LDFRAGMENTS "${ldfragments}")
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -12,10 +12,84 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#include "esp_vfs.h"
|
#include <sys/select.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
int poll(struct pollfd *fds, nfds_t nfds, int timeout)
|
int poll(struct pollfd *fds, nfds_t nfds, int timeout)
|
||||||
{
|
{
|
||||||
return esp_vfs_poll(fds, nfds, timeout);
|
struct timeval tv = {
|
||||||
|
// timeout is in milliseconds
|
||||||
|
.tv_sec = timeout / 1000,
|
||||||
|
.tv_usec = (timeout % 1000) * 1000,
|
||||||
|
};
|
||||||
|
int max_fd = -1;
|
||||||
|
fd_set readfds;
|
||||||
|
fd_set writefds;
|
||||||
|
fd_set errorfds;
|
||||||
|
struct _reent* r = __getreent();
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (fds == NULL) {
|
||||||
|
__errno_r(r) = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_ZERO(&writefds);
|
||||||
|
FD_ZERO(&errorfds);
|
||||||
|
|
||||||
|
for (int i = 0; i < nfds; ++i) {
|
||||||
|
fds[i].revents = 0;
|
||||||
|
|
||||||
|
if (fds[i].fd < 0) {
|
||||||
|
// revents should remain 0 and events ignored (according to the documentation of poll()).
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fds[i].fd >= FD_SETSIZE) {
|
||||||
|
fds[i].revents |= POLLNVAL;
|
||||||
|
++ret;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fds[i].events & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
|
||||||
|
FD_SET(fds[i].fd, &readfds);
|
||||||
|
FD_SET(fds[i].fd, &errorfds);
|
||||||
|
max_fd = MAX(max_fd, fds[i].fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
|
||||||
|
FD_SET(fds[i].fd, &writefds);
|
||||||
|
FD_SET(fds[i].fd, &errorfds);
|
||||||
|
max_fd = MAX(max_fd, fds[i].fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const int select_ret = select(max_fd + 1, &readfds, &writefds, &errorfds, timeout < 0 ? NULL: &tv);
|
||||||
|
|
||||||
|
if (select_ret > 0) {
|
||||||
|
ret += select_ret;
|
||||||
|
|
||||||
|
for (int i = 0; i < nfds; ++i) {
|
||||||
|
if (FD_ISSET(fds[i].fd, &readfds)) {
|
||||||
|
fds[i].revents |= POLLIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FD_ISSET(fds[i].fd, &writefds)) {
|
||||||
|
fds[i].revents |= POLLOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FD_ISSET(fds[i].fd, &errorfds)) {
|
||||||
|
fds[i].revents |= POLLERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = select_ret;
|
||||||
|
// keeping the errno from select()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed 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.
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "esp_vfs.h"
|
|
||||||
|
|
||||||
ssize_t pread(int fd, void *dst, size_t size, off_t offset)
|
|
||||||
{
|
|
||||||
return esp_vfs_pread(fd, dst, size, offset);
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed 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.
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "esp_vfs.h"
|
|
||||||
|
|
||||||
ssize_t pwrite(int fd, const void *src, size_t size, off_t offset)
|
|
||||||
{
|
|
||||||
return esp_vfs_pwrite(fd, src, size, offset);
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed 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.
|
|
||||||
|
|
||||||
#include <sys/select.h>
|
|
||||||
#include "esp_vfs.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
|
|
||||||
#ifdef CONFIG_LWIP_USE_ONLY_LWIP_SELECT
|
|
||||||
#include "lwip/sockets.h"
|
|
||||||
|
|
||||||
#ifdef CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT
|
|
||||||
#define LOG_LOCAL_LEVEL ESP_LOG_NONE
|
|
||||||
#endif //CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT
|
|
||||||
#include "esp_log.h"
|
|
||||||
|
|
||||||
static const char *TAG = "newlib_select";
|
|
||||||
|
|
||||||
static void log_fd_set(const char *fds_name, const fd_set *fds)
|
|
||||||
{
|
|
||||||
if (fds_name && fds) {
|
|
||||||
ESP_LOGD(TAG, "FDs in %s =", fds_name);
|
|
||||||
for (int i = 0; i < MAX_FDS; ++i) {
|
|
||||||
if (FD_ISSET(i, fds)) {
|
|
||||||
ESP_LOGD(TAG, "%d", i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif //CONFIG_LWIP_USE_ONLY_LWIP_SELECT
|
|
||||||
|
|
||||||
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_LWIP_USE_ONLY_LWIP_SELECT
|
|
||||||
ESP_LOGD(TAG, "lwip_select starts with nfds = %d", nfds);
|
|
||||||
if (timeout) {
|
|
||||||
ESP_LOGD(TAG, "timeout is %lds + %ldus", (long)timeout->tv_sec, timeout->tv_usec);
|
|
||||||
}
|
|
||||||
log_fd_set("readfds", readfds);
|
|
||||||
log_fd_set("writefds", writefds);
|
|
||||||
log_fd_set("errorfds", errorfds);
|
|
||||||
|
|
||||||
int ret = lwip_select(nfds, readfds, writefds, errorfds, timeout);
|
|
||||||
|
|
||||||
ESP_LOGD(TAG, "lwip_select returns %d", ret);
|
|
||||||
log_fd_set("readfds", readfds);
|
|
||||||
log_fd_set("writefds", writefds);
|
|
||||||
log_fd_set("errorfds", errorfds);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
#else
|
|
||||||
return esp_vfs_select(nfds, readfds, writefds, errorfds, timeout);
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -59,23 +59,23 @@ static struct syscall_stub_table s_stub_table = {
|
||||||
._calloc_r = &_calloc_r,
|
._calloc_r = &_calloc_r,
|
||||||
._abort = &abort,
|
._abort = &abort,
|
||||||
._system_r = &_system_r,
|
._system_r = &_system_r,
|
||||||
._rename_r = &esp_vfs_rename,
|
._rename_r = &_rename_r,
|
||||||
._times_r = &_times_r,
|
._times_r = &_times_r,
|
||||||
._gettimeofday_r = &_gettimeofday_r,
|
._gettimeofday_r = &_gettimeofday_r,
|
||||||
._raise_r = &raise_r_stub,
|
._raise_r = &raise_r_stub,
|
||||||
._unlink_r = &esp_vfs_unlink,
|
._unlink_r = &_unlink_r,
|
||||||
._link_r = &esp_vfs_link,
|
._link_r = &_link_r,
|
||||||
._stat_r = &esp_vfs_stat,
|
._stat_r = &_stat_r,
|
||||||
._fstat_r = &esp_vfs_fstat,
|
._fstat_r = &_fstat_r,
|
||||||
._sbrk_r = &_sbrk_r,
|
._sbrk_r = &_sbrk_r,
|
||||||
._getpid_r = &_getpid_r,
|
._getpid_r = &_getpid_r,
|
||||||
._kill_r = &_kill_r,
|
._kill_r = &_kill_r,
|
||||||
._exit_r = NULL, // never called in ROM
|
._exit_r = NULL, // never called in ROM
|
||||||
._close_r = &esp_vfs_close,
|
._close_r = &_close_r,
|
||||||
._open_r = &esp_vfs_open,
|
._open_r = &_open_r,
|
||||||
._write_r = (int (*)(struct _reent *r, int, const void *, int)) &esp_vfs_write,
|
._write_r = (int (*)(struct _reent *r, int, const void *, int)) &_write_r,
|
||||||
._lseek_r = (int (*)(struct _reent *r, int, int, int)) &esp_vfs_lseek,
|
._lseek_r = (int (*)(struct _reent *r, int, int, int)) &_lseek_r,
|
||||||
._read_r = (int (*)(struct _reent *r, int, void *, int)) &esp_vfs_read,
|
._read_r = (int (*)(struct _reent *r, int, void *, int)) &_read_r,
|
||||||
._lock_init = &_lock_init,
|
._lock_init = &_lock_init,
|
||||||
._lock_init_recursive = &_lock_init_recursive,
|
._lock_init_recursive = &_lock_init_recursive,
|
||||||
._lock_close = &_lock_close,
|
._lock_close = &_lock_close,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -12,7 +12,6 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -21,51 +20,111 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <reent.h>
|
#include <reent.h>
|
||||||
#include <sys/fcntl.h>
|
#include <sys/fcntl.h>
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
#include "esp32/rom/uart.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#include "esp32s2/rom/uart.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
int system(const char* str)
|
static int syscall_not_implemented(void)
|
||||||
{
|
{
|
||||||
errno = ENOSYS;
|
errno = ENOSYS;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int syscall_not_implemented_aborts(void)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t _write_r_console(struct _reent *r, int fd, const void * data, size_t size)
|
||||||
|
{
|
||||||
|
const char* cdata = (const char*) data;
|
||||||
|
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
|
||||||
|
for (size_t i = 0; i < size; ++i) {
|
||||||
|
uart_tx_one_char(cdata[i]);
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t _read_r_console(struct _reent *r, int fd, void * data, size_t size)
|
||||||
|
{
|
||||||
|
char* cdata = (char*) data;
|
||||||
|
if (fd == STDIN_FILENO) {
|
||||||
|
size_t received;
|
||||||
|
for (received = 0; received < size; ++received) {
|
||||||
|
int status = uart_rx_one_char((uint8_t*) &cdata[received]);
|
||||||
|
if (status != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return received;
|
||||||
|
}
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* The following weak definitions of syscalls will be used unless
|
||||||
|
* another definition is provided. That definition may come from
|
||||||
|
* VFS, LWIP, or the application.
|
||||||
|
*/
|
||||||
|
ssize_t _read_r(struct _reent *r, int fd, void * dst, size_t size)
|
||||||
|
__attribute__((weak,alias("_read_r_console")));
|
||||||
|
ssize_t _write_r(struct _reent *r, int fd, const void * data, size_t size)
|
||||||
|
__attribute__((weak,alias("_write_r_console")));
|
||||||
|
|
||||||
|
|
||||||
|
/* The aliases below are to "syscall_not_implemented", which
|
||||||
|
* doesn't have the same signature as the original function.
|
||||||
|
* Disable type mismatch warnings for this reason.
|
||||||
|
*/
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wattribute-alias"
|
||||||
|
|
||||||
|
int _open_r(struct _reent *r, const char * path, int flags, int mode)
|
||||||
|
__attribute__((weak,alias("syscall_not_implemented")));
|
||||||
|
int _close_r(struct _reent *r, int fd)
|
||||||
|
__attribute__((weak,alias("syscall_not_implemented")));
|
||||||
|
off_t _lseek_r(struct _reent *r, int fd, off_t size, int mode)
|
||||||
|
__attribute__((weak,alias("syscall_not_implemented")));
|
||||||
|
int _fcntl_r(struct _reent *r, int fd, int cmd, int arg)
|
||||||
|
__attribute__((weak,alias("syscall_not_implemented")));
|
||||||
|
int _fstat_r(struct _reent *r, int fd, struct stat * st)
|
||||||
|
__attribute__((weak,alias("syscall_not_implemented")));
|
||||||
|
int _stat_r(struct _reent *r, const char * path, struct stat * st)
|
||||||
|
__attribute__((weak,alias("syscall_not_implemented")));
|
||||||
|
int _link_r(struct _reent *r, const char* n1, const char* n2)
|
||||||
|
__attribute__((weak,alias("syscall_not_implemented")));
|
||||||
|
int _unlink_r(struct _reent *r, const char *path)
|
||||||
|
__attribute__((weak,alias("syscall_not_implemented")));
|
||||||
|
int _rename_r(struct _reent *r, const char *src, const char *dst)
|
||||||
|
__attribute__((weak,alias("syscall_not_implemented")));
|
||||||
|
|
||||||
|
/* These functions are not expected to be overridden */
|
||||||
|
int system(const char* str)
|
||||||
|
__attribute__((alias("syscall_not_implemented")));
|
||||||
int _system_r(struct _reent *r, const char *str)
|
int _system_r(struct _reent *r, const char *str)
|
||||||
{
|
__attribute__((alias("syscall_not_implemented")));
|
||||||
__errno_r(r) = ENOSYS;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int raise(int sig)
|
int raise(int sig)
|
||||||
{
|
__attribute__((alias("syscall_not_implemented_aborts")));
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
int _raise_r(struct _reent *r, int sig)
|
int _raise_r(struct _reent *r, int sig)
|
||||||
{
|
__attribute__((alias("syscall_not_implemented_aborts")));
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
void* _sbrk_r(struct _reent *r, ptrdiff_t sz)
|
void* _sbrk_r(struct _reent *r, ptrdiff_t sz)
|
||||||
{
|
__attribute__((alias("syscall_not_implemented_aborts")));
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
int _getpid_r(struct _reent *r)
|
int _getpid_r(struct _reent *r)
|
||||||
{
|
__attribute__((alias("syscall_not_implemented")));
|
||||||
__errno_r(r) = ENOSYS;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _kill_r(struct _reent *r, int pid, int sig)
|
int _kill_r(struct _reent *r, int pid, int sig)
|
||||||
{
|
__attribute__((alias("syscall_not_implemented")));
|
||||||
__errno_r(r) = ENOSYS;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _exit(int __status)
|
void _exit(int __status)
|
||||||
{
|
__attribute__((alias("syscall_not_implemented_aborts")));
|
||||||
abort();
|
|
||||||
}
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
/* Replaces newlib fcntl, which has been compiled without HAVE_FCNTL */
|
/* Replaces newlib fcntl, which has been compiled without HAVE_FCNTL */
|
||||||
int fcntl(int fd, int cmd, ...)
|
int fcntl(int fd, int cmd, ...)
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed 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.
|
|
||||||
|
|
||||||
#include <utime.h>
|
|
||||||
#include "esp_vfs.h"
|
|
||||||
|
|
||||||
int utime(const char *path, const struct utimbuf *times)
|
|
||||||
{
|
|
||||||
return esp_vfs_utime(path, times);
|
|
||||||
}
|
|
|
@ -61,6 +61,7 @@ static ssize_t vfs_spiffs_read(void* ctx, int fd, void * dst, size_t size);
|
||||||
static int vfs_spiffs_close(void* ctx, int fd);
|
static int vfs_spiffs_close(void* ctx, int fd);
|
||||||
static off_t vfs_spiffs_lseek(void* ctx, int fd, off_t offset, int mode);
|
static off_t vfs_spiffs_lseek(void* ctx, int fd, off_t offset, int mode);
|
||||||
static int vfs_spiffs_fstat(void* ctx, int fd, struct stat * st);
|
static int vfs_spiffs_fstat(void* ctx, int fd, struct stat * st);
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
static int vfs_spiffs_stat(void* ctx, const char * path, struct stat * st);
|
static int vfs_spiffs_stat(void* ctx, const char * path, struct stat * st);
|
||||||
static int vfs_spiffs_unlink(void* ctx, const char *path);
|
static int vfs_spiffs_unlink(void* ctx, const char *path);
|
||||||
static int vfs_spiffs_link(void* ctx, const char* n1, const char* n2);
|
static int vfs_spiffs_link(void* ctx, const char* n1, const char* n2);
|
||||||
|
@ -74,11 +75,12 @@ static long vfs_spiffs_telldir(void* ctx, DIR* pdir);
|
||||||
static void vfs_spiffs_seekdir(void* ctx, DIR* pdir, long offset);
|
static void vfs_spiffs_seekdir(void* ctx, DIR* pdir, long offset);
|
||||||
static int vfs_spiffs_mkdir(void* ctx, const char* name, mode_t mode);
|
static int vfs_spiffs_mkdir(void* ctx, const char* name, mode_t mode);
|
||||||
static int vfs_spiffs_rmdir(void* ctx, const char* name);
|
static int vfs_spiffs_rmdir(void* ctx, const char* name);
|
||||||
static void vfs_spiffs_update_mtime(spiffs *fs, spiffs_file f);
|
|
||||||
static time_t vfs_spiffs_get_mtime(const spiffs_stat* s);
|
|
||||||
#ifdef CONFIG_SPIFFS_USE_MTIME
|
#ifdef CONFIG_SPIFFS_USE_MTIME
|
||||||
static int vfs_spiffs_utime(void *ctx, const char *path, const struct utimbuf *times);
|
static int vfs_spiffs_utime(void *ctx, const char *path, const struct utimbuf *times);
|
||||||
#endif
|
#endif // CONFIG_SPIFFS_USE_MTIME
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
|
static void vfs_spiffs_update_mtime(spiffs *fs, spiffs_file f);
|
||||||
|
static time_t vfs_spiffs_get_mtime(const spiffs_stat* s);
|
||||||
|
|
||||||
static esp_spiffs_t * _efs[CONFIG_SPIFFS_MAX_PARTITIONS];
|
static esp_spiffs_t * _efs[CONFIG_SPIFFS_MAX_PARTITIONS];
|
||||||
|
|
||||||
|
@ -344,6 +346,7 @@ esp_err_t esp_vfs_spiffs_register(const esp_vfs_spiffs_conf_t * conf)
|
||||||
.open_p = &vfs_spiffs_open,
|
.open_p = &vfs_spiffs_open,
|
||||||
.close_p = &vfs_spiffs_close,
|
.close_p = &vfs_spiffs_close,
|
||||||
.fstat_p = &vfs_spiffs_fstat,
|
.fstat_p = &vfs_spiffs_fstat,
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
.stat_p = &vfs_spiffs_stat,
|
.stat_p = &vfs_spiffs_stat,
|
||||||
.link_p = &vfs_spiffs_link,
|
.link_p = &vfs_spiffs_link,
|
||||||
.unlink_p = &vfs_spiffs_unlink,
|
.unlink_p = &vfs_spiffs_unlink,
|
||||||
|
@ -361,6 +364,7 @@ esp_err_t esp_vfs_spiffs_register(const esp_vfs_spiffs_conf_t * conf)
|
||||||
#else
|
#else
|
||||||
.utime_p = NULL,
|
.utime_p = NULL,
|
||||||
#endif // CONFIG_SPIFFS_USE_MTIME
|
#endif // CONFIG_SPIFFS_USE_MTIME
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
};
|
};
|
||||||
|
|
||||||
esp_err_t err = esp_spiffs_init(conf);
|
esp_err_t err = esp_spiffs_init(conf);
|
||||||
|
@ -540,6 +544,8 @@ static int vfs_spiffs_fstat(void* ctx, int fd, struct stat * st)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
|
|
||||||
static int vfs_spiffs_stat(void* ctx, const char * path, struct stat * st)
|
static int vfs_spiffs_stat(void* ctx, const char * path, struct stat * st)
|
||||||
{
|
{
|
||||||
assert(path);
|
assert(path);
|
||||||
|
@ -730,36 +736,6 @@ static int vfs_spiffs_link(void* ctx, const char* n1, const char* n2)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vfs_spiffs_update_mtime(spiffs *fs, spiffs_file fd)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_SPIFFS_USE_MTIME
|
|
||||||
spiffs_time_t t = (spiffs_time_t)time(NULL);
|
|
||||||
spiffs_stat s;
|
|
||||||
int ret = SPIFFS_OK;
|
|
||||||
if (CONFIG_SPIFFS_META_LENGTH > sizeof(t)) {
|
|
||||||
ret = SPIFFS_fstat(fs, fd, &s);
|
|
||||||
}
|
|
||||||
if (ret == SPIFFS_OK) {
|
|
||||||
memcpy(s.meta, &t, sizeof(t));
|
|
||||||
ret = SPIFFS_fupdate_meta(fs, fd, s.meta);
|
|
||||||
}
|
|
||||||
if (ret != SPIFFS_OK) {
|
|
||||||
ESP_LOGW(TAG, "Failed to update mtime (%d)", ret);
|
|
||||||
}
|
|
||||||
#endif //CONFIG_SPIFFS_USE_MTIME
|
|
||||||
}
|
|
||||||
|
|
||||||
static time_t vfs_spiffs_get_mtime(const spiffs_stat* s)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_SPIFFS_USE_MTIME
|
|
||||||
spiffs_time_t t = 0;
|
|
||||||
memcpy(&t, s->meta, sizeof(t));
|
|
||||||
#else
|
|
||||||
time_t t = 0;
|
|
||||||
#endif
|
|
||||||
return (time_t)t;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_SPIFFS_USE_MTIME
|
#ifdef CONFIG_SPIFFS_USE_MTIME
|
||||||
static int vfs_spiffs_update_mtime_value(spiffs *fs, const char *path, spiffs_time_t t)
|
static int vfs_spiffs_update_mtime_value(spiffs *fs, const char *path, spiffs_time_t t)
|
||||||
{
|
{
|
||||||
|
@ -805,3 +781,35 @@ static int vfs_spiffs_utime(void *ctx, const char *path, const struct utimbuf *t
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif //CONFIG_SPIFFS_USE_MTIME
|
#endif //CONFIG_SPIFFS_USE_MTIME
|
||||||
|
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
|
|
||||||
|
static void vfs_spiffs_update_mtime(spiffs *fs, spiffs_file fd)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SPIFFS_USE_MTIME
|
||||||
|
spiffs_time_t t = (spiffs_time_t)time(NULL);
|
||||||
|
spiffs_stat s;
|
||||||
|
int ret = SPIFFS_OK;
|
||||||
|
if (CONFIG_SPIFFS_META_LENGTH > sizeof(t)) {
|
||||||
|
ret = SPIFFS_fstat(fs, fd, &s);
|
||||||
|
}
|
||||||
|
if (ret == SPIFFS_OK) {
|
||||||
|
memcpy(s.meta, &t, sizeof(t));
|
||||||
|
ret = SPIFFS_fupdate_meta(fs, fd, s.meta);
|
||||||
|
}
|
||||||
|
if (ret != SPIFFS_OK) {
|
||||||
|
ESP_LOGW(TAG, "Failed to update mtime (%d)", ret);
|
||||||
|
}
|
||||||
|
#endif //CONFIG_SPIFFS_USE_MTIME
|
||||||
|
}
|
||||||
|
|
||||||
|
static time_t vfs_spiffs_get_mtime(const spiffs_stat* s)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SPIFFS_USE_MTIME
|
||||||
|
spiffs_time_t t = 0;
|
||||||
|
memcpy(&t, s->meta, sizeof(t));
|
||||||
|
#else
|
||||||
|
time_t t = 0;
|
||||||
|
#endif
|
||||||
|
return (time_t)t;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,56 @@
|
||||||
menu "Virtual file system"
|
menu "Virtual file system"
|
||||||
|
|
||||||
|
config VFS_SUPPORT_IO
|
||||||
|
bool "Provide basic I/O functions"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
If enabled, the following functions are provided by the VFS component.
|
||||||
|
|
||||||
|
open, close, read, write, pread, pwrite, lseek, fstat, fsync, ioctl, fcntl
|
||||||
|
|
||||||
|
Filesystem drivers can then be registered to handle these functions
|
||||||
|
for specific paths.
|
||||||
|
|
||||||
|
Disabling this option can save memory when the support for these functions
|
||||||
|
is not required.
|
||||||
|
|
||||||
|
config VFS_SUPPORT_DIR
|
||||||
|
bool "Provide directory related functions"
|
||||||
|
default y
|
||||||
|
# If some filesystem is used, adding I/O support is probably needed and
|
||||||
|
# is not a big overhead, compared to code size of the filesystem,
|
||||||
|
# so make this depend on IO.
|
||||||
|
depends on VFS_SUPPORT_IO
|
||||||
|
help
|
||||||
|
If enabled, the following functions are provided by the VFS component.
|
||||||
|
|
||||||
|
stat, link, unlink, rename, utime, access, truncate, rmdir, mkdir,
|
||||||
|
opendir, closedir, readdir, readdir_r, seekdir, telldir, rewinddir
|
||||||
|
|
||||||
|
Filesystem drivers can then be registered to handle these functions
|
||||||
|
for specific paths.
|
||||||
|
|
||||||
|
Disabling this option can save memory when the support for these functions
|
||||||
|
is not required.
|
||||||
|
|
||||||
|
config VFS_SUPPORT_SELECT
|
||||||
|
bool "Provide select function"
|
||||||
|
default y
|
||||||
|
# Dependency on !LWIP_USE_ONLY_LWIP_SELECT is for compatibility
|
||||||
|
depends on VFS_SUPPORT_IO && !LWIP_USE_ONLY_LWIP_SELECT
|
||||||
|
help
|
||||||
|
If enabled, select function is provided by the VFS component, and can be used
|
||||||
|
on peripheral file descriptors (such as UART) and sockets at the same time.
|
||||||
|
|
||||||
|
If disabled, the default select implementation will be provided by LWIP for
|
||||||
|
sockets only.
|
||||||
|
|
||||||
|
Disabling this option can reduce code size if support for "select" on UART file
|
||||||
|
descriptors is not required.
|
||||||
|
|
||||||
config VFS_SUPPRESS_SELECT_DEBUG_OUTPUT
|
config VFS_SUPPRESS_SELECT_DEBUG_OUTPUT
|
||||||
bool "Suppress select() related debug outputs"
|
bool "Suppress select() related debug outputs"
|
||||||
|
depends on VFS_SUPPORT_SELECT
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
Select() related functions might produce an unconveniently lot of
|
Select() related functions might produce an unconveniently lot of
|
||||||
|
@ -10,12 +59,16 @@ menu "Virtual file system"
|
||||||
option.
|
option.
|
||||||
|
|
||||||
config VFS_SUPPORT_TERMIOS
|
config VFS_SUPPORT_TERMIOS
|
||||||
bool "Add support for termios.h"
|
bool "Provide termios.h functions"
|
||||||
default y
|
default y
|
||||||
|
# Very likely, only makes sense for UART VFS driver, which itself depends on VFS_SUPPORT_IO
|
||||||
|
depends on VFS_SUPPORT_IO
|
||||||
help
|
help
|
||||||
Disabling this option can save memory when the support for termios.h is not required.
|
Disabling this option can save memory when the support for termios.h is not required.
|
||||||
|
|
||||||
menu "Host File System I/O (Semihosting)"
|
menu "Host File System I/O (Semihosting)"
|
||||||
|
depends on VFS_SUPPORT_IO
|
||||||
|
|
||||||
config SEMIHOSTFS_MAX_MOUNT_POINTS
|
config SEMIHOSTFS_MAX_MOUNT_POINTS
|
||||||
int "Maximum number of the host filesystem mount points"
|
int "Maximum number of the host filesystem mount points"
|
||||||
default 1
|
default 1
|
||||||
|
|
|
@ -132,6 +132,7 @@ typedef struct
|
||||||
int (*fstat_p)(void* ctx, int fd, struct stat * st); /*!< fstat with context pointer */
|
int (*fstat_p)(void* ctx, int fd, struct stat * st); /*!< fstat with context pointer */
|
||||||
int (*fstat)(int fd, struct stat * st); /*!< fstat without context pointer */
|
int (*fstat)(int fd, struct stat * st); /*!< fstat without context pointer */
|
||||||
};
|
};
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
union {
|
union {
|
||||||
int (*stat_p)(void* ctx, const char * path, struct stat * st); /*!< stat with context pointer */
|
int (*stat_p)(void* ctx, const char * path, struct stat * st); /*!< stat with context pointer */
|
||||||
int (*stat)(const char * path, struct stat * st); /*!< stat without context pointer */
|
int (*stat)(const char * path, struct stat * st); /*!< stat without context pointer */
|
||||||
|
@ -180,6 +181,7 @@ typedef struct
|
||||||
int (*rmdir_p)(void* ctx, const char* name); /*!< rmdir with context pointer */
|
int (*rmdir_p)(void* ctx, const char* name); /*!< rmdir with context pointer */
|
||||||
int (*rmdir)(const char* name); /*!< rmdir without context pointer */
|
int (*rmdir)(const char* name); /*!< rmdir without context pointer */
|
||||||
};
|
};
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
union {
|
union {
|
||||||
int (*fcntl_p)(void* ctx, int fd, int cmd, int arg); /*!< fcntl with context pointer */
|
int (*fcntl_p)(void* ctx, int fd, int cmd, int arg); /*!< fcntl with context pointer */
|
||||||
int (*fcntl)(int fd, int cmd, int arg); /*!< fcntl without context pointer */
|
int (*fcntl)(int fd, int cmd, int arg); /*!< fcntl without context pointer */
|
||||||
|
@ -192,6 +194,7 @@ typedef struct
|
||||||
int (*fsync_p)(void* ctx, int fd); /*!< fsync with context pointer */
|
int (*fsync_p)(void* ctx, int fd); /*!< fsync with context pointer */
|
||||||
int (*fsync)(int fd); /*!< fsync without context pointer */
|
int (*fsync)(int fd); /*!< fsync without context pointer */
|
||||||
};
|
};
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
union {
|
union {
|
||||||
int (*access_p)(void* ctx, const char *path, int amode); /*!< access with context pointer */
|
int (*access_p)(void* ctx, const char *path, int amode); /*!< access with context pointer */
|
||||||
int (*access)(const char *path, int amode); /*!< access without context pointer */
|
int (*access)(const char *path, int amode); /*!< access without context pointer */
|
||||||
|
@ -204,6 +207,7 @@ typedef struct
|
||||||
int (*utime_p)(void* ctx, const char *path, const struct utimbuf *times); /*!< utime with context pointer */
|
int (*utime_p)(void* ctx, const char *path, const struct utimbuf *times); /*!< utime with context pointer */
|
||||||
int (*utime)(const char *path, const struct utimbuf *times); /*!< utime without context pointer */
|
int (*utime)(const char *path, const struct utimbuf *times); /*!< utime without context pointer */
|
||||||
};
|
};
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
||||||
union {
|
union {
|
||||||
int (*tcsetattr_p)(void *ctx, int fd, int optional_actions, const struct termios *p); /*!< tcsetattr with context pointer */
|
int (*tcsetattr_p)(void *ctx, int fd, int optional_actions, const struct termios *p); /*!< tcsetattr with context pointer */
|
||||||
|
@ -234,7 +238,7 @@ typedef struct
|
||||||
int (*tcsendbreak)(int fd, int duration); /*!< tcsendbreak without context pointer */
|
int (*tcsendbreak)(int fd, int duration); /*!< tcsendbreak without context pointer */
|
||||||
};
|
};
|
||||||
#endif // CONFIG_VFS_SUPPORT_TERMIOS
|
#endif // CONFIG_VFS_SUPPORT_TERMIOS
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||||
/** start_select is called for setting up synchronous I/O multiplexing of the desired file descriptors in the given VFS */
|
/** start_select is called for setting up synchronous I/O multiplexing of the desired file descriptors in the given VFS */
|
||||||
esp_err_t (*start_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, esp_vfs_select_sem_t sem, void **end_select_args);
|
esp_err_t (*start_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, esp_vfs_select_sem_t sem, void **end_select_args);
|
||||||
/** socket select function for socket FDs with the functionality of POSIX select(); this should be set only for the socket VFS */
|
/** socket select function for socket FDs with the functionality of POSIX select(); this should be set only for the socket VFS */
|
||||||
|
@ -247,6 +251,7 @@ typedef struct
|
||||||
void* (*get_socket_select_semaphore)(void);
|
void* (*get_socket_select_semaphore)(void);
|
||||||
/** get_socket_select_semaphore returns semaphore allocated in the socket driver; set only for the socket driver */
|
/** get_socket_select_semaphore returns semaphore allocated in the socket driver; set only for the socket driver */
|
||||||
esp_err_t (*end_select)(void *end_select_args);
|
esp_err_t (*end_select)(void *end_select_args);
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||||
} esp_vfs_t;
|
} esp_vfs_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -406,23 +411,6 @@ void esp_vfs_select_triggered(esp_vfs_select_sem_t sem);
|
||||||
*/
|
*/
|
||||||
void esp_vfs_select_triggered_isr(esp_vfs_select_sem_t sem, BaseType_t *woken);
|
void esp_vfs_select_triggered_isr(esp_vfs_select_sem_t sem, BaseType_t *woken);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Implements the VFS layer for synchronous I/O multiplexing by poll()
|
|
||||||
*
|
|
||||||
* The implementation is based on esp_vfs_select. The parameters and return values are compatible with POSIX poll().
|
|
||||||
*
|
|
||||||
* @param fds Pointer to the array containing file descriptors and events poll() should consider.
|
|
||||||
* @param nfds Number of items in the array fds.
|
|
||||||
* @param timeout Poll() should wait at least timeout milliseconds. If the value is 0 then it should return
|
|
||||||
* immediately. If the value is -1 then it should wait (block) until the event occurs.
|
|
||||||
*
|
|
||||||
* @return A positive return value indicates the number of file descriptors that have been selected. The 0
|
|
||||||
* return value indicates a timed-out poll. -1 is return on failure and errno is set accordingly.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int esp_vfs_poll(struct pollfd *fds, nfds_t nfds, int timeout);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @brief Implements the VFS layer of POSIX pread()
|
* @brief Implements the VFS layer of POSIX pread()
|
||||||
|
|
|
@ -507,6 +507,52 @@ int esp_vfs_fstat(struct _reent *r, int fd, struct stat * st)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int esp_vfs_fcntl_r(struct _reent *r, int fd, int cmd, int arg)
|
||||||
|
{
|
||||||
|
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
||||||
|
const int local_fd = get_local_fd(vfs, fd);
|
||||||
|
if (vfs == NULL || local_fd < 0) {
|
||||||
|
__errno_r(r) = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int ret;
|
||||||
|
CHECK_AND_CALL(ret, r, vfs, fcntl, local_fd, cmd, arg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int esp_vfs_ioctl(int fd, int cmd, ...)
|
||||||
|
{
|
||||||
|
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
||||||
|
const int local_fd = get_local_fd(vfs, fd);
|
||||||
|
struct _reent* r = __getreent();
|
||||||
|
if (vfs == NULL || local_fd < 0) {
|
||||||
|
__errno_r(r) = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int ret;
|
||||||
|
va_list args;
|
||||||
|
va_start(args, cmd);
|
||||||
|
CHECK_AND_CALL(ret, r, vfs, ioctl, local_fd, cmd, args);
|
||||||
|
va_end(args);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int esp_vfs_fsync(int fd)
|
||||||
|
{
|
||||||
|
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
||||||
|
const int local_fd = get_local_fd(vfs, fd);
|
||||||
|
struct _reent* r = __getreent();
|
||||||
|
if (vfs == NULL || local_fd < 0) {
|
||||||
|
__errno_r(r) = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int ret;
|
||||||
|
CHECK_AND_CALL(ret, r, vfs, fsync, local_fd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
|
|
||||||
int esp_vfs_stat(struct _reent *r, const char * path, struct stat * st)
|
int esp_vfs_stat(struct _reent *r, const char * path, struct stat * st)
|
||||||
{
|
{
|
||||||
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
||||||
|
@ -520,6 +566,20 @@ int esp_vfs_stat(struct _reent *r, const char * path, struct stat * st)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int esp_vfs_utime(const char *path, const struct utimbuf *times)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
||||||
|
struct _reent* r = __getreent();
|
||||||
|
if (vfs == NULL) {
|
||||||
|
__errno_r(r) = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
const char* path_within_vfs = translate_path(vfs, path);
|
||||||
|
CHECK_AND_CALL(ret, r, vfs, utime, path_within_vfs, times);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int esp_vfs_link(struct _reent *r, const char* n1, const char* n2)
|
int esp_vfs_link(struct _reent *r, const char* n1, const char* n2)
|
||||||
{
|
{
|
||||||
const vfs_entry_t* vfs = get_vfs_for_path(n1);
|
const vfs_entry_t* vfs = get_vfs_for_path(n1);
|
||||||
|
@ -571,35 +631,7 @@ int esp_vfs_rename(struct _reent *r, const char *src, const char *dst)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create aliases for newlib syscalls
|
DIR* esp_vfs_opendir(const char* name)
|
||||||
|
|
||||||
These functions are also available in ROM as stubs which use the syscall table, but linking them
|
|
||||||
directly here saves an additional function call when a software function is linked to one, and
|
|
||||||
makes linking with -stdlib easier.
|
|
||||||
*/
|
|
||||||
int _open_r(struct _reent *r, const char * path, int flags, int mode)
|
|
||||||
__attribute__((alias("esp_vfs_open")));
|
|
||||||
ssize_t _write_r(struct _reent *r, int fd, const void * data, size_t size)
|
|
||||||
__attribute__((alias("esp_vfs_write")));
|
|
||||||
off_t _lseek_r(struct _reent *r, int fd, off_t size, int mode)
|
|
||||||
__attribute__((alias("esp_vfs_lseek")));
|
|
||||||
ssize_t _read_r(struct _reent *r, int fd, void * dst, size_t size)
|
|
||||||
__attribute__((alias("esp_vfs_read")));
|
|
||||||
int _close_r(struct _reent *r, int fd)
|
|
||||||
__attribute__((alias("esp_vfs_close")));
|
|
||||||
int _fstat_r(struct _reent *r, int fd, struct stat * st)
|
|
||||||
__attribute__((alias("esp_vfs_fstat")));
|
|
||||||
int _stat_r(struct _reent *r, const char * path, struct stat * st)
|
|
||||||
__attribute__((alias("esp_vfs_stat")));
|
|
||||||
int _link_r(struct _reent *r, const char* n1, const char* n2)
|
|
||||||
__attribute__((alias("esp_vfs_link")));
|
|
||||||
int _unlink_r(struct _reent *r, const char *path)
|
|
||||||
__attribute__((alias("esp_vfs_unlink")));
|
|
||||||
int _rename_r(struct _reent *r, const char *src, const char *dst)
|
|
||||||
__attribute__((alias("esp_vfs_rename")));
|
|
||||||
|
|
||||||
|
|
||||||
DIR* opendir(const char* name)
|
|
||||||
{
|
{
|
||||||
const vfs_entry_t* vfs = get_vfs_for_path(name);
|
const vfs_entry_t* vfs = get_vfs_for_path(name);
|
||||||
struct _reent* r = __getreent();
|
struct _reent* r = __getreent();
|
||||||
|
@ -616,7 +648,7 @@ DIR* opendir(const char* name)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dirent* readdir(DIR* pdir)
|
struct dirent* esp_vfs_readdir(DIR* pdir)
|
||||||
{
|
{
|
||||||
const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||||
struct _reent* r = __getreent();
|
struct _reent* r = __getreent();
|
||||||
|
@ -629,7 +661,7 @@ struct dirent* readdir(DIR* pdir)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int readdir_r(DIR* pdir, struct dirent* entry, struct dirent** out_dirent)
|
int esp_vfs_readdir_r(DIR* pdir, struct dirent* entry, struct dirent** out_dirent)
|
||||||
{
|
{
|
||||||
const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||||
struct _reent* r = __getreent();
|
struct _reent* r = __getreent();
|
||||||
|
@ -642,7 +674,7 @@ int readdir_r(DIR* pdir, struct dirent* entry, struct dirent** out_dirent)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
long telldir(DIR* pdir)
|
long esp_vfs_telldir(DIR* pdir)
|
||||||
{
|
{
|
||||||
const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||||
struct _reent* r = __getreent();
|
struct _reent* r = __getreent();
|
||||||
|
@ -655,7 +687,7 @@ long telldir(DIR* pdir)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void seekdir(DIR* pdir, long loc)
|
void esp_vfs_seekdir(DIR* pdir, long loc)
|
||||||
{
|
{
|
||||||
const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||||
struct _reent* r = __getreent();
|
struct _reent* r = __getreent();
|
||||||
|
@ -666,12 +698,12 @@ void seekdir(DIR* pdir, long loc)
|
||||||
CHECK_AND_CALLV(r, vfs, seekdir, pdir, loc);
|
CHECK_AND_CALLV(r, vfs, seekdir, pdir, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rewinddir(DIR* pdir)
|
void esp_vfs_rewinddir(DIR* pdir)
|
||||||
{
|
{
|
||||||
seekdir(pdir, 0);
|
seekdir(pdir, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int closedir(DIR* pdir)
|
int esp_vfs_closedir(DIR* pdir)
|
||||||
{
|
{
|
||||||
const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx);
|
||||||
struct _reent* r = __getreent();
|
struct _reent* r = __getreent();
|
||||||
|
@ -684,7 +716,7 @@ int closedir(DIR* pdir)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mkdir(const char* name, mode_t mode)
|
int esp_vfs_mkdir(const char* name, mode_t mode)
|
||||||
{
|
{
|
||||||
const vfs_entry_t* vfs = get_vfs_for_path(name);
|
const vfs_entry_t* vfs = get_vfs_for_path(name);
|
||||||
struct _reent* r = __getreent();
|
struct _reent* r = __getreent();
|
||||||
|
@ -698,7 +730,7 @@ int mkdir(const char* name, mode_t mode)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rmdir(const char* name)
|
int esp_vfs_rmdir(const char* name)
|
||||||
{
|
{
|
||||||
const vfs_entry_t* vfs = get_vfs_for_path(name);
|
const vfs_entry_t* vfs = get_vfs_for_path(name);
|
||||||
struct _reent* r = __getreent();
|
struct _reent* r = __getreent();
|
||||||
|
@ -712,51 +744,7 @@ int rmdir(const char* name)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fcntl_r(struct _reent *r, int fd, int cmd, int arg)
|
int esp_vfs_access(const char *path, int amode)
|
||||||
{
|
|
||||||
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
|
||||||
const int local_fd = get_local_fd(vfs, fd);
|
|
||||||
if (vfs == NULL || local_fd < 0) {
|
|
||||||
__errno_r(r) = EBADF;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int ret;
|
|
||||||
CHECK_AND_CALL(ret, r, vfs, fcntl, local_fd, cmd, arg);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ioctl(int fd, int cmd, ...)
|
|
||||||
{
|
|
||||||
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
|
||||||
const int local_fd = get_local_fd(vfs, fd);
|
|
||||||
struct _reent* r = __getreent();
|
|
||||||
if (vfs == NULL || local_fd < 0) {
|
|
||||||
__errno_r(r) = EBADF;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int ret;
|
|
||||||
va_list args;
|
|
||||||
va_start(args, cmd);
|
|
||||||
CHECK_AND_CALL(ret, r, vfs, ioctl, local_fd, cmd, args);
|
|
||||||
va_end(args);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fsync(int fd)
|
|
||||||
{
|
|
||||||
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
|
||||||
const int local_fd = get_local_fd(vfs, fd);
|
|
||||||
struct _reent* r = __getreent();
|
|
||||||
if (vfs == NULL || local_fd < 0) {
|
|
||||||
__errno_r(r) = EBADF;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int ret;
|
|
||||||
CHECK_AND_CALL(ret, r, vfs, fsync, local_fd);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int access(const char *path, int amode)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
||||||
|
@ -770,7 +758,7 @@ int access(const char *path, int amode)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int truncate(const char *path, off_t length)
|
int esp_vfs_truncate(const char *path, off_t length)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
||||||
|
@ -784,6 +772,10 @@ int truncate(const char *path, off_t length)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
static void call_end_selects(int end_index, const fds_triple_t *vfs_fds_triple, void **driver_args)
|
static void call_end_selects(int end_index, const fds_triple_t *vfs_fds_triple, void **driver_args)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < end_index; ++i) {
|
for (int i = 0; i < end_index; ++i) {
|
||||||
|
@ -1074,7 +1066,10 @@ void esp_vfs_select_triggered_isr(esp_vfs_select_sem_t sem, BaseType_t *woken)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
||||||
|
|
||||||
int tcgetattr(int fd, struct termios *p)
|
int tcgetattr(int fd, struct termios *p)
|
||||||
{
|
{
|
||||||
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
||||||
|
@ -1174,95 +1169,77 @@ int tcsendbreak(int fd, int duration)
|
||||||
}
|
}
|
||||||
#endif // CONFIG_VFS_SUPPORT_TERMIOS
|
#endif // CONFIG_VFS_SUPPORT_TERMIOS
|
||||||
|
|
||||||
int esp_vfs_utime(const char *path, const struct utimbuf *times)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
|
||||||
struct _reent* r = __getreent();
|
|
||||||
if (vfs == NULL) {
|
|
||||||
__errno_r(r) = ENOENT;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
const char* path_within_vfs = translate_path(vfs, path);
|
|
||||||
CHECK_AND_CALL(ret, r, vfs, utime, path_within_vfs, times);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int esp_vfs_poll(struct pollfd *fds, nfds_t nfds, int timeout)
|
/* Create aliases for newlib syscalls
|
||||||
{
|
|
||||||
struct timeval tv = {
|
|
||||||
// timeout is in milliseconds
|
|
||||||
.tv_sec = timeout / 1000,
|
|
||||||
.tv_usec = (timeout % 1000) * 1000,
|
|
||||||
};
|
|
||||||
int max_fd = -1;
|
|
||||||
fd_set readfds;
|
|
||||||
fd_set writefds;
|
|
||||||
fd_set errorfds;
|
|
||||||
struct _reent* r = __getreent();
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (fds == NULL) {
|
These functions are also available in ROM as stubs which use the syscall table, but linking them
|
||||||
__errno_r(r) = ENOENT;
|
directly here saves an additional function call when a software function is linked to one, and
|
||||||
return -1;
|
makes linking with -stdlib easier.
|
||||||
}
|
*/
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_IO
|
||||||
|
int _open_r(struct _reent *r, const char * path, int flags, int mode)
|
||||||
|
__attribute__((alias("esp_vfs_open")));
|
||||||
|
int _close_r(struct _reent *r, int fd)
|
||||||
|
__attribute__((alias("esp_vfs_close")));
|
||||||
|
ssize_t _read_r(struct _reent *r, int fd, void * dst, size_t size)
|
||||||
|
__attribute__((alias("esp_vfs_read")));
|
||||||
|
ssize_t _write_r(struct _reent *r, int fd, const void * data, size_t size)
|
||||||
|
__attribute__((alias("esp_vfs_write")));
|
||||||
|
ssize_t pread(int fd, void *dst, size_t size, off_t offset)
|
||||||
|
__attribute__((alias("esp_vfs_pread")));
|
||||||
|
ssize_t pwrite(int fd, const void *src, size_t size, off_t offset)
|
||||||
|
__attribute__((alias("esp_vfs_pwrite")));
|
||||||
|
off_t _lseek_r(struct _reent *r, int fd, off_t size, int mode)
|
||||||
|
__attribute__((alias("esp_vfs_lseek")));
|
||||||
|
int _fcntl_r(struct _reent *r, int fd, int cmd, int arg)
|
||||||
|
__attribute__((alias("esp_vfs_fcntl_r")));
|
||||||
|
int _fstat_r(struct _reent *r, int fd, struct stat * st)
|
||||||
|
__attribute__((alias("esp_vfs_fstat")));
|
||||||
|
int fsync(int fd)
|
||||||
|
__attribute__((alias("esp_vfs_fsync")));
|
||||||
|
int ioctl(int fd, int cmd, ...)
|
||||||
|
__attribute__((alias("esp_vfs_ioctl")));
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_IO
|
||||||
|
|
||||||
FD_ZERO(&readfds);
|
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||||
FD_ZERO(&writefds);
|
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)
|
||||||
FD_ZERO(&errorfds);
|
__attribute__((alias("esp_vfs_select")));
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
for (int i = 0; i < nfds; ++i) {
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
fds[i].revents = 0;
|
int _stat_r(struct _reent *r, const char * path, struct stat * st)
|
||||||
|
__attribute__((alias("esp_vfs_stat")));
|
||||||
if (fds[i].fd < 0) {
|
int _link_r(struct _reent *r, const char* n1, const char* n2)
|
||||||
// revents should remain 0 and events ignored (according to the documentation of poll()).
|
__attribute__((alias("esp_vfs_link")));
|
||||||
continue;
|
int _unlink_r(struct _reent *r, const char *path)
|
||||||
}
|
__attribute__((alias("esp_vfs_unlink")));
|
||||||
|
int _rename_r(struct _reent *r, const char *src, const char *dst)
|
||||||
if (fds[i].fd >= MAX_FDS) {
|
__attribute__((alias("esp_vfs_rename")));
|
||||||
fds[i].revents |= POLLNVAL;
|
int truncate(const char *path, off_t length)
|
||||||
++ret;
|
__attribute__((alias("esp_vfs_truncate")));
|
||||||
continue;
|
int access(const char *path, int amode)
|
||||||
}
|
__attribute__((alias("esp_vfs_access")));
|
||||||
|
int utime(const char *path, const struct utimbuf *times)
|
||||||
if (fds[i].events & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
|
__attribute__((alias("esp_vfs_utime")));
|
||||||
FD_SET(fds[i].fd, &readfds);
|
int rmdir(const char* name)
|
||||||
FD_SET(fds[i].fd, &errorfds);
|
__attribute__((alias("esp_vfs_rmdir")));
|
||||||
max_fd = MAX(max_fd, fds[i].fd);
|
int mkdir(const char* name, mode_t mode)
|
||||||
}
|
__attribute__((alias("esp_vfs_mkdir")));
|
||||||
|
DIR* opendir(const char* name)
|
||||||
if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
|
__attribute__((alias("esp_vfs_opendir")));
|
||||||
FD_SET(fds[i].fd, &writefds);
|
int closedir(DIR* pdir)
|
||||||
FD_SET(fds[i].fd, &errorfds);
|
__attribute__((alias("esp_vfs_closedir")));
|
||||||
max_fd = MAX(max_fd, fds[i].fd);
|
int readdir_r(DIR* pdir, struct dirent* entry, struct dirent** out_dirent)
|
||||||
}
|
__attribute__((alias("esp_vfs_readdir_r")));
|
||||||
}
|
struct dirent* readdir(DIR* pdir)
|
||||||
|
__attribute__((alias("esp_vfs_readdir")));
|
||||||
const int select_ret = esp_vfs_select(max_fd + 1, &readfds, &writefds, &errorfds, timeout < 0 ? NULL: &tv);
|
long telldir(DIR* pdir)
|
||||||
|
__attribute__((alias("esp_vfs_telldir")));
|
||||||
if (select_ret > 0) {
|
void seekdir(DIR* pdir, long loc)
|
||||||
ret += select_ret;
|
__attribute__((alias("esp_vfs_seekdir")));
|
||||||
|
void rewinddir(DIR* pdir)
|
||||||
for (int i = 0; i < nfds; ++i) {
|
__attribute__((alias("esp_vfs_rewinddir")));
|
||||||
if (FD_ISSET(fds[i].fd, &readfds)) {
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
fds[i].revents |= POLLIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FD_ISSET(fds[i].fd, &writefds)) {
|
|
||||||
fds[i].revents |= POLLOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FD_ISSET(fds[i].fd, &errorfds)) {
|
|
||||||
fds[i].revents |= POLLERR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret = select_ret;
|
|
||||||
// keeping the errno from select()
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vfs_include_syscalls_impl(void)
|
void vfs_include_syscalls_impl(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,6 +23,14 @@
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_vfs.h"
|
#include "esp_vfs.h"
|
||||||
|
|
||||||
|
#ifndef CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS
|
||||||
|
#define CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN
|
||||||
|
#define CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN 128
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LOG_LOCAL_LEVEL ESP_LOG_NONE
|
#define LOG_LOCAL_LEVEL ESP_LOG_NONE
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
const static char *TAG = "esp_semihost";
|
const static char *TAG = "esp_semihost";
|
||||||
|
|
|
@ -116,6 +116,8 @@ static vfs_uart_context_t* s_ctx[UART_NUM] = {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
esp_vfs_select_sem_t select_sem;
|
esp_vfs_select_sem_t select_sem;
|
||||||
fd_set *readfds;
|
fd_set *readfds;
|
||||||
|
@ -132,6 +134,8 @@ static portMUX_TYPE s_registered_select_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
|
||||||
static esp_err_t uart_end_select(void *end_select_args);
|
static esp_err_t uart_end_select(void *end_select_args);
|
||||||
|
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
static int uart_open(const char * path, int flags, int mode)
|
static int uart_open(const char * path, int flags, int mode)
|
||||||
{
|
{
|
||||||
// this is fairly primitive, we should check if file is opened read only,
|
// this is fairly primitive, we should check if file is opened read only,
|
||||||
|
@ -319,6 +323,8 @@ static int uart_fcntl(int fd, int cmd, int arg)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
|
|
||||||
static int uart_access(const char *path, int amode)
|
static int uart_access(const char *path, int amode)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
@ -340,6 +346,8 @@ static int uart_access(const char *path, int amode)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
|
|
||||||
static int uart_fsync(int fd)
|
static int uart_fsync(int fd)
|
||||||
{
|
{
|
||||||
assert(fd >= 0 && fd < 3);
|
assert(fd >= 0 && fd < 3);
|
||||||
|
@ -349,6 +357,8 @@ static int uart_fsync(int fd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
static esp_err_t register_select(uart_select_args_t *args)
|
static esp_err_t register_select(uart_select_args_t *args)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_ERR_INVALID_ARG;
|
esp_err_t ret = ESP_ERR_INVALID_ARG;
|
||||||
|
@ -509,6 +519,8 @@ static esp_err_t uart_end_select(void *end_select_args)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
||||||
static int uart_tcsetattr(int fd, int optional_actions, const struct termios *p)
|
static int uart_tcsetattr(int fd, int optional_actions, const struct termios *p)
|
||||||
{
|
{
|
||||||
|
@ -972,9 +984,13 @@ void esp_vfs_dev_uart_register(void)
|
||||||
.read = &uart_read,
|
.read = &uart_read,
|
||||||
.fcntl = &uart_fcntl,
|
.fcntl = &uart_fcntl,
|
||||||
.fsync = &uart_fsync,
|
.fsync = &uart_fsync,
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
.access = &uart_access,
|
.access = &uart_access,
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||||
.start_select = &uart_start_select,
|
.start_select = &uart_start_select,
|
||||||
.end_select = &uart_end_select,
|
.end_select = &uart_end_select,
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||||
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
||||||
.tcsetattr = &uart_tcsetattr,
|
.tcsetattr = &uart_tcsetattr,
|
||||||
.tcgetattr = &uart_tcgetattr,
|
.tcgetattr = &uart_tcgetattr,
|
||||||
|
|
|
@ -31,6 +31,8 @@ void app_main(void)
|
||||||
printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
|
printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
|
||||||
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
|
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
|
||||||
|
|
||||||
|
printf("Free heap: %d\n", esp_get_free_heap_size());
|
||||||
|
|
||||||
for (int i = 10; i >= 0; i--) {
|
for (int i = 10; i >= 0; i--) {
|
||||||
printf("Restarting in %d seconds...\n", i);
|
printf("Restarting in %d seconds...\n", i);
|
||||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
|
2
tools/test_apps/system/startup/sdkconfig.ci.no_vfs
Normal file
2
tools/test_apps/system/startup/sdkconfig.ci.no_vfs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# Disable VFS support
|
||||||
|
CONFIG_VFS_SUPPORT_IO=n
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Disable VFS support except for basic I/O
|
||||||
|
CONFIG_VFS_SUPPORT_SELECT=n
|
||||||
|
CONFIG_VFS_SUPPORT_DIR=n
|
||||||
|
CONFIG_VFS_SUPPORT_TERMIOS=n
|
Loading…
Reference in a new issue