mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-18 21:12:22 +02:00
CMUX: debug cmux protocol issues and recovery
This commit is contained in:
@ -17,6 +17,7 @@
|
|||||||
#include "esp_modem_config.h"
|
#include "esp_modem_config.h"
|
||||||
#include "cxx_include/esp_modem_api.hpp"
|
#include "cxx_include/esp_modem_api.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "esp_https_ota.h"
|
||||||
|
|
||||||
#define BROKER_URL "mqtt://mqtt.eclipseprojects.io"
|
#define BROKER_URL "mqtt://mqtt.eclipseprojects.io"
|
||||||
|
|
||||||
@ -132,7 +133,7 @@ extern "C" void app_main(void)
|
|||||||
.dte_buffer_size = 512,
|
.dte_buffer_size = 512,
|
||||||
.vfs_config = {.port_num = UART_NUM_1,
|
.vfs_config = {.port_num = UART_NUM_1,
|
||||||
.dev_name = "/dev/uart/1",
|
.dev_name = "/dev/uart/1",
|
||||||
.rx_buffer_size = 512,
|
.rx_buffer_size = 1024,
|
||||||
.tx_buffer_size = 512,
|
.tx_buffer_size = 512,
|
||||||
.baud_rate = 115200,
|
.baud_rate = 115200,
|
||||||
.tx_io_num = 25,
|
.tx_io_num = 25,
|
||||||
@ -147,8 +148,9 @@ extern "C" void app_main(void)
|
|||||||
/* Configure the PPP netif */
|
/* Configure the PPP netif */
|
||||||
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
|
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
|
||||||
|
|
||||||
// auto uart_dte = create_uart_dte(&dte_config);
|
dte_config.dte_buffer_size = 512;
|
||||||
auto uart_dte = create_vfs_dte(&dte_config2);
|
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);
|
esp_netif_t *esp_netif = esp_netif_new(&netif_ppp_config);
|
||||||
assert(esp_netif);
|
assert(esp_netif);
|
||||||
@ -171,8 +173,8 @@ extern "C" void app_main(void)
|
|||||||
bool pin_ok = true;
|
bool pin_ok = true;
|
||||||
if (dce->read_pin(pin_ok) == command_result::OK && !pin_ok) {
|
if (dce->read_pin(pin_ok) == command_result::OK && !pin_ok) {
|
||||||
throw_if_false(dce->set_pin(CONFIG_EXAMPLE_SIM_PIN) == command_result::OK, "Cannot set PIN!");
|
throw_if_false(dce->set_pin(CONFIG_EXAMPLE_SIM_PIN) == command_result::OK, "Cannot set PIN!");
|
||||||
}
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
// dce->get_imsi(str);
|
// dce->get_imsi(str);
|
||||||
// std::cout << "Modem IMSI number:" << str << "|" << std::endl;
|
// std::cout << "Modem IMSI number:" << str << "|" << std::endl;
|
||||||
// std::cout << "|" << str << "|" << std::endl;
|
// std::cout << "|" << str << "|" << std::endl;
|
||||||
@ -186,6 +188,8 @@ extern "C" void app_main(void)
|
|||||||
std::cout << "Operator name:" << str << "|" << std::endl;
|
std::cout << "Operator name:" << str << "|" << std::endl;
|
||||||
// return;
|
// return;
|
||||||
|
|
||||||
|
|
||||||
|
// dce->set_mode(esp_modem::modem_mode::CMUX_MODE);
|
||||||
dce->set_data();
|
dce->set_data();
|
||||||
|
|
||||||
// MQTT connection
|
// MQTT connection
|
||||||
@ -198,13 +202,28 @@ extern "C" void app_main(void)
|
|||||||
|
|
||||||
EventBits_t got_data = 0;
|
EventBits_t got_data = 0;
|
||||||
while (got_data == 0) { // reading IMSI number until we get published data from MQTT
|
while (got_data == 0) { // reading IMSI number until we get published data from MQTT
|
||||||
dce->get_imsi(str);
|
// dce->get_imsi(str);
|
||||||
std::cout << "Modem IMSI number:" << str << "|" << std::endl;
|
// std::cout << "Modem IMSI number:" << str << "|" << std::endl;
|
||||||
got_data = xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, pdMS_TO_TICKS(500));
|
got_data = xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, pdMS_TO_TICKS(500));
|
||||||
}
|
}
|
||||||
esp_mqtt_client_destroy(mqtt_client);
|
esp_mqtt_client_destroy(mqtt_client);
|
||||||
dce->get_imsi(str);
|
// dce->get_imsi(str);
|
||||||
std::cout << "Modem IMSI number:" << str << "|" << std::endl;
|
// std::cout << "Modem IMSI number:" << str << "|" << std::endl;
|
||||||
|
|
||||||
|
esp_http_client_config_t config = { };
|
||||||
|
config.skip_cert_common_name_check = true;
|
||||||
|
config.url = "https://github.com/david-cermak/esp32-ipv6-examples/raw/test/ota/hello-world.bin";
|
||||||
|
|
||||||
|
esp_err_t ret = esp_https_ota(&config);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
esp_restart();
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Firmware upgrade failed");
|
||||||
|
}
|
||||||
|
while (1) {
|
||||||
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Example finished");
|
ESP_LOGI(TAG, "Example finished");
|
||||||
|
@ -64,7 +64,7 @@ public:
|
|||||||
int write(int i, uint8_t *data, size_t len);
|
int write(int i, uint8_t *data, size_t len);
|
||||||
private:
|
private:
|
||||||
std::function<bool(uint8_t *data, size_t len)> read_cb[max_terms];
|
std::function<bool(uint8_t *data, size_t len)> read_cb[max_terms];
|
||||||
void data_available(uint8_t *data, size_t len, size_t payload_offset);
|
void data_available(uint8_t *data, size_t len);
|
||||||
void send_sabm(size_t i);
|
void send_sabm(size_t i);
|
||||||
std::unique_ptr<Terminal> term;
|
std::unique_ptr<Terminal> term;
|
||||||
cmux_state state;
|
cmux_state state;
|
||||||
|
@ -85,23 +85,24 @@ void CMux::send_sabm(size_t dlci)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CMux::data_available(uint8_t *data, size_t len, size_t payload_offset)
|
void CMux::data_available(uint8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
if (type == 0xFF && len > 0 && dlci > 0) {
|
if (data && type == 0xFF && len > 0 && dlci > 0) {
|
||||||
int virtual_term = dlci - 1;
|
int virtual_term = dlci - 1;
|
||||||
if (virtual_term < max_terms && read_cb[virtual_term]) {
|
if (virtual_term < max_terms && read_cb[virtual_term]) {
|
||||||
if (payload_start == nullptr) {
|
if (payload_start == nullptr) {
|
||||||
payload_start = data;
|
payload_start = data;
|
||||||
|
total_payload_size = 0;
|
||||||
}
|
}
|
||||||
total_payload_size += len;
|
total_payload_size += len;
|
||||||
// Post partial data (if configured)
|
// Post partial data (if configured)
|
||||||
// read_cb[virtual_term](payload_start, total_payload_size);
|
// read_cb[virtual_term](payload_start, total_payload_size);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if (type == 0x73 && len == 0) { // notify the initial SABM command
|
} else if (data == nullptr && type == 0x73 && len == 0) { // notify the initial SABM command
|
||||||
Scoped<Lock> l(lock);
|
Scoped<Lock> l(lock);
|
||||||
sabm_ack = dlci;
|
sabm_ack = dlci;
|
||||||
} else if (payload_offset == -1) {
|
} else if (data == nullptr) {
|
||||||
int virtual_term = dlci - 1;
|
int virtual_term = dlci - 1;
|
||||||
if (virtual_term < max_terms && read_cb[virtual_term]) {
|
if (virtual_term < max_terms && read_cb[virtual_term]) {
|
||||||
read_cb[virtual_term](payload_start, total_payload_size);
|
read_cb[virtual_term](payload_start, total_payload_size);
|
||||||
@ -113,14 +114,21 @@ void CMux::data_available(uint8_t *data, size_t len, size_t payload_offset)
|
|||||||
bool CMux::on_cmux(uint8_t *data, size_t actual_len)
|
bool CMux::on_cmux(uint8_t *data, size_t actual_len)
|
||||||
{
|
{
|
||||||
if (!data) {
|
if (!data) {
|
||||||
auto data_to_read = buffer_size;
|
auto data_to_read = buffer_size - 155;
|
||||||
if (payload_start)
|
if (payload_start) {
|
||||||
data = payload_start + total_payload_size;
|
data = payload_start + total_payload_size;
|
||||||
else
|
data_to_read = payload_len + 2;
|
||||||
|
} else {
|
||||||
data = buffer.get();
|
data = buffer.get();
|
||||||
actual_len = term->read(data, data_to_read);
|
|
||||||
}
|
}
|
||||||
ESP_LOG_BUFFER_HEXDUMP("Received", data, actual_len, ESP_LOG_DEBUG);
|
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);
|
||||||
|
}
|
||||||
|
printf("my_data[%d] = { ", actual_len);
|
||||||
|
for (int i=0; i<actual_len; ++i)
|
||||||
|
printf("0x%02x, ", data[i]);
|
||||||
|
printf("};\n");
|
||||||
|
// ESP_LOG_BUFFER_HEXDUMP("Received", data, actual_len, ESP_LOG_INFO);
|
||||||
uint8_t* frame = data;
|
uint8_t* frame = data;
|
||||||
uint8_t* recover_ptr;
|
uint8_t* recover_ptr;
|
||||||
auto available_len = actual_len;
|
auto available_len = actual_len;
|
||||||
@ -139,7 +147,7 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
|
|||||||
available_len -= (recover_ptr - frame);
|
available_len -= (recover_ptr - frame);
|
||||||
frame = recover_ptr;
|
frame = recover_ptr;
|
||||||
state = cmux_state::INIT;
|
state = cmux_state::INIT;
|
||||||
ESP_LOGD("CMUX", "Protocol recovered");
|
ESP_LOGW("CMUX", "Protocol recovered");
|
||||||
if (available_len > 1 && frame[1] == SOF_MARKER) {
|
if (available_len > 1 && frame[1] == SOF_MARKER) {
|
||||||
// empty frame
|
// empty frame
|
||||||
available_len -= 1;
|
available_len -= 1;
|
||||||
@ -167,13 +175,12 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
|
|||||||
frame++;
|
frame++;
|
||||||
break;
|
break;
|
||||||
case cmux_state::HEADER:
|
case cmux_state::HEADER:
|
||||||
if (available_len > 0 && frame_header_offset == 1) {
|
// if (available_len > 0 && frame_header_offset == 1 && frame[0] == SOF_MARKER) {
|
||||||
if (frame[0] == SOF_MARKER) {
|
// // Previously trailing SOF interpreted as heading SOF, remove it and restart HEADER
|
||||||
available_len--;
|
// available_len--;
|
||||||
frame++;
|
// frame++;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
|
||||||
if (available_len + frame_header_offset < 4) {
|
if (available_len + frame_header_offset < 4) {
|
||||||
memcpy(frame_header + frame_header_offset, frame, available_len);
|
memcpy(frame_header + frame_header_offset, frame, available_len);
|
||||||
frame_header_offset += available_len;
|
frame_header_offset += available_len;
|
||||||
@ -185,62 +192,52 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
|
|||||||
dlci = frame_header[1] >> 2;
|
dlci = frame_header[1] >> 2;
|
||||||
type = frame_header[2];
|
type = frame_header[2];
|
||||||
payload_len = (frame_header[3] >> 1);
|
payload_len = (frame_header[3] >> 1);
|
||||||
ESP_LOGD("CMUX", "CMUX FR: A:%02x T:%02x L:%d", dlci, type, payload_len);
|
|
||||||
frame += payload_offset;
|
frame += payload_offset;
|
||||||
available_len -= payload_offset;
|
available_len -= payload_offset;
|
||||||
state = cmux_state::PAYLOAD;
|
state = cmux_state::PAYLOAD;
|
||||||
break;
|
break;
|
||||||
case cmux_state::PAYLOAD:
|
case cmux_state::PAYLOAD:
|
||||||
// ESP_LOGD("PAYLOAD", "CMUX FR: A:%02x T:%02x available:%d payloadLen:%d", dlci, type, available_len, payload_len);
|
ESP_LOGI("CMUX", "CMUX FR: A:%02x T:%02x L:%d available: %d", dlci, type, payload_len, available_len);
|
||||||
if (available_len < payload_len) { // payload
|
if (available_len < payload_len) { // payload
|
||||||
state = cmux_state::PAYLOAD;
|
state = cmux_state::PAYLOAD;
|
||||||
data_available(frame, available_len, 0); // partial read
|
data_available(frame, available_len); // partial read
|
||||||
payload_len -= available_len;
|
payload_len -= available_len;
|
||||||
return false;
|
return false;
|
||||||
} else { // complete
|
} else { // complete
|
||||||
if (payload_len > 0) {
|
if (payload_len > 0) {
|
||||||
data_available(&frame[0], payload_len, 0); // rest read
|
data_available(&frame[0], payload_len); // rest read
|
||||||
}
|
}
|
||||||
available_len -= payload_len;
|
available_len -= payload_len;
|
||||||
frame += payload_len;
|
frame += payload_len;
|
||||||
state = cmux_state::FOOTER;
|
state = cmux_state::FOOTER;
|
||||||
|
payload_len = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case cmux_state::FOOTER:
|
case cmux_state::FOOTER:
|
||||||
if (available_len == 0) {
|
if (available_len + frame_header_offset < 6) {
|
||||||
return false; // need read more
|
memcpy(frame_header + frame_header_offset, frame, available_len);
|
||||||
} else if (available_len == 1) {
|
frame_header_offset += available_len;
|
||||||
frame_header[4] = frame[0];
|
|
||||||
frame ++;
|
|
||||||
available_len --;
|
|
||||||
return false; // need read more
|
return false; // need read more
|
||||||
} else {
|
} 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) {
|
if (frame_header[5] != SOF_MARKER) {
|
||||||
ESP_LOGE("CMUX", "Footer Protocol mismatch!");
|
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;
|
state = cmux_state::RECOVER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (payload_len == 0) {
|
// if (payload_len == 0) {
|
||||||
data_available(frame_header, 0, 0); // Null payload
|
// data_available(frame_header, 0); // Null payload
|
||||||
}
|
// }
|
||||||
frame += footer_offset;
|
frame += footer_offset;
|
||||||
available_len -= footer_offset;
|
available_len -= footer_offset;
|
||||||
state = cmux_state::INIT;
|
state = cmux_state::INIT;
|
||||||
frame_header_offset = 0;
|
frame_header_offset = 0;
|
||||||
if (payload_len)
|
data_available(nullptr, 0);
|
||||||
data_available(nullptr, 0, -1); // Null payload
|
|
||||||
payload_start = nullptr;
|
payload_start = nullptr;
|
||||||
total_payload_size = 0;
|
total_payload_size = 0;
|
||||||
}
|
}
|
||||||
@ -264,7 +261,7 @@ bool CMux::init()
|
|||||||
{
|
{
|
||||||
int timeout = 0;
|
int timeout = 0;
|
||||||
send_sabm(i);
|
send_sabm(i);
|
||||||
while (true) {
|
while (1) {
|
||||||
usleep(10'000);
|
usleep(10'000);
|
||||||
Scoped<Lock> l(lock);
|
Scoped<Lock> l(lock);
|
||||||
if (sabm_ack == i) {
|
if (sabm_ack == i) {
|
||||||
|
@ -36,7 +36,7 @@ void Netif::on_ppp_changed(void *arg, esp_event_base_t event_base,
|
|||||||
esp_err_t Netif::esp_modem_dte_transmit(void *h, void *buffer, size_t len) {
|
esp_err_t Netif::esp_modem_dte_transmit(void *h, void *buffer, size_t len) {
|
||||||
auto *ppp = static_cast<Netif *>(h);
|
auto *ppp = static_cast<Netif *>(h);
|
||||||
if (ppp->signal.is_any(PPP_STARTED)) {
|
if (ppp->signal.is_any(PPP_STARTED)) {
|
||||||
if (ppp->ppp_dte->write((uint8_t *) buffer, len) > 0) {
|
if (ppp->ppp_dte && ppp->ppp_dte->write((uint8_t *) buffer, len) > 0) {
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,10 @@ void vfs_terminal::task() {
|
|||||||
|
|
||||||
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 size = ::read(uart.fd, data, len);
|
||||||
|
// if (size < 0 && errno == EWOULDBLOCK)
|
||||||
|
// return 0;
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vfs_terminal::write(uint8_t *data, size_t len)
|
int vfs_terminal::write(uint8_t *data, size_t len)
|
||||||
|
@ -224,6 +224,12 @@ void uart_terminal::task() {
|
|||||||
int uart_terminal::read(uint8_t *data, size_t len) {
|
int uart_terminal::read(uint8_t *data, size_t len) {
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
uart_get_buffered_data_len(uart.port, &length);
|
uart_get_buffered_data_len(uart.port, &length);
|
||||||
|
// if (esp_random() < UINT32_MAX/4 && length > 32) {
|
||||||
|
// printf("ahoj!\n");
|
||||||
|
// length = length - length/2;
|
||||||
|
// }
|
||||||
|
// size_t new_size = length/2;
|
||||||
|
length = std::min(len, length);
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
return uart_read_bytes(uart.port, data, length, portMAX_DELAY);
|
return uart_read_bytes(uart.port, data, length, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user