mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-18 21:12:22 +02:00
Terminal: Use vfs as an alternative for ITerminal
This commit is contained in:
@ -20,6 +20,7 @@ set(srcs ${platform_srcs}
|
|||||||
"src/esp_modem_factory.cpp"
|
"src/esp_modem_factory.cpp"
|
||||||
"src/esp_modem_cmux.cpp"
|
"src/esp_modem_cmux.cpp"
|
||||||
"src/esp_modem_command_library.cpp"
|
"src/esp_modem_command_library.cpp"
|
||||||
|
"src/esp_modem_term_fs.cpp"
|
||||||
"src/esp_modem_modules.cpp")
|
"src/esp_modem_modules.cpp")
|
||||||
|
|
||||||
set(include_dirs "include")
|
set(include_dirs "include")
|
||||||
|
@ -47,14 +47,24 @@ extern "C" void app_main(void)
|
|||||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||||
|
|
||||||
// init the DTE
|
// init the DTE
|
||||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
esp_modem_dte_config_t dte_config = {
|
||||||
dte_config.uart_config.event_task_stack_size = 4096;
|
.dte_buffer_size = 512,
|
||||||
dte_config.uart_config.event_task_priority = 15;
|
.vfs_config = {.port_num = UART_NUM_1,
|
||||||
|
.dev_name = "/dev/uart/1",
|
||||||
|
.rx_buffer_size = 512,
|
||||||
|
.tx_buffer_size = 512,
|
||||||
|
.baud_rate = 115200,
|
||||||
|
.tx_io_num = 25,
|
||||||
|
.rx_io_num = 26,
|
||||||
|
.task_stack_size = 4096,
|
||||||
|
.task_prio = 5}
|
||||||
|
};
|
||||||
|
|
||||||
esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP();
|
esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP();
|
||||||
|
|
||||||
esp_netif_t *esp_netif = esp_netif_new(&ppp_netif_config);
|
esp_netif_t *esp_netif = esp_netif_new(&ppp_netif_config);
|
||||||
assert(esp_netif);
|
assert(esp_netif);
|
||||||
auto uart_dte = create_uart_dte(&dte_config);
|
auto uart_dte = create_vfs_dte(&dte_config);
|
||||||
|
|
||||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("internet");
|
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("internet");
|
||||||
|
|
||||||
|
@ -48,6 +48,11 @@ using dte_config = ::esp_modem_dte_config;
|
|||||||
* if exceptions are disabled the API abort()'s on error
|
* if exceptions are disabled the API abort()'s on error
|
||||||
*/
|
*/
|
||||||
std::shared_ptr<DTE> create_uart_dte(const dte_config *config);
|
std::shared_ptr<DTE> create_uart_dte(const dte_config *config);
|
||||||
|
|
||||||
|
|
||||||
|
std::shared_ptr<DTE> create_vfs_dte(const dte_config *config);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
@ -58,9 +58,24 @@ struct esp_modem_uart_term_config {
|
|||||||
int event_task_priority; /*!< UART Event Task Priority */
|
int event_task_priority; /*!< UART Event Task Priority */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct esp_modem_vfs_term_config {
|
||||||
|
int port_num;
|
||||||
|
const char* dev_name;
|
||||||
|
int rx_buffer_size;
|
||||||
|
int tx_buffer_size;
|
||||||
|
int baud_rate;
|
||||||
|
int tx_io_num;
|
||||||
|
int rx_io_num;
|
||||||
|
uint32_t task_stack_size;
|
||||||
|
int task_prio;
|
||||||
|
};
|
||||||
|
|
||||||
struct esp_modem_dte_config {
|
struct esp_modem_dte_config {
|
||||||
size_t dte_buffer_size;
|
size_t dte_buffer_size;
|
||||||
struct esp_modem_uart_term_config uart_config;
|
union {
|
||||||
|
struct esp_modem_uart_term_config uart_config;
|
||||||
|
struct esp_modem_vfs_term_config vfs_config;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
28
esp_modem/private_include/vfs_termial.hpp
Normal file
28
esp_modem/private_include/vfs_termial.hpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef _VFS_TERMINAL_HPP_
|
||||||
|
#define _VFS_TERMINAL_HPP_
|
||||||
|
|
||||||
|
#include "cxx_include/esp_modem_dte.hpp"
|
||||||
|
|
||||||
|
struct esp_modem_dte_config;
|
||||||
|
|
||||||
|
namespace esp_modem::terminal {
|
||||||
|
|
||||||
|
std::unique_ptr<Terminal> create_vfs_terminal(const esp_modem_dte_config *config);
|
||||||
|
|
||||||
|
} // namespace esp_modem::terminal
|
||||||
|
|
||||||
|
#endif // _VFS_TERMINAL_HPP_
|
@ -13,9 +13,10 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include "esp_log.h"
|
||||||
#include "cxx_include/esp_modem_dte.hpp"
|
#include "cxx_include/esp_modem_dte.hpp"
|
||||||
#include "uart_terminal.hpp"
|
#include "uart_terminal.hpp"
|
||||||
#include "esp_log.h"
|
#include "vfs_termial.hpp"
|
||||||
#include "cxx_include/esp_modem_api.hpp"
|
#include "cxx_include/esp_modem_api.hpp"
|
||||||
#include "cxx_include/esp_modem_dce_factory.hpp"
|
#include "cxx_include/esp_modem_dce_factory.hpp"
|
||||||
#include "esp_modem_config.h"
|
#include "esp_modem_config.h"
|
||||||
@ -36,6 +37,14 @@ std::shared_ptr<DTE> create_uart_dte(const dte_config *config) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<DTE> create_vfs_dte(const dte_config *config) {
|
||||||
|
TRY_CATCH_RET_NULL(
|
||||||
|
auto term = terminal::create_vfs_terminal(config);
|
||||||
|
return std::make_shared<DTE>(config, std::move(term));
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline std::unique_ptr<DCE>
|
static inline std::unique_ptr<DCE>
|
||||||
create_modem_dce(dce_factory::Modem m, const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif) {
|
create_modem_dce(dce_factory::Modem m, const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif) {
|
||||||
dce_factory::Factory f(m);
|
dce_factory::Factory f(m);
|
||||||
|
199
esp_modem/src/esp_modem_term_fs.cpp
Normal file
199
esp_modem/src/esp_modem_term_fs.cpp
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <sys/fcntl.h>
|
||||||
|
#include "cxx_include/esp_modem_dte.hpp"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "driver/uart.h"
|
||||||
|
#include "esp_modem_config.h"
|
||||||
|
#include "exception_stub.hpp"
|
||||||
|
#include "esp_vfs_dev.h"
|
||||||
|
|
||||||
|
static const char *TAG = "fs_terminal";
|
||||||
|
|
||||||
|
namespace esp_modem::terminal {
|
||||||
|
|
||||||
|
struct uart_resource {
|
||||||
|
explicit uart_resource(const esp_modem_dte_config *config);
|
||||||
|
~uart_resource();
|
||||||
|
uart_port_t port;
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vfs_task {
|
||||||
|
explicit vfs_task(size_t stack_size, size_t priority, void *task_param, TaskFunction_t task_function) :
|
||||||
|
task_handle(nullptr) {
|
||||||
|
BaseType_t ret = xTaskCreate(task_function, "vfs_task"
|
||||||
|
"", stack_size, task_param, priority, &task_handle);
|
||||||
|
throw_if_false(ret == pdTRUE, "create uart event task failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
~vfs_task() {
|
||||||
|
if (task_handle) vTaskDelete(task_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskHandle_t task_handle; /*!< UART event task handle */
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_resource::~uart_resource()
|
||||||
|
{
|
||||||
|
if (port >= UART_NUM_0 && port < UART_NUM_MAX) {
|
||||||
|
uart_driver_delete(port);
|
||||||
|
}
|
||||||
|
if (fd >= 0) {
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uart_resource::uart_resource(const esp_modem_dte_config *config) :
|
||||||
|
port(-1), fd(-1)
|
||||||
|
{
|
||||||
|
/* Config UART */
|
||||||
|
uart_config_t uart_config = {};
|
||||||
|
uart_config.baud_rate = config->vfs_config.baud_rate;
|
||||||
|
uart_config.data_bits = UART_DATA_8_BITS;
|
||||||
|
uart_config.parity = UART_PARITY_DISABLE;
|
||||||
|
uart_config.stop_bits = UART_STOP_BITS_1;
|
||||||
|
uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE;
|
||||||
|
uart_config.source_clk = UART_SCLK_REF_TICK;
|
||||||
|
|
||||||
|
throw_if_esp_fail(uart_param_config(config->vfs_config.port_num, &uart_config), "config uart parameter failed");
|
||||||
|
|
||||||
|
throw_if_esp_fail(uart_set_pin(config->vfs_config.port_num, config->vfs_config.tx_io_num, config->vfs_config.rx_io_num,
|
||||||
|
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE), "config uart gpio failed");
|
||||||
|
|
||||||
|
throw_if_esp_fail(uart_driver_install(config->vfs_config.port_num, config->vfs_config.rx_buffer_size, config->vfs_config.tx_buffer_size,
|
||||||
|
0, nullptr, 0), "install uart driver failed");
|
||||||
|
|
||||||
|
throw_if_esp_fail(uart_set_rx_timeout(config->vfs_config.port_num, 1), "set rx timeout failed");
|
||||||
|
|
||||||
|
throw_if_esp_fail(uart_set_rx_full_threshold(config->uart_config.port_num, 64), "config rx full threshold failed");
|
||||||
|
|
||||||
|
/* mark UART as initialized */
|
||||||
|
port = config->vfs_config.port_num;
|
||||||
|
|
||||||
|
fd = open(config->vfs_config.dev_name, O_RDWR);
|
||||||
|
|
||||||
|
throw_if_false(fd >= 0, "Cannot open the fd");
|
||||||
|
}
|
||||||
|
|
||||||
|
class vfs_terminal : public Terminal {
|
||||||
|
public:
|
||||||
|
explicit vfs_terminal(const esp_modem_dte_config *config) :
|
||||||
|
uart(config), signal(),
|
||||||
|
task_handle(config->vfs_config.task_stack_size, config->vfs_config.task_prio, this, s_task) {}
|
||||||
|
|
||||||
|
~vfs_terminal() override = default;
|
||||||
|
|
||||||
|
void start() override {
|
||||||
|
signal.set(TASK_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop() override {
|
||||||
|
signal.set(TASK_STOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
int write(uint8_t *data, size_t len) override;
|
||||||
|
|
||||||
|
int read(uint8_t *data, size_t len) override;
|
||||||
|
|
||||||
|
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override {
|
||||||
|
on_data = std::move(f);
|
||||||
|
signal.set(TASK_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void s_task(void *task_param) {
|
||||||
|
auto t = static_cast<vfs_terminal *>(task_param);
|
||||||
|
t->task();
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void task();
|
||||||
|
|
||||||
|
static const size_t TASK_INIT = BIT0;
|
||||||
|
static const size_t TASK_START = BIT1;
|
||||||
|
static const size_t TASK_STOP = BIT2;
|
||||||
|
static const size_t TASK_PARAMS = BIT3;
|
||||||
|
|
||||||
|
uart_resource uart;
|
||||||
|
signal_group signal;
|
||||||
|
vfs_task task_handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<Terminal> create_vfs_terminal(const esp_modem_dte_config *config) {
|
||||||
|
TRY_CATCH_RET_NULL(
|
||||||
|
auto term = std::make_unique<vfs_terminal>(config);
|
||||||
|
term->start();
|
||||||
|
return term;
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
void vfs_terminal::task() {
|
||||||
|
std::function<bool(uint8_t *data, size_t len)> on_data_priv = nullptr;
|
||||||
|
size_t len;
|
||||||
|
signal.set(TASK_INIT);
|
||||||
|
signal.wait_any(TASK_START | TASK_STOP, portMAX_DELAY);
|
||||||
|
if (signal.is_any(TASK_STOP)) {
|
||||||
|
return; // exits to the static method where the task gets deleted
|
||||||
|
}
|
||||||
|
esp_vfs_dev_uart_use_driver(uart.port);
|
||||||
|
|
||||||
|
while (signal.is_any(TASK_START)) {
|
||||||
|
int s;
|
||||||
|
fd_set rfds;
|
||||||
|
struct timeval tv = {
|
||||||
|
.tv_sec = 5,
|
||||||
|
.tv_usec = 0,
|
||||||
|
};
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(uart.fd, &rfds);
|
||||||
|
|
||||||
|
s = select(uart.fd + 1, &rfds, NULL, NULL, &tv);
|
||||||
|
// if (signal.is_any(TASK_PARAMS)) {
|
||||||
|
on_data_priv = on_data;
|
||||||
|
// signal.clear(TASK_PARAMS);
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (s < 0) {
|
||||||
|
ESP_LOGE(TAG, "Select failed: errno %d", errno);
|
||||||
|
break;
|
||||||
|
} else if (s == 0) {
|
||||||
|
ESP_LOGI(TAG, "Timeout has been reached and nothing has been received");
|
||||||
|
} else {
|
||||||
|
if (FD_ISSET(uart.fd, &rfds)) {
|
||||||
|
uart_get_buffered_data_len(uart.port, &len);
|
||||||
|
if (len && on_data_priv) {
|
||||||
|
if (on_data_priv(nullptr, len)) {
|
||||||
|
on_data_priv = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vTaskDelay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vfs_terminal::read(uint8_t *data, size_t len) {
|
||||||
|
return ::read(uart.fd, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vfs_terminal::write(uint8_t *data, size_t len) {
|
||||||
|
return ::write(uart.fd, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace esp_modem
|
||||||
|
|
@ -97,14 +97,15 @@ uart_resource::uart_resource(const esp_modem_dte_config *config) :
|
|||||||
res = uart_set_sw_flow_ctrl(config->uart_config.port_num, true, 8, UART_FIFO_LEN - 8);
|
res = uart_set_sw_flow_ctrl(config->uart_config.port_num, true, 8, UART_FIFO_LEN - 8);
|
||||||
}
|
}
|
||||||
throw_if_esp_fail(res, "config uart flow control failed");
|
throw_if_esp_fail(res, "config uart flow control failed");
|
||||||
|
|
||||||
/* Install UART driver and get event queue used inside driver */
|
/* Install UART driver and get event queue used inside driver */
|
||||||
res = uart_driver_install(config->uart_config.port_num, config->uart_config.rx_buffer_size, config->uart_config.tx_buffer_size,
|
res = uart_driver_install(config->uart_config.port_num, config->uart_config.rx_buffer_size, config->uart_config.tx_buffer_size,
|
||||||
config->uart_config.event_queue_size, &(event_queue), 0);
|
config->uart_config.event_queue_size, &(event_queue), 0);
|
||||||
throw_if_esp_fail(res, "install uart driver failed");
|
throw_if_esp_fail(res, "install uart driver failed");
|
||||||
throw_if_esp_fail(uart_set_rx_timeout(config->uart_config.port_num, 1), "set rx timeout failed");
|
throw_if_esp_fail(uart_set_rx_timeout(config->uart_config.port_num, 1), "set rx timeout failed");
|
||||||
|
|
||||||
uart_set_rx_full_threshold(config->uart_config.port_num, 64);
|
throw_if_esp_fail(uart_set_rx_full_threshold(config->uart_config.port_num, 64), "config rx full threshold failed");
|
||||||
throw_if_esp_fail(res, "config uart pattern failed");
|
|
||||||
/* mark UART as initialized */
|
/* mark UART as initialized */
|
||||||
port = config->uart_config.port_num;
|
port = config->uart_config.port_num;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user