Files
esp-protocols/esp_modem/src/esp_modem_uart.cpp

238 lines
8.3 KiB
C++
Raw Normal View History

2021-03-29 19:34:45 +02:00
// 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.
2021-03-03 20:35:08 +01:00
#include "cxx_include/esp_modem_dte.hpp"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_log.h"
#include "driver/uart.h"
2021-03-08 15:10:15 +01:00
#include "esp_modem_config.h"
2021-03-16 21:36:13 +01:00
#include "exception_stub.hpp"
2021-03-03 20:35:08 +01:00
static const char *TAG = "uart_terminal";
2021-03-29 19:34:45 +02:00
namespace esp_modem {
2021-03-03 20:35:08 +01:00
struct uart_resource {
2021-03-08 15:10:15 +01:00
explicit uart_resource(const esp_modem_dte_config *config);
2021-03-03 20:35:08 +01:00
~uart_resource();
2021-03-29 19:34:45 +02:00
bool get_event(uart_event_t &event, uint32_t time_ms) {
2021-03-03 20:35:08 +01:00
return xQueueReceive(event_queue, &event, pdMS_TO_TICKS(time_ms));
}
2021-03-29 19:34:45 +02:00
void reset_events() {
2021-03-03 20:35:08 +01:00
uart_flush_input(port);
xQueueReset(event_queue);
}
uart_port_t port; /*!< UART port */
QueueHandle_t event_queue; /*!< UART event queue handle */
};
struct uart_task {
2021-03-29 19:34:45 +02:00
explicit uart_task(size_t stack_size, size_t priority, void *task_param, TaskFunction_t task_function) :
task_handle(nullptr) {
2021-04-18 19:14:22 +02:00
BaseType_t ret = xTaskCreate(task_function, "uart_task", stack_size, task_param, priority, &task_handle);
2021-03-03 20:35:08 +01:00
throw_if_false(ret == pdTRUE, "create uart event task failed");
}
2021-03-29 19:34:45 +02:00
~uart_task() {
2021-03-03 20:35:08 +01:00
if (task_handle) vTaskDelete(task_handle);
}
TaskHandle_t task_handle; /*!< UART event task handle */
};
2021-04-18 19:14:22 +02:00
uart_resource::~uart_resource()
{
2021-03-03 20:35:08 +01:00
if (port >= UART_NUM_0 && port < UART_NUM_MAX) {
uart_driver_delete(port);
}
}
2021-03-29 19:34:45 +02:00
uart_resource::uart_resource(const esp_modem_dte_config *config) :
2021-04-18 19:14:22 +02:00
port(-1)
{
2021-03-03 20:35:08 +01:00
esp_err_t res;
/* Config UART */
uart_config_t uart_config = {};
2021-04-18 19:14:22 +02:00
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;
2021-03-03 20:35:08 +01:00
uart_config.source_clk = UART_SCLK_REF_TICK;
2021-04-18 19:14:22 +02:00
throw_if_esp_fail(uart_param_config(config->uart_config.port_num, &uart_config), "config uart parameter failed");
2021-03-03 20:35:08 +01:00
2021-04-18 19:14:22 +02:00
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);
2021-03-03 20:35:08 +01:00
} else {
2021-04-18 19:14:22 +02:00
res = uart_set_pin(config->uart_config.port_num, config->uart_config.tx_io_num, config->uart_config.rx_io_num,
2021-03-03 20:35:08 +01:00
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}
throw_if_esp_fail(res, "config uart gpio failed");
/* Set flow control threshold */
2021-04-18 19:14:22 +02:00
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);
2021-03-03 20:35:08 +01:00
}
throw_if_esp_fail(res, "config uart flow control failed");
/* Install UART driver and get event queue used inside driver */
2021-04-18 19:14:22 +02:00
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);
2021-03-03 20:35:08 +01:00
throw_if_esp_fail(res, "install uart driver failed");
2021-04-18 19:14:22 +02:00
throw_if_esp_fail(uart_set_rx_timeout(config->uart_config.port_num, 1), "set rx timeout failed");
2021-03-03 20:35:08 +01:00
2021-04-18 19:14:22 +02:00
uart_set_rx_full_threshold(config->uart_config.port_num, 64);
2021-03-03 20:35:08 +01:00
throw_if_esp_fail(res, "config uart pattern failed");
/* mark UART as initialized */
2021-04-18 19:14:22 +02:00
port = config->uart_config.port_num;
2021-03-03 20:35:08 +01:00
}
2021-03-29 19:34:45 +02:00
class uart_terminal : public Terminal {
2021-03-03 20:35:08 +01:00
public:
2021-03-29 19:34:45 +02:00
explicit uart_terminal(const esp_modem_dte_config *config) :
2021-04-18 19:14:22 +02:00
uart(config), signal(),
task_handle(config->uart_config.event_task_stack_size, config->uart_config.event_task_priority, this, s_task) {}
2021-03-03 20:35:08 +01:00
~uart_terminal() override = default;
2021-03-29 19:34:45 +02:00
void start() override {
2021-03-03 20:35:08 +01:00
signal.set(TASK_START);
}
2021-03-29 19:34:45 +02:00
void stop() override {
2021-03-03 20:35:08 +01:00
signal.set(TASK_STOP);
}
int write(uint8_t *data, size_t len) override;
2021-03-29 19:34:45 +02:00
2021-03-03 20:35:08 +01:00
int read(uint8_t *data, size_t len) override;
2021-03-29 19:34:45 +02:00
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override {
2021-03-04 20:19:18 +01:00
on_data = std::move(f);
signal.set(TASK_PARAMS);
}
2021-03-29 19:34:45 +02:00
2021-03-03 20:35:08 +01:00
private:
2021-03-29 19:34:45 +02:00
static void s_task(void *task_param) {
auto t = static_cast<uart_terminal *>(task_param);
2021-03-03 20:35:08 +01:00
t->task();
vTaskDelete(NULL);
}
2021-03-29 19:34:45 +02:00
2021-03-03 20:35:08 +01:00
void task();
2021-03-04 20:19:18 +01:00
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;
2021-03-03 20:35:08 +01:00
uart_resource uart;
signal_group signal;
uart_task task_handle;
};
2021-03-29 19:34:45 +02:00
std::unique_ptr<Terminal> create_uart_terminal(const esp_modem_dte_config *config) {
2021-03-16 21:36:13 +01:00
TRY_CATCH_RET_NULL(
2021-03-29 19:34:45 +02:00
auto term = std::make_unique<uart_terminal>(config);
term->start();
return term;
2021-03-16 21:36:13 +01:00
)
2021-03-03 20:35:08 +01:00
}
2021-03-29 19:34:45 +02:00
void uart_terminal::task() {
std::function<bool(uint8_t *data, size_t len)> on_data_priv = nullptr;
2021-03-03 20:35:08 +01:00
uart_event_t event;
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
}
2021-03-29 19:34:45 +02:00
while (signal.is_any(TASK_START)) {
2021-03-03 20:35:08 +01:00
if (uart.get_event(event, 100)) {
2021-03-04 20:19:18 +01:00
if (signal.is_any(TASK_PARAMS)) {
on_data_priv = on_data;
signal.clear(TASK_PARAMS);
}
2021-03-03 20:35:08 +01:00
switch (event.type) {
case UART_DATA:
uart_get_buffered_data_len(uart.port, &len);
2021-03-04 20:19:18 +01:00
if (len && on_data_priv) {
if (on_data_priv(nullptr, len)) {
2021-03-04 20:19:18 +01:00
on_data_priv = nullptr;
}
2021-03-03 20:35:08 +01:00
}
break;
case UART_FIFO_OVF:
ESP_LOGW(TAG, "HW FIFO Overflow");
2021-04-18 19:14:22 +02:00
if (on_error)
on_error(terminal_error::BUFFER_OVERFLOW);
2021-03-03 20:35:08 +01:00
uart.reset_events();
break;
case UART_BUFFER_FULL:
ESP_LOGW(TAG, "Ring Buffer Full");
2021-04-18 19:14:22 +02:00
if (on_error)
on_error(terminal_error::BUFFER_OVERFLOW);
2021-03-03 20:35:08 +01:00
uart.reset_events();
break;
case UART_BREAK:
ESP_LOGW(TAG, "Rx Break");
2021-04-18 19:14:22 +02:00
if (on_error)
on_error(terminal_error::UNEXPECTED_CONTROL_FLOW);
2021-03-03 20:35:08 +01:00
break;
case UART_PARITY_ERR:
ESP_LOGE(TAG, "Parity Error");
2021-04-18 19:14:22 +02:00
if (on_error)
on_error(terminal_error::CHECKSUM_ERROR);
2021-03-03 20:35:08 +01:00
break;
case UART_FRAME_ERR:
ESP_LOGE(TAG, "Frame Error");
2021-04-18 19:14:22 +02:00
if (on_error)
on_error(terminal_error::UNEXPECTED_CONTROL_FLOW);
2021-03-03 20:35:08 +01:00
break;
default:
ESP_LOGW(TAG, "unknown uart event type: %d", event.type);
break;
}
}
}
}
2021-03-29 19:34:45 +02:00
int uart_terminal::read(uint8_t *data, size_t len) {
2021-03-03 20:35:08 +01:00
size_t length = 0;
uart_get_buffered_data_len(uart.port, &length);
if (length > 0) {
return uart_read_bytes(uart.port, data, length, portMAX_DELAY);
}
return 0;
}
2021-03-29 19:34:45 +02:00
int uart_terminal::write(uint8_t *data, size_t len) {
2021-03-03 20:35:08 +01:00
return uart_write_bytes(uart.port, data, len);
}
2021-03-29 19:34:45 +02:00
} // namespace esp_modem
2021-03-03 20:35:08 +01:00