serial port moved to webguiapp component, configuration created
This commit is contained in:
parent
44152875b1
commit
98fe7edbb5
|
|
@ -26,6 +26,7 @@ idf_component_register(
|
|||
"src/SNTP.c"
|
||||
"src/MQTT.c"
|
||||
"src/CronTimers.c"
|
||||
"src/SerialPort.c"
|
||||
src/OTA.c
|
||||
src/RestApiHandler.c
|
||||
src/SysComm.c
|
||||
|
|
|
|||
75
Kconfig
75
Kconfig
|
|
@ -785,6 +785,81 @@ menu "WebGUIApp"
|
|||
endif
|
||||
endmenu
|
||||
|
||||
menu "Serial port configuration"
|
||||
|
||||
config UART_TRANSPORT_ENABLE
|
||||
bool "Enabled serial port"
|
||||
default n
|
||||
help
|
||||
Set enabled uart output data
|
||||
|
||||
if UART_TRANSPORT_ENABLE
|
||||
config UART_PORT_NUM
|
||||
int "UART port number"
|
||||
range 0 2
|
||||
default 2
|
||||
help
|
||||
UART communication port number for the example.
|
||||
See UART documentation for available port numbers.
|
||||
|
||||
config UART_TO_MQTT_BRIDGE_ENABLED
|
||||
bool "Enabled UART<->MQTT bridge"
|
||||
default n
|
||||
help
|
||||
Switch on bridge uart to mqtt, else uart operate same way as rest and mqtt data exchange
|
||||
|
||||
config UART_BAUD_RATE
|
||||
int "UART communication speed"
|
||||
range 1200 115200
|
||||
default 115200
|
||||
help
|
||||
UART communication speed.
|
||||
|
||||
config UART_RXD
|
||||
int "UART RXD pin number"
|
||||
range 0 39
|
||||
default 35
|
||||
help
|
||||
GPIO number for UART RX pin. See UART documentation for more information
|
||||
about available pin numbers for UART.
|
||||
|
||||
config UART_TXD
|
||||
int "UART TXD pin number"
|
||||
range 0 33
|
||||
default 33
|
||||
help
|
||||
GPIO number for UART TX pin. See UART documentation for more information
|
||||
about available pin numbers for UART.
|
||||
|
||||
|
||||
config UART_MODE_RS485_ENABLED
|
||||
bool "Enabled RS485 mode"
|
||||
default n
|
||||
help
|
||||
Set UART to RS485 mode with hardware driver
|
||||
|
||||
if UART_MODE_RS485_ENABLED
|
||||
|
||||
config UART_RTS
|
||||
int "RS485 RE/DE pin number"
|
||||
range -1 33
|
||||
default 32
|
||||
help
|
||||
GPIO number for UART RTS pin. This pin is connected to
|
||||
~RE/DE pin of RS485 transceiver to switch direction.
|
||||
|
||||
endif
|
||||
|
||||
config UART_BUF_SIZE
|
||||
int "UART RAM buffer size"
|
||||
range 64 4096
|
||||
default 1024
|
||||
help
|
||||
UART buffer size both for rx and tx.
|
||||
|
||||
endif
|
||||
endmenu
|
||||
|
||||
menu "Modbus settings"
|
||||
config WEBGUIAPP_MBTCP_ENABLED
|
||||
bool "Enabled modbus TCP"
|
||||
|
|
|
|||
|
|
@ -107,6 +107,15 @@ typedef struct
|
|||
int err_code;
|
||||
} data_message_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *raw_data_ptr;
|
||||
int data_length;
|
||||
}UART_DATA_SEND_STRUCT;
|
||||
|
||||
void InitSerialPort(void);
|
||||
esp_err_t TransmitSerialPort(char *data, int ln);
|
||||
|
||||
esp_err_t GetConfVar(char* name, char* val, rest_var_types *tp);
|
||||
esp_err_t SetConfVar(char* name, char* val, rest_var_types *tp);
|
||||
|
||||
|
|
|
|||
262
src/SerialPort.c
Normal file
262
src/SerialPort.c
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
/*! Copyright 2023 Bogdan Pilyugin
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* \file SerialPort.c
|
||||
* \version 1.0
|
||||
* \date 2023-10-15
|
||||
* \author Bogdan Pilyugin
|
||||
* \brief
|
||||
* \details
|
||||
* \copyright Apache License, Version 2.0
|
||||
*/
|
||||
|
||||
#include <driver/uart.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_log.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/portmacro.h>
|
||||
#include <freertos/projdefs.h>
|
||||
#include <freertos/queue.h>
|
||||
#include <freertos/task.h>
|
||||
#include <hal/uart_types.h>
|
||||
#include <MQTT.h>
|
||||
#include <sdkconfig.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "webguiapp.h"
|
||||
|
||||
#define TAG "serial_port"
|
||||
#define UART_READ_TOUT (100) // 3.5T * 8 = 28 ticks, TOUT=3 -> ~24..33 ticks
|
||||
#define PATTERN_CHR_NUM (3) /*!< Set the number of consecutive and identical characters received by receiver which defines a UART pattern*/
|
||||
|
||||
#define UART_TX_QUEUE_SIZE (5)
|
||||
#define UART_RX_QUEUE_SIZE (5)
|
||||
|
||||
#define UART_DEBUG_MODE 0
|
||||
|
||||
QueueHandle_t UARTtxQueueHandle;
|
||||
static StaticQueue_t xStaticUARTtxQueue;
|
||||
uint8_t UARTtxQueueStorageArea[UART_TX_QUEUE_SIZE * sizeof(UART_DATA_SEND_STRUCT)];
|
||||
|
||||
static QueueHandle_t uart_event_queue;
|
||||
static char rxbuf[CONFIG_UART_BUF_SIZE];
|
||||
|
||||
esp_err_t TransmitSerialPort(char *data, int ln)
|
||||
{
|
||||
UART_DATA_SEND_STRUCT DSS;
|
||||
char *buf = malloc(ln);
|
||||
if (!buf)
|
||||
return ESP_ERR_NO_MEM;
|
||||
|
||||
memcpy(buf, data, ln);
|
||||
DSS.raw_data_ptr = buf;
|
||||
DSS.data_length = ln;
|
||||
if (xQueueSend(UARTtxQueueHandle, &DSS, 0) != pdPASS)
|
||||
{
|
||||
free(buf);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void ReceiveHandlerAPI()
|
||||
{
|
||||
char *respbuf = malloc(EXPECTED_MAX_DATA_SIZE);
|
||||
if (respbuf)
|
||||
{
|
||||
data_message_t M = { 0 };
|
||||
M.inputDataBuffer = rxbuf;
|
||||
M.inputDataLength = strlen(rxbuf);
|
||||
M.chlidx = 100;
|
||||
M.outputDataBuffer = respbuf;
|
||||
M.outputDataLength = EXPECTED_MAX_DATA_SIZE;
|
||||
ServiceDataHandler(&M);
|
||||
|
||||
if (M.outputDataBuffer[0] != 0x00 && M.outputDataLength > 0)
|
||||
{
|
||||
TransmitSerialPort(M.outputDataBuffer, MIN(EXPECTED_MAX_DATA_SIZE, strlen(M.outputDataBuffer)));
|
||||
}
|
||||
free(respbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "Out of free RAM for HTTP API handle");
|
||||
}
|
||||
}
|
||||
|
||||
void serial_RX_task(void *arg)
|
||||
{
|
||||
uart_event_t event;
|
||||
int buffered_size;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
//Waiting for UART event.
|
||||
if (xQueueReceive(uart_event_queue, (void*) &event, portMAX_DELAY))
|
||||
{
|
||||
#if UART_DEBUG_MODE == 1
|
||||
ESP_LOGI(TAG, "uart[%d] event:%d", CONFIG_UART_PORT_NUM, event.type);
|
||||
#endif
|
||||
switch (event.type)
|
||||
{
|
||||
//Event of UART receving data
|
||||
/*We'd better handler data event fast, there would be much more data events than
|
||||
other types of events. If we take too much time on data event, the queue might
|
||||
be full.*/
|
||||
case UART_DATA:
|
||||
if (event.timeout_flag)
|
||||
{
|
||||
|
||||
bzero(rxbuf, CONFIG_UART_BUF_SIZE);
|
||||
uart_get_buffered_data_len(CONFIG_UART_PORT_NUM, (size_t*) &buffered_size);
|
||||
if (buffered_size)
|
||||
{
|
||||
uart_read_bytes(CONFIG_UART_PORT_NUM, rxbuf, buffered_size, 100);
|
||||
#if UART_DEBUG_MODE == 1
|
||||
ESP_LOGI(TAG, "read of %d bytes: %s", buffered_size, rxbuf);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ UART_TO_MQTT_BRIDGE_ENABLED
|
||||
ExternalServiceMQTTSend(rxbuf, buffered_size, 0);
|
||||
ExternalServiceMQTTSend(rxbuf, buffered_size, 1);
|
||||
#else
|
||||
ReceiveHandlerAPI();
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
//Event of HW FIFO overflow detected
|
||||
case UART_FIFO_OVF:
|
||||
|
||||
#if UART_DEBUG_MODE == 1
|
||||
ESP_LOGI(TAG, "hw fifo overflow");
|
||||
#endif
|
||||
// If fifo overflow happened, you should consider adding flow control for your application.
|
||||
// The ISR has already reset the rx FIFO,
|
||||
// As an example, we directly flush the rx buffer here in order to read more data.
|
||||
uart_flush_input(CONFIG_UART_PORT_NUM);
|
||||
xQueueReset(uart_event_queue);
|
||||
break;
|
||||
//Event of UART ring buffer full
|
||||
case UART_BUFFER_FULL:
|
||||
ESP_LOGE(TAG, "ring buffer full");
|
||||
// If buffer full happened, you should consider encreasing your buffer size
|
||||
// As an example, we directly flush the rx buffer here in order to read more data.
|
||||
uart_flush_input(CONFIG_UART_PORT_NUM);
|
||||
xQueueReset(uart_event_queue);
|
||||
break;
|
||||
//Event of UART RX break detected
|
||||
case UART_BREAK:
|
||||
#if UART_DEBUG_MODE == 1
|
||||
ESP_LOGI(TAG, "uart rx break");
|
||||
#endif
|
||||
break;
|
||||
//Event of UART parity check error
|
||||
case UART_PARITY_ERR:
|
||||
ESP_LOGE(TAG, "uart parity error");
|
||||
break;
|
||||
//Event of UART frame error
|
||||
case UART_FRAME_ERR:
|
||||
ESP_LOGE(TAG, "uart frame error");
|
||||
break;
|
||||
//UART_PATTERN_DET
|
||||
case UART_PATTERN_DET:
|
||||
|
||||
uart_get_buffered_data_len(CONFIG_UART_PORT_NUM, (size_t*) &buffered_size);
|
||||
int pos = uart_pattern_pop_pos(CONFIG_UART_PORT_NUM);
|
||||
#if UART_DEBUG_MODE == 1
|
||||
ESP_LOGI(TAG, "[UART PATTERN DETECTED] pos: %d, buffered size: %d", (int )pos, (int )buffered_size);
|
||||
#endif
|
||||
if (pos == -1)
|
||||
{
|
||||
// There used to be a UART_PATTERN_DET event, but the pattern position queue is full so that it can not
|
||||
// record the position. We should set a larger queue size.
|
||||
// As an example, we directly flush the rx buffer here.
|
||||
uart_flush_input(CONFIG_UART_PORT_NUM);
|
||||
}
|
||||
else
|
||||
{
|
||||
uart_read_bytes(CONFIG_UART_PORT_NUM, rxbuf, pos, 100 / portTICK_PERIOD_MS);
|
||||
uint8_t pat[PATTERN_CHR_NUM + 1];
|
||||
memset(pat, 0, sizeof(pat));
|
||||
uart_read_bytes(CONFIG_UART_PORT_NUM, pat, PATTERN_CHR_NUM, 100 / portTICK_PERIOD_MS);
|
||||
#if UART_DEBUG_MODE == 1
|
||||
ESP_LOGI(TAG, "read data: %s", rxbuf);
|
||||
ESP_LOGI(TAG, "read pat : %s", pat);
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
//Others
|
||||
default:
|
||||
ESP_LOGW(TAG, "uart event type: %d", event.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void static serial_TX_task(void *arg)
|
||||
{
|
||||
UART_DATA_SEND_STRUCT DSS;
|
||||
while (1)
|
||||
{
|
||||
xQueueReceive(UARTtxQueueHandle, &DSS, portMAX_DELAY);
|
||||
if (uart_write_bytes(CONFIG_UART_PORT_NUM, DSS.raw_data_ptr, DSS.data_length)
|
||||
!= DSS.data_length)
|
||||
ESP_LOGE(TAG, "RS485 write data failure");
|
||||
free(DSS.raw_data_ptr);
|
||||
if (uart_wait_tx_done(CONFIG_UART_PORT_NUM, pdMS_TO_TICKS(1000)) != ESP_OK)
|
||||
ESP_LOGE(TAG, "RS485 transmit data failure");
|
||||
}
|
||||
}
|
||||
|
||||
void InitSerialPort(void)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = CONFIG_UART_BAUD_RATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_APB,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(uart_driver_install(CONFIG_UART_PORT_NUM, CONFIG_UART_BUF_SIZE * 2, 0, 20, &uart_event_queue, 0));
|
||||
ESP_ERROR_CHECK(uart_param_config(CONFIG_UART_PORT_NUM, &uart_config));
|
||||
ESP_ERROR_CHECK(uart_set_pin(CONFIG_UART_PORT_NUM, CONFIG_UART_TXD, CONFIG_UART_RXD, CONFIG_UART_RTS, -1));
|
||||
ESP_ERROR_CHECK(uart_set_mode(CONFIG_UART_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX));
|
||||
|
||||
ESP_ERROR_CHECK(uart_enable_rx_intr(CONFIG_UART_PORT_NUM));
|
||||
ESP_ERROR_CHECK(uart_set_rx_timeout(CONFIG_UART_PORT_NUM, UART_READ_TOUT));
|
||||
//ESP_ERROR_CHECK(uart_enable_pattern_det_baud_intr(CONFIG_UART_PORT_NUM, '+', PATTERN_CHR_NUM, 9, 0, 0));
|
||||
uart_pattern_queue_reset(CONFIG_UART_PORT_NUM, 20);
|
||||
|
||||
UARTtxQueueHandle = NULL;
|
||||
UARTtxQueueHandle = xQueueCreateStatic(UART_TX_QUEUE_SIZE,
|
||||
sizeof(UART_DATA_SEND_STRUCT),
|
||||
UARTtxQueueStorageArea,
|
||||
&xStaticUARTtxQueue);
|
||||
|
||||
xTaskCreate(serial_TX_task, "RS485txTask", 1024 * 2, (void*) 0, 7, NULL);
|
||||
xTaskCreate(serial_RX_task, "RS485rxTask", 1024 * 4, (void*) 0, 12, NULL);
|
||||
ESP_LOGI(TAG, "Serial port initialized on UART%d with baudrate %d", CONFIG_UART_PORT_NUM,
|
||||
CONFIG_UART_BAUD_RATE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user