From 59c38373458305be61df5d5b7722d6f2a5c543ed Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 17 May 2021 14:59:03 +0200 Subject: [PATCH] VFS Terminal cleanup --- .../examples/linux_modem/main/modem_main.cpp | 3 + .../simple_cxx_client/main/simple_client.cpp | 42 ++++---- esp_modem/include/esp_modem_config.h | 46 ++++---- esp_modem/private_include/vfs_termial.hpp | 4 +- esp_modem/src/esp_modem_api.cpp | 2 +- esp_modem/src/esp_modem_cmux.cpp | 85 +++++++-------- esp_modem/src/esp_modem_command_library.cpp | 50 +++++++-- esp_modem/src/esp_modem_dte.cpp | 7 +- esp_modem/src/esp_modem_term_fs.cpp | 93 +++++++++------- esp_modem/src/esp_modem_term_uart.cpp | 99 ++++++++--------- esp_modem/src/esp_modem_uart.cpp | 101 +++++------------- 11 files changed, 268 insertions(+), 264 deletions(-) diff --git a/esp_modem/examples/linux_modem/main/modem_main.cpp b/esp_modem/examples/linux_modem/main/modem_main.cpp index 90868b1d6..456bb6469 100644 --- a/esp_modem/examples/linux_modem/main/modem_main.cpp +++ b/esp_modem/examples/linux_modem/main/modem_main.cpp @@ -19,6 +19,9 @@ int main() // init the DTE esp_modem_dte_config_t dte_config = { .dte_buffer_size = 512, + .task_stack_size = 1024, + .task_priority = 10, + .uart_config = { }, .vfs_config = { } }; dte_config.vfs_config.dev_name = "/dev/ttyUSB0"; diff --git a/esp_modem/examples/simple_cxx_client/main/simple_client.cpp b/esp_modem/examples/simple_cxx_client/main/simple_client.cpp index 6c65760da..da3d71f56 100644 --- a/esp_modem/examples/simple_cxx_client/main/simple_client.cpp +++ b/esp_modem/examples/simple_cxx_client/main/simple_client.cpp @@ -18,7 +18,7 @@ #include "cxx_include/esp_modem_api.hpp" #include #include "esp_https_ota.h" -#include "esp_app_trace.h" +#include "esp_vfs_dev.h" #define BROKER_URL "mqtt://mqtt.eclipseprojects.io" @@ -130,18 +130,22 @@ extern "C" void app_main(void) /* Configure the DTE */ esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG(); - esp_modem_dte_config_t dte_config2 = { - .dte_buffer_size = 512, - .vfs_config = {.port_num = UART_NUM_1, - .dev_name = "/dev/uart/1", - .rx_buffer_size = 1024, - .tx_buffer_size = 512, - .baud_rate = 115200, - .tx_io_num = 25, - .rx_io_num = 26, - .task_stack_size = 4096, - .task_prio = 5} - }; +// dte_config.task_stack_size = 8192; + dte_config.vfs_config.dev_name = "/dev/uart/1"; + dte_config.uart_config.event_queue_size = 0; + +// esp_modem_dte_config_t dte_config2 = { +// .dte_buffer_size = 512, +// .vfs_config = {.port_num = UART_NUM_1, +// .dev_name = "/dev/uart/1", +// .rx_buffer_size = 1024, +// .tx_buffer_size = 512, +// .baud_rate = 115200, +// .tx_io_num = 25, +// .rx_io_num = 26, +// .task_stack_size = 4096, +// .task_prio = 5} +// }; /* Configure the DCE */ esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_EXAMPLE_MODEM_PPP_APN); @@ -149,13 +153,11 @@ extern "C" void app_main(void) /* Configure the PPP netif */ esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP(); - dte_config.dte_buffer_size = 512; - dte_config.uart_config.port_num = UART_NUM_2; - auto uart_dte = create_uart_dte(&dte_config); - - - -// auto uart_dte = create_vfs_dte(&dte_config2); +// dte_config.dte_buffer_size = 512; +// dte_config.uart_config.port_num = UART_NUM_2; +// auto uart_dte = create_uart_dte(&dte_config); + auto uart_dte = create_vfs_dte(&dte_config); + esp_vfs_dev_uart_use_driver(dte_config.uart_config.port_num); esp_netif_t *esp_netif = esp_netif_new(&netif_ppp_config); assert(esp_netif); diff --git a/esp_modem/include/esp_modem_config.h b/esp_modem/include/esp_modem_config.h index e510a8ca3..a3fa3923c 100644 --- a/esp_modem/include/esp_modem_config.h +++ b/esp_modem/include/esp_modem_config.h @@ -53,29 +53,30 @@ struct esp_modem_uart_term_config { int cts_io_num; /*!< CTS Pin Number */ int rx_buffer_size; /*!< UART RX Buffer Size */ int tx_buffer_size; /*!< UART TX Buffer Size */ - int event_queue_size; /*!< UART Event Queue Size */ - uint32_t event_task_stack_size; /*!< UART Event Task Stack size */ - int event_task_priority; /*!< UART Event Task Priority */ + int event_queue_size; /*!< UART Event Queue Size, set to 0 if no event queue needed */ }; +/** + * @brief Resources used by VFS terminal + * + */ +typedef enum { + ESP_MODEM_VFS_IS_EXTERN = 0, /*!< External resource: internal VFS terminal takes no action to setup this */ + ESP_MODEM_VFS_IS_UART, /*!< VFS uses UART: internal VFS initializes UART based on esp_modem_uart_term_config */ +} esp_modem_vfs_resource_t; + + 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; + const char* dev_name; /*!< VFS device name, e.g. /dev/uart/n */ + esp_modem_vfs_resource_t resource; /*!< Underlying device which gets initialized during VFS init */ }; struct esp_modem_dte_config { - size_t dte_buffer_size; - union { - struct esp_modem_uart_term_config uart_config; - struct esp_modem_vfs_term_config vfs_config; - }; + size_t dte_buffer_size; /*!< DTE buffer size */ + uint32_t task_stack_size; /*!< Terminal task stack size */ + int task_priority; /*!< Terminal task priority */ + struct esp_modem_uart_term_config uart_config; /*!< Configuration for UART Terminal */ + struct esp_modem_vfs_term_config vfs_config; /*!< Configuration for VFS Terminal */ }; @@ -86,7 +87,9 @@ struct esp_modem_dte_config { #define ESP_MODEM_DTE_DEFAULT_CONFIG() \ { \ .dte_buffer_size = 512, \ - .uart_config = { \ + .task_stack_size = 4096, \ + .task_priority = 5, \ + .uart_config = { \ .port_num = UART_NUM_1, \ .data_bits = UART_DATA_8_BITS, \ .stop_bits = UART_STOP_BITS_1, \ @@ -100,9 +103,10 @@ struct esp_modem_dte_config { .rx_buffer_size = 4096, \ .tx_buffer_size = 512, \ .event_queue_size = 30, \ - .event_task_stack_size = 4096, \ - .event_task_priority = 20, \ - } \ + }, \ + .vfs_config = { \ + .dev_name = "/null", \ + }\ } typedef struct esp_modem_dte_config esp_modem_dte_config_t; diff --git a/esp_modem/private_include/vfs_termial.hpp b/esp_modem/private_include/vfs_termial.hpp index ac29ebc92..85d30bf77 100644 --- a/esp_modem/private_include/vfs_termial.hpp +++ b/esp_modem/private_include/vfs_termial.hpp @@ -19,10 +19,10 @@ struct esp_modem_dte_config; -namespace esp_modem::terminal { +namespace esp_modem { std::unique_ptr create_vfs_terminal(const esp_modem_dte_config *config); -} // namespace esp_modem::terminal +} // namespace esp_modem #endif // _VFS_TERMINAL_HPP_ diff --git a/esp_modem/src/esp_modem_api.cpp b/esp_modem/src/esp_modem_api.cpp index fb86f37d6..2ed69ce89 100644 --- a/esp_modem/src/esp_modem_api.cpp +++ b/esp_modem/src/esp_modem_api.cpp @@ -39,7 +39,7 @@ std::shared_ptr create_uart_dte(const dte_config *config) { std::shared_ptr create_vfs_dte(const dte_config *config) { TRY_CATCH_RET_NULL( - auto term = terminal::create_vfs_terminal(config); + auto term = create_vfs_terminal(config); return std::make_shared(config, std::move(term)); ) } diff --git a/esp_modem/src/esp_modem_cmux.cpp b/esp_modem/src/esp_modem_cmux.cpp index 6a80d9137..efb77381f 100644 --- a/esp_modem/src/esp_modem_cmux.cpp +++ b/esp_modem/src/esp_modem_cmux.cpp @@ -15,12 +15,18 @@ #include #include #include -//#include "esp_app_trace.h" #include "cxx_include/esp_modem_dte.hpp" #include "esp_log.h" using namespace esp_modem; +/** + * @brief Define this to defragment partially received data of CMUX payload + * This is useful if upper layers expect the entire payload available + * for parsing. + */ +#define DEFRAGMENT_CMUX_PAYLOAD + #define EA 0x01 /* Extension bit */ #define CR 0x02 /* Command / Response */ #define PF 0x10 /* Poll / Final */ @@ -72,11 +78,11 @@ uint8_t CMux::fcs_crc(const uint8_t frame[6]) return crc; } -void CMux::send_sabm(size_t dlci) +void CMux::send_sabm(size_t i) { uint8_t frame[6]; frame[0] = SOF_MARKER; - frame[1] = (dlci << 2) | 0x3; + frame[1] = (i << 2) | 0x3; frame[2] = FT_SABM | PF; frame[3] = 1; frame[4] = 0xFF - fcs_crc(frame); @@ -90,14 +96,16 @@ void CMux::data_available(uint8_t *data, size_t len) if (data && type == 0xFF && len > 0 && dlci > 0) { int virtual_term = dlci - 1; if (virtual_term < max_terms && read_cb[virtual_term]) { -// if (payload_start == nullptr) { -// payload_start = data; -// total_payload_size = 0; -// } -// total_payload_size += len; - // Post partial data (if configured) + // Post partial data (or defragment to post on CMUX footer) +#ifdef DEFRAGMENT_CMUX_PAYLOAD + if (payload_start == nullptr) { + payload_start = data; + total_payload_size = 0; + } + total_payload_size += len; +#else read_cb[virtual_term](data, len); - +#endif } } else if (data == nullptr && type == 0x73 && len == 0) { // notify the initial SABM command Scoped l(lock); @@ -105,7 +113,9 @@ void CMux::data_available(uint8_t *data, size_t len) } else if (data == nullptr) { int virtual_term = dlci - 1; if (virtual_term < max_terms && read_cb[virtual_term]) { -// read_cb[virtual_term](payload_start, total_payload_size); +#ifdef DEFRAGMENT_CMUX_PAYLOAD + read_cb[virtual_term](payload_start, total_payload_size); +#endif } } @@ -114,7 +124,8 @@ void CMux::data_available(uint8_t *data, size_t len) bool CMux::on_cmux(uint8_t *data, size_t actual_len) { if (!data) { - auto data_to_read = buffer_size - 155; +#ifdef DEFRAGMENT_CMUX_PAYLOAD + auto data_to_read = buffer_size - 128; // keep 128 (max CMUX payload) backup buffer) if (payload_start) { data = payload_start + total_payload_size; data_to_read = payload_len + 2; @@ -122,27 +133,12 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len) data = buffer.get(); } actual_len = term->read(data, data_to_read); -// ESP_LOGE("Received", "data_to_read=%d, actual_len=%d, total_payload=%d", data_to_read, actual_len, total_payload_size); - } -#if 0 - if (0){ - static char buf[8*1024]; - for (int i=0; iread(data, buffer_size); #endif -// printf("my_data[%d] = { ", actual_len); -// for (int i=0; i 1 && frame[1] == SOF_MARKER) { // empty frame available_len -= 1; @@ -173,7 +169,7 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len) return false; case cmux_state::INIT: if (frame[0] != SOF_MARKER) { - ESP_LOGE("CMUX", "Protocol mismatch!"); + ESP_LOGW("CMUX", "Protocol mismatch: Missed leading SOF, recovering..."); state = cmux_state::RECOVER; break; } @@ -211,7 +207,7 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len) state = cmux_state::PAYLOAD; break; case cmux_state::PAYLOAD: - ESP_LOGI("CMUX", "CMUX FR: A:%02x T:%02x L:%d available: %d", dlci, type, payload_len, available_len); + ESP_LOGD("CMUX", "Payload frame: dlci:%02x type:%02x payload:%d available:%d", dlci, type, payload_len, available_len); if (available_len < payload_len) { // payload state = cmux_state::PAYLOAD; data_available(frame, available_len); // partial read @@ -236,17 +232,18 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len) footer_offset = std::min(available_len, 6 - frame_header_offset); memcpy(frame_header + frame_header_offset, frame, footer_offset); if (frame_header[5] != SOF_MARKER) { - ESP_LOGE("CMUX-Footer", "Protocol mismatch! total pyaload: %d", total_payload_size); - ESP_LOG_BUFFER_HEXDUMP("Data-valid", payload_start, total_payload_size, ESP_LOG_INFO); - ESP_LOG_BUFFER_HEXDUMP("Footer", frame-8, 16, ESP_LOG_ERROR); - while(1) { usleep(10000); }; - abort(); + ESP_LOGW("CMUX", "Protocol mismatch: Missed trailing SOF, recovering..."); + payload_start = nullptr; + total_payload_size = 0; + +// ESP_LOGE("CMUX-Footer", "Protocol mismatch! total pyaload: %d", total_payload_size); +// ESP_LOG_BUFFER_HEXDUMP("Data-valid", payload_start, total_payload_size, ESP_LOG_INFO); +// ESP_LOG_BUFFER_HEXDUMP("Footer", frame-8, 16, ESP_LOG_ERROR); +// while(1) { usleep(10000); }; +// abort(); state = cmux_state::RECOVER; break; } -// if (payload_len == 0) { -// data_available(frame_header, 0); // Null payload -// } frame += footer_offset; available_len -= footer_offset; state = cmux_state::INIT; @@ -275,7 +272,7 @@ bool CMux::init() { int timeout = 0; send_sabm(i); - while (1) { + while (true) { usleep(10'000); Scoped l(lock); if (sabm_ack == i) { diff --git a/esp_modem/src/esp_modem_command_library.cpp b/esp_modem/src/esp_modem_command_library.cpp index 491714a62..9e9785c98 100644 --- a/esp_modem/src/esp_modem_command_library.cpp +++ b/esp_modem/src/esp_modem_command_library.cpp @@ -19,22 +19,25 @@ #include "cxx_include/esp_modem_dce_module.hpp" #include "cxx_include/esp_modem_command_library.hpp" - namespace esp_modem::dce_commands { +static const char *TAG = "command_lib"; + command_result generic_command(CommandableIf* t, const std::string &command, const std::list& pass_phrase, const std::list& fail_phrase, uint32_t timeout_ms) { - printf("Command %s\n", command.c_str()); + ESP_LOGI(TAG, "%s command %s\n", __func__, command.c_str()); return t->command(command, [&](uint8_t *data, size_t len) { std::string_view response((char*)data, len); - printf("Response: %.*s\n", (int)response.length(), response.data()); - for (auto it : pass_phrase) + if (data == nullptr || len == 0 || response.empty()) + return command_result::TIMEOUT; + ESP_LOGI(TAG, "Response: %.*s\n", (int)response.length(), response.data()); + for (auto &it : pass_phrase) if (response.find(it) != std::string::npos) return command_result::OK; - for (auto it : fail_phrase) + for (auto &it : fail_phrase) if (response.find(it) != std::string::npos) return command_result::FAIL; return command_result::TIMEOUT; @@ -46,6 +49,7 @@ static inline command_result generic_command(CommandableIf* t, const std::string const std::string& pass_phrase, const std::string& fail_phrase, uint32_t timeout_ms) { + ESP_LOGV(TAG,"%s", __func__ ); const auto pass = std::list({pass_phrase}); const auto fail = std::list({fail_phrase}); return generic_command(t, command, pass, fail, timeout_ms); @@ -53,6 +57,7 @@ static inline command_result generic_command(CommandableIf* t, const std::string static inline command_result generic_get_string(CommandableIf* t, const std::string& command, std::string_view& output, uint32_t timeout_ms = 500) { + ESP_LOGV(TAG,"%s", __func__ ); return t->command(command, [&](uint8_t *data, size_t len) { size_t pos = 0; std::string_view response((char*)data, len); @@ -61,7 +66,7 @@ static inline command_result generic_get_string(CommandableIf* t, const std::str for (auto it = token.end() - 1; it > token.begin(); it--) // strip trailing CR or LF if (*it == '\r' || *it == '\n') token.remove_suffix(1); - printf("{%.*s}\n", static_cast(token.size()), token.data()); + ESP_LOGV(TAG, "Token: {%.*s}\n", static_cast(token.size()), token.data()); if (token.find("OK") != std::string::npos) { return command_result::OK; @@ -78,6 +83,7 @@ static inline command_result generic_get_string(CommandableIf* t, const std::str static inline command_result generic_get_string(CommandableIf* t, const std::string& command, std::string& output, uint32_t timeout_ms = 500) { + ESP_LOGV(TAG,"%s", __func__ ); std::string_view out; auto ret = generic_get_string(t, command, out, timeout_ms); if (ret == command_result::OK) @@ -88,51 +94,61 @@ static inline command_result generic_get_string(CommandableIf* t, const std::str static inline command_result generic_command_common(CommandableIf* t, const std::string &command, uint32_t timeout = 500) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_command(t, command, "OK", "ERROR", timeout); } command_result sync(CommandableIf* t) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_command_common(t, "AT\r"); } command_result store_profile(CommandableIf* t) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_command_common(t, "AT&W\r"); } command_result power_down(CommandableIf* t) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_command(t, "AT+QPOWD=1\r", "POWERED DOWN", "ERROR", 1000); } command_result power_down_sim7xxx(CommandableIf* t) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_command_common(t, "AT+CPOF\r", 1000); } command_result power_down_sim8xx(CommandableIf* t) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_command(t, "AT+CPOWD=1\r", "POWER DOWN", "ERROR", 1000); } command_result reset(CommandableIf* t) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_command(t, "AT+CRESET\r", "PB DONE", "ERROR", 60000); } command_result set_baud(CommandableIf* t, int baud) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_command_common(t, "AT+IPR=" + std::to_string(baud) + "\r"); } command_result hang_up(CommandableIf* t) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_command_common(t, "ATH\r", 90000); } command_result get_battery_status(CommandableIf* t, int& voltage, int &bcs, int &bcl) { + ESP_LOGV(TAG,"%s", __func__ ); std::string_view out; auto ret = generic_get_string(t, "AT+CBC\r", out); if (ret != command_result::OK) @@ -164,6 +180,7 @@ command_result get_battery_status(CommandableIf* t, int& voltage, int &bcs, int command_result get_battery_status_sim7xxx(CommandableIf* t, int& voltage, int &bcs, int &bcl) { + ESP_LOGV(TAG,"%s", __func__ ); std::string_view out; auto ret = generic_get_string(t, "AT+CBC\r", out); if (ret != command_result::OK) @@ -188,11 +205,13 @@ command_result get_battery_status_sim7xxx(CommandableIf* t, int& voltage, int &b command_result set_flow_control(CommandableIf* t, int dce_flow, int dte_flow) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_command_common(t, "AT+IFC=" + std::to_string(dce_flow) + ", " + std::to_string(dte_flow) + "\r"); } command_result get_operator_name(CommandableIf* t, std::string& operator_name) { + ESP_LOGV(TAG,"%s", __func__ ); std::string_view out; auto ret = generic_get_string(t, "AT+COPS?\r", out, 75000); if (ret != command_result::OK) @@ -212,6 +231,7 @@ command_result get_operator_name(CommandableIf* t, std::string& operator_name) command_result set_echo(CommandableIf* t, bool on) { + ESP_LOGV(TAG,"%s", __func__ ); if (on) return generic_command_common(t, "ATE1\r"); return generic_command_common(t, "ATE0\r"); @@ -219,6 +239,7 @@ command_result set_echo(CommandableIf* t, bool on) command_result set_pdp_context(CommandableIf* t, PdpContext& pdp) { + ESP_LOGV(TAG,"%s", __func__ ); std::string pdp_command = "AT+CGDCONT=" + std::to_string(pdp.context_id) + ",\"" + pdp.protocol_type + "\",\"" + pdp.apn + "\"\r"; return generic_command_common(t, pdp_command); @@ -226,21 +247,25 @@ command_result set_pdp_context(CommandableIf* t, PdpContext& pdp) command_result set_data_mode(CommandableIf* t) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_command(t, "ATD*99##\r", "CONNECT", "ERROR", 5000); } command_result set_data_mode_sim8xx(CommandableIf* t) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_command(t, "ATD*99##\r", "CONNECT", "ERROR", 5000); } command_result resume_data_mode(CommandableIf* t) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_command(t, "ATO\r", "CONNECT", "ERROR", 5000); } command_result set_command_mode(CommandableIf* t) { + ESP_LOGV(TAG,"%s", __func__ ); const auto pass = std::list({"NO CARRIER", "OK"}); const auto fail = std::list({"ERROR"}); return generic_command(t, "+++", pass, fail, 5000); @@ -248,21 +273,25 @@ command_result set_command_mode(CommandableIf* t) command_result get_imsi(CommandableIf* t, std::string& imsi_number) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_get_string(t, "AT+CIMI\r", imsi_number, 5000); } command_result get_imei(CommandableIf* t, std::string& out) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_get_string(t, "AT+CGSN\r", out, 5000); } command_result get_module_name(CommandableIf* t, std::string& out) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_get_string(t, "AT+CGMM\r", out, 5000); } command_result sms_txt_mode(CommandableIf* t, bool txt = true) { + ESP_LOGV(TAG,"%s", __func__ ); if (txt) return generic_command_common(t, "AT+CMGF=1\r"); // Text mode (default) return generic_command_common(t, "AT+CMGF=0\r"); // PDU mode @@ -271,14 +300,16 @@ command_result sms_txt_mode(CommandableIf* t, bool txt = true) command_result sms_character_set(CommandableIf* t) { // Sets the default GSM character set + ESP_LOGV(TAG,"%s", __func__ ); return generic_command_common(t, "AT+CSCS=\"GSM\"\r"); } command_result send_sms(CommandableIf* t, const std::string& number, const std::string& message) { + ESP_LOGV(TAG,"%s", __func__ ); auto ret = t->command("AT+CMGS=\"" + number + "\"\r", [&](uint8_t *data, size_t len) { std::string_view response((char*)data, len); - printf("%.*s", static_cast(response.size()), response.data()); + ESP_LOGD(TAG,"Send SMS response %.*s", static_cast(response.size()), response.data()); if (response.find('>') != std::string::npos) { return command_result::OK; } @@ -292,11 +323,13 @@ command_result send_sms(CommandableIf* t, const std::string& number, const std:: command_result set_cmux(CommandableIf* t) { + ESP_LOGV(TAG,"%s", __func__ ); return generic_command_common(t, "AT+CMUX=0\r"); } command_result read_pin(CommandableIf* t, bool& pin_ok) { + ESP_LOGV(TAG,"%s", __func__ ); std::string_view out; auto ret = generic_get_string(t, "AT+CPIN?\r", out); if (ret != command_result::OK) @@ -316,13 +349,14 @@ command_result read_pin(CommandableIf* t, bool& pin_ok) command_result set_pin(CommandableIf* t, const std::string& pin) { + ESP_LOGV(TAG,"%s", __func__ ); std::string set_pin_command = "AT+CPIN=" + pin + "\r"; return generic_command_common(t, set_pin_command); } command_result get_signal_quality(CommandableIf* t, int &rssi, int &ber) { - printf("%s", __func__ ); + ESP_LOGV(TAG,"%s", __func__ ); std::string_view out; auto ret = generic_get_string(t, "AT+CSQ\r", out); if (ret != command_result::OK) diff --git a/esp_modem/src/esp_modem_dte.cpp b/esp_modem/src/esp_modem_dte.cpp index 2e595be65..ab4b9c7ea 100644 --- a/esp_modem/src/esp_modem_dte.cpp +++ b/esp_modem/src/esp_modem_dte.cpp @@ -39,13 +39,11 @@ command_result DTE::command(const std::string &command, got_line_cb got_line, ui command_result res = command_result::TIMEOUT; command_term->set_read_cb([&](uint8_t *data, size_t len) { if (!data) { - data = buffer.get(); // + consumed; + data = buffer.get(); len = command_term->read(data + consumed, buffer_size - consumed); } else { - consumed = 0; + consumed = 0; // if the underlying terminal contains data, we cannot fragment } -// ESP_LOGD("CMD_read!", "-----"); -// for (int i=0; istart(); mode = m; if (m == modem_mode::DATA_MODE) { term->set_read_cb(on_data); diff --git a/esp_modem/src/esp_modem_term_fs.cpp b/esp_modem/src/esp_modem_term_fs.cpp index 1d32c5842..dea8777e0 100644 --- a/esp_modem/src/esp_modem_term_fs.cpp +++ b/esp_modem/src/esp_modem_term_fs.cpp @@ -12,40 +12,31 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include #include #include #include "cxx_include/esp_modem_dte.hpp" #include "esp_log.h" -#include "driver/uart.h" #include "esp_modem_config.h" #include "exception_stub.hpp" +#include "uart_resource.hpp" // In case of VFS using UART static const char *TAG = "fs_terminal"; -namespace esp_modem::terminal { +namespace esp_modem { -struct uart_resource { - explicit uart_resource(const esp_modem_dte_config *config); - ~uart_resource(); - uart_port_t port; - int fd; +class Resource { +public: + Resource(const esp_modem_dte_config *config); + + std::optional uart; }; - - -class vfs_terminal : public Terminal { +class FdTerminal : 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, [](void* p){ - auto t = static_cast(p); - t->task(); - Task::Delete(); - }) {} + explicit FdTerminal(const esp_modem_dte_config *config); - ~vfs_terminal() override { - stop(); - } + ~FdTerminal() override; void start() override { signal.set(TASK_START); @@ -74,28 +65,45 @@ private: uart_resource uart; SignalGroup signal; + int fd; Task task_handle; }; std::unique_ptr create_vfs_terminal(const esp_modem_dte_config *config) { TRY_CATCH_RET_NULL( - auto term = std::make_unique(config); + auto term = std::make_unique(config); term->start(); return term; ) } -void vfs_terminal::task() { +FdTerminal::FdTerminal(const esp_modem_dte_config *config) : + uart(config, nullptr), signal(), fd(-1), + task_handle(config->task_stack_size, config->task_priority, this, [](void* p){ + auto t = static_cast(p); + t->task(); + Task::Delete(); + if (t->fd >= 0) { + close(t->fd); + } + }) +{ + fd = open(config->vfs_config.dev_name, O_RDWR); + throw_if_false(fd >= 0, "Cannot open the fd"); +} + +void FdTerminal::task() +{ std::function 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); - int flags = fcntl(uart.fd, F_GETFL, NULL) | O_NONBLOCK; - fcntl(uart.fd, F_SETFL, flags); + + // Set the FD to non-blocking mode + int flags = fcntl(fd, F_GETFL, nullptr) | O_NONBLOCK; + fcntl(fd, F_SETFL, flags); while (signal.is_any(TASK_START)) { int s; @@ -105,9 +113,9 @@ void vfs_terminal::task() { .tv_usec = 0, }; FD_ZERO(&rfds); - FD_SET(uart.fd, &rfds); + FD_SET(fd, &rfds); - s = select(uart.fd + 1, &rfds, NULL, NULL, &tv); + s = select(fd + 1, &rfds, nullptr, nullptr, &tv); if (signal.is_any(TASK_PARAMS)) { on_data_priv = on_data; signal.clear(TASK_PARAMS); @@ -116,11 +124,9 @@ void vfs_terminal::task() { if (s < 0) { break; } else if (s == 0) { -// ESP_LOGV(TAG, "Select exitted with timeout"); +// ESP_LOGV(TAG, "Select exited with timeout"); } else { - if (FD_ISSET(uart.fd, &rfds)) { -// ESP_LOGV(TAG, "FD is readable"); -// uart_get_buffered_data_len(uart.port, &len); + if (FD_ISSET(fd, &rfds)) { if (on_data_priv) { if (on_data_priv(nullptr, 0)) { on_data_priv = nullptr; @@ -132,23 +138,32 @@ void vfs_terminal::task() { } } -int vfs_terminal::read(uint8_t *data, size_t len) +int FdTerminal::read(uint8_t *data, size_t len) { - int size = ::read(uart.fd, data, len); -// for (int i=0; i - - -static const char *TAG = "uart_terminal"; - -namespace esp_modem::terminal { +namespace esp_modem { struct uart_resource { - explicit uart_resource(const esp_modem_dte_config *config); + explicit uart_resource(const esp_modem_dte_config *config, struct QueueDefinition** event_queue); ~uart_resource(); uart_port_t port; - int fd; }; -uart_resource::uart_resource(const esp_modem_dte_config *config) : - port(-1), fd(-1) +uart_resource::~uart_resource() { - /* 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; - esp_vfs_dev_uart_use_driver(port); - - fd = open(config->vfs_config.dev_name, O_RDWR); - - throw_if_false(fd >= 0, "Cannot open the fd"); -} - -uart_resource::~uart_resource() { if (port >= UART_NUM_0 && port < UART_NUM_MAX) { uart_driver_delete(port); } - } -} // namespace esp_modem::terminal +uart_resource::uart_resource(const esp_modem_dte_config *config, struct QueueDefinition** event_queue) : + port(-1) +{ + esp_err_t res; + + /* Config UART */ + uart_config_t uart_config = {}; + uart_config.baud_rate = config->uart_config.baud_rate; + uart_config.data_bits = config->uart_config.data_bits; + uart_config.parity = config->uart_config.parity; + uart_config.stop_bits = config->uart_config.stop_bits; + uart_config.flow_ctrl = (config->uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) ? UART_HW_FLOWCTRL_CTS_RTS + : UART_HW_FLOWCTRL_DISABLE; + uart_config.source_clk = UART_SCLK_APB; + + throw_if_esp_fail(uart_param_config(config->uart_config.port_num, &uart_config), "config uart parameter failed"); + + if (config->uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) { + res = uart_set_pin(config->uart_config.port_num, config->uart_config.tx_io_num, config->uart_config.rx_io_num, + config->uart_config.rts_io_num, config->uart_config.cts_io_num); + } else { + res = uart_set_pin(config->uart_config.port_num, config->uart_config.tx_io_num, config->uart_config.rx_io_num, + UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); + } + throw_if_esp_fail(res, "config uart gpio failed"); + /* Set flow control threshold */ + if (config->uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) { + res = uart_set_hw_flow_ctrl(config->uart_config.port_num, UART_HW_FLOWCTRL_CTS_RTS, UART_FIFO_LEN - 8); + } else if (config->uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_SW) { + 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"); + + /* 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, + config->uart_config.event_queue_size, config->uart_config.event_queue_size ? event_queue : nullptr, + 0); + 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_full_threshold(config->uart_config.port_num, 64), "config rx full threshold failed"); + + /* mark UART as initialized */ + port = config->uart_config.port_num; +} + +} // namespace esp_modem diff --git a/esp_modem/src/esp_modem_uart.cpp b/esp_modem/src/esp_modem_uart.cpp index f6eae2429..7c7872b10 100644 --- a/esp_modem/src/esp_modem_uart.cpp +++ b/esp_modem/src/esp_modem_uart.cpp @@ -25,22 +25,13 @@ static const char *TAG = "uart_terminal"; namespace esp_modem { +/** + * @brief Uart Resource is a platform specific struct which is implemented separately + */ struct uart_resource { - explicit uart_resource(const esp_modem_dte_config *config); - + explicit uart_resource(const esp_modem_dte_config *config, struct QueueDefinition** event_queue); ~uart_resource(); - - bool get_event(uart_event_t &event, uint32_t time_ms) { - return xQueueReceive(event_queue, &event, pdMS_TO_TICKS(time_ms)); - } - - void reset_events() { - uart_flush_input(port); - xQueueReset(event_queue); - } - - uart_port_t port; /*!< UART port */ - QueueHandle_t event_queue; /*!< UART event queue handle */ + uart_port_t port; }; struct uart_task { @@ -57,64 +48,13 @@ struct uart_task { 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); - } -} -uart_resource::uart_resource(const esp_modem_dte_config *config) : - port(-1) -{ - esp_err_t res; - - /* Config UART */ - uart_config_t uart_config = {}; - uart_config.baud_rate = config->uart_config.baud_rate; - uart_config.data_bits = config->uart_config.data_bits; - uart_config.parity = config->uart_config.parity; - uart_config.stop_bits = config->uart_config.stop_bits; - uart_config.flow_ctrl = (config->uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) ? UART_HW_FLOWCTRL_CTS_RTS - : UART_HW_FLOWCTRL_DISABLE; - uart_config.source_clk = UART_SCLK_APB; - - throw_if_esp_fail(uart_param_config(config->uart_config.port_num, &uart_config), "config uart parameter failed"); - - if (config->uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) { - res = uart_set_pin(config->uart_config.port_num, config->uart_config.tx_io_num, config->uart_config.rx_io_num, - config->uart_config.rts_io_num, config->uart_config.cts_io_num); - } else { - res = uart_set_pin(config->uart_config.port_num, config->uart_config.tx_io_num, config->uart_config.rx_io_num, - UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); - } - throw_if_esp_fail(res, "config uart gpio failed"); - /* Set flow control threshold */ - if (config->uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) { - res = uart_set_hw_flow_ctrl(config->uart_config.port_num, UART_HW_FLOWCTRL_CTS_RTS, UART_FIFO_LEN - 8); - } else if (config->uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_SW) { - 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"); - - /* 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, - config->uart_config.event_queue_size, &(event_queue), 0); - 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_full_threshold(config->uart_config.port_num, 64), "config rx full threshold failed"); - - /* mark UART as initialized */ - port = config->uart_config.port_num; -} - class uart_terminal : public Terminal { public: explicit uart_terminal(const esp_modem_dte_config *config) : - uart(config), signal(), - task_handle(config->uart_config.event_task_stack_size, config->uart_config.event_task_priority, this, s_task) {} + event_queue(), uart(config, &event_queue), signal(), + task_handle(config->task_stack_size, config->task_priority, this, s_task) {} ~uart_terminal() override = default; @@ -139,16 +79,25 @@ private: static void s_task(void *task_param) { auto t = static_cast(task_param); t->task(); - vTaskDelete(NULL); + vTaskDelete(nullptr); } void task(); + bool get_event(uart_event_t &event, uint32_t time_ms) { + return xQueueReceive(event_queue, &event, pdMS_TO_TICKS(time_ms)); + } + + void reset_events() { + uart_flush_input(uart.port); + xQueueReset(event_queue); + } 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; + QueueHandle_t event_queue; uart_resource uart; SignalGroup signal; uart_task task_handle; @@ -172,7 +121,7 @@ void uart_terminal::task() { return; // exits to the static method where the task gets deleted } while (signal.is_any(TASK_START)) { - if (uart.get_event(event, 100)) { + if (get_event(event, 100)) { if (signal.is_any(TASK_PARAMS)) { on_data_priv = on_data; signal.clear(TASK_PARAMS); @@ -190,13 +139,13 @@ void uart_terminal::task() { ESP_LOGW(TAG, "HW FIFO Overflow"); if (on_error) on_error(terminal_error::BUFFER_OVERFLOW); - uart.reset_events(); + reset_events(); break; case UART_BUFFER_FULL: ESP_LOGW(TAG, "Ring Buffer Full"); if (on_error) on_error(terminal_error::BUFFER_OVERFLOW); - uart.reset_events(); + reset_events(); break; case UART_BREAK: ESP_LOGW(TAG, "Rx Break"); @@ -224,11 +173,11 @@ void uart_terminal::task() { int uart_terminal::read(uint8_t *data, size_t len) { size_t length = 0; uart_get_buffered_data_len(uart.port, &length); - if (esp_random() < UINT32_MAX/4 && length > 32) { - printf("ahoj!\n"); - length -= length/4; - } - size_t new_size = length/2; +// if (esp_random() < UINT32_MAX/4 && length > 32) { +// printf("ahoj!\n"); +// length -= length/4; +// } +// size_t new_size = length/2; length = std::min(len, length); if (length > 0) { return uart_read_bytes(uart.port, data, length, portMAX_DELAY);