From 17de1dd9dd265313a604ae765ff431198f813a8d Mon Sep 17 00:00:00 2001 From: aleks Date: Mon, 6 May 2024 14:26:30 +0200 Subject: [PATCH] master add modbus buffer propagation --- freemodbus/modbus/include/mbport.h | 18 +++-- freemodbus/modbus/mb_m.c | 58 +++++++++------- freemodbus/port/port.h | 19 ++++++ freemodbus/port/portevent_m.c | 66 +++++++++++++++---- idf_component.yml | 2 + .../mb_serial_master/main/CMakeLists.txt | 1 + test/serial/mb_serial_master/main/master.c | 23 +++++++ 7 files changed, 142 insertions(+), 45 deletions(-) diff --git a/freemodbus/modbus/include/mbport.h b/freemodbus/modbus/include/mbport.h index c5e9ff2..6de021c 100644 --- a/freemodbus/modbus/include/mbport.h +++ b/freemodbus/modbus/include/mbport.h @@ -207,16 +207,20 @@ void vMBMasterPortTimersDisable( void ); /* ----------------- Callback for the master error process ------------------*/ -void vMBMasterErrorCBRespondTimeout( UCHAR ucDestAddress, const UCHAR* pucPDUData, - USHORT ucPDULength ); +void vMBMasterErrorCBRespondTimeout( uint64_t xTransId, UCHAR ucDestAddress, + const UCHAR* pucSendData, USHORT ucSendLength ); -void vMBMasterErrorCBReceiveData( UCHAR ucDestAddress, const UCHAR* pucPDUData, - USHORT ucPDULength ); +void vMBMasterErrorCBReceiveData( uint64_t xTransId, UCHAR ucDestAddress, + const UCHAR* pucRecvData, USHORT ucRecvLength, + const UCHAR* pucSendData, USHORT ucSendLength ); -void vMBMasterErrorCBExecuteFunction( UCHAR ucDestAddress, const UCHAR* pucPDUData, - USHORT ucPDULength ); +void vMBMasterErrorCBExecuteFunction( uint64_t xTransId, UCHAR ucDestAddress, + const UCHAR* pucRecvData, USHORT ucRecvLength, + const UCHAR* pucSendData, USHORT ucSendLength ); -void vMBMasterCBRequestSuccess( void ); +void vMBMasterCBRequestSuccess( uint64_t xTransId, UCHAR ucDestAddress, + const UCHAR* pucRecvData, USHORT ucRecvLength, + const UCHAR* pucSendData, USHORT ucSendLength ); #endif /* ----------------------- Callback for the protocol stack ------------------*/ /*! diff --git a/freemodbus/modbus/mb_m.c b/freemodbus/modbus/mb_m.c index df1d07e..3addcbe 100644 --- a/freemodbus/modbus/mb_m.c +++ b/freemodbus/modbus/mb_m.c @@ -311,8 +311,8 @@ eMBMasterDisable( void ) eMBErrorCode eMBMasterPoll( void ) { - static UCHAR *ucMBSendFrame = NULL; - static UCHAR *ucMBRcvFrame = NULL; + static UCHAR *pucMBSendFrame = NULL; + static UCHAR *pucMBRecvFrame = NULL; static UCHAR ucRcvAddress; static UCHAR ucFunctionCode; static USHORT usLength; @@ -343,9 +343,9 @@ eMBMasterPoll( void ) case EV_MASTER_FRAME_TRANSMIT: ESP_LOGD(MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_FRAME_TRANSMIT", xEvent.xTransactionId); /* Master is busy now. */ - vMBMasterGetPDUSndBuf( &ucMBSendFrame ); - ESP_LOG_BUFFER_HEX_LEVEL("POLL transmit buffer", (void*)ucMBSendFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG); - eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBSendFrame, usMBMasterGetPDUSndLength() ); + vMBMasterGetPDUSndBuf( &pucMBSendFrame ); + ESP_LOG_BUFFER_HEX_LEVEL("POLL transmit buffer", (void*)pucMBSendFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG); + eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), pucMBSendFrame, usMBMasterGetPDUSndLength() ); if (eStatus != MB_ENOERR) { vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA); ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); @@ -356,24 +356,24 @@ eMBMasterPoll( void ) case EV_MASTER_FRAME_SENT: if (xCurTransactionId == xEvent.xTransactionId) { ESP_LOGD( MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_FRAME_SENT", xEvent.xTransactionId ); - ESP_LOG_BUFFER_HEX_LEVEL("POLL sent buffer", (void*)ucMBSendFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEX_LEVEL("POLL sent buffer", (void*)pucMBSendFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG); } break; case EV_MASTER_FRAME_RECEIVED: ESP_LOGD( MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_FRAME_RECEIVED", xEvent.xTransactionId ); - eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBRcvFrame, &usLength); + eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &pucMBRecvFrame, &usLength); if (xCurTransactionId == xEvent.xTransactionId) { - MB_PORT_CHECK(ucMBSendFrame, MB_EILLSTATE, "Send buffer initialization fail."); + MB_PORT_CHECK(pucMBSendFrame, MB_EILLSTATE, "Send buffer initialization fail."); // Check if the frame is for us. If not ,send an error process event. if ( ( eStatus == MB_ENOERR ) && ( ( ucRcvAddress == ucMBMasterGetDestAddress() ) || ( ucRcvAddress == MB_TCP_PSEUDO_ADDRESS) ) ) { - if ( ( ucMBRcvFrame[MB_PDU_FUNC_OFF] & ~MB_FUNC_ERROR ) == ( ucMBSendFrame[MB_PDU_FUNC_OFF] ) ) { + if ( ( pucMBRecvFrame[MB_PDU_FUNC_OFF] & ~MB_FUNC_ERROR ) == ( pucMBSendFrame[MB_PDU_FUNC_OFF] ) ) { ESP_LOGD(MB_PORT_TAG, "%" PRIu64 ": Packet data received successfully (%u).", xEvent.xTransactionId, (unsigned)eStatus); - ESP_LOG_BUFFER_HEX_LEVEL("POLL receive buffer", (void*)ucMBRcvFrame, (uint16_t)usLength, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEX_LEVEL("POLL receive buffer", (void*)pucMBRecvFrame, (uint16_t)usLength, ESP_LOG_DEBUG); ( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE ); } else { ESP_LOGE( MB_PORT_TAG, "Drop incorrect frame, receive_func(%u) != send_func(%u)", - ucMBRcvFrame[MB_PDU_FUNC_OFF], ucMBSendFrame[MB_PDU_FUNC_OFF]); + pucMBRecvFrame[MB_PDU_FUNC_OFF], pucMBSendFrame[MB_PDU_FUNC_OFF]); vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA); ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); } @@ -393,15 +393,15 @@ eMBMasterPoll( void ) if (xCurTransactionId == xEvent.xTransactionId) { if ( xMBMasterRequestIsBroadcast() && (( ucMBMasterGetCommMode() == MB_RTU ) || ( ucMBMasterGetCommMode() == MB_ASCII ) ) ) { - ucMBRcvFrame = ucMBSendFrame; + pucMBRecvFrame = pucMBSendFrame; } - MB_PORT_CHECK(ucMBRcvFrame, MB_EILLSTATE, "receive buffer initialization fail."); + MB_PORT_CHECK(pucMBRecvFrame, MB_EILLSTATE, "receive buffer initialization fail."); ESP_LOGD(MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_EXECUTE", xEvent.xTransactionId); - ucFunctionCode = ucMBRcvFrame[MB_PDU_FUNC_OFF]; + ucFunctionCode = pucMBRecvFrame[MB_PDU_FUNC_OFF]; eException = MB_EX_ILLEGAL_FUNCTION; /* If receive frame has exception. The receive function code highest bit is 1.*/ if (ucFunctionCode & MB_FUNC_ERROR) { - eException = (eMBException)ucMBRcvFrame[MB_PDU_DATA_OFF]; + eException = (eMBException)pucMBRecvFrame[MB_PDU_DATA_OFF]; } else { for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) { @@ -419,10 +419,10 @@ eMBMasterPoll( void ) for(j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++) { vMBMasterSetDestAddress(j); - eException = xMasterFuncHandlers[i].pxHandler(ucMBRcvFrame, &usLength); + eException = xMasterFuncHandlers[i].pxHandler(pucMBRecvFrame, &usLength); } } else { - eException = xMasterFuncHandlers[i].pxHandler( ucMBRcvFrame, &usLength ); + eException = xMasterFuncHandlers[i].pxHandler( pucMBRecvFrame, &usLength ); } vMBMasterSetCBRunInMasterMode( FALSE ); break; @@ -449,23 +449,31 @@ eMBMasterPoll( void ) ESP_LOGD( MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_ERROR_PROCESS", xEvent.xTransactionId); /* Execute specified error process callback function. */ errorType = eMBMasterGetErrorType( ); - vMBMasterGetPDUSndBuf( &ucMBSendFrame ); + vMBMasterGetPDUSndBuf( &pucMBSendFrame ); switch ( errorType ) { case EV_ERROR_RESPOND_TIMEOUT: - vMBMasterErrorCBRespondTimeout( ucMBMasterGetDestAddress( ), - ucMBSendFrame, usMBMasterGetPDUSndLength( ) ); + vMBMasterErrorCBRespondTimeout( xEvent.xTransactionId, + ucMBMasterGetDestAddress( ), + pucMBSendFrame, usMBMasterGetPDUSndLength( ) ); break; case EV_ERROR_RECEIVE_DATA: - vMBMasterErrorCBReceiveData( ucMBMasterGetDestAddress( ), - ucMBSendFrame, usMBMasterGetPDUSndLength( ) ); + vMBMasterErrorCBReceiveData( xEvent.xTransactionId, + ucMBMasterGetDestAddress( ), + pucMBRecvFrame, usLength, + pucMBSendFrame, usMBMasterGetPDUSndLength( ) ); break; case EV_ERROR_EXECUTE_FUNCTION: - vMBMasterErrorCBExecuteFunction( ucMBMasterGetDestAddress( ), - ucMBSendFrame, usMBMasterGetPDUSndLength( ) ); + vMBMasterErrorCBExecuteFunction( xEvent.xTransactionId, + ucMBMasterGetDestAddress( ), + pucMBRecvFrame, usLength, + pucMBSendFrame, usMBMasterGetPDUSndLength( ) ); break; case EV_ERROR_OK: - vMBMasterCBRequestSuccess( ); + vMBMasterCBRequestSuccess( xEvent.xTransactionId, + ucMBMasterGetDestAddress( ), + pucMBRecvFrame, usLength, + pucMBSendFrame, usMBMasterGetPDUSndLength( ) ); break; default: ESP_LOGE( MB_PORT_TAG, "%" PRIu64 ":incorrect error type = %d.", xEvent.xTransactionId, (int)errorType); diff --git a/freemodbus/port/port.h b/freemodbus/port/port.h index 418876a..623f71f 100644 --- a/freemodbus/port/port.h +++ b/freemodbus/port/port.h @@ -105,6 +105,8 @@ #define MB_TCP_DEBUG (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) // Enable legacy debug output in TCP module. +#define MB_ATTR_WEAK __attribute__ ((weak)) + #define MB_TCP_GET_FIELD(buffer, field) ((USHORT)((buffer[field] << 8U) | buffer[field + 1])) #define MB_PORT_CHECK(a, ret_val, str, ...) \ @@ -198,6 +200,23 @@ UCHAR ucMBPortGetMode( void ); BOOL xMBPortSerialWaitEvent(QueueHandle_t xMbUartQueue, uart_event_t* pxEvent, ULONG xTimeout); +/** + * This is modbus master user error handling funcion. + * If it is defined in the user application, then helps to handle the errors + * and received/sent buffers to transfer as well as handle the slave exception codes. + * + * @param xTransId - the identification of the trasaction + * @param ucDestAddress destination salve address + * @param usError - the error code, see the enumeration eMBMasterErrorEventType + * @param pucRecvData current receive data pointer + * @param ucRecvLength current length of receive buffer + * @param pucSendData Send buffer data + * @param ucSendLength Send buffer length + */ +MB_ATTR_WEAK +void vMBMasterErrorCBUserHandler( uint64_t xTransId, USHORT usError, UCHAR ucDestAddress, const UCHAR* pucRecvData, USHORT ucRecvLength, + const UCHAR* pucSendData, USHORT ucSendLength ); + #ifdef __cplusplus PR_END_EXTERN_C #endif /* __cplusplus */ diff --git a/freemodbus/port/portevent_m.c b/freemodbus/port/portevent_m.c index 664371e..e3c3b8b 100644 --- a/freemodbus/port/portevent_m.c +++ b/freemodbus/port/portevent_m.c @@ -191,30 +191,47 @@ void vMBMasterRunResRelease( void ) * This is modbus master respond timeout error process callback function. * @note There functions will block modbus master poll while execute OS waiting. * + * @param xTransId - the identification of the trasaction * @param ucDestAddress destination salve address - * @param pucPDUData PDU buffer data - * @param ucPDULength PDU buffer length + * @param pucRecvData current receive data pointer + * @param ucRecvLength current length of receive buffer + * @param pucSendData Send buffer data + * @param ucSendLength Send buffer length * */ -void vMBMasterErrorCBRespondTimeout(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength) +void vMBMasterErrorCBRespondTimeout(uint64_t xTransId, UCHAR ucDestAddress, const UCHAR* pucSendData, USHORT ucSendLength) { (void)xEventGroupSetBits( xEventGroupMasterHdl, EV_MASTER_ERROR_RESPOND_TIMEOUT ); ESP_LOGD(MB_PORT_TAG,"%s:Callback respond timeout.", __func__); + if (vMBMasterErrorCBUserHandler) { + vMBMasterErrorCBUserHandler( xTransId, (USHORT)EV_ERROR_RESPOND_TIMEOUT, + ucDestAddress, NULL, 0, + pucSendData, ucSendLength ); + } } /** * This is modbus master receive data error process callback function. * @note There functions will block modbus master poll while execute OS waiting. * + * @param xTransId - the identification of the trasaction * @param ucDestAddress destination salve address - * @param pucPDUData PDU buffer data - * @param ucPDULength PDU buffer length + * @param pucRecvData current receive data pointer + * @param ucRecvLength current length of receive buffer + * @param pucSendData Send buffer data + * @param ucSendLength Send buffer length */ -void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength) +void vMBMasterErrorCBReceiveData(uint64_t xTransId, UCHAR ucDestAddress, + const UCHAR* pucRecvData, USHORT ucRecvLength, + const UCHAR* pucSendData, USHORT ucSendLength) { (void)xEventGroupSetBits( xEventGroupMasterHdl, EV_MASTER_ERROR_RECEIVE_DATA ); - ESP_LOGD(MB_PORT_TAG,"%s:Callback receive data timeout failure.", __func__); - ESP_LOG_BUFFER_HEX_LEVEL("Err rcv buf", (void *)pucPDUData, (USHORT)ucPDULength, ESP_LOG_DEBUG); + ESP_LOGD(MB_PORT_TAG,"%s:Callback receive data failure.", __func__); + if (vMBMasterErrorCBUserHandler) { + vMBMasterErrorCBUserHandler( xTransId, (USHORT)EV_ERROR_RECEIVE_DATA, + ucDestAddress, pucRecvData, ucRecvLength, + pucSendData, ucSendLength ); + } } /** @@ -222,27 +239,50 @@ void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData, U * @note There functions will block modbus master poll while execute OS waiting. * So,for real-time of system.Do not execute too much waiting process. * + * @param xTransId - the identification of the trasaction * @param ucDestAddress destination salve address - * @param pucPDUData PDU buffer data - * @param ucPDULength PDU buffer length + * @param pucRecvData current receive data pointer + * @param ucRecvLength current length of receive buffer + * @param pucSendData Send buffer data + * @param ucSendLength Send buffer length * */ -void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength) +void vMBMasterErrorCBExecuteFunction(uint64_t xTransId, UCHAR ucDestAddress, + const UCHAR* pucRecvData, USHORT ucRecvLength, + const UCHAR* pucSendData, USHORT ucSendLength) { xEventGroupSetBits( xEventGroupMasterHdl, EV_MASTER_ERROR_EXECUTE_FUNCTION ); ESP_LOGD(MB_PORT_TAG,"%s:Callback execute data handler failure.", __func__); - ESP_LOG_BUFFER_HEX_LEVEL("Exec func buf", (void*)pucPDUData, (USHORT)ucPDULength, ESP_LOG_DEBUG); + if (vMBMasterErrorCBUserHandler) { + vMBMasterErrorCBUserHandler( xTransId, (USHORT)EV_ERROR_EXECUTE_FUNCTION, + ucDestAddress, pucRecvData, ucRecvLength, + pucSendData, ucSendLength ); + } } /** * This is modbus master request process success callback function. * @note There functions will block modbus master poll while execute OS waiting. * So,for real-time of system. Do not execute too much waiting process. + * + * @param xTransId - the identification of the trasaction + * @param ucDestAddress destination salve address + * @param pucRecvData current receive data pointer + * @param ucRecvLength current length of receive buffer + * @param pucSendData Send buffer data + * @param ucSendLength Send buffer length */ -void vMBMasterCBRequestSuccess( void ) +void vMBMasterCBRequestSuccess(uint64_t xTransId, UCHAR ucDestAddress, + const UCHAR* pucRecvData, USHORT ucRecvLength, + const UCHAR* pucSendData, USHORT ucSendLength) { (void)xEventGroupSetBits( xEventGroupMasterHdl, EV_MASTER_PROCESS_SUCCESS ); ESP_LOGD(MB_PORT_TAG,"%s: Callback request success.", __func__); + if (vMBMasterErrorCBUserHandler) { + vMBMasterErrorCBUserHandler( xTransId, (USHORT)EV_ERROR_OK, + ucDestAddress, pucRecvData, ucRecvLength, + pucSendData, ucSendLength ); + } } /** diff --git a/idf_component.yml b/idf_component.yml index 631ee0e..00296d5 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -9,3 +9,5 @@ files: - "docs" - "test/**/*" - "test" + - "arch" + - "arch/**/*" diff --git a/test/serial/mb_serial_master/main/CMakeLists.txt b/test/serial/mb_serial_master/main/CMakeLists.txt index f9ab7f6..9a6cf30 100644 --- a/test/serial/mb_serial_master/main/CMakeLists.txt +++ b/test/serial/mb_serial_master/main/CMakeLists.txt @@ -2,3 +2,4 @@ set(PROJECT_NAME "modbus_master") idf_component_register(SRCS "master.c" INCLUDE_DIRS ".") + diff --git a/test/serial/mb_serial_master/main/master.c b/test/serial/mb_serial_master/main/master.c index e6e0fd1..113e668 100644 --- a/test/serial/mb_serial_master/main/master.c +++ b/test/serial/mb_serial_master/main/master.c @@ -483,6 +483,29 @@ static esp_err_t master_init(void) return err; } +#ifndef UCHAR +#define UCHAR uint8_t +#define USHORT uint16_t +#define MB_PDU_DATA_OFF 1 +#endif + +#define EV_ERROR_EXECUTE_FUNCTION 3 + +void vMBMasterErrorCBUserHandler( uint64_t xTransId, USHORT usError, UCHAR ucDestAddress, const UCHAR* pucRecvData, USHORT ucRecvLength, + const UCHAR* pucSendData, USHORT ucSendLength ) +{ + ESP_LOGW("USER_ERR_CB", "The transaction error type: %u", usError); + if ((usError == EV_ERROR_EXECUTE_FUNCTION) && pucRecvData && ucRecvLength) { + ESP_LOGW("USER_ERR_CB", "The command is unsupported or an exception on slave happened: %x", (int)pucRecvData[1]); + } + if (pucRecvData && ucRecvLength) { + ESP_LOG_BUFFER_HEX_LEVEL("Received buffer", (void *)pucRecvData, (USHORT)ucRecvLength, ESP_LOG_WARN); + } + if (pucSendData && ucSendLength) { + ESP_LOG_BUFFER_HEX_LEVEL("Sent buffer", (void *)pucSendData, (USHORT)ucSendLength, ESP_LOG_WARN); + } +} + void app_main(void) { // Initialization of device peripheral and objects