esp-modem: Update DTE processing per bugfix esp-idf!11006

This commit is contained in:
David Cermak
2021-01-04 16:22:26 +01:00
parent c8e89098bd
commit 8c066104a5
5 changed files with 63 additions and 28 deletions

View File

@ -85,5 +85,3 @@ esp_modem_recov_resend_t *esp_modem_recov_resend_new(esp_modem_dce_t *dce, dce_c
* *
*/ */
esp_modem_recov_gpio_t *esp_modem_recov_gpio_new(int gpio_num, int inactive_level, int active_width_ms, int inactive_width_ms); esp_modem_recov_gpio_t *esp_modem_recov_gpio_new(int gpio_num, int inactive_level, int active_width_ms, int inactive_width_ms);

View File

@ -187,4 +187,4 @@ esp_err_t esp_modem_dce_default_start_up(esp_modem_dce_t *dce)
return ESP_OK; return ESP_OK;
err: err:
return ESP_FAIL; return ESP_FAIL;
} }

View File

@ -200,5 +200,3 @@ esp_err_t esp_modem_command_list_deinit(esp_modem_dce_t *dce)
free(dce->dce_cmd_list); free(dce->dce_cmd_list);
return ESP_OK; return ESP_OK;
} }

View File

@ -354,4 +354,4 @@ esp_err_t esp_modem_dce_set_baud_temp(esp_modem_dce_t *dce, void *param, void *r
command[cmd_len+1] = '\0'; command[cmd_len+1] = '\0';
return esp_modem_dce_generic_command(dce, command, MODEM_COMMAND_TIMEOUT_DEFAULT, return esp_modem_dce_generic_command(dce, command, MODEM_COMMAND_TIMEOUT_DEFAULT,
esp_modem_dce_handle_response_default, NULL); esp_modem_dce_handle_response_default, NULL);
} }

View File

@ -71,23 +71,28 @@ esp_err_t esp_modem_set_rx_cb(esp_modem_dte_t *dte, esp_modem_on_receive receive
*/ */
static esp_err_t esp_dte_handle_line(esp_modem_dte_internal_t *esp_dte) static esp_err_t esp_dte_handle_line(esp_modem_dte_internal_t *esp_dte)
{ {
esp_err_t err = ESP_FAIL;
esp_modem_dce_t *dce = esp_dte->parent.dce; esp_modem_dce_t *dce = esp_dte->parent.dce;
ESP_MODEM_ERR_CHECK(dce, "DTE has not yet bind with DCE", err); ESP_MODEM_ERR_CHECK(dce, "DTE has not yet bind with DCE", err);
const char *line = (const char *)(esp_dte->buffer); const char *line = (const char *)(esp_dte->buffer);
size_t len = strlen(line); size_t len = strlen(line);
/* Skip pure "\r\n" lines */ /* Skip pure "\r\n" lines */
if (len > 2 && !is_only_cr_lf(line, len)) { if (len > 2 && !is_only_cr_lf(line, len)) {
ESP_MODEM_ERR_CHECK(dce->handle_line, "no handler for line", err_handle); if (dce->handle_line == NULL) {
ESP_LOGD(TAG, "%s: %s", __func__ , line); /* Received an asynchronous line, but no handler waiting this this */
ESP_MODEM_ERR_CHECK(dce->handle_line(dce, line) == ESP_OK, "handle line failed", err_handle); ESP_LOGD(TAG, "No handler for line: %s", line);
err = ESP_OK; /* Not an error, just propagate the line to user handler */
goto post_event_unknown;
}
ESP_MODEM_ERR_CHECK(dce->handle_line(dce, line) == ESP_OK, "handle line failed", err);
} }
return ESP_OK; return ESP_OK;
err_handle: post_event_unknown:
/* Send ESP_MODEM_EVENT_UNKNOWN signal to event loop */ /* Send ESP_MODEM_EVENT_UNKNOWN signal to event loop */
esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, ESP_MODEM_EVENT_UNKNOWN, esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, ESP_MODEM_EVENT_UNKNOWN,
(void *)line, strlen(line) + 1, pdMS_TO_TICKS(100)); (void *)line, strlen(line) + 1, pdMS_TO_TICKS(100));
err: err:
return ESP_FAIL; return err;
} }
/** /**
@ -99,6 +104,15 @@ static void esp_handle_uart_pattern(esp_modem_dte_internal_t *esp_dte)
{ {
int pos = uart_pattern_pop_pos(esp_dte->uart_port); int pos = uart_pattern_pop_pos(esp_dte->uart_port);
int read_len = 0; int read_len = 0;
if (esp_dte->parent.dce->mode == ESP_MODEM_PPP_MODE) {
ESP_LOGD(TAG, "Pattern event in PPP mode ignored");
// Ignore potential pattern detection events in PPP mode
// Note 1: the interrupt is disabled, but some events might still be pending
// Note 2: checking the mode *after* uart_pattern_pop_pos() to consume the event
return;
}
if (pos != -1) { if (pos != -1) {
if (pos < esp_dte->line_buffer_size - 1) { if (pos < esp_dte->line_buffer_size - 1) {
/* read one line(include '\n') */ /* read one line(include '\n') */
@ -119,11 +133,12 @@ static void esp_handle_uart_pattern(esp_modem_dte_internal_t *esp_dte)
} else { } else {
size_t length = 0; size_t length = 0;
uart_get_buffered_data_len(esp_dte->uart_port, &length); uart_get_buffered_data_len(esp_dte->uart_port, &length);
ESP_LOGW(TAG, "Pattern not found in the pattern queue, uart data length = %d", length); if (length) {
length = MIN(esp_dte->line_buffer_size-1, length); ESP_LOGD(TAG, "Pattern not found in the pattern queue, uart data length = %d", length);
length = uart_read_bytes(esp_dte->uart_port, esp_dte->buffer, length, portMAX_DELAY); length = MIN(esp_dte->line_buffer_size-1, length);
ESP_LOG_BUFFER_HEXDUMP("esp-modem-dte: debug_data", esp_dte->buffer, length, ESP_LOG_DEBUG); length = uart_read_bytes(esp_dte->uart_port, esp_dte->buffer, length, portMAX_DELAY);
ESP_LOG_BUFFER_HEXDUMP("esp-modem-pattern: debug_data", esp_dte->buffer, length, ESP_LOG_DEBUG);
}
uart_flush(esp_dte->uart_port); uart_flush(esp_dte->uart_port);
} }
} }
@ -135,17 +150,12 @@ static void esp_handle_uart_pattern(esp_modem_dte_internal_t *esp_dte)
*/ */
static void esp_handle_uart_data(esp_modem_dte_internal_t *esp_dte) static void esp_handle_uart_data(esp_modem_dte_internal_t *esp_dte)
{ {
if (!esp_dte->parent.dce) {
// we could possibly get a data event before
// the DCE gets bound yet with the DTE, so just return
return;
}
size_t length = 0; size_t length = 0;
uart_get_buffered_data_len(esp_dte->uart_port, &length); uart_get_buffered_data_len(esp_dte->uart_port, &length);
if (esp_dte->parent.dce->mode != ESP_MODEM_PPP_MODE) { if (esp_dte->parent.dce->mode != ESP_MODEM_PPP_MODE && length) {
// Check if matches the pattern to process the data as pattern // Check if matches the pattern to process the data as pattern
int pos = uart_pattern_pop_pos(esp_dte->uart_port); int pos = uart_pattern_get_pos(esp_dte->uart_port);
if (pos > -1) { if (pos > -1) {
esp_handle_uart_pattern(esp_dte); esp_handle_uart_pattern(esp_dte);
return; return;
@ -153,10 +163,24 @@ static void esp_handle_uart_data(esp_modem_dte_internal_t *esp_dte)
// Read the data and process it using `handle_line` logic // Read the data and process it using `handle_line` logic
length = MIN(esp_dte->line_buffer_size-1, length); length = MIN(esp_dte->line_buffer_size-1, length);
length = uart_read_bytes(esp_dte->uart_port, esp_dte->buffer, length, portMAX_DELAY); length = uart_read_bytes(esp_dte->uart_port, esp_dte->buffer, length, portMAX_DELAY);
ESP_LOG_BUFFER_HEXDUMP("esp-modem-dte: debug_data", esp_dte->buffer, length, ESP_LOG_DEBUG);
esp_dte->buffer[length] = '\0'; esp_dte->buffer[length] = '\0';
if (strchr((char*)esp_dte->buffer, '\n') == NULL) {
size_t max = esp_dte->line_buffer_size-1;
size_t bytes;
// if pattern not found in the data,
// continue reading as long as the modem is in MODEM_STATE_PROCESSING, checking for the pattern
while (length < max && esp_dte->buffer[length-1] != '\n' &&
esp_dte->parent.dce->state == ESP_MODEM_STATE_PROCESSING) {
bytes = uart_read_bytes(esp_dte->uart_port,
esp_dte->buffer + length, 1, pdMS_TO_TICKS(100));
length += bytes;
ESP_LOGV("esp-modem: debug_data", "Continuous read in non-data mode: length: %d char: %x", length, esp_dte->buffer[length-1]);
}
esp_dte->buffer[length] = '\0';
}
ESP_LOG_BUFFER_HEXDUMP("esp-modem: debug_data", esp_dte->buffer, length, ESP_LOG_DEBUG);
if (esp_dte->parent.dce->handle_line) { if (esp_dte->parent.dce->handle_line) {
// Send new line to handle if handler registered /* Send new line to handle if handler registered */
esp_dte_handle_line(esp_dte); esp_dte_handle_line(esp_dte);
} }
return; return;
@ -185,7 +209,20 @@ static void uart_event_task_entry(void *param)
} }
while (xEventGroupGetBits(esp_dte->process_group) & ESP_MODEM_START_BIT) { while (xEventGroupGetBits(esp_dte->process_group) & ESP_MODEM_START_BIT) {
/* Drive the event loop */
esp_event_loop_run(esp_dte->event_loop_hdl, pdMS_TO_TICKS(0));
/* Process UART events */
if (xQueueReceive(esp_dte->event_queue, &event, pdMS_TO_TICKS(100))) { if (xQueueReceive(esp_dte->event_queue, &event, pdMS_TO_TICKS(100))) {
if (esp_dte->parent.dce == NULL) {
ESP_LOGD(TAG, "Ignore UART event for DTE with no DCE attached");
// No action on any uart event with null DCE.
// This might happen before DCE gets initialized and attached to running DTE,
// or after destroying the DCE when DTE is up and gets a data event.
uart_flush(esp_dte->uart_port);
continue;
}
switch (event.type) { switch (event.type) {
case UART_DATA: case UART_DATA:
esp_handle_uart_data(esp_dte); esp_handle_uart_data(esp_dte);
@ -217,8 +254,6 @@ static void uart_event_task_entry(void *param)
break; break;
} }
} }
/* Drive the event loop */
esp_event_loop_run(esp_dte->event_loop_hdl, pdMS_TO_TICKS(0));
} }
vTaskDelete(NULL); vTaskDelete(NULL);
} }
@ -270,6 +305,10 @@ static int esp_modem_dte_send_data(esp_modem_dte_t *dte, const char *data, uint3
ESP_LOGD(TAG, "Not sending data in transition mode"); ESP_LOGD(TAG, "Not sending data in transition mode");
return -1; return -1;
} }
if (esp_dte->parent.dce->mode == ESP_MODEM_TRANSITION_MODE) {
ESP_LOGD(TAG, "Not sending data in transition mode");
return -1;
}
ESP_LOG_BUFFER_HEXDUMP("esp-modem-dte: ppp_output", data, length, ESP_LOG_VERBOSE); ESP_LOG_BUFFER_HEXDUMP("esp-modem-dte: ppp_output", data, length, ESP_LOG_VERBOSE);
return uart_write_bytes(esp_dte->uart_port, data, length); return uart_write_bytes(esp_dte->uart_port, data, length);
@ -502,4 +541,4 @@ esp_err_t esp_modem_dte_set_params(esp_modem_dte_t *dte, const esp_modem_dte_con
{ {
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent); esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
return uart_set_baudrate(esp_dte->uart_port, config->baud_rate); return uart_set_baudrate(esp_dte->uart_port, config->baud_rate);
} }