1 /*
2  * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * File: $Id: mbrtu_m.c,v 1.60 2013/08/20 11:18:10 Armink Add Master Functions $
29  */
30 
31 /* ----------------------- System includes ----------------------------------*/
32 #include "stdlib.h"
33 #include "string.h"
34 
35 /* ----------------------- Platform includes --------------------------------*/
36 #include "port.h"
37 
38 /* ----------------------- Modbus includes ----------------------------------*/
39 
40 #include "mb_m.h"
41 #include "mbconfig.h"
42 #include "mbframe.h"
43 #include "mbproto.h"
44 #include "mbfunc.h"
45 
46 #include "mbport.h"
47 #if MB_MASTER_RTU_ENABLED
48 #include "mbrtu.h"
49 #endif
50 #if MB_MASTER_ASCII_ENABLED
51 #include "mbascii.h"
52 #endif
53 #if MB_MASTER_TCP_ENABLED
54 #include "mbtcp.h"
55 #include "mbtcp_m.h"
56 #endif
57 
58 #if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED
59 
60 #ifndef MB_PORT_HAS_CLOSE
61 #define MB_PORT_HAS_CLOSE 1
62 #endif
63 
64 /* ----------------------- Static variables ---------------------------------*/
65 
66 static UCHAR    ucMBMasterDestAddress;
67 static BOOL     xMBRunInMasterMode = FALSE;
68 static volatile eMBMasterErrorEventType eMBMasterCurErrorType;
69 static volatile USHORT  usMasterSendPDULength;
70 static volatile eMBMode eMBMasterCurrentMode;
71 
72 /*------------------------ Shared variables ---------------------------------*/
73 
74 volatile UCHAR  ucMasterSndBuf[MB_SERIAL_BUF_SIZE];
75 volatile UCHAR  ucMasterRcvBuf[MB_SERIAL_BUF_SIZE];
76 volatile eMBMasterTimerMode eMasterCurTimerMode;
77 volatile BOOL   xFrameIsBroadcast = FALSE;
78 
79 static enum
80 {
81     STATE_ENABLED,
82     STATE_DISABLED,
83     STATE_NOT_INITIALIZED
84 } eMBState = STATE_NOT_INITIALIZED;
85 
86 /* Functions pointer which are initialized in eMBInit( ). Depending on the
87  * mode (RTU or ASCII) the are set to the correct implementations.
88  * Using for Modbus Master,Add by Armink 20130813
89  */
90 static peMBFrameSend peMBMasterFrameSendCur;
91 static pvMBFrameStart pvMBMasterFrameStartCur;
92 static pvMBFrameStop pvMBMasterFrameStopCur;
93 static peMBFrameReceive peMBMasterFrameReceiveCur;
94 static pvMBFrameClose pvMBMasterFrameCloseCur;
95 
96 /* Callback functions required by the porting layer. They are called when
97  * an external event has happend which includes a timeout or the reception
98  * or transmission of a character.
99  * Using for Modbus Master,Add by Armink 20130813
100  */
101 BOOL( *pxMBMasterFrameCBByteReceived ) ( void );
102 
103 BOOL( *pxMBMasterFrameCBTransmitterEmpty ) ( void );
104 
105 BOOL( *pxMBMasterPortCBTimerExpired ) ( void );
106 
107 BOOL( *pxMBMasterFrameCBReceiveFSMCur ) ( void );
108 
109 BOOL( *pxMBMasterFrameCBTransmitFSMCur ) ( void );
110 
111 /* An array of Modbus functions handlers which associates Modbus function
112  * codes with implementing functions.
113  */
114 static xMBFunctionHandler xMasterFuncHandlers[MB_FUNC_HANDLERS_MAX] = {
115 #if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0
116     {MB_FUNC_OTHER_REPORT_SLAVEID, eMBFuncReportSlaveID},
117 #endif
118 #if MB_FUNC_READ_INPUT_ENABLED > 0
119     {MB_FUNC_READ_INPUT_REGISTER, eMBMasterFuncReadInputRegister},
120 #endif
121 #if MB_FUNC_READ_HOLDING_ENABLED > 0
122     {MB_FUNC_READ_HOLDING_REGISTER, eMBMasterFuncReadHoldingRegister},
123 #endif
124 #if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0
125     {MB_FUNC_WRITE_MULTIPLE_REGISTERS, eMBMasterFuncWriteMultipleHoldingRegister},
126 #endif
127 #if MB_FUNC_WRITE_HOLDING_ENABLED > 0
128     {MB_FUNC_WRITE_REGISTER, eMBMasterFuncWriteHoldingRegister},
129 #endif
130 #if MB_FUNC_READWRITE_HOLDING_ENABLED > 0
131     {MB_FUNC_READWRITE_MULTIPLE_REGISTERS, eMBMasterFuncReadWriteMultipleHoldingRegister},
132 #endif
133 #if MB_FUNC_READ_COILS_ENABLED > 0
134     {MB_FUNC_READ_COILS, eMBMasterFuncReadCoils},
135 #endif
136 #if MB_FUNC_WRITE_COIL_ENABLED > 0
137     {MB_FUNC_WRITE_SINGLE_COIL, eMBMasterFuncWriteCoil},
138 #endif
139 #if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0
140     {MB_FUNC_WRITE_MULTIPLE_COILS, eMBMasterFuncWriteMultipleCoils},
141 #endif
142 #if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0
143     {MB_FUNC_READ_DISCRETE_INPUTS, eMBMasterFuncReadDiscreteInputs},
144 #endif
145 };
146 
147 /* ----------------------- Start implementation -----------------------------*/
148 #if MB_MASTER_TCP_ENABLED > 0
149 eMBErrorCode
eMBMasterTCPInit(USHORT ucTCPPort)150 eMBMasterTCPInit( USHORT ucTCPPort )
151 {
152     eMBErrorCode    eStatus = MB_ENOERR;
153 
154     if( ( eStatus = eMBMasterTCPDoInit( ucTCPPort ) ) != MB_ENOERR ) {
155         eMBState = STATE_DISABLED;
156     }
157     else if( !xMBMasterPortEventInit(  ) ) {
158         /* Port dependent event module initialization failed. */
159         eStatus = MB_EPORTERR;
160     } else {
161         pvMBMasterFrameStartCur = eMBMasterTCPStart;
162         pvMBMasterFrameStopCur = eMBMasterTCPStop;
163         peMBMasterFrameReceiveCur = eMBMasterTCPReceive;
164         peMBMasterFrameSendCur = eMBMasterTCPSend;
165         pxMBMasterPortCBTimerExpired = xMBMasterTCPTimerExpired;
166         pvMBMasterFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBMasterTCPPortClose : NULL;
167         ucMBMasterDestAddress = MB_TCP_PSEUDO_ADDRESS;
168         eMBMasterCurrentMode = MB_TCP;
169         eMBState = STATE_DISABLED;
170 
171         // initialize the OS resource for modbus master.
172         vMBMasterOsResInit();
173         if( xMBMasterPortTimersInit( MB_MASTER_TIMEOUT_MS_RESPOND * MB_TIMER_TICS_PER_MS ) != TRUE )
174         {
175             eStatus = MB_EPORTERR;
176         }
177 
178     }
179     return eStatus;
180 }
181 #endif
182 
183 eMBErrorCode
eMBMasterSerialInit(eMBMode eMode,UCHAR ucPort,ULONG ulBaudRate,eMBParity eParity)184 eMBMasterSerialInit( eMBMode eMode, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity )
185 {
186     eMBErrorCode    eStatus = MB_ENOERR;
187 
188     switch (eMode)
189     {
190 #if MB_MASTER_RTU_ENABLED > 0
191     case MB_RTU:
192         pvMBMasterFrameStartCur = eMBMasterRTUStart;
193         pvMBMasterFrameStopCur = eMBMasterRTUStop;
194         peMBMasterFrameSendCur = eMBMasterRTUSend;
195         peMBMasterFrameReceiveCur = eMBMasterRTUReceive;
196         pvMBMasterFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBMasterPortClose : NULL;
197         pxMBMasterFrameCBByteReceived = xMBMasterRTUReceiveFSM;
198         pxMBMasterFrameCBTransmitterEmpty = xMBMasterRTUTransmitFSM;
199         pxMBMasterPortCBTimerExpired = xMBMasterRTUTimerExpired;
200         eMBMasterCurrentMode = MB_ASCII;
201 
202         eStatus = eMBMasterRTUInit(ucPort, ulBaudRate, eParity);
203         break;
204 #endif
205 #if MB_MASTER_ASCII_ENABLED > 0
206     case MB_ASCII:
207         pvMBMasterFrameStartCur = eMBMasterASCIIStart;
208         pvMBMasterFrameStopCur = eMBMasterASCIIStop;
209         peMBMasterFrameSendCur = eMBMasterASCIISend;
210         peMBMasterFrameReceiveCur = eMBMasterASCIIReceive;
211         pvMBMasterFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBMasterPortClose : NULL;
212         pxMBMasterFrameCBByteReceived = xMBMasterASCIIReceiveFSM;
213         pxMBMasterFrameCBTransmitterEmpty = xMBMasterASCIITransmitFSM;
214         pxMBMasterPortCBTimerExpired = xMBMasterASCIITimerT1SExpired;
215         eMBMasterCurrentMode = MB_RTU;
216 
217         eStatus = eMBMasterASCIIInit(ucPort, ulBaudRate, eParity );
218         break;
219 #endif
220     default:
221         eStatus = MB_EINVAL;
222         break;
223     }
224 
225     if (eStatus == MB_ENOERR)
226     {
227         if (!xMBMasterPortEventInit())
228         {
229             /* port dependent event module initalization failed. */
230             eStatus = MB_EPORTERR;
231         }
232         else
233         {
234             eMBState = STATE_DISABLED;
235         }
236         /* initialize the OS resource for modbus master. */
237         vMBMasterOsResInit();
238     }
239     return eStatus;
240 }
241 
242 eMBErrorCode
eMBMasterClose(void)243 eMBMasterClose( void )
244 {
245     eMBErrorCode    eStatus = MB_ENOERR;
246 
247     if( eMBState == STATE_DISABLED )
248     {
249         if( pvMBMasterFrameCloseCur != NULL )
250         {
251             pvMBMasterFrameCloseCur(  );
252         }
253     }
254     else
255     {
256         eStatus = MB_EILLSTATE;
257     }
258     return eStatus;
259 }
260 
261 eMBErrorCode
eMBMasterEnable(void)262 eMBMasterEnable( void )
263 {
264     eMBErrorCode    eStatus = MB_ENOERR;
265 
266     if( eMBState == STATE_DISABLED )
267     {
268         /* Activate the protocol stack. */
269         pvMBMasterFrameStartCur(  );
270         /* Release the resource, because it created in busy state */
271         //vMBMasterRunResRelease( );
272         eMBState = STATE_ENABLED;
273     }
274     else
275     {
276         eStatus = MB_EILLSTATE;
277     }
278     return eStatus;
279 }
280 
281 eMBErrorCode
eMBMasterDisable(void)282 eMBMasterDisable( void )
283 {
284     eMBErrorCode    eStatus;
285 
286     if( eMBState == STATE_ENABLED )
287     {
288         pvMBMasterFrameStopCur(  );
289         eMBState = STATE_DISABLED;
290         eStatus = MB_ENOERR;
291     }
292     else if( eMBState == STATE_DISABLED )
293     {
294         eStatus = MB_ENOERR;
295     }
296     else
297     {
298         eStatus = MB_EILLSTATE;
299     }
300     return eStatus;
301 }
302 
303 eMBErrorCode
eMBMasterPoll(void)304 eMBMasterPoll( void )
305 {
306     static UCHAR    *ucMBFrame = NULL;
307     static UCHAR    ucRcvAddress;
308     static UCHAR    ucFunctionCode;
309     static USHORT   usLength;
310     static eMBException eException;
311     int             i;
312     int             j;
313     eMBErrorCode    eStatus = MB_ENOERR;
314     eMBMasterEventType    eEvent;
315     eMBMasterErrorEventType errorType;
316 
317     /* Check if the protocol stack is ready. */
318     if( eMBState != STATE_ENABLED )
319     {
320         return MB_EILLSTATE;
321     }
322 
323     /* Check if there is a event available. If not return control to caller.
324      * Otherwise we will handle the event. */
325     if ( xMBMasterPortEventGet( &eEvent ) == TRUE )
326     {
327         while( eEvent ) {
328             // In some cases it is possible that more than one event set
329             // together (even from one subset mask) than process them consistently
330             if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_READY ) ) {
331                 ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_READY", __func__);
332                 MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_READY );
333             } else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT ) ) {
334                 ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_FRAME_TRANSMIT", __func__);
335                 /* Master is busy now. */
336                 vMBMasterGetPDUSndBuf( &ucMBFrame );
337                 ESP_LOG_BUFFER_HEX_LEVEL("POLL transmit buffer", (void*)ucMBFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
338                 eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength() );
339                 if (eStatus != MB_ENOERR)
340                 {
341                     ESP_LOGE( MB_PORT_TAG, "%s:Frame send error. %d", __func__, eStatus );
342                 }
343                 MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT );
344             } else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_SENT ) ) {
345                 ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_FRAME_SENT", __func__ );
346                 ESP_LOG_BUFFER_HEX_LEVEL("POLL sent buffer", (void*)ucMBFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
347                 MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_SENT );
348             } else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED ) ) {
349                 eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength);
350 
351                 // Check if the frame is for us. If not ,send an error process event.
352                 if ( ( eStatus == MB_ENOERR ) && ( ( ucRcvAddress == ucMBMasterGetDestAddress() )
353                                               || ( ucRcvAddress == MB_TCP_PSEUDO_ADDRESS ) ) )
354                 {
355                     ( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE );
356                     ESP_LOGD(MB_PORT_TAG, "%s: Packet data received successfully (%u).", __func__, eStatus);
357                     ESP_LOG_BUFFER_HEX_LEVEL("POLL receive buffer", (void*)ucMBFrame, (uint16_t)usLength, ESP_LOG_DEBUG);
358                 }
359                 else
360                 {
361                     vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
362                     ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
363                     ESP_LOGD( MB_PORT_TAG, "%s: Packet data receive failed (addr=%u)(%u).",
364                                            __func__, ucRcvAddress, eStatus);
365                 }
366                 MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED );
367             } else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_EXECUTE ) ) {
368                 if ( !ucMBFrame )
369                 {
370                     return MB_EILLSTATE;
371                 }
372                 ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_EXECUTE", __func__);
373                 ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
374                 eException = MB_EX_ILLEGAL_FUNCTION;
375                 /* If receive frame has exception. The receive function code highest bit is 1.*/
376                 if (ucFunctionCode & MB_FUNC_ERROR)
377                 {
378                     eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF];
379                 } else {
380                     for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
381                     {
382                         /* No more function handlers registered. Abort. */
383                         if (xMasterFuncHandlers[i].ucFunctionCode == 0)
384                         {
385                             break;
386                         }
387                         if (xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode)
388                         {
389                             vMBMasterSetCBRunInMasterMode(TRUE);
390                             /* If master request is broadcast,
391                              * the master need execute function for all slave.
392                              */
393                             if ( xMBMasterRequestIsBroadcast() )
394                             {
395                                 usLength = usMBMasterGetPDUSndLength();
396                                 for(j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++)
397                                 {
398                                     vMBMasterSetDestAddress(j);
399                                     eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength);
400                                 }
401                             }
402                             else
403                             {
404                                 eException = xMasterFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
405                             }
406                             vMBMasterSetCBRunInMasterMode( FALSE );
407                             break;
408                         }
409                     }
410                 }
411                 /* If master has exception, will send error process event. Otherwise the master is idle.*/
412                 if ( eException != MB_EX_NONE )
413                 {
414                     vMBMasterSetErrorType( EV_ERROR_EXECUTE_FUNCTION );
415                     ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
416                 }
417                 else
418                 {
419                     if ( eMBMasterGetErrorType( ) == EV_ERROR_INIT ) {
420                         vMBMasterSetErrorType(EV_ERROR_OK);
421                         ESP_LOGD( MB_PORT_TAG, "%s: set event EV_ERROR_OK", __func__ );
422                         ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
423                     }
424                 }
425                 MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_EXECUTE );
426             } else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_ERROR_PROCESS ) ) {
427                 ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_ERROR_PROCESS", __func__ );
428                 /* Execute specified error process callback function. */
429                 errorType = eMBMasterGetErrorType( );
430                 vMBMasterGetPDUSndBuf( &ucMBFrame );
431                 switch ( errorType )
432                 {
433                     case EV_ERROR_RESPOND_TIMEOUT:
434                         vMBMasterErrorCBRespondTimeout( ucMBMasterGetDestAddress( ),
435                                 ucMBFrame, usMBMasterGetPDUSndLength( ) );
436                         break;
437                     case EV_ERROR_RECEIVE_DATA:
438                         vMBMasterErrorCBReceiveData( ucMBMasterGetDestAddress( ),
439                                 ucMBFrame, usMBMasterGetPDUSndLength( ) );
440                         break;
441                     case EV_ERROR_EXECUTE_FUNCTION:
442                         vMBMasterErrorCBExecuteFunction( ucMBMasterGetDestAddress( ),
443                                 ucMBFrame, usMBMasterGetPDUSndLength( ) );
444                         break;
445                     case EV_ERROR_OK:
446                         vMBMasterCBRequestSuccess( );
447                         break;
448                     default:
449                         ESP_LOGE( MB_PORT_TAG, "%s: incorrect error type = %d.", __func__, errorType);
450                         break;
451                 }
452                 vMBMasterSetErrorType( EV_ERROR_INIT );
453                 MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_ERROR_PROCESS );
454                 vMBMasterRunResRelease( );
455             }
456         }
457     } else {
458         // Something went wrong and task unblocked but there are no any correct events set
459         ESP_LOGE( MB_PORT_TAG, "%s: Unexpected event triggered 0x%02x.", __func__, eEvent );
460         eStatus = MB_EILLSTATE;
461     }
462     return eStatus;
463 }
464 
465 // Get whether the Modbus Master is run in master mode.
xMBMasterGetCBRunInMasterMode(void)466 BOOL xMBMasterGetCBRunInMasterMode( void )
467 {
468     return xMBRunInMasterMode;
469 }
470 
471 // Set whether the Modbus Master is run in master mode.
vMBMasterSetCBRunInMasterMode(BOOL IsMasterMode)472 void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode )
473 {
474     xMBRunInMasterMode = IsMasterMode;
475 }
476 
477 // Get Modbus Master send destination address.
ucMBMasterGetDestAddress(void)478 UCHAR ucMBMasterGetDestAddress( void )
479 {
480     return ucMBMasterDestAddress;
481 }
482 
483 // Set Modbus Master send destination address.
vMBMasterSetDestAddress(UCHAR Address)484 void vMBMasterSetDestAddress( UCHAR Address )
485 {
486     ucMBMasterDestAddress = Address;
487 }
488 
489 // Get Modbus Master current error event type.
eMBMasterGetErrorType(void)490 eMBMasterErrorEventType inline eMBMasterGetErrorType( void )
491 {
492     return eMBMasterCurErrorType;
493 }
494 
495 // Set Modbus Master current error event type.
vMBMasterSetErrorType(eMBMasterErrorEventType errorType)496 void IRAM_ATTR vMBMasterSetErrorType( eMBMasterErrorEventType errorType )
497 {
498     eMBMasterCurErrorType = errorType;
499 }
500 
501 /* Get Modbus Master send PDU's buffer address pointer.*/
vMBMasterGetPDUSndBuf(UCHAR ** pucFrame)502 void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame )
503 {
504     *pucFrame = ( UCHAR * ) &ucMasterSndBuf[MB_SER_PDU_PDU_OFF];
505 }
506 
507 /* Set Modbus Master send PDU's buffer length.*/
vMBMasterSetPDUSndLength(USHORT SendPDULength)508 void vMBMasterSetPDUSndLength( USHORT SendPDULength )
509 {
510     usMasterSendPDULength = SendPDULength;
511 }
512 
513 /* Get Modbus Master send PDU's buffer length.*/
usMBMasterGetPDUSndLength(void)514 USHORT usMBMasterGetPDUSndLength( void )
515 {
516     return usMasterSendPDULength;
517 }
518 
519 /* Set Modbus Master current timer mode.*/
vMBMasterSetCurTimerMode(eMBMasterTimerMode eMBTimerMode)520 void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode )
521 {
522     eMasterCurTimerMode = eMBTimerMode;
523 }
524 
525 /* Get Modbus Master current timer mode.*/
xMBMasterGetCurTimerMode(void)526 eMBMasterTimerMode MB_PORT_ISR_ATTR xMBMasterGetCurTimerMode( void )
527 {
528     return eMasterCurTimerMode;
529 }
530 
531 /* The master request is broadcast? */
xMBMasterRequestIsBroadcast(void)532 BOOL MB_PORT_ISR_ATTR xMBMasterRequestIsBroadcast( void )
533 {
534     return xFrameIsBroadcast;
535 }
536 
537 /* The master request is broadcast? */
vMBMasterRequestSetType(BOOL xIsBroadcast)538 void vMBMasterRequestSetType( BOOL xIsBroadcast ){
539     xFrameIsBroadcast = xIsBroadcast;
540 }
541 
542 #endif // MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED
543