vfs_usb_serial: set secondary selection for making usb port can output under default menu

This commit is contained in:
Cao Sen Miao 2021-10-21 12:46:24 +08:00
parent 5206afe755
commit adfb7bed96
17 changed files with 489 additions and 181 deletions

View File

@ -62,7 +62,7 @@ TEST_CASE("can use std::vector", "[cxx]")
#elif CONFIG_IDF_TARGET_ESP32S2
#define LEAKS "800"
#elif CONFIG_IDF_TARGET_ESP32C3
#define LEAKS "600"
#define LEAKS "700"
#else
#error "unknown target in CXX tests, can't set leaks threshold"
#endif

View File

@ -236,8 +236,31 @@ menu "ESP System Settings"
bool "None"
endchoice
# Internal option, indicates that console UART is used (and not USB, for example)
choice ESP_CONSOLE_SECONDARY
depends on IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C3
prompt "Channel for console secondary output"
default ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
help
This secondary option supports output through other specific port like USB_SERIAL_JTAG
when UART0 port as a primary is selected but not connected. This secondary output currently only supports
non-blocking mode without using REPL. If you want to output in blocking mode with REPL or
input through this secondary port, please change the primary config to this port
in `Channel for console output` menu.
config ESP_CONSOLE_SECONDARY_NONE
bool "No secondary console"
config ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
bool "USB_SERIAL_JTAG PORT"
depends on !ESP_CONSOLE_USB_SERIAL_JTAG
help
This option supports output through USB_SERIAL_JTAG port when the UART0 port is not connected.
The output currently only supports non-blocking mode without using the console.
If you want to output in blocking mode with REPL or input through USB_SERIAL_JTAG port,
please change the primary config to ESP_CONSOLE_USB_SERIAL_JTAG above.
endchoice
config ESP_CONSOLE_UART
# Internal option, indicates that console UART is used (and not USB, for example)
bool
default y if ESP_CONSOLE_UART_DEFAULT || ESP_CONSOLE_UART_CUSTOM

View File

@ -50,9 +50,7 @@
#include "esp_pm.h"
#include "esp_private/pm_impl.h"
#include "esp_pthread.h"
#include "esp_private/usb_console.h"
#include "esp_vfs_cdcacm.h"
#include "esp_vfs_usb_serial_jtag.h"
#include "esp_vfs_console.h"
#include "brownout.h"
@ -83,9 +81,6 @@
#error "System has been configured to run on multiple cores, but target SoC only has a single core."
#endif
#define STRINGIFY(s) STRINGIFY2(s)
#define STRINGIFY2(s) #s
uint64_t g_startup_time = 0;
#if SOC_APB_BACKUP_DMA
@ -271,23 +266,14 @@ static void do_core_init(void)
esp_timer_early_init();
esp_newlib_time_init();
#ifdef CONFIG_VFS_SUPPORT_IO
#ifdef CONFIG_ESP_CONSOLE_UART
esp_vfs_dev_uart_register();
const char *default_stdio_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
#endif // CONFIG_ESP_CONSOLE_UART
#ifdef CONFIG_ESP_CONSOLE_USB_CDC
ESP_ERROR_CHECK(esp_usb_console_init());
ESP_ERROR_CHECK(esp_vfs_dev_cdcacm_register());
const char *default_stdio_dev = "/dev/cdcacm";
#endif // CONFIG_ESP_CONSOLE_USB_CDC
#ifdef CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
ESP_ERROR_CHECK(esp_vfs_dev_usb_serial_jtag_register());
const char *default_stdio_dev = "/dev/usbserjtag";
#endif // CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
#endif // CONFIG_VFS_SUPPORT_IO
#if CONFIG_VFS_SUPPORT_IO
// VFS console register.
esp_err_t vfs_err = esp_vfs_console_register();
assert(vfs_err == ESP_OK && "Failed to register vfs console");
#endif
#if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE)
const static char *default_stdio_dev = "/dev/console/";
esp_reent_init(_GLOBAL_REENT);
_GLOBAL_REENT->_stdin = fopen(default_stdio_dev, "r");
_GLOBAL_REENT->_stdout = fopen(default_stdio_dev, "w");

View File

@ -2,14 +2,16 @@ idf_component_register(SRCS "vfs.c"
"vfs_eventfd.c"
"vfs_uart.c"
"vfs_semihost.c"
"vfs_console.c"
INCLUDE_DIRS include
PRIV_INCLUDE_DIRS private_include
PRIV_REQUIRES driver)
if(CONFIG_ESP_CONSOLE_USB_CDC)
target_sources(${COMPONENT_LIB} PRIVATE "vfs_cdcacm.c")
endif()
if(CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG)
if(CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG OR CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG)
target_sources(${COMPONENT_LIB} PRIVATE "vfs_usb_serial_jtag.c")
endif()

View File

@ -1,3 +1,4 @@
COMPONENT_PRIV_INCLUDEDIRS := private_include
ifndef CONFIG_ESP_CONSOLE_USB_CDC
COMPONENT_OBJEXCLUDE := vfs_cdcacm.o
endif

View File

@ -246,7 +246,6 @@ typedef struct
#endif // CONFIG_VFS_SUPPORT_SELECT
} esp_vfs_t;
/**
* Register a virtual filesystem for given path prefix.
*

View File

@ -1,16 +1,8 @@
// Copyright 2015-2017 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.
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

View File

@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief add uart/usb_serial_jtag/usb_otg_acmcdc virtual filesystem driver
*
* This function is called from startup code to enable serial output
*/
esp_err_t esp_vfs_console_register(void);
#ifdef __cplusplus
}
#endif

View File

@ -1,16 +1,8 @@
// Copyright 2015-2017 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.
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

View File

@ -1,16 +1,8 @@
// Copyright 2021 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.
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

View File

@ -0,0 +1,101 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_vfs.h"
#include "esp_vfs_common.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct vfs_entry_ {
esp_vfs_t vfs; // contains pointers to VFS functions
char path_prefix[ESP_VFS_PATH_MAX]; // path prefix mapped to this VFS
size_t path_prefix_len; // micro-optimization to avoid doing extra strlen
void* ctx; // optional pointer which can be passed to VFS
int offset; // index of this structure in s_vfs array
} vfs_entry_t;
/**
* @brief get pointer of uart vfs.
*
* This function is called in vfs_console in order to get the vfs implementation
* of uart.
*
* @return pointer to structure esp_vfs_t
*/
const esp_vfs_t *esp_vfs_uart_get_vfs(void);
/**
* @brief get pointer of cdcacm vfs.
*
* This function is called in vfs_console in order to get the vfs implementation
* of cdcacm.
*
* @return pointer to structure esp_vfs_t
*/
const esp_vfs_t *esp_vfs_cdcacm_get_vfs(void);
/**
* @brief get pointer of usb_serial_jtag vfs.
*
* This function is called in vfs_console in order to get the vfs implementation
* of usb_serial_jtag.
*
* @return pointer to structure esp_vfs_nonblocking_console_t
*/
const esp_vfs_t *esp_vfs_usb_serial_jtag_get_vfs(void);
/**
* Register a virtual filesystem.
*
* @param base_path file path prefix associated with the filesystem.
* Must be a zero-terminated C string, may be empty.
* If not empty, must be up to ESP_VFS_PATH_MAX
* characters long, and at least 2 characters long.
* Name must start with a "/" and must not end with "/".
* For example, "/data" or "/dev/spi" are valid.
* These VFSes would then be called to handle file paths such as
* "/data/myfile.txt" or "/dev/spi/0".
* In the special case of an empty base_path, a "fallback"
* VFS is registered. Such VFS will handle paths which are not
* matched by any other registered VFS.
* @param len Length of the base_path.
* @param vfs Pointer to esp_vfs_t, a structure which maps syscalls to
* the filesystem driver functions. VFS component doesn't
* assume ownership of this pointer.
* @param ctx If vfs->flags has ESP_VFS_FLAG_CONTEXT_PTR set, a pointer
* which should be passed to VFS functions. Otherwise, NULL.
* @param vfs_index Index for getting the vfs content.
*
* @return ESP_OK if successful.
* ESP_ERR_NO_MEM if too many VFSes are registered.
* ESP_ERR_INVALID_ARG if given an invalid parameter.
*/
esp_err_t esp_vfs_register_common(const char *base_path, size_t len, const esp_vfs_t* vfs, void* ctx, int *vfs_index);
/**
* Get vfs fd with given path.
*
* @param path file path prefix associated with the filesystem.
*
* @return Pointer to the `vfs_entry_t` corresponding to the given path, which cannot be NULL.
*/
const vfs_entry_t *get_vfs_for_path(const char *path);
/**
* Get vfs fd with given vfs index.
*
* @param index VFS index.
*
* @return Pointer to the `vfs_entry_t` corresponding to the given path, which cannot be NULL.
*/
const vfs_entry_t *get_vfs_for_index(int index);
#ifdef __cplusplus
}
#endif

View File

@ -18,6 +18,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "esp_vfs.h"
#include "esp_vfs_private.h"
#include "sdkconfig.h"
#ifdef CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT
@ -47,14 +48,6 @@ typedef struct {
local_fd_t local_fd;
} fd_table_t;
typedef struct vfs_entry_ {
esp_vfs_t vfs; // contains pointers to VFS functions
char path_prefix[ESP_VFS_PATH_MAX]; // path prefix mapped to this VFS
size_t path_prefix_len; // micro-optimization to avoid doing extra strlen
void* ctx; // optional pointer which can be passed to VFS
int offset; // index of this structure in s_vfs array
} vfs_entry_t;
typedef struct {
bool isset; // none or at least one bit is set in the following 3 fd sets
fd_set readfds;
@ -68,7 +61,7 @@ static size_t s_vfs_count = 0;
static fd_table_t s_fd_table[MAX_FDS] = { [0 ... MAX_FDS-1] = FD_TABLE_ENTRY_UNUSED };
static _lock_t s_fd_table_lock;
static esp_err_t esp_vfs_register_common(const char* base_path, size_t len, const esp_vfs_t* vfs, void* ctx, int *vfs_index)
esp_err_t esp_vfs_register_common(const char* base_path, size_t len, const esp_vfs_t* vfs, void* ctx, int *vfs_index)
{
if (len != LEN_PATH_PREFIX_IGNORED) {
/* empty prefix is allowed, "/" is not allowed */
@ -263,7 +256,7 @@ esp_err_t esp_vfs_unregister_fd(esp_vfs_id_t vfs_id, int fd)
return ret;
}
static inline const vfs_entry_t *get_vfs_for_index(int index)
const vfs_entry_t *get_vfs_for_index(int index)
{
if (index < 0 || index >= s_vfs_count) {
return NULL;
@ -308,7 +301,7 @@ static const char* translate_path(const vfs_entry_t* vfs, const char* src_path)
return src_path + vfs->path_prefix_len;
}
static const vfs_entry_t* get_vfs_for_path(const char* path)
const vfs_entry_t* get_vfs_for_path(const char* path)
{
const vfs_entry_t* best_match = NULL;
ssize_t best_match_prefix_len = -1;

View File

@ -1,16 +1,8 @@
// 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.
// 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.
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdbool.h>
@ -309,17 +301,23 @@ void esp_vfs_dev_cdcacm_set_rx_line_endings(esp_line_endings_t mode)
s_rx_mode = mode;
}
static const esp_vfs_t vfs = {
.flags = ESP_VFS_FLAG_DEFAULT,
.write = &cdcacm_write,
.open = &cdcacm_open,
.fstat = &cdcacm_fstat,
.close = &cdcacm_close,
.read = &cdcacm_read,
.fcntl = &cdcacm_fcntl,
.fsync = &cdcacm_fsync
};
const esp_vfs_t *esp_vfs_cdcacm_get_vfs(void)
{
return &vfs;
}
esp_err_t esp_vfs_dev_cdcacm_register(void)
{
const esp_vfs_t vfs = {
.flags = ESP_VFS_FLAG_DEFAULT,
.write = &cdcacm_write,
.open = &cdcacm_open,
.fstat = &cdcacm_fstat,
.close = &cdcacm_close,
.read = &cdcacm_read,
.fcntl = &cdcacm_fcntl,
.fsync = &cdcacm_fsync
};
return esp_vfs_register("/dev/cdcacm", &vfs, NULL);
}

View File

@ -0,0 +1,218 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_vfs_console.h"
#include "esp_rom_sys.h"
#include "esp_vfs_cdcacm.h"
#include "esp_vfs_private.h"
#include "esp_vfs_usb_serial_jtag.h"
#include "esp_vfs_dev.h"
#include "esp_private/usb_console.h"
#include "sdkconfig.h"
#define STRINGIFY(s) STRINGIFY2(s)
#define STRINGIFY2(s) #s
/**
* This file is to concentrate all the vfs(UART, USB_SERIAL_JTAG, CDCACM) console into one single file.
* Get the vfs information from their component (i.e. vfs_uart.c) through `esp_vfs_usb_xxx_get_console()`,
* which can help us to output some string to two different ports(i.e both through uart and usb_serial_jtag).
* Usually, we set a port as primary and another as secondary. For primary, it is used for all the features supported by each vfs implementation,
* while the secondary is only used for output.
*/
typedef struct {
int fd_primary;
int fd_secondary;
} vfs_console_context_t;
#if CONFIG_VFS_SUPPORT_IO
// Primary register part.
#ifdef CONFIG_ESP_CONSOLE_UART
const static char *primary_path = "/dev/uart";
#elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
const static char *primary_path = "/dev/usbserjtag";
#elif CONFIG_ESP_CONSOLE_USB_CDC
const static char *primary_path = "/dev/cdcacm";
#endif
// Secondary register part.
#if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
const static char *secondary_path = "/dev/secondary";
static int secondary_vfs_index;
#endif // Secondary part
static int primary_vfs_index;
static vfs_console_context_t vfs_console= {0};
int console_open(const char * path, int flags, int mode)
{
// Primary port open
#if CONFIG_ESP_CONSOLE_UART
vfs_console.fd_primary = get_vfs_for_path(primary_path)->vfs.open("/"STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM), flags, mode);
#elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
vfs_console.fd_primary = esp_vfs_usb_serial_jtag_get_vfs()->open("/", flags, mode);
#elif CONFIG_ESP_CONSOLE_USB_CDC
vfs_console.fd_primary = esp_vfs_cdcacm_get_vfs()->open("/", flags, mode);
#endif
// Secondary port open
#if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
vfs_console.fd_secondary = get_vfs_for_path(secondary_path)->vfs.open("/", flags, mode);
#endif
return 0;
}
ssize_t console_write(int fd, const void *data, size_t size)
{
// All function calls are to primary, except from write and close, which will be forwarded to both primary and secondary.
get_vfs_for_index(primary_vfs_index)->vfs.write(vfs_console.fd_primary, data, size);
#if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
get_vfs_for_index(secondary_vfs_index)->vfs.write(vfs_console.fd_secondary, data, size);
#endif
return size;
}
int console_fstat(int fd, struct stat * st)
{
return get_vfs_for_index(primary_vfs_index)->vfs.fstat(fd, st);
}
int console_close(int fd)
{
// All function calls are to primary, except from write and close, which will be forwarded to both primary and secondary.
get_vfs_for_index(primary_vfs_index)->vfs.close(vfs_console.fd_primary);
#if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
get_vfs_for_index(secondary_vfs_index)->vfs.close(vfs_console.fd_secondary);
#endif
return 0;
}
ssize_t console_read(int fd, void * dst, size_t size)
{
return get_vfs_for_index(primary_vfs_index)->vfs.read(vfs_console.fd_primary, dst, size);
}
int console_fcntl(int fd, int cmd, int arg)
{
return get_vfs_for_index(primary_vfs_index)->vfs.fcntl(vfs_console.fd_primary, cmd, arg);
}
int console_fsync(int fd)
{
return get_vfs_for_index(primary_vfs_index)->vfs.fsync(vfs_console.fd_primary);
}
#ifdef CONFIG_VFS_SUPPORT_DIR
int console_access(const char *path, int amode)
{
// currently only UART support DIR.
return get_vfs_for_index(primary_vfs_index)->vfs.access("/"STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM), amode);
}
#endif // CONFIG_VFS_SUPPORT_DIR
#ifdef CONFIG_VFS_SUPPORT_SELECT
static esp_err_t console_start_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
esp_vfs_select_sem_t select_sem, void **end_select_args)
{
return get_vfs_for_index(primary_vfs_index)->vfs.start_select(nfds, readfds, writefds, exceptfds, select_sem, end_select_args);
}
esp_err_t console_end_select(void *end_select_args)
{
return get_vfs_for_index(primary_vfs_index)->vfs.end_select(end_select_args);
}
#endif // CONFIG_VFS_SUPPORT_SELECT
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
int console_tcsetattr(int fd, int optional_actions, const struct termios *p)
{
return get_vfs_for_index(primary_vfs_index)->vfs.tcsetattr(vfs_console.fd_primary, optional_actions, p);
}
int console_tcgetattr(int fd, struct termios *p)
{
return get_vfs_for_index(primary_vfs_index)->vfs.tcgetattr(vfs_console.fd_primary, p);
}
int console_tcdrain(int fd)
{
return get_vfs_for_index(primary_vfs_index)->vfs.tcdrain(vfs_console.fd_primary);
}
int console_tcflush(int fd, int select)
{
return get_vfs_for_index(primary_vfs_index)->vfs.tcflush(vfs_console.fd_primary, select);
}
#endif // CONFIG_VFS_SUPPORT_TERMIOS
static const esp_vfs_t vfs = {
.flags = ESP_VFS_FLAG_DEFAULT,
.write = &console_write,
.open = &console_open,
.fstat = &console_fstat,
.close = &console_close,
.read = &console_read,
.fcntl = &console_fcntl,
.fsync = &console_fsync,
#ifdef CONFIG_VFS_SUPPORT_DIR
.access = &console_access,
#endif // CONFIG_VFS_SUPPORT_DIR
#ifdef CONFIG_VFS_SUPPORT_SELECT
.start_select = &console_start_select,
.end_select = &console_end_select,
#endif // CONFIG_VFS_SUPPORT_SELECT
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
.tcsetattr = &console_tcsetattr,
.tcgetattr = &console_tcgetattr,
.tcdrain = &console_tcdrain,
.tcflush = &console_tcflush,
#endif // CONFIG_VFS_SUPPORT_TERMIOS
};
esp_err_t esp_vfs_dev_console_register(void)
{
return esp_vfs_register("/dev/console", &vfs, NULL);
}
esp_err_t esp_vfs_console_register(void)
{
esp_err_t err = ESP_OK;
// Primary register part.
#ifdef CONFIG_ESP_CONSOLE_UART
const esp_vfs_t *uart_vfs = esp_vfs_uart_get_vfs();
err = esp_vfs_register_common(primary_path, strlen(primary_path), uart_vfs, NULL, &primary_vfs_index);
#elif CONFIG_ESP_CONSOLE_USB_CDC
const esp_vfs_t *cdcacm_vfs = esp_vfs_cdcacm_get_vfs();
err = esp_usb_console_init();
if (err != ESP_OK) {
return err;
}
err = esp_vfs_register_common(primary_path, strlen(primary_path), cdcacm_vfs, NULL, &primary_vfs_index);
#elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
const esp_vfs_t *usb_serial_jtag_vfs = esp_vfs_usb_serial_jtag_get_vfs();
err = esp_vfs_register_common(primary_path, strlen(primary_path), usb_serial_jtag_vfs, NULL, &primary_vfs_index);
#endif // CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
if (err != ESP_OK) {
return err;
}
// Secondary register part.
#if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
const esp_vfs_t *usb_serial_jtag_vfs = esp_vfs_usb_serial_jtag_get_vfs();
err = esp_vfs_register_common(secondary_path, strlen(secondary_path), usb_serial_jtag_vfs, NULL, &secondary_vfs_index);
if(err != ESP_OK) {
return err;
}
#endif
err = esp_vfs_dev_console_register();
return err;
}
#endif // CONFIG_VFS_SUPPORT_IO

View File

@ -1,16 +1,8 @@
// Copyright 2015-2017 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.
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdbool.h>
@ -969,31 +961,37 @@ static int uart_tcflush(int fd, int select)
}
#endif // CONFIG_VFS_SUPPORT_TERMIOS
void esp_vfs_dev_uart_register(void)
{
esp_vfs_t vfs = {
.flags = ESP_VFS_FLAG_DEFAULT,
.write = &uart_write,
.open = &uart_open,
.fstat = &uart_fstat,
.close = &uart_close,
.read = &uart_read,
.fcntl = &uart_fcntl,
.fsync = &uart_fsync,
static const esp_vfs_t vfs = {
.flags = ESP_VFS_FLAG_DEFAULT,
.write = &uart_write,
.open = &uart_open,
.fstat = &uart_fstat,
.close = &uart_close,
.read = &uart_read,
.fcntl = &uart_fcntl,
.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,
.end_select = &uart_end_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,
.tcdrain = &uart_tcdrain,
.tcflush = &uart_tcflush,
.tcsetattr = &uart_tcsetattr,
.tcgetattr = &uart_tcgetattr,
.tcdrain = &uart_tcdrain,
.tcflush = &uart_tcflush,
#endif // CONFIG_VFS_SUPPORT_TERMIOS
};
};
const esp_vfs_t* esp_vfs_uart_get_vfs(void)
{
return &vfs;
}
void esp_vfs_dev_uart_register(void)
{
ESP_ERROR_CHECK(esp_vfs_register("/dev/uart", &vfs, NULL));
}

View File

@ -1,16 +1,8 @@
// Copyright 2015-2017 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.
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
//This is a simple non-blocking (well, tx may spin for a bit if the buffer
//is full) USB-serial-jtag driver. Select etc is not supported yet.
@ -113,23 +105,21 @@ static int usb_serial_jtag_open(const char * path, int flags, int mode)
static void usb_serial_jtag_tx_char(int fd, int c)
{
uint8_t cc=(uint8_t)c;
if (usb_serial_jtag_ll_txfifo_writable()) {
//We can write to the buffer. Immediately do so.
usb_serial_jtag_ll_write_txfifo(&cc, 1);
s_ctx.last_tx_ts = esp_timer_get_time();
} else {
//Try to write to the buffer as long as we still expect the buffer to have
//a chance of being emptied by an active host. Just drop the data if there's
//no chance anymore.
while ((esp_timer_get_time() - s_ctx.last_tx_ts) < TX_FLUSH_TIMEOUT_US) {
if (usb_serial_jtag_ll_txfifo_writable()) {
//Woohoo, we can write again. Do so and exit the while loop.
usb_serial_jtag_ll_write_txfifo(&cc, 1);
s_ctx.last_tx_ts = esp_timer_get_time();
break;
}
// Try to write to the buffer as long as we still expect the buffer to have
// a chance of being emptied by an active host. Just drop the data if there's
// no chance anymore.
// When we first try to send a character and the buffer is not accessible yet,
// we wait until the time has been more than TX_FLUSH_TIMEOUT_US since we successfully
// sent the last byte. If it takes longer than TX_FLUSH_TIMEOUT_US, we drop every
// byte until the buffer can be accessible again.
do {
if (usb_serial_jtag_ll_txfifo_writable()) {
usb_serial_jtag_ll_write_txfifo(&cc, 1);
s_ctx.last_tx_ts = esp_timer_get_time();
break;
}
}
} while ((esp_timer_get_time() - s_ctx.last_tx_ts) < TX_FLUSH_TIMEOUT_US);
}
static int usb_serial_jtag_rx_char(int fd)
@ -364,25 +354,30 @@ void esp_vfs_dev_usb_serial_jtag_set_rx_line_endings(esp_line_endings_t mode)
s_ctx.rx_mode = mode;
}
static const esp_vfs_t vfs = {
.flags = ESP_VFS_FLAG_DEFAULT,
.write = &usb_serial_jtag_write,
.open = &usb_serial_jtag_open,
.fstat = &usb_serial_jtag_fstat,
.close = &usb_serial_jtag_close,
.read = &usb_serial_jtag_read,
.fcntl = &usb_serial_jtag_fcntl,
.fsync = &usb_serial_jtag_fsync,
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
.tcsetattr = &usb_serial_jtag_tcsetattr,
.tcgetattr = &usb_serial_jtag_tcgetattr,
.tcdrain = &usb_serial_jtag_tcdrain,
.tcflush = &usb_serial_jtag_tcflush,
#endif // CONFIG_VFS_SUPPORT_TERMIOS
};
const esp_vfs_t* esp_vfs_usb_serial_jtag_get_vfs(void)
{
return &vfs;
}
esp_err_t esp_vfs_dev_usb_serial_jtag_register(void)
{
esp_vfs_t vfs = {
.flags = ESP_VFS_FLAG_DEFAULT,
.write = &usb_serial_jtag_write,
.open = &usb_serial_jtag_open,
.fstat = &usb_serial_jtag_fstat,
.close = &usb_serial_jtag_close,
.read = &usb_serial_jtag_read,
.fcntl = &usb_serial_jtag_fcntl,
.fsync = &usb_serial_jtag_fsync,
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
.tcsetattr = &usb_serial_jtag_tcsetattr,
.tcgetattr = &usb_serial_jtag_tcgetattr,
.tcdrain = &usb_serial_jtag_tcdrain,
.tcflush = &usb_serial_jtag_tcflush,
#endif // CONFIG_VFS_SUPPORT_TERMIOS
};
// "/dev/usb_serial_jtag" unfortunately is too long for vfs
return esp_vfs_register("/dev/usbserjtag", &vfs, NULL);
}

View File

@ -2552,12 +2552,9 @@ components/unity/unity_runner.c
components/usb/test/common/test_usb_mock_classes.c
components/usb/test/common/test_usb_mock_classes.h
components/usb/test/hcd/test_hcd_ctrl.c
components/vfs/include/esp_vfs_cdcacm.h
components/vfs/include/esp_vfs_common.h
components/vfs/include/esp_vfs_dev.h
components/vfs/include/esp_vfs_eventfd.h
components/vfs/include/esp_vfs_semihost.h
components/vfs/include/esp_vfs_usb_serial_jtag.h
components/vfs/test/test_vfs_access.c
components/vfs/test/test_vfs_append.c
components/vfs/test/test_vfs_eventfd.c
@ -2566,11 +2563,8 @@ components/vfs/test/test_vfs_lwip.c
components/vfs/test/test_vfs_paths.c
components/vfs/test/test_vfs_select.c
components/vfs/test/test_vfs_uart.c
components/vfs/vfs_cdcacm.c
components/vfs/vfs_eventfd.c
components/vfs/vfs_semihost.c
components/vfs/vfs_uart.c
components/vfs/vfs_usb_serial_jtag.c
components/wear_levelling/Partition.cpp
components/wear_levelling/SPI_Flash.cpp
components/wear_levelling/WL_Ext_Perf.cpp