Corrections on fragmenting/buffering for vfs/cmux

This commit is contained in:
David Cermak
2021-05-13 07:28:05 +02:00
parent 927ad418b6
commit 0d9b5dd8b7
21 changed files with 578 additions and 335 deletions

View File

@ -8,6 +8,7 @@ if(${target} STREQUAL "linux")
else()
set(platform_srcs src/esp_modem_primitives_freertos.cpp
src/esp_modem_uart.cpp
src/esp_modem_term_uart.cpp
src/esp_modem_netif.cpp)
set(dependencies driver)
endif()

View File

@ -47,12 +47,13 @@ extern "C" void app_main(void)
ESP_ERROR_CHECK(esp_event_loop_create_default());
// init the DTE
esp_modem_dte_config_t dte_config = {
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 = 512,
.tx_buffer_size = 512,
.rx_buffer_size = 1024,
.tx_buffer_size = 1024,
.baud_rate = 115200,
.tx_io_num = 25,
.rx_io_num = 26,
@ -64,7 +65,8 @@ extern "C" void app_main(void)
esp_netif_t *esp_netif = esp_netif_new(&ppp_netif_config);
assert(esp_netif);
auto uart_dte = create_vfs_dte(&dte_config);
auto uart_dte = create_vfs_dte(&dte_config2);
// auto uart_dte = create_uart_dte(&dte_config);
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("internet");
@ -192,7 +194,7 @@ extern "C" void app_main(void)
CHECK_ERR(dce->reset(), ESP_LOGI(TAG, "OK"));
});
signal_group exit_signal;
SignalGroup exit_signal;
const ConsoleCommand ExitConsole("exit", "exit the console application", no_args, [&](ConsoleCommand *c){
ESP_LOGI(TAG, "Exiting...");
exit_signal.set(1);

View File

@ -128,6 +128,18 @@ 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 = 512,
.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);
@ -135,7 +147,8 @@ extern "C" void app_main(void)
/* Configure the PPP netif */
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
auto uart_dte = create_uart_dte(&dte_config);
// auto uart_dte = create_uart_dte(&dte_config);
auto uart_dte = create_vfs_dte(&dte_config2);
esp_netif_t *esp_netif = esp_netif_new(&netif_ppp_config);
assert(esp_netif);
@ -160,10 +173,18 @@ extern "C" void app_main(void)
throw_if_false(dce->set_pin(CONFIG_EXAMPLE_SIM_PIN) == command_result::OK, "Cannot set PIN!");
}
vTaskDelay(pdMS_TO_TICKS(1000));
// dce->get_imsi(str);
// std::cout << "Modem IMSI number:" << str << "|" << std::endl;
// std::cout << "|" << str << "|" << std::endl;
dce->set_mode(esp_modem::modem_mode::CMUX_MODE);
dce->get_imsi(str);
std::cout << "Modem IMSI number:" << str << "|" << std::endl;
dce->get_imei(str);
std::cout << "Modem IMEI number:" << str << "|" << std::endl;
dce->get_operator_name(str);
std::cout << "Operator name:" << str << "|" << std::endl;
// return;
dce->set_data();

View File

@ -56,7 +56,7 @@ class CMuxInstance;
class CMux {
public:
explicit CMux(std::unique_ptr<Terminal> t, std::unique_ptr<uint8_t[]> b, size_t buff_size):
term(std::move(t)), buffer_size(buff_size), buffer(std::move(b)) {}
term(std::move(t)), buffer_size(buff_size), buffer(std::move(b)), payload_start(nullptr), total_payload_size(0) {}
~CMux() = default;
[[nodiscard]] bool init();
void set_read_cb(int inst, std::function<bool(uint8_t *data, size_t len)> f);
@ -64,7 +64,7 @@ public:
int write(int i, uint8_t *data, size_t len);
private:
std::function<bool(uint8_t *data, size_t len)> read_cb[max_terms];
void data_available(uint8_t *data, size_t len);
void data_available(uint8_t *data, size_t len, size_t payload_offset);
void send_sabm(size_t i);
std::unique_ptr<Terminal> term;
cmux_state state;
@ -80,6 +80,8 @@ private:
Lock lock;
int instance;
int sabm_ack;
uint8_t *payload_start;
size_t total_payload_size;
};

View File

@ -96,7 +96,7 @@ public:
command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms, char separator) override;
private:
static const size_t GOT_LINE = signal_group::bit0; /*!< Bit indicating response available */
static const size_t GOT_LINE = SignalGroup::bit0; /*!< Bit indicating response available */
[[nodiscard]] bool setup_cmux(); /*!< Internal setup of CMUX mode */
@ -108,7 +108,7 @@ private:
Terminal *command_term; /*!< Reference to the terminal used for sending commands */
std::unique_ptr<Terminal> other_term; /*!< Secondary terminal for this DTE */
modem_mode mode; /*!< DTE operation mode */
signal_group signal; /*!< Event group used to signal request-response operations */
SignalGroup signal; /*!< Event group used to signal request-response operations */
std::function<bool(uint8_t *data, size_t len)> on_data; /*!< on data callback for current terminal */
};

View File

@ -75,9 +75,9 @@ private:
std::shared_ptr<DTE> ppp_dte;
esp_netif_t *netif;
struct ppp_netif_driver driver{};
signal_group signal;
static const size_t PPP_STARTED = signal_group::bit0;
static const size_t PPP_EXIT = signal_group::bit1;
SignalGroup signal;
static const size_t PPP_STARTED = SignalGroup::bit0;
static const size_t PPP_EXIT = SignalGroup::bit1;
};
/**

View File

@ -18,6 +18,8 @@
#if defined(CONFIG_IDF_TARGET_LINUX)
#include <mutex>
#include <thread>
#else
// forward declarations of FreeRTOS primitives
struct QueueDefinition;
@ -27,10 +29,12 @@ typedef void * EventGroupHandle_t;
namespace esp_modem {
// Forward declaration for both linux/FreeRTOS targets
//
using TaskFunction_t = void (*)(void*);
#if !defined(CONFIG_IDF_TARGET_LINUX)
struct Lock {
using MutexT = QueueDefinition*;
explicit Lock();
~Lock();
void lock();
@ -38,13 +42,14 @@ struct Lock {
private:
MutexT m{};
};
using Signal = void*;
using TaskT = void*;
using SignalT = void*;
#else
using Lock = std::mutex;
struct SignalGroup;
using Signal = std::unique_ptr<SignalGroup>;
struct SignalGroupInternal;
using SignalT = std::unique_ptr<SignalGroupInternal>;
using TaskT = std::thread;
static constexpr uint32_t portMAX_DELAY = UINT32_MAX;
#endif
template<class T>
@ -57,13 +62,26 @@ private:
T& lock;
};
struct signal_group {
class Task {
public:
explicit Task(size_t stack_size, size_t priority, void *task_param, TaskFunction_t task_function);
~Task();
static void Delete();
static void Relinquish();
private:
TaskT task_handle;
};
class SignalGroup {
public:
static constexpr size_t bit0 = 1 << 0;
static constexpr size_t bit1 = 1 << 1;
static constexpr size_t bit2 = 1 << 2;
static constexpr size_t bit3 = 1 << 3;
explicit signal_group();
explicit SignalGroup();
void set(uint32_t bits);
@ -77,10 +95,10 @@ struct signal_group {
// waiting for any bit, not clearing them
bool wait_any(uint32_t flags, uint32_t time_ms);
~signal_group();
~SignalGroup();
private:
Signal event_group;
SignalT event_group;
};
} // namespace esp_modem

View File

@ -85,22 +85,38 @@ void CMux::send_sabm(size_t dlci)
}
void CMux::data_available(uint8_t *data, size_t len)
void CMux::data_available(uint8_t *data, size_t len, size_t payload_offset)
{
if (type == 0xFF && len > 0 && dlci > 0) {
int virtual_term = dlci - 1;
if (virtual_term < max_terms && read_cb[virtual_term])
read_cb[virtual_term](data, len);
if (virtual_term < max_terms && read_cb[virtual_term]) {
if (payload_start == nullptr) {
payload_start = data;
}
total_payload_size += len;
// Post partial data (if configured)
// read_cb[virtual_term](payload_start, total_payload_size);
}
} else if (type == 0x73 && len == 0) { // notify the initial SABM command
Scoped<Lock> l(lock);
sabm_ack = dlci;
} else if (payload_offset == -1) {
int virtual_term = dlci - 1;
if (virtual_term < max_terms && read_cb[virtual_term]) {
read_cb[virtual_term](payload_start, total_payload_size);
}
}
}
bool CMux::on_cmux(uint8_t *data, size_t actual_len)
{
if (!data) {
auto data_to_read = std::min(actual_len, buffer_size);
auto data_to_read = buffer_size;
if (payload_start)
data = payload_start + total_payload_size;
else
data = buffer.get();
actual_len = term->read(data, data_to_read);
}
@ -135,7 +151,7 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
return false;
case cmux_state::INIT:
if (frame[0] != SOF_MARKER) {
ESP_LOGI("CMUX", "Protocol mismatch!");
ESP_LOGE("CMUX", "Protocol mismatch!");
state = cmux_state::RECOVER;
break;
}
@ -151,6 +167,13 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
frame++;
break;
case cmux_state::HEADER:
if (available_len > 0 && frame_header_offset == 1) {
if (frame[0] == SOF_MARKER) {
available_len--;
frame++;
break;
}
}
if (available_len + frame_header_offset < 4) {
memcpy(frame_header + frame_header_offset, frame, available_len);
frame_header_offset += available_len;
@ -168,14 +191,15 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
state = cmux_state::PAYLOAD;
break;
case cmux_state::PAYLOAD:
// ESP_LOGD("PAYLOAD", "CMUX FR: A:%02x T:%02x available:%d payloadLen:%d", dlci, type, available_len, payload_len);
if (available_len < payload_len) { // payload
state = cmux_state::PAYLOAD;
data_available(frame, available_len); // partial read
data_available(frame, available_len, 0); // partial read
payload_len -= available_len;
return false;
} else { // complete
if (payload_len > 0) {
data_available(&frame[0], payload_len); // rest read
data_available(&frame[0], payload_len, 0); // rest read
}
available_len -= payload_len;
frame += payload_len;
@ -183,25 +207,42 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
}
break;
case cmux_state::FOOTER:
if (available_len + frame_header_offset < 6) {
memcpy(frame_header + frame_header_offset, frame, available_len);
frame_header_offset += available_len;
if (available_len == 0) {
return false; // need read more
} else if (available_len == 1) {
frame_header[4] = frame[0];
frame ++;
available_len --;
return false; // need read more
} else {
footer_offset = std::min(available_len, 6 - frame_header_offset);
memcpy(frame_header + frame_header_offset, frame, footer_offset);
//
// }
// if (available_len + frame_header_offset < 6) {
// memcpy(frame_header + frame_header_offset, frame, available_len);
// frame_header_offset += available_len;
// return false; // need read more
// } else {
frame_header[4] = frame[0];
frame_header[5] = frame[1];
footer_offset = 2;
// 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_LOGI("CMUX", "Protocol mismatch!");
ESP_LOGE("CMUX", "Footer Protocol mismatch!");
state = cmux_state::RECOVER;
break;
}
if (payload_len == 0) {
data_available(frame_header, 0); // Null payload
data_available(frame_header, 0, 0); // Null payload
}
frame += footer_offset;
available_len -= footer_offset;
state = cmux_state::INIT;
frame_header_offset = 0;
if (payload_len)
data_available(nullptr, 0, -1); // Null payload
payload_start = nullptr;
total_payload_size = 0;
}
break;
}
@ -223,7 +264,7 @@ bool CMux::init()
{
int timeout = 0;
send_sabm(i);
while (1) {
while (true) {
usleep(10'000);
Scoped<Lock> l(lock);
if (sabm_ack == i) {

View File

@ -12,50 +12,62 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <charconv>
#include <list>
#include "esp_log.h"
#include "cxx_include/esp_modem_dte.hpp"
#include "cxx_include/esp_modem_dce_module.hpp"
#include "cxx_include/esp_modem_command_library.hpp"
#include <cstring>
// TODO: Remove iostream
#include <iostream>
namespace esp_modem::dce_commands {
command_result generic_command(CommandableIf* t, const std::string &command,
const std::list<std::string_view>& pass_phrase,
const std::list<std::string_view>& fail_phrase,
uint32_t timeout_ms)
{
printf("Command %s\n", 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 (response.find(it) != std::string::npos)
return command_result::OK;
for (auto it : fail_phrase)
if (response.find(it) != std::string::npos)
return command_result::FAIL;
return command_result::TIMEOUT;
}, timeout_ms);
}
static inline command_result generic_command(CommandableIf* t, const std::string& command,
const std::string& pass_phrase,
const std::string& fail_phrase, uint32_t timeout_ms)
{
std::cout << command << std::endl;
return t->command(command, [&](uint8_t *data, size_t len) {
std::string response((char*)data, len);
std::cout << response << std::endl;
if (response.find(pass_phrase) != std::string::npos) {
return command_result::OK;
} else if (response.find(fail_phrase) != std::string::npos) {
return command_result::FAIL;
}
return command_result::TIMEOUT;
}, timeout_ms);
const auto pass = std::list<std::string_view>({pass_phrase});
const auto fail = std::list<std::string_view>({fail_phrase});
return generic_command(t, command, pass, fail, timeout_ms);
}
static inline command_result generic_get_string(CommandableIf* t, const std::string& command, std::string& output, uint32_t timeout_ms = 500)
static inline command_result generic_get_string(CommandableIf* t, const std::string& command, std::string_view& output, uint32_t timeout_ms = 500)
{
return t->command(command, [&](uint8_t *data, size_t len) {
size_t pos = 0;
std::string response((char*)data, len);
std::string_view response((char*)data, len);
while ((pos = response.find('\n')) != std::string::npos) {
std::string token = response.substr(0, pos);
for (auto i = 0; i<2; ++i) // trip trailing \n\r of last two chars
if (pos >= 1 && (token[pos-1] == '\r' || token[pos-1] == '\n'))
token.pop_back();
std::string_view token = response.substr(0, pos);
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<int>(token.size()), token.data());
if (token.find("OK") != std::string::npos) {
return command_result::OK;
} else if (token.find("ERROR") != std::string::npos) {
return command_result::FAIL;
} else if (token.length() > 2) {
} else if (token.size() > 2) {
output = token;
}
response = response.substr(pos+1);
@ -64,7 +76,17 @@ static inline command_result generic_get_string(CommandableIf* t, const std::str
}, timeout_ms);
}
static inline command_result generic_command_common(CommandableIf* t, std::string command, uint32_t timeout = 500)
static inline command_result generic_get_string(CommandableIf* t, const std::string& command, std::string& output, uint32_t timeout_ms = 500)
{
std::string_view out;
auto ret = generic_get_string(t, command, out, timeout_ms);
if (ret == command_result::OK)
output = out;
return ret;
}
static inline command_result generic_command_common(CommandableIf* t, const std::string &command, uint32_t timeout = 500)
{
return generic_command(t, command, "OK", "ERROR", timeout);
}
@ -111,28 +133,54 @@ command_result hang_up(CommandableIf* t)
command_result get_battery_status(CommandableIf* t, int& voltage, int &bcs, int &bcl)
{
std::string out;
std::string_view out;
auto ret = generic_get_string(t, "AT+CBC\r", out);
if (ret != command_result::OK)
return ret;
if (out.find("+CBC") == std::string::npos)
constexpr std::string_view pattern = "+CBC: ";
if (out.find(pattern) == std::string_view::npos)
return command_result::FAIL;
// Parsing +CBC: <bcs>,<bcl>,<voltage>
sscanf(out.c_str(), "%*s%d,%d,%d", &bcs, &bcl, &voltage);
out = out.substr(pattern.size());
int pos, value, property = 0;
while ((pos = out.find(',') != std::string::npos)) {
if (std::from_chars(out.data(), out.data() + pos, value).ec == std::errc::invalid_argument)
return command_result::FAIL;
switch (property++) {
case 0: bcs = value;
break;
case 1: bcl = value;
break;
default:
return command_result::FAIL;
}
out = out.substr(pos + 1);
}
if (std::from_chars(out.data(), out.data() + out.size(), voltage).ec == std::errc::invalid_argument)
return command_result::FAIL;
return command_result::OK;
}
command_result get_battery_status_sim7xxx(CommandableIf* t, int& voltage, int &bcs, int &bcl)
{
std::string out;
std::string_view out;
auto ret = generic_get_string(t, "AT+CBC\r", out);
if (ret != command_result::OK)
return ret;
if (out.find("+CBC") == std::string::npos)
return command_result::FAIL;
// Parsing +CBC: <voltage in Volts> V
constexpr std::string_view pattern = "+CBC: ";
constexpr int num_pos = pattern.size();
int dot_pos;
if (out.find(pattern) == std::string::npos ||
(dot_pos = out.find('.')) == std::string::npos)
return command_result::FAIL;
int volt, fraction;
sscanf(out.c_str(), "+CBC: %d.%dV", &volt, &fraction);
if (std::from_chars(out.data() + num_pos, out.data() + dot_pos, volt).ec == std::errc::invalid_argument)
return command_result::FAIL;
if (std::from_chars(out.data() + dot_pos + 1, out.data() + out.size() - 1, fraction).ec == std::errc::invalid_argument)
return command_result::FAIL;
bcl = bcs = -1; // not available for these models
voltage = 1000*volt + fraction;
return command_result::OK;
@ -145,7 +193,7 @@ command_result set_flow_control(CommandableIf* t, int dce_flow, int dte_flow)
command_result get_operator_name(CommandableIf* t, std::string& operator_name)
{
std::string out;
std::string_view out;
auto ret = generic_get_string(t, "AT+COPS?\r", out, 75000);
if (ret != command_result::OK)
return ret;
@ -193,19 +241,9 @@ command_result resume_data_mode(CommandableIf* t)
command_result set_command_mode(CommandableIf* t)
{
std::cout << "Sending +++" << std::endl;
return t->command("+++", [&](uint8_t *data, size_t len) {
std::string response((char*)data, len);
std::cout << response << std::endl;
if (response.find("OK") != std::string::npos) {
return command_result::OK;
} else if (response.find("NO CARRIER") != std::string::npos) {
return command_result::OK;
} else if (response.find("ERROR") != std::string::npos) {
return command_result::FAIL;
}
return command_result::TIMEOUT;
}, 5000);
const auto pass = std::list<std::string_view>({"NO CARRIER", "OK"});
const auto fail = std::list<std::string_view>({"ERROR"});
return generic_command(t, "+++", pass, fail, 5000);
}
command_result get_imsi(CommandableIf* t, std::string& imsi_number)
@ -239,8 +277,8 @@ command_result sms_character_set(CommandableIf* t)
command_result send_sms(CommandableIf* t, const std::string& number, const std::string& message)
{
auto ret = t->command("AT+CMGS=\"" + number + "\"\r", [&](uint8_t *data, size_t len) {
std::string response((char*)data, len);
std::cout << response << std::endl;
std::string_view response((char*)data, len);
printf("%.*s", static_cast<int>(response.size()), response.data());
if (response.find('>') != std::string::npos) {
return command_result::OK;
}
@ -259,53 +297,49 @@ command_result set_cmux(CommandableIf* t)
command_result read_pin(CommandableIf* t, bool& pin_ok)
{
std::cout << "Sending read_pin" << std::endl;
return t->command("AT+CPIN?\r", [&](uint8_t *data, size_t len) {
std::string response((char*)data, len);
std::cout << response << std::endl;
if (response.find("READY") != std::string::npos) {
pin_ok = true;
return command_result::OK;
} else if (response.find("PIN") != std::string::npos || response.find("PUK") != std::string::npos ) {
std::string_view out;
auto ret = generic_get_string(t, "AT+CPIN?\r", out);
if (ret != command_result::OK)
return ret;
if (out.find("+CPIN:") == std::string::npos)
return command_result::FAIL;
if (out.find("SIM PIN") != std::string::npos || out.find("SIM PUK") != std::string::npos) {
pin_ok = false;
return command_result::OK;
} else if (response.find("ERROR") != std::string::npos) {
return command_result::FAIL;
}
return command_result::TIMEOUT;
}, 5000);
if (out.find("READY") != std::string::npos) {
pin_ok = true;
return command_result::OK;
}
return command_result::FAIL; // Neither pin-ok, nor waiting for pin/puk -> mark as error
}
command_result set_pin(CommandableIf* t, const std::string& pin)
{
std::cout << "Sending set_pin" << std::endl;
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)
{
std::cout << "get_signal_quality" << std::endl;
return t->command("AT+CSQ\r", [&](uint8_t *data, size_t len) {
size_t pos = 0;
std::string response((char*)data, len);
while ((pos = response.find('\n')) != std::string::npos) {
std::string token = response.substr(0, pos);
for (auto i = 0; i<2; ++i) // trip trailing \n\r of last two chars
if (pos >= 1 && (token[pos-1] == '\r' || token[pos-1] == '\n'))
token.pop_back();
printf("%s", __func__ );
std::string_view out;
auto ret = generic_get_string(t, "AT+CSQ\r", out);
if (ret != command_result::OK)
return ret;
if (token.find("OK") != std::string::npos) {
return command_result::OK;
} else if (token.find("ERROR") != std::string::npos) {
constexpr std::string_view pattern = "+CSQ: ";
constexpr int rssi_pos = pattern.size();
int ber_pos;
if (out.find(pattern) == std::string::npos ||
(ber_pos = out.find(',')) == std::string::npos)
return command_result::FAIL;
} else if (token.find("+CSQ") != std::string::npos) {
sscanf(token.c_str(), "%*s%d,%d", &rssi, &ber);
}
response = response.substr(pos+1);
}
return command_result::TIMEOUT;
}, 500);
if (std::from_chars(out.data() + rssi_pos, out.data() + ber_pos, rssi).ec == std::errc::invalid_argument)
return command_result::FAIL;
if (std::from_chars(out.data() + ber_pos + 1, out.data() + out.size(), ber).ec == std::errc::invalid_argument)
return command_result::FAIL;
return command_result::OK;
}
} // esp_modem::dce_commands

View File

@ -39,18 +39,19 @@ 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) {
auto data_to_read = std::min(len, buffer_size - consumed);
data = buffer.get() + consumed;
len = command_term->read(data, data_to_read);
data = buffer.get(); // + consumed;
len = command_term->read(data + consumed, buffer_size - consumed);
} else {
consumed = 0;
}
consumed += len;
if (memchr(data, separator, len)) {
res = got_line(data, consumed);
if (memchr(data + consumed, separator, len)) {
res = got_line(data, consumed + len);
if (res == command_result::OK || res == command_result::FAIL) {
signal.set(GOT_LINE);
return true;
}
}
consumed += len;
return false;
});
command_term->write((uint8_t *)command.c_str(), command.length());
@ -107,9 +108,8 @@ void DTE::set_read_cb(std::function<bool(uint8_t *, size_t)> f)
on_data = std::move(f);
term->set_read_cb([this](uint8_t *data, size_t len) {
if (!data) { // if no data available from terminal callback -> need to explicitly read some
auto data_to_read = std::min(len, buffer_size - consumed);
data = buffer.get();
len = term->read(data, data_to_read);
len = term->read(buffer.get(), buffer_size);
}
if (on_data)
return on_data(data, len);

View File

@ -18,12 +18,8 @@
#include "freertos/event_groups.h"
#include "freertos/semphr.h"
namespace esp_modem {
void Lock::unlock() {
xSemaphoreGiveRecursive(m);
}
@ -43,42 +39,66 @@ void Lock::lock() {
}
signal_group::signal_group(): event_group(nullptr)
SignalGroup::SignalGroup(): event_group(nullptr)
{
event_group = xEventGroupCreate();
throw_if_false(event_group != nullptr, "create signal event group failed");
}
void signal_group::set(uint32_t bits)
void SignalGroup::set(uint32_t bits)
{
xEventGroupSetBits(event_group, bits);
}
void signal_group::clear(uint32_t bits)
void SignalGroup::clear(uint32_t bits)
{
xEventGroupClearBits(event_group, bits);
}
bool signal_group::wait(uint32_t flags, uint32_t time_ms)
bool SignalGroup::wait(uint32_t flags, uint32_t time_ms)
{
EventBits_t bits = xEventGroupWaitBits(event_group, flags, pdTRUE, pdTRUE, pdMS_TO_TICKS(time_ms));
return bits & flags;
}
bool signal_group::is_any(uint32_t flags)
bool SignalGroup::is_any(uint32_t flags)
{
return xEventGroupGetBits(event_group) & flags;
}
bool signal_group::wait_any(uint32_t flags, uint32_t time_ms)
bool SignalGroup::wait_any(uint32_t flags, uint32_t time_ms)
{
EventBits_t bits = xEventGroupWaitBits(event_group, flags, pdFALSE, pdFALSE, pdMS_TO_TICKS(time_ms));
return bits & flags;
}
signal_group::~signal_group()
SignalGroup::~SignalGroup()
{
if (event_group) vEventGroupDelete(event_group);
if (event_group)
vEventGroupDelete(event_group);
}
Task::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 vfs task failed");
}
Task::~Task()
{
if (task_handle)
vTaskDelete(task_handle);
}
void Task::Delete()
{
vTaskDelete(nullptr);
}
void Task::Relinquish()
{
vTaskDelay(1);
}
} // namespace esp_modem

View File

@ -13,35 +13,35 @@
// limitations under the License.
#include <condition_variable>
#include <unistd.h>
#include "cxx_include/esp_modem_primitives.hpp"
namespace esp_modem {
struct SignalGroup {
struct SignalGroupInternal {
std::condition_variable notify;
std::mutex m;
uint32_t flags{ 0 };
};
signal_group::signal_group(): event_group(std::make_unique<SignalGroup>())
SignalGroup::SignalGroup(): event_group(std::make_unique<SignalGroupInternal>())
{
}
void signal_group::set(uint32_t bits)
void SignalGroup::set(uint32_t bits)
{
std::unique_lock<std::mutex> lock(event_group->m);
event_group->flags |= bits;
}
void signal_group::clear(uint32_t bits)
void SignalGroup::clear(uint32_t bits)
{
std::unique_lock<std::mutex> lock(event_group->m);
event_group->flags &= ~bits;
}
bool signal_group::wait(uint32_t flags, uint32_t time_ms)
bool SignalGroup::wait(uint32_t flags, uint32_t time_ms)
{
std::unique_lock<std::mutex> lock(event_group->m);
return event_group->notify.wait_for(lock, std::chrono::milliseconds(time_ms), [&]{
@ -55,18 +55,35 @@ bool signal_group::wait(uint32_t flags, uint32_t time_ms)
// , [&]{return flags&event_group->flags; });
}
bool signal_group::is_any(uint32_t flags)
bool SignalGroup::is_any(uint32_t flags)
{
std::unique_lock<std::mutex> lock(event_group->m);
return flags&event_group->flags;
}
bool signal_group::wait_any(uint32_t flags, uint32_t time_ms)
bool SignalGroup::wait_any(uint32_t flags, uint32_t time_ms)
{
std::unique_lock<std::mutex> lock(event_group->m);
return event_group->notify.wait_for(lock, std::chrono::milliseconds(time_ms), [&]{ return flags&event_group->flags; });
}
signal_group::~signal_group() = default;
SignalGroup::~SignalGroup() = default;
Task::Task(size_t stack_size, size_t priority, void *task_param, TaskFunction_t task_function)
{
#warning "Define this for linux"
}
Task::~Task()
{
}
void Task::Delete() {}
void Task::Relinquish()
{
usleep(0);
}
} // namespace esp_modem

View File

@ -12,15 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <unistd.h>
#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";
@ -33,68 +31,16 @@ struct uart_resource {
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) {}
task_handle(config->vfs_config.task_stack_size, config->vfs_config.task_prio, this, [](void* p){
auto t = static_cast<vfs_terminal *>(p);
t->task();
Task::Delete();
}) {}
~vfs_terminal() override = default;
@ -116,22 +62,16 @@ public:
}
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;
static const size_t TASK_INIT = SignalGroup::bit0;
static const size_t TASK_START = SignalGroup::bit1;
static const size_t TASK_STOP = SignalGroup::bit2;
static const size_t TASK_PARAMS = SignalGroup::bit3;
uart_resource uart;
signal_group signal;
vfs_task task_handle;
SignalGroup signal;
Task task_handle;
};
std::unique_ptr<Terminal> create_vfs_terminal(const esp_modem_dte_config *config) {
@ -144,13 +84,15 @@ std::unique_ptr<Terminal> create_vfs_terminal(const esp_modem_dte_config *config
void vfs_terminal::task() {
std::function<bool(uint8_t *data, size_t len)> on_data_priv = nullptr;
size_t len;
// 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);
// esp_vfs_dev_uart_use_driver(uart.port);
int flags = fcntl(uart.fd, F_GETFL, NULL) | O_NONBLOCK;
fcntl(uart.fd, F_SETFL, flags);
while (signal.is_any(TASK_START)) {
int s;
@ -163,35 +105,36 @@ void vfs_terminal::task() {
FD_SET(uart.fd, &rfds);
s = select(uart.fd + 1, &rfds, NULL, NULL, &tv);
// if (signal.is_any(TASK_PARAMS)) {
if (signal.is_any(TASK_PARAMS)) {
on_data_priv = on_data;
// signal.clear(TASK_PARAMS);
// }
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)) {
// uart_get_buffered_data_len(uart.port, &len);
if (on_data_priv) {
if (on_data_priv(nullptr, 0)) {
on_data_priv = nullptr;
}
}
}
}
vTaskDelay(1);
Task::Relinquish();
}
}
int vfs_terminal::read(uint8_t *data, size_t len) {
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) {
int vfs_terminal::write(uint8_t *data, size_t len)
{
return ::write(uart.fd, data, len);
}

View File

@ -0,0 +1,77 @@
// 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 "cxx_include/esp_modem_dte.hpp"
#include "esp_log.h"
#include "driver/uart.h"
#include "esp_modem_config.h"
#include "exception_stub.hpp"
#include "esp_vfs_dev.h"
#include <sys/fcntl.h>
static const char *TAG = "uart_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;
};
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;
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

View File

@ -150,7 +150,7 @@ private:
static const size_t TASK_PARAMS = BIT3;
uart_resource uart;
signal_group signal;
SignalGroup signal;
uart_task task_handle;
};

View File

@ -1,4 +1,4 @@
idf_component_register(SRCS "test_modem.cpp"
idf_component_register(SRCS "test_modem.cpp" "LoopbackTerm.cpp"
INCLUDE_DIRS "$ENV{IDF_PATH}/tools/catch"
REQUIRES esp_modem)

View File

@ -0,0 +1,82 @@
#include <memory>
#include <future>
#include <cstring>
#include "LoopbackTerm.h"
void LoopbackTerm::start()
{
status = status_t::STARTED;
}
void LoopbackTerm::stop()
{
status = status_t::STOPPED;
}
int LoopbackTerm::write(uint8_t *data, size_t len)
{
if (len > 2 && (data[len-1] == '\r' || data[len-1] == '+') ) { // Simple AT responder
std::string command((char*)data, len);
std::string response;
if (command == "+++") {
response = "NO CARRIER\r\n";
} else if (command == "ATE1\r" || command == "ATE0\r") {
response = "OK\r\n";
} else if (command == "ATO\r") {
response = "ERROR\r\n";
} else if (command.find("ATD") != std::string::npos) {
response = "CONNECT\r\n";
} else if (command.find("AT+CSQ\r") != std::string::npos) {
response = "+CSQ: 123,456\n\r\nOK\r\n";
} else if (command.find("AT+CBC\r") != std::string::npos) {
response = is_bg96 ? "+CBC: 1,2,123456V\r\r\n\r\nOK\r\n\n\r\n":
"+CBC: 123.456V\r\r\n\r\nOK\r\n\n\r\n";
} else if (command.find("AT+CPIN=1234\r") != std::string::npos) {
response = "OK\r\n";
pin_ok = true;
} else if (command.find("AT+CPIN?\r") != std::string::npos) {
response = pin_ok?"+CPIN: READY\r\nOK\r\n":"+CPIN: SIM PIN\r\nOK\r\n";
} else if (command.find("AT") != std::string::npos) {
response = "OK\r\n";
}
if (!response.empty()) {
data_len = response.length();
loopback_data.resize(data_len);
memcpy(&loopback_data[0], &response[0], data_len);
auto ret = std::async(on_data, nullptr, data_len);
return len;
}
}
if (len > 2 && data[0] == 0xf9) { // Simple CMUX responder
// turn the request into a reply -> implements CMUX loopback
if (data[2] == 0x3f) // SABM command
data[2] = 0x73;
else if (data[2] == 0xef) { // Generic request
data[2] = 0xff; // generic reply
}
}
loopback_data.resize(data_len + len);
memcpy(&loopback_data[data_len], data, len);
data_len += len;
auto ret = std::async(on_data, nullptr, data_len);
return len;
}
int LoopbackTerm::read(uint8_t *data, size_t len)
{
size_t read_len = std::min(data_len, len);
if (read_len) {
if (loopback_data.capacity() < len)
loopback_data.reserve(len);
memcpy(data, &loopback_data[0], read_len);
loopback_data.erase(loopback_data.begin(), loopback_data.begin() + read_len);
data_len -= read_len;
}
return read_len;
}
LoopbackTerm::LoopbackTerm(bool is_bg96): loopback_data(), data_len(0), pin_ok(false), is_bg96(is_bg96) {}
LoopbackTerm::LoopbackTerm(): loopback_data(), data_len(0), pin_ok(false), is_bg96(false) {}
LoopbackTerm::~LoopbackTerm() = default;

View File

@ -0,0 +1,36 @@
#ifndef _LOOPBACKTERM_H_
#define _LOOPBACKTERM_H_
#include "cxx_include/esp_modem_api.hpp"
#include "cxx_include/esp_modem_terminal.hpp"
using namespace esp_modem;
class LoopbackTerm : public Terminal {
public:
explicit LoopbackTerm(bool is_bg96);
explicit LoopbackTerm();
~LoopbackTerm() override;
void start() override;
void stop() override;
int write(uint8_t *data, size_t len) override;
int read(uint8_t *data, size_t len) override;
private:
enum class status_t {
STARTED,
STOPPED
};
status_t status;
SignalGroup signal;
std::vector<uint8_t> loopback_data;
size_t data_len;
bool pin_ok;
bool is_bg96;
};
#endif //_LOOPBACKTERM_H_

View File

@ -2,81 +2,43 @@
#include <memory>
#include <future>
#include "catch.hpp"
#include "cxx_include/esp_modem_terminal.hpp"
#include "cxx_include/esp_modem_api.hpp"
#include "LoopbackTerm.h"
using namespace esp_modem;
class LoopbackTerm : public Terminal {
public:
explicit LoopbackTerm(): loopback_data(), data_len(0) {}
TEST_CASE("DCE AT parser", "[esp_modem]")
{
auto term = std::make_unique<LoopbackTerm>(true);
auto dte = std::make_shared<DTE>(std::move(term));
CHECK(term == nullptr);
~LoopbackTerm() override = default;
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("APN");
esp_netif_t netif{};
auto dce = create_BG96_dce(&dce_config, dte, &netif);
CHECK(dce != nullptr);
void start() override {
status = status_t::STARTED;
CHECK(dce->set_command_mode() == command_result::OK);
int milli_volt, bcl, bcs;
CHECK(dce->get_battery_status(milli_volt, bcl, bcs) == command_result::OK);
CHECK(milli_volt == 123456);
CHECK(bcl == 1);
CHECK(bcs == 2);
int rssi, ber;
CHECK(dce->get_signal_quality(rssi, ber) == command_result::OK);
CHECK(rssi == 123);
CHECK(ber == 456);
bool pin_ok;
CHECK(dce->read_pin(pin_ok) == command_result::OK);
CHECK(pin_ok == false);
CHECK(dce->set_pin("1234") == command_result::OK);
CHECK(dce->read_pin(pin_ok) == command_result::OK);
CHECK(pin_ok == true);
}
void stop() override {
status = status_t::STOPPED;
}
int write(uint8_t *data, size_t len) override {
if (len > 2 && (data[len-1] == '\r' || data[len-1] == '+') ) { // Simple AT responder
std::string command((char*)data, len);
std::string response;
if (command == "ATE1\r" || command == "ATE0\r" || command == "+++") {
response = "OK\r\n";
} else if (command == "ATO\r") {
response = "ERROR\r\n";
} else if (command.find("ATD") != std::string::npos) {
response = "CONNECT\r\n";
} else if (command.find("AT") != std::string::npos) {
response = "OK\r\n";
}
if (!response.empty()) {
data_len = response.length();
loopback_data.resize(data_len);
memcpy(&loopback_data[0], &response[0], data_len);
auto ret = std::async(on_data, nullptr, data_len);
return len;
}
}
if (len > 2 && data[0] == 0xf9) { // Simple CMUX responder
// turn the request into a reply -> implements CMUX loopback
if (data[2] == 0x3f) // SABM command
data[2] = 0x73;
else if (data[2] == 0xef) // Generic request
data[2] = 0xff; // generic reply
}
loopback_data.resize(data_len + len);
memcpy(&loopback_data[data_len], data, len);
data_len += len;
auto ret = std::async(on_data, nullptr, data_len);
return len;
}
int read(uint8_t *data, size_t len) override {
size_t read_len = std::min(data_len, len);
if (read_len) {
memcpy(data, &loopback_data[0], len);
loopback_data.erase(loopback_data.begin(), loopback_data.begin() + read_len);
data_len -= len;
}
return read_len;
}
private:
enum class status_t {
STARTED,
STOPPED
};
status_t status;
signal_group signal;
std::vector<uint8_t> loopback_data;
size_t data_len;
};
TEST_CASE("DTE send/receive command", "[esp_modem]")
{
@ -127,11 +89,15 @@ TEST_CASE("DCE AT commands", "[esp_modem]")
auto dce = create_SIM7600_dce(&dce_config, dte, &netif);
CHECK(dce != nullptr);
int milli_volt, bcl, bcs;
CHECK(dce->set_echo(false) == command_result::OK);
CHECK(dce->set_echo(true) == command_result::OK);
CHECK(dce->get_battery_status(milli_volt, bcl, bcs) == command_result::OK);
CHECK(milli_volt == 123456);
CHECK(dce->resume_data_mode() == command_result::FAIL);
}
TEST_CASE("DCE modes", "[esp_modem]")
{
auto term = std::make_unique<LoopbackTerm>();
@ -162,6 +128,7 @@ TEST_CASE("DCE CMUX test", "[esp_modem]") {
const auto test_command = "Test\n";
auto ret = dce->command(test_command, [&](uint8_t *data, size_t len) {
std::string response((char *) data, len);
std::cout << "Response:" << response << std::endl;
CHECK(response == test_command);
return command_result::OK;
}, 1000);

View File

@ -1,31 +0,0 @@
-- Found Git: /usr/bin/git (found version "2.30.2")
-- Component directory /home/david/esp/idf/components/aws_iot does not contain a CMakeLists.txt file. No component will be added
-- Component directory /home/david/esp/idf/components/micro-ecc does not contain a CMakeLists.txt file. No component will be added
-- Component directory /home/david/esp/idf/components/nimble does not contain a CMakeLists.txt file. No component will be added
-- ccache will be used for faster recompilation
-- The C compiler identification is GNU 10.2.1
-- The CXX compiler identification is GNU 10.2.1
-- The ASM compiler identification is GNU
-- Found assembler: /usr/lib64/ccache/cc
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/lib64/ccache/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/lib64/ccache/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Building ESP-IDF components for target linux
-- adding linux stuff...
-- Found Git: /usr/bin/git (found version "2.30.2")
-- Configuring incomplete, errors occurred!
See also "/home/david/repos/esp-idf-contrib/esp_modem/test/host_test/build/CMakeFiles/CMakeOutput.log".
Adding "set-target"'s dependency "fullclean" to list of commands with default set of options.
Executing action: fullclean
Build directory '/home/david/repos/esp-idf-contrib/esp_modem/test/host_test/build' not found. Nothing to clean.
Executing action: set-target
Set Target to: linux, new sdkconfig created. Existing sdkconfig renamed to sdkconfig.old.
Running cmake in directory /home/david/repos/esp-idf-contrib/esp_modem/test/host_test/build
Executing "cmake -G Ninja -DPYTHON_DEPS_CHECKED=1 -DESP_PLATFORM=1 -DIDF_TARGET=linux -DIDF_TARGET=linux -DCCACHE_ENABLE=1 /home/david/repos/esp-idf-contrib/esp_modem/test/host_test"...

View File

@ -54,10 +54,23 @@ public:
{
// configure
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 = 1024,
.baud_rate = 115200,
.tx_io_num = 25,
.rx_io_num = 26,
.task_stack_size = 4096,
.task_prio = 5}
};
esp_modem_dce_config dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("");
// create DTE and minimal network DCE
auto uart_dte = create_uart_dte(&dte_config);
auto uart_dte = create_vfs_dte(&dte_config2);
// auto uart_dte = create_uart_dte(&dte_config);
dce = NetDCE_Factory::create<NetModule>(&dce_config, uart_dte, netif);
return dce == nullptr ? ESP_FAIL : ESP_OK;
}