mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
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
@ -354,18 +354,21 @@ void start_cpu0_default(void)
|
||||
esp_efuse_disable_basic_rom_console();
|
||||
#endif
|
||||
rtc_gpio_force_hold_dis_all();
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_IO
|
||||
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);
|
||||
#ifndef CONFIG_ESP_CONSOLE_UART_NONE
|
||||
const char* default_uart_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
_GLOBAL_REENT->_stdin = fopen(default_uart_dev, "r");
|
||||
_GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w");
|
||||
_GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w");
|
||||
#else
|
||||
_GLOBAL_REENT->_stdin = (FILE*) &__sf_fake_stdin;
|
||||
_GLOBAL_REENT->_stdout = (FILE*) &__sf_fake_stdout;
|
||||
_GLOBAL_REENT->_stderr = (FILE*) &__sf_fake_stderr;
|
||||
#endif
|
||||
#else // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||
_REENT_SMALL_CHECK_INIT(_GLOBAL_REENT);
|
||||
#endif // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||
|
||||
esp_timer_init();
|
||||
esp_set_time_from_rtc();
|
||||
#if CONFIG_APPTRACE_ENABLE
|
||||
|
@ -284,18 +284,21 @@ void start_cpu0_default(void)
|
||||
esp_efuse_disable_basic_rom_console();
|
||||
#endif
|
||||
rtc_gpio_force_hold_dis_all();
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_IO
|
||||
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);
|
||||
#ifndef CONFIG_ESP_CONSOLE_UART_NONE
|
||||
const char *default_uart_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
_GLOBAL_REENT->_stdin = fopen(default_uart_dev, "r");
|
||||
_GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w");
|
||||
_GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w");
|
||||
#else
|
||||
_GLOBAL_REENT->_stdin = (FILE *) &__sf_fake_stdin;
|
||||
_GLOBAL_REENT->_stdout = (FILE *) &__sf_fake_stdout;
|
||||
_GLOBAL_REENT->_stderr = (FILE *) &__sf_fake_stderr;
|
||||
#endif
|
||||
#else // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||
_REENT_SMALL_CHECK_INIT(_GLOBAL_REENT);
|
||||
#endif // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||
|
||||
esp_timer_init();
|
||||
esp_set_time_from_rtc();
|
||||
#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_close(void* ctx, int fd);
|
||||
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);
|
||||
#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_unlink(void* ctx, const char *path);
|
||||
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_truncate(void* ctx, const char *path, off_t length);
|
||||
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 };
|
||||
//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,
|
||||
.close_p = &vfs_fat_close,
|
||||
.fstat_p = &vfs_fat_fstat,
|
||||
.stat_p = &vfs_fat_stat,
|
||||
.fsync_p = &vfs_fat_fsync,
|
||||
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||
.stat_p = &vfs_fat_stat,
|
||||
.link_p = &vfs_fat_link,
|
||||
.unlink_p = &vfs_fat_unlink,
|
||||
.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,
|
||||
.truncate_p = &vfs_fat_truncate,
|
||||
.utime_p = &vfs_fat_utime,
|
||||
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||
};
|
||||
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);
|
||||
@ -511,6 +515,8 @@ static int vfs_fat_fstat(void* ctx, int fd, struct stat * st)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||
|
||||
static inline mode_t get_stat_mode(bool is_dir)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||
|
@ -85,7 +85,6 @@ set(srcs
|
||||
"lwip/src/netif/ppp/upap.c"
|
||||
"lwip/src/netif/ppp/utils.c"
|
||||
"lwip/src/netif/ppp/vj.c"
|
||||
"port/esp32/vfs_lwip.c"
|
||||
"port/esp32/debug/lwip_debug.c"
|
||||
"port/esp32/freertos/sys_arch.c"
|
||||
"port/esp32/netif/dhcp_state.c"
|
||||
@ -129,6 +128,12 @@ if(CONFIG_ETH_ENABLED)
|
||||
list(APPEND srcs "port/esp32/netif/ethernetif.c")
|
||||
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}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
LDFRAGMENTS linker.lf
|
||||
|
@ -63,9 +63,12 @@ menu "LWIP"
|
||||
to 16.
|
||||
|
||||
config LWIP_USE_ONLY_LWIP_SELECT
|
||||
bool "Support LWIP socket select() only"
|
||||
bool "Support LWIP socket select() only (DEPRECATED)"
|
||||
default n
|
||||
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
|
||||
lwip_select() and non-socket file descriptors to their respective driver
|
||||
implementations. If this option is enabled then all calls of select()
|
||||
|
@ -29,6 +29,11 @@ COMPONENT_SRCDIRS := \
|
||||
ifndef CONFIG_IDF_TARGET_ESP32
|
||||
COMPONENT_OBJEXCLUDE := port/esp32/netif/ethernetif.o
|
||||
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
|
||||
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/lock.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include "esp_vfs.h"
|
||||
#include "esp_vfs_dev.h"
|
||||
#include "esp_attr.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "esp_vfs.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "lwip/sockets.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");
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||
|
||||
static void lwip_stop_socket_select(void *sem)
|
||||
{
|
||||
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();
|
||||
}
|
||||
#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)
|
||||
{
|
||||
@ -68,10 +81,12 @@ void esp_vfs_lwip_sockets_register(void)
|
||||
.read = &lwip_read,
|
||||
.fcntl = &lwip_fcntl_r_wrapper,
|
||||
.ioctl = &lwip_ioctl_r_wrapper,
|
||||
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||
.socket_select = &lwip_select,
|
||||
.get_socket_select_semaphore = &lwip_get_socket_select_semaphore,
|
||||
.stop_socket_select = &lwip_stop_socket_select,
|
||||
.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
|
||||
* file descriptors are registered from LWIP_SOCKET_OFFSET to
|
||||
|
@ -3,17 +3,13 @@ set(srcs
|
||||
"heap.c"
|
||||
"locks.c"
|
||||
"poll.c"
|
||||
"pread.c"
|
||||
"pwrite.c"
|
||||
"pthread.c"
|
||||
"random.c"
|
||||
"reent_init.c"
|
||||
"select.c"
|
||||
"syscall_table.c"
|
||||
"syscalls.c"
|
||||
"termios.c"
|
||||
"time.c"
|
||||
"utime.c")
|
||||
"time.c")
|
||||
set(include_dirs platform_include)
|
||||
|
||||
if(CONFIG_SPIRAM_CACHE_WORKAROUND)
|
||||
@ -24,7 +20,6 @@ list(APPEND ldfragments newlib.lf)
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
REQUIRES vfs
|
||||
PRIV_REQUIRES soc esp_timer
|
||||
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");
|
||||
// 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
|
||||
// limitations under the License.
|
||||
|
||||
#include <stddef.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)
|
||||
{
|
||||
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,
|
||||
._abort = &abort,
|
||||
._system_r = &_system_r,
|
||||
._rename_r = &esp_vfs_rename,
|
||||
._rename_r = &_rename_r,
|
||||
._times_r = &_times_r,
|
||||
._gettimeofday_r = &_gettimeofday_r,
|
||||
._raise_r = &raise_r_stub,
|
||||
._unlink_r = &esp_vfs_unlink,
|
||||
._link_r = &esp_vfs_link,
|
||||
._stat_r = &esp_vfs_stat,
|
||||
._fstat_r = &esp_vfs_fstat,
|
||||
._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, // never called in ROM
|
||||
._close_r = &esp_vfs_close,
|
||||
._open_r = &esp_vfs_open,
|
||||
._write_r = (int (*)(struct _reent *r, int, const void *, int)) &esp_vfs_write,
|
||||
._lseek_r = (int (*)(struct _reent *r, int, int, int)) &esp_vfs_lseek,
|
||||
._read_r = (int (*)(struct _reent *r, int, void *, int)) &esp_vfs_read,
|
||||
._close_r = &_close_r,
|
||||
._open_r = &_open_r,
|
||||
._write_r = (int (*)(struct _reent *r, int, const void *, int)) &_write_r,
|
||||
._lseek_r = (int (*)(struct _reent *r, int, int, int)) &_lseek_r,
|
||||
._read_r = (int (*)(struct _reent *r, int, void *, int)) &_read_r,
|
||||
._lock_init = &_lock_init,
|
||||
._lock_init_recursive = &_lock_init_recursive,
|
||||
._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");
|
||||
// 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
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
@ -21,51 +20,111 @@
|
||||
#include <errno.h>
|
||||
#include <reent.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;
|
||||
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)
|
||||
{
|
||||
__errno_r(r) = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((alias("syscall_not_implemented")));
|
||||
int raise(int sig)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
__attribute__((alias("syscall_not_implemented_aborts")));
|
||||
int _raise_r(struct _reent *r, int sig)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
__attribute__((alias("syscall_not_implemented_aborts")));
|
||||
void* _sbrk_r(struct _reent *r, ptrdiff_t sz)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
__attribute__((alias("syscall_not_implemented_aborts")));
|
||||
int _getpid_r(struct _reent *r)
|
||||
{
|
||||
__errno_r(r) = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((alias("syscall_not_implemented")));
|
||||
int _kill_r(struct _reent *r, int pid, int sig)
|
||||
{
|
||||
__errno_r(r) = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((alias("syscall_not_implemented")));
|
||||
void _exit(int __status)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
__attribute__((alias("syscall_not_implemented_aborts")));
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
/* Replaces newlib fcntl, which has been compiled without HAVE_FCNTL */
|
||||
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 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);
|
||||
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||
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_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 int vfs_spiffs_mkdir(void* ctx, const char* name, mode_t mode);
|
||||
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
|
||||
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];
|
||||
|
||||
@ -344,6 +346,7 @@ esp_err_t esp_vfs_spiffs_register(const esp_vfs_spiffs_conf_t * conf)
|
||||
.open_p = &vfs_spiffs_open,
|
||||
.close_p = &vfs_spiffs_close,
|
||||
.fstat_p = &vfs_spiffs_fstat,
|
||||
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||
.stat_p = &vfs_spiffs_stat,
|
||||
.link_p = &vfs_spiffs_link,
|
||||
.unlink_p = &vfs_spiffs_unlink,
|
||||
@ -361,6 +364,7 @@ esp_err_t esp_vfs_spiffs_register(const esp_vfs_spiffs_conf_t * conf)
|
||||
#else
|
||||
.utime_p = NULL,
|
||||
#endif // CONFIG_SPIFFS_USE_MTIME
|
||||
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||
|
||||
static int vfs_spiffs_stat(void* ctx, const char * path, struct stat * st)
|
||||
{
|
||||
assert(path);
|
||||
@ -730,36 +736,6 @@ static int vfs_spiffs_link(void* ctx, const char* n1, const char* n2)
|
||||
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
|
||||
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;
|
||||
}
|
||||
#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"
|
||||
|
||||
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
|
||||
bool "Suppress select() related debug outputs"
|
||||
depends on VFS_SUPPORT_SELECT
|
||||
default y
|
||||
help
|
||||
Select() related functions might produce an unconveniently lot of
|
||||
@ -10,12 +59,16 @@ menu "Virtual file system"
|
||||
option.
|
||||
|
||||
config VFS_SUPPORT_TERMIOS
|
||||
bool "Add support for termios.h"
|
||||
bool "Provide termios.h functions"
|
||||
default y
|
||||
# Very likely, only makes sense for UART VFS driver, which itself depends on VFS_SUPPORT_IO
|
||||
depends on VFS_SUPPORT_IO
|
||||
help
|
||||
Disabling this option can save memory when the support for termios.h is not required.
|
||||
|
||||
menu "Host File System I/O (Semihosting)"
|
||||
depends on VFS_SUPPORT_IO
|
||||
|
||||
config SEMIHOSTFS_MAX_MOUNT_POINTS
|
||||
int "Maximum number of the host filesystem mount points"
|
||||
default 1
|
||||
|
@ -132,6 +132,7 @@ typedef struct
|
||||
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 */
|
||||
};
|
||||
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||
union {
|
||||
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 */
|
||||
@ -180,6 +181,7 @@ typedef struct
|
||||
int (*rmdir_p)(void* ctx, const char* name); /*!< rmdir with context pointer */
|
||||
int (*rmdir)(const char* name); /*!< rmdir without context pointer */
|
||||
};
|
||||
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||
union {
|
||||
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 */
|
||||
@ -192,6 +194,7 @@ typedef struct
|
||||
int (*fsync_p)(void* ctx, int fd); /*!< fsync with context pointer */
|
||||
int (*fsync)(int fd); /*!< fsync without context pointer */
|
||||
};
|
||||
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||
union {
|
||||
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 */
|
||||
@ -204,6 +207,7 @@ typedef struct
|
||||
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 */
|
||||
};
|
||||
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
||||
union {
|
||||
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 */
|
||||
};
|
||||
#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 */
|
||||
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 */
|
||||
@ -247,6 +251,7 @@ typedef struct
|
||||
void* (*get_socket_select_semaphore)(void);
|
||||
/** 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);
|
||||
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||
} 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);
|
||||
|
||||
/**
|
||||
* @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()
|
||||
|
@ -507,6 +507,52 @@ int esp_vfs_fstat(struct _reent *r, int fd, struct stat * st)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* Create aliases for newlib syscalls
|
||||
|
||||
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)
|
||||
DIR* esp_vfs_opendir(const char* name)
|
||||
{
|
||||
const vfs_entry_t* vfs = get_vfs_for_path(name);
|
||||
struct _reent* r = __getreent();
|
||||
@ -616,7 +648,7 @@ DIR* opendir(const char* name)
|
||||
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);
|
||||
struct _reent* r = __getreent();
|
||||
@ -629,7 +661,7 @@ struct dirent* readdir(DIR* pdir)
|
||||
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);
|
||||
struct _reent* r = __getreent();
|
||||
@ -642,7 +674,7 @@ int readdir_r(DIR* pdir, struct dirent* entry, struct dirent** out_dirent)
|
||||
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);
|
||||
struct _reent* r = __getreent();
|
||||
@ -655,7 +687,7 @@ long telldir(DIR* pdir)
|
||||
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);
|
||||
struct _reent* r = __getreent();
|
||||
@ -666,12 +698,12 @@ void seekdir(DIR* pdir, long loc)
|
||||
CHECK_AND_CALLV(r, vfs, seekdir, pdir, loc);
|
||||
}
|
||||
|
||||
void rewinddir(DIR* pdir)
|
||||
void esp_vfs_rewinddir(DIR* pdir)
|
||||
{
|
||||
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);
|
||||
struct _reent* r = __getreent();
|
||||
@ -684,7 +716,7 @@ int closedir(DIR* pdir)
|
||||
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);
|
||||
struct _reent* r = __getreent();
|
||||
@ -698,7 +730,7 @@ int mkdir(const char* name, mode_t mode)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rmdir(const char* name)
|
||||
int esp_vfs_rmdir(const char* name)
|
||||
{
|
||||
const vfs_entry_t* vfs = get_vfs_for_path(name);
|
||||
struct _reent* r = __getreent();
|
||||
@ -712,51 +744,7 @@ int rmdir(const char* name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _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 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 esp_vfs_access(const char *path, int amode)
|
||||
{
|
||||
int ret;
|
||||
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
||||
@ -770,7 +758,7 @@ int access(const char *path, int amode)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int truncate(const char *path, off_t length)
|
||||
int esp_vfs_truncate(const char *path, off_t length)
|
||||
{
|
||||
int ret;
|
||||
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
||||
@ -784,6 +772,10 @@ int truncate(const char *path, off_t length)
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
||||
int tcgetattr(int fd, struct termios *p)
|
||||
{
|
||||
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
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
/* Create aliases for newlib syscalls
|
||||
|
||||
if (fds == NULL) {
|
||||
__errno_r(r) = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
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.
|
||||
*/
|
||||
#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);
|
||||
FD_ZERO(&writefds);
|
||||
FD_ZERO(&errorfds);
|
||||
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)
|
||||
__attribute__((alias("esp_vfs_select")));
|
||||
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||
|
||||
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 >= MAX_FDS) {
|
||||
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 = esp_vfs_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;
|
||||
}
|
||||
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||
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")));
|
||||
int truncate(const char *path, off_t length)
|
||||
__attribute__((alias("esp_vfs_truncate")));
|
||||
int access(const char *path, int amode)
|
||||
__attribute__((alias("esp_vfs_access")));
|
||||
int utime(const char *path, const struct utimbuf *times)
|
||||
__attribute__((alias("esp_vfs_utime")));
|
||||
int rmdir(const char* name)
|
||||
__attribute__((alias("esp_vfs_rmdir")));
|
||||
int mkdir(const char* name, mode_t mode)
|
||||
__attribute__((alias("esp_vfs_mkdir")));
|
||||
DIR* opendir(const char* name)
|
||||
__attribute__((alias("esp_vfs_opendir")));
|
||||
int closedir(DIR* pdir)
|
||||
__attribute__((alias("esp_vfs_closedir")));
|
||||
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")));
|
||||
long telldir(DIR* pdir)
|
||||
__attribute__((alias("esp_vfs_telldir")));
|
||||
void seekdir(DIR* pdir, long loc)
|
||||
__attribute__((alias("esp_vfs_seekdir")));
|
||||
void rewinddir(DIR* pdir)
|
||||
__attribute__((alias("esp_vfs_rewinddir")));
|
||||
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||
|
||||
void vfs_include_syscalls_impl(void)
|
||||
{
|
||||
|
@ -23,6 +23,14 @@
|
||||
#include "freertos/task.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
|
||||
#include "esp_log.h"
|
||||
const static char *TAG = "esp_semihost";
|
||||
|
@ -116,6 +116,8 @@ static vfs_uart_context_t* s_ctx[UART_NUM] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||
|
||||
typedef struct {
|
||||
esp_vfs_select_sem_t select_sem;
|
||||
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);
|
||||
|
||||
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||
|
||||
static int uart_open(const char * path, int flags, int mode)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||
|
||||
static int uart_access(const char *path, int amode)
|
||||
{
|
||||
int ret = -1;
|
||||
@ -340,6 +346,8 @@ static int uart_access(const char *path, int amode)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||
|
||||
static int uart_fsync(int fd)
|
||||
{
|
||||
assert(fd >= 0 && fd < 3);
|
||||
@ -349,6 +357,8 @@ static int uart_fsync(int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||
|
||||
static esp_err_t register_select(uart_select_args_t *args)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
||||
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,
|
||||
.fcntl = &uart_fcntl,
|
||||
.fsync = &uart_fsync,
|
||||
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||
.access = &uart_access,
|
||||
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||
.start_select = &uart_start_select,
|
||||
.end_select = &uart_end_select,
|
||||
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
||||
.tcsetattr = &uart_tcsetattr,
|
||||
.tcgetattr = &uart_tcgetattr,
|
||||
|
@ -31,6 +31,8 @@ void app_main(void)
|
||||
printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
|
||||
(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--) {
|
||||
printf("Restarting in %d seconds...\n", i);
|
||||
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 New Issue
Block a user