serial master, slave fix parity check

This commit is contained in:
aleks
2023-02-09 17:40:59 +01:00
parent a854d3b188
commit cc04189b0a
7 changed files with 124 additions and 99 deletions

View File

@ -159,6 +159,17 @@ typedef struct {
BOOL xTimerState;
} xTimerContext_t;
typedef struct {
QueueHandle_t xMbUartQueue; /*!< A queue to handle UART event. */
TaskHandle_t xMbTaskHandle; /*!< Serial task handle */
UCHAR ucUartNumber; /*!< The UART hardware port number */
BOOL bRxStateEnabled; /*!< Receiver enabled flag */
BOOL bTxStateEnabled; /*!< Transmitter enabled flag */
SemaphoreHandle_t xRxSemaHandle; /*!< Rx blocking semaphore handle */
ULONG ulParityErrors; /*!< Parity errors counter */
ULONG ulFrameErrors; /*!< Frame errors counter */
} MBMSerialContext_t;
void vMBPortEnterCritical(void);
void vMBPortExitCritical(void);

View File

@ -292,12 +292,12 @@ eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) {
xEventGroupSetBits( xEventGroupMasterConfirmHdl, (xRecvedEvent & MB_EVENT_REQ_MASK) );
if (MB_PORT_CHECK_EVENT(xRecvedEvent, EV_MASTER_PROCESS_SUCCESS)) {
eErrStatus = MB_MRE_NO_ERR;
} else if (MB_PORT_CHECK_EVENT(xRecvedEvent, EV_MASTER_ERROR_RESPOND_TIMEOUT)) {
eErrStatus = MB_MRE_TIMEDOUT;
} else if (MB_PORT_CHECK_EVENT(xRecvedEvent, EV_MASTER_ERROR_RECEIVE_DATA)) {
eErrStatus = MB_MRE_REV_DATA;
} else if (MB_PORT_CHECK_EVENT(xRecvedEvent, EV_MASTER_ERROR_EXECUTE_FUNCTION)) {
eErrStatus = MB_MRE_EXE_FUN;
} else if (MB_PORT_CHECK_EVENT(xRecvedEvent, EV_MASTER_ERROR_RESPOND_TIMEOUT)) {
eErrStatus = MB_MRE_TIMEDOUT;
}
} else {
ESP_LOGE(MB_PORT_TAG,"%s: Incorrect event or timeout xRecvedEvent = 0x%x", __func__, uxBits);

View File

@ -50,33 +50,34 @@
#include "port_serial_slave.h"
// Note: This code uses mixed coding standard from legacy IDF code and used freemodbus stack
// A queue to handle UART event.
static QueueHandle_t xMbUartQueue;
static TaskHandle_t xMbTaskHandle;
static const CHAR *TAG = "MB_SERIAL";
// The UART hardware port number
static UCHAR ucUartNumber = UART_NUM_MAX - 1;
static BOOL bRxStateEnabled = FALSE; // Receiver enabled flag
static BOOL bTxStateEnabled = FALSE; // Transmitter enabled flag
// Serial communication context structure
static MBMSerialContext_t xMBSCtx = {
.xMbUartQueue = NULL,
.xMbTaskHandle = NULL,
.ucUartNumber = UART_NUM_MAX - 1,
.xRxSemaHandle = NULL,
.bTxStateEnabled = FALSE,
.bRxStateEnabled = FALSE,
.ulParityErrors = 0
};
void vMBPortSerialEnable(BOOL bRxEnable, BOOL bTxEnable)
{
// This function can be called from xMBRTUTransmitFSM() of different task
if (bTxEnable) {
bTxStateEnabled = TRUE;
xMBSCtx.bTxStateEnabled = TRUE;
} else {
bTxStateEnabled = FALSE;
xMBSCtx.bTxStateEnabled = FALSE;
}
if (bRxEnable) {
//uart_enable_rx_intr(ucUartNumber);
bRxStateEnabled = TRUE;
vTaskResume(xMbTaskHandle); // Resume receiver task
xMBSCtx.bRxStateEnabled = TRUE;
vTaskResume(xMBSCtx.xMbTaskHandle); // Resume receiver task
} else {
vTaskSuspend(xMbTaskHandle); // Block receiver task
bRxStateEnabled = FALSE;
vTaskSuspend(xMBSCtx.xMbTaskHandle); // Block receiver task
xMBSCtx.bRxStateEnabled = FALSE;
}
}
@ -85,13 +86,13 @@ static USHORT usMBPortSerialRxPoll(size_t xEventSize)
BOOL xReadStatus = TRUE;
USHORT usCnt = 0;
if (bRxStateEnabled) {
if (xMBSCtx.bRxStateEnabled) {
// Get received packet into Rx buffer
while(xReadStatus && (usCnt++ <= xEventSize)) {
// Call the Modbus stack callback function and let it fill the buffers.
xReadStatus = pxMBFrameCBByteReceived(); // callback to execute receive FSM
}
uart_flush_input(ucUartNumber);
uart_flush_input(xMBSCtx.ucUartNumber);
// Send event EV_FRAME_RECEIVED to allow stack process packet
#if !CONFIG_FMB_TIMER_PORT_ENABLED
pxMBPortCBTimerExpired();
@ -106,7 +107,7 @@ BOOL xMBPortSerialTxPoll(void)
USHORT usCount = 0;
BOOL bNeedPoll = TRUE;
if( bTxStateEnabled ) {
if(xMBSCtx.bTxStateEnabled) {
// Continue while all response bytes put in buffer or out of buffer
while((bNeedPoll) && (usCount++ < MB_SERIAL_BUF_SIZE)) {
// Calls the modbus stack callback function to let it fill the UART transmit buffer.
@ -114,7 +115,7 @@ BOOL xMBPortSerialTxPoll(void)
}
ESP_LOGD(TAG, "MB_TX_buffer send: (%d) bytes\n", (uint16_t)usCount);
// Waits while UART sending the packet
esp_err_t xTxStatus = uart_wait_tx_done(ucUartNumber, MB_SERIAL_TX_TOUT_TICKS);
esp_err_t xTxStatus = uart_wait_tx_done(xMBSCtx.ucUartNumber, MB_SERIAL_TX_TOUT_TICKS);
vMBPortSerialEnable(TRUE, FALSE);
MB_PORT_CHECK((xTxStatus == ESP_OK), FALSE, "mb serial sent buffer failure.");
return TRUE;
@ -127,8 +128,8 @@ static void vUartTask(void *pvParameters)
uart_event_t xEvent;
USHORT usResult = 0;
for(;;) {
if (xMBPortSerialWaitEvent(xMbUartQueue, (void*)&xEvent, portMAX_DELAY)) {
ESP_LOGD(TAG, "MB_uart[%d] event:", ucUartNumber);
if (xMBPortSerialWaitEvent(xMBSCtx.xMbUartQueue, (void*)&xEvent, portMAX_DELAY)) {
ESP_LOGD(TAG, "MB_uart[%d] event:", xMBSCtx.ucUartNumber);
switch(xEvent.type) {
//Event of UART receving data
case UART_DATA:
@ -137,7 +138,7 @@ static void vUartTask(void *pvParameters)
// data received during configured timeout and UART TOUT feature is triggered
if (xEvent.timeout_flag) {
// Get buffered data length
ESP_ERROR_CHECK(uart_get_buffered_data_len(ucUartNumber, &xEvent.size));
ESP_ERROR_CHECK(uart_get_buffered_data_len(xMBSCtx.ucUartNumber, &xEvent.size));
// Read received data and send it to modbus stack
usResult = usMBPortSerialRxPoll(xEvent.size);
ESP_LOGD(TAG,"Timeout occured, processed: %d bytes", usResult);
@ -146,13 +147,13 @@ static void vUartTask(void *pvParameters)
//Event of HW FIFO overflow detected
case UART_FIFO_OVF:
ESP_LOGD(TAG, "hw fifo overflow\n");
xQueueReset(xMbUartQueue);
xQueueReset(xMBSCtx.xMbUartQueue);
break;
//Event of UART ring buffer full
case UART_BUFFER_FULL:
ESP_LOGD(TAG, "ring buffer full\n");
xQueueReset(xMbUartQueue);
uart_flush_input(ucUartNumber);
xQueueReset(xMBSCtx.xMbUartQueue);
uart_flush_input(xMBSCtx.ucUartNumber);
break;
//Event of UART RX break detected
case UART_BREAK:
@ -160,7 +161,10 @@ static void vUartTask(void *pvParameters)
break;
//Event of UART parity check error
case UART_PARITY_ERR:
ESP_LOGD(TAG, "uart parity error\n");
ESP_LOGD(TAG, "uart parity error, count: %lu.", xMBSCtx.ulParityErrors);
xMBSCtx.ulParityErrors++;
xQueueReset(xMBSCtx.xMbUartQueue);
uart_flush_input(xMBSCtx.ucUartNumber);
break;
//Event of UART frame error
case UART_FRAME_ERR:
@ -180,7 +184,8 @@ BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate,
{
esp_err_t xErr = ESP_OK;
// Set communication port number
ucUartNumber = ucPORT;
xMBSCtx.ucUartNumber = ucPORT;
xMBSCtx.ulParityErrors = 0;
// Configure serial communication parameters
UCHAR ucParity = UART_PARITY_DISABLE;
UCHAR ucData = UART_DATA_8_BITS;
@ -229,53 +234,53 @@ BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate,
#endif
};
// Set UART config
xErr = uart_param_config(ucUartNumber, &xUartConfig);
xErr = uart_param_config(xMBSCtx.ucUartNumber, &xUartConfig);
MB_PORT_CHECK((xErr == ESP_OK),
FALSE, "mb config failure, uart_param_config() returned (0x%x).", xErr);
// Install UART driver, and get the queue.
xErr = uart_driver_install(ucUartNumber, MB_SERIAL_BUF_SIZE, MB_SERIAL_BUF_SIZE,
MB_QUEUE_LENGTH, &xMbUartQueue, MB_PORT_SERIAL_ISR_FLAG);
xErr = uart_driver_install(xMBSCtx.ucUartNumber, MB_SERIAL_BUF_SIZE, MB_SERIAL_BUF_SIZE,
MB_QUEUE_LENGTH, &xMBSCtx.xMbUartQueue, MB_PORT_SERIAL_ISR_FLAG);
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
"mb serial driver failure, uart_driver_install() returned (0x%x).", xErr);
#if !CONFIG_FMB_TIMER_PORT_ENABLED
// Set timeout for TOUT interrupt (T3.5 modbus time)
xErr = uart_set_rx_timeout(ucUartNumber, MB_SERIAL_TOUT);
xErr = uart_set_rx_timeout(xMBSCtx.ucUartNumber, MB_SERIAL_TOUT);
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
"mb serial set rx timeout failure, uart_set_rx_timeout() returned (0x%x).", xErr);
#endif
// Set always timeout flag to trigger timeout interrupt even after rx fifo full
uart_set_always_rx_timeout(ucUartNumber, true);
uart_set_always_rx_timeout(xMBSCtx.ucUartNumber, true);
// Create a task to handle UART events
BaseType_t xStatus = xTaskCreatePinnedToCore(vUartTask, "uart_queue_task",
MB_SERIAL_TASK_STACK_SIZE,
NULL, MB_SERIAL_TASK_PRIO,
&xMbTaskHandle, MB_PORT_TASK_AFFINITY);
&xMBSCtx.xMbTaskHandle, MB_PORT_TASK_AFFINITY);
if (xStatus != pdPASS) {
vTaskDelete(xMbTaskHandle);
vTaskDelete(xMBSCtx.xMbTaskHandle);
// Force exit from function with failure
MB_PORT_CHECK(FALSE, FALSE,
"mb stack serial task creation error. xTaskCreate() returned (0x%x).",
xStatus);
} else {
vTaskSuspend(xMbTaskHandle); // Suspend serial task while stack is not started
vTaskSuspend(xMBSCtx.xMbTaskHandle); // Suspend serial task while stack is not started
}
return TRUE;
}
void vMBPortSerialClose(void)
{
(void)vTaskSuspend(xMbTaskHandle);
(void)vTaskDelete(xMbTaskHandle);
ESP_ERROR_CHECK(uart_driver_delete(ucUartNumber));
(void)vTaskSuspend(xMBSCtx.xMbTaskHandle);
(void)vTaskDelete(xMBSCtx.xMbTaskHandle);
ESP_ERROR_CHECK(uart_driver_delete(xMBSCtx.ucUartNumber));
}
BOOL xMBPortSerialPutByte(CHAR ucByte)
{
// Send one byte to UART transmission buffer
// This function is called by Modbus stack
UCHAR ucLength = uart_write_bytes(ucUartNumber, &ucByte, 1);
UCHAR ucLength = uart_write_bytes(xMBSCtx.ucUartNumber, &ucByte, 1);
return (ucLength == 1);
}
@ -283,6 +288,6 @@ BOOL xMBPortSerialPutByte(CHAR ucByte)
BOOL xMBPortSerialGetByte(CHAR* pucByte)
{
assert(pucByte != NULL);
USHORT usLength = uart_read_bytes(ucUartNumber, (uint8_t*)pucByte, 1, MB_SERIAL_RX_TOUT_TICKS);
USHORT usLength = uart_read_bytes(xMBSCtx.ucUartNumber, (uint8_t*)pucByte, 1, MB_SERIAL_RX_TOUT_TICKS);
return (usLength == 1);
}

View File

@ -59,38 +59,40 @@
/* ----------------------- Static variables ---------------------------------*/
static const CHAR *TAG = "MB_MASTER_SERIAL";
// A queue to handle UART event.
static QueueHandle_t xMbUartQueue;
static TaskHandle_t xMbTaskHandle;
// The UART hardware port number
static UCHAR ucUartNumber = UART_NUM_MAX - 1;
static BOOL bRxStateEnabled = FALSE; // Receiver enabled flag
static BOOL bTxStateEnabled = FALSE; // Transmitter enabled flag
static SemaphoreHandle_t xMasterSemaRxHandle; // Rx blocking semaphore handle
// Serial communication context structure
static MBMSerialContext_t xMBMCtx = {
.xMbUartQueue = NULL,
.xMbTaskHandle = NULL,
.ucUartNumber = UART_NUM_MAX - 1,
.xRxSemaHandle = NULL,
.bTxStateEnabled = FALSE,
.bRxStateEnabled = FALSE,
.ulParityErrors = 0, // Debug counters, can overrun
.ulFrameErrors = 0
};
static BOOL xMBMasterPortRxSemaInit( void )
{
xMasterSemaRxHandle = xSemaphoreCreateBinary();
MB_PORT_CHECK((xMasterSemaRxHandle != NULL), FALSE , "%s: RX semaphore create failure.", __func__);
xMBMCtx.xRxSemaHandle = xSemaphoreCreateBinary();
MB_PORT_CHECK((xMBMCtx.xRxSemaHandle != NULL), FALSE , "%s: RX semaphore create failure.", __func__);
return TRUE;
}
static void vMBMasterPortRxSemaClose( void )
{
if (xMasterSemaRxHandle) {
vSemaphoreDelete(xMasterSemaRxHandle);
xMasterSemaRxHandle = NULL;
if (xMBMCtx.xRxSemaHandle) {
vSemaphoreDelete(xMBMCtx.xRxSemaHandle);
xMBMCtx.xRxSemaHandle = NULL;
}
}
static BOOL xMBMasterPortRxSemaTake( LONG lTimeOut )
{
BaseType_t xStatus = pdTRUE;
xStatus = xSemaphoreTake(xMasterSemaRxHandle, lTimeOut );
MB_PORT_CHECK((xStatus == pdTRUE), FALSE , "%s: RX semaphore take failure.", __func__);
xStatus = xSemaphoreTake(xMBMCtx.xRxSemaHandle, lTimeOut );
if (xStatus != pdTRUE) {
ESP_LOGD(TAG, "%s: RX semaphore take failure.", __func__);
}
ESP_LOGV(MB_PORT_TAG,"%s:Take RX semaphore (%lu ticks).", __func__, lTimeOut);
return TRUE;
}
@ -98,7 +100,7 @@ static BOOL xMBMasterPortRxSemaTake( LONG lTimeOut )
static void vMBMasterRxSemaRelease( void )
{
BaseType_t xStatus = pdFALSE;
xStatus = xSemaphoreGive(xMasterSemaRxHandle);
xStatus = xSemaphoreGive(xMBMCtx.xRxSemaHandle);
if (xStatus != pdTRUE) {
ESP_LOGD(MB_PORT_TAG,"%s:RX semaphore is free.", __func__);
}
@ -107,7 +109,7 @@ static void vMBMasterRxSemaRelease( void )
static BOOL vMBMasterRxSemaIsBusy( void )
{
BaseType_t xStatus = pdFALSE;
xStatus = (uxSemaphoreGetCount(xMasterSemaRxHandle) == 0) ? TRUE : FALSE;
xStatus = (uxSemaphoreGetCount(xMBMCtx.xRxSemaHandle) == 0) ? TRUE : FALSE;
return xStatus;
}
@ -116,11 +118,11 @@ void vMBMasterRxFlush( void )
size_t xSize = 1;
esp_err_t xErr = ESP_OK;
for (int xCount = 0; (xCount < MB_SERIAL_RX_FLUSH_RETRY) && xSize; xCount++) {
xErr = uart_get_buffered_data_len(ucUartNumber, &xSize);
xErr = uart_get_buffered_data_len(xMBMCtx.ucUartNumber, &xSize);
MB_PORT_CHECK((xErr == ESP_OK), ; , "mb flush serial fail, error = 0x%x.", xErr);
BaseType_t xStatus = xQueueReset(xMbUartQueue);
BaseType_t xStatus = xQueueReset(xMBMCtx.xMbUartQueue);
if (xStatus) {
xErr = uart_flush_input(ucUartNumber);
xErr = uart_flush_input(xMBMCtx.ucUartNumber);
MB_PORT_CHECK((xErr == ESP_OK), ; , "mb flush serial fail, error = 0x%x.", xErr);
}
}
@ -131,17 +133,17 @@ void vMBMasterPortSerialEnable(BOOL bRxEnable, BOOL bTxEnable)
// This function can be called from xMBRTUTransmitFSM() of different task
if (bTxEnable) {
vMBMasterRxFlush();
bTxStateEnabled = TRUE;
xMBMCtx.bTxStateEnabled = TRUE;
} else {
bTxStateEnabled = FALSE;
xMBMCtx.bTxStateEnabled = FALSE;
}
if (bRxEnable) {
bRxStateEnabled = TRUE;
xMBMCtx.bRxStateEnabled = TRUE;
vMBMasterRxSemaRelease();
vTaskResume(xMbTaskHandle); // Resume receiver task
vTaskResume(xMBMCtx.xMbTaskHandle); // Resume receiver task
} else {
vTaskSuspend(xMbTaskHandle); // Block receiver task
bRxStateEnabled = FALSE;
vTaskSuspend(xMBMCtx.xMbTaskHandle); // Block receiver task
xMBMCtx.bRxStateEnabled = FALSE;
}
}
@ -157,7 +159,7 @@ static USHORT usMBMasterPortSerialRxPoll(size_t xEventSize)
xStatus = pxMBMasterFrameCBByteReceived(); // callback to receive FSM
}
// The buffer is transferred into Modbus stack and is not needed here any more
uart_flush_input(ucUartNumber);
uart_flush_input(xMBMCtx.ucUartNumber);
ESP_LOGD(TAG, "Received data: %d(bytes in buffer)\n", (uint32_t)usCnt);
#if !CONFIG_FMB_TIMER_PORT_ENABLED
vMBMasterSetCurTimerMode(MB_TMODE_T35);
@ -178,7 +180,7 @@ BOOL xMBMasterPortSerialTxPoll(void)
USHORT usCount = 0;
BOOL bNeedPoll = TRUE;
if( bTxStateEnabled ) {
if(xMBMCtx.bTxStateEnabled) {
// Continue while all response bytes put in buffer or out of buffer
while(bNeedPoll && (usCount++ < MB_SERIAL_BUF_SIZE)) {
// Calls the modbus stack callback function to let it fill the UART transmit buffer.
@ -186,7 +188,7 @@ BOOL xMBMasterPortSerialTxPoll(void)
}
ESP_LOGD(TAG, "MB_TX_buffer sent: (%d) bytes.", (uint16_t)(usCount - 1));
// Waits while UART sending the packet
esp_err_t xTxStatus = uart_wait_tx_done(ucUartNumber, MB_SERIAL_TX_TOUT_TICKS);
esp_err_t xTxStatus = uart_wait_tx_done(xMBMCtx.ucUartNumber, MB_SERIAL_TX_TOUT_TICKS);
vMBMasterPortSerialEnable(TRUE, FALSE);
MB_PORT_CHECK((xTxStatus == ESP_OK), FALSE, "mb serial sent buffer failure.");
return TRUE;
@ -200,8 +202,8 @@ static void vUartTask(void* pvParameters)
uart_event_t xEvent;
USHORT usResult = 0;
for(;;) {
if (xMBPortSerialWaitEvent(xMbUartQueue, (void*)&xEvent, portMAX_DELAY)) {
ESP_LOGD(TAG, "MB_uart[%d] event:", ucUartNumber);
if (xMBPortSerialWaitEvent(xMBMCtx.xMbUartQueue, (void*)&xEvent, portMAX_DELAY)) {
ESP_LOGD(TAG, "MB_uart[%d] event:", xMBMCtx.ucUartNumber);
switch(xEvent.type) {
//Event of UART receiving data
case UART_DATA:
@ -213,10 +215,12 @@ static void vUartTask(void* pvParameters)
// Do not wait completion of processing and just discard received data as incorrect
if (vMBMasterRxSemaIsBusy()) {
vMBMasterRxFlush();
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS);
break;
}
// Get buffered data length
ESP_ERROR_CHECK(uart_get_buffered_data_len(ucUartNumber, &xEvent.size));
ESP_ERROR_CHECK(uart_get_buffered_data_len(xMBMCtx.ucUartNumber, &xEvent.size));
// Read received data and send it to modbus stack
usResult = usMBMasterPortSerialRxPoll(xEvent.size);
ESP_LOGD(TAG,"Timeout occured, processed: %d bytes", usResult);
@ -225,13 +229,13 @@ static void vUartTask(void* pvParameters)
//Event of HW FIFO overflow detected
case UART_FIFO_OVF:
ESP_LOGD(TAG, "hw fifo overflow.");
xQueueReset(xMbUartQueue);
xQueueReset(xMBMCtx.xMbUartQueue);
break;
//Event of UART ring buffer full
case UART_BUFFER_FULL:
ESP_LOGD(TAG, "ring buffer full.");
xQueueReset(xMbUartQueue);
uart_flush_input(ucUartNumber);
xQueueReset(xMBMCtx.xMbUartQueue);
uart_flush_input(xMBMCtx.ucUartNumber);
break;
//Event of UART RX break detected
case UART_BREAK:
@ -239,11 +243,15 @@ static void vUartTask(void* pvParameters)
break;
//Event of UART parity check error
case UART_PARITY_ERR:
ESP_LOGD(TAG, "uart parity error.");
ESP_LOGD(TAG, "uart parity error, count: %lu.", xMBMCtx.ulParityErrors);
xMBMasterPortRxSemaTake(0);
xMBMCtx.ulParityErrors++;
break;
//Event of UART frame error
case UART_FRAME_ERR:
ESP_LOGD(TAG, "uart frame error.");
ESP_LOGD(TAG, "uart frame error, count: %lu.", xMBMCtx.ulFrameErrors);
xMBMasterPortRxSemaTake(0);
xMBMCtx.ulFrameErrors++;
break;
default:
ESP_LOGD(TAG, "uart event type: %d.", xEvent.type);
@ -259,7 +267,9 @@ BOOL xMBMasterPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
{
esp_err_t xErr = ESP_OK;
// Set communication port number
ucUartNumber = ucPORT;
xMBMCtx.ucUartNumber = ucPORT;
xMBMCtx.ulParityErrors = 0;
xMBMCtx.ulFrameErrors = 0;
// Configure serial communication parameters
UCHAR ucParity = UART_PARITY_DISABLE;
UCHAR ucData = UART_DATA_8_BITS;
@ -308,36 +318,35 @@ BOOL xMBMasterPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
#endif
};
// Set UART config
xErr = uart_param_config(ucUartNumber, &xUartConfig);
xErr = uart_param_config(xMBMCtx.ucUartNumber, &xUartConfig);
MB_PORT_CHECK((xErr == ESP_OK),
FALSE, "mb config failure, uart_param_config() returned (0x%x).", xErr);
// Install UART driver, and get the queue.
xErr = uart_driver_install(ucUartNumber, MB_SERIAL_BUF_SIZE, MB_SERIAL_BUF_SIZE,
MB_QUEUE_LENGTH, &xMbUartQueue, MB_PORT_SERIAL_ISR_FLAG);
xErr = uart_driver_install(xMBMCtx.ucUartNumber, MB_SERIAL_BUF_SIZE, MB_SERIAL_BUF_SIZE,
MB_QUEUE_LENGTH, &xMBMCtx.xMbUartQueue, MB_PORT_SERIAL_ISR_FLAG);
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
"mb serial driver failure, uart_driver_install() returned (0x%x).", xErr);
// Set timeout for TOUT interrupt (T3.5 modbus time)
xErr = uart_set_rx_timeout(ucUartNumber, MB_SERIAL_TOUT);
xErr = uart_set_rx_timeout(xMBMCtx.ucUartNumber, MB_SERIAL_TOUT);
MB_PORT_CHECK((xErr == ESP_OK), FALSE,
"mb serial set rx timeout failure, uart_set_rx_timeout() returned (0x%x).", xErr);
// Set always timeout flag to trigger timeout interrupt even after rx fifo full
uart_set_always_rx_timeout(ucUartNumber, true);
uart_set_always_rx_timeout(xMBMCtx.ucUartNumber, true);
MB_PORT_CHECK((xMBMasterPortRxSemaInit()), FALSE,
"mb serial RX semaphore create fail.");
// Create a task to handle UART events
BaseType_t xStatus = xTaskCreatePinnedToCore(vUartTask, "uart_queue_task",
MB_SERIAL_TASK_STACK_SIZE,
NULL, MB_SERIAL_TASK_PRIO,
&xMbTaskHandle, MB_PORT_TASK_AFFINITY);
&xMBMCtx.xMbTaskHandle, MB_PORT_TASK_AFFINITY);
if (xStatus != pdPASS) {
vTaskDelete(xMbTaskHandle);
vTaskDelete(xMBMCtx.xMbTaskHandle);
// Force exit from function with failure
MB_PORT_CHECK(FALSE, FALSE,
"mb stack serial task creation error. xTaskCreate() returned (0x%x).",
xStatus);
} else {
vTaskSuspend(xMbTaskHandle); // Suspend serial task while stack is not started
vTaskSuspend(xMBMCtx.xMbTaskHandle); // Suspend serial task while stack is not started
}
ESP_LOGD(MB_PORT_TAG,"%s Init serial.", __func__);
return TRUE;
@ -346,15 +355,15 @@ BOOL xMBMasterPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
void vMBMasterPortSerialClose(void)
{
vMBMasterPortRxSemaClose();
(void)vTaskDelete(xMbTaskHandle);
ESP_ERROR_CHECK(uart_driver_delete(ucUartNumber));
(void)vTaskDelete(xMBMCtx.xMbTaskHandle);
ESP_ERROR_CHECK(uart_driver_delete(xMBMCtx.ucUartNumber));
}
BOOL xMBMasterPortSerialPutByte(CHAR ucByte)
{
// Send one byte to UART transmission buffer
// This function is called by Modbus stack
UCHAR ucLength = uart_write_bytes(ucUartNumber, &ucByte, 1);
UCHAR ucLength = uart_write_bytes(xMBMCtx.ucUartNumber, &ucByte, 1);
return (ucLength == 1);
}
@ -362,6 +371,6 @@ BOOL xMBMasterPortSerialPutByte(CHAR ucByte)
BOOL xMBMasterPortSerialGetByte(CHAR* pucByte)
{
assert(pucByte != NULL);
USHORT usLength = uart_read_bytes(ucUartNumber, (uint8_t*)pucByte, 1, MB_SERIAL_RX_TOUT_TICKS);
USHORT usLength = uart_read_bytes(xMBMCtx.ucUartNumber, (uint8_t*)pucByte, 1, MB_SERIAL_RX_TOUT_TICKS);
return (usLength == 1);
}

View File

@ -54,4 +54,4 @@ void vMBPortSetMode( UCHAR ucMode );
PR_END_EXTERN_C
#endif /* __cplusplus */
#endif
#endif

View File

@ -256,7 +256,7 @@ static esp_err_t master_init(void)
.mode = MB_MODE_RTU,
#endif
.baudrate = MB_DEV_SPEED,
.parity = MB_PARITY_NONE
.parity = UART_PARITY_EVEN
};
void* master_handler = NULL;

View File

@ -108,7 +108,7 @@ void app_main(void)
comm_info.slave_addr = MB_SLAVE_ADDR;
comm_info.port = MB_PORT_NUM;
comm_info.baudrate = MB_DEV_SPEED;
comm_info.parity = MB_PARITY_NONE;
comm_info.parity = UART_PARITY_EVEN;
ESP_ERROR_CHECK(mbc_slave_setup((void*)&comm_info));
// The code below initializes Modbus register area descriptors