xref: /nrf52832-nimble/rt-thread/components/net/freemodbus/modbus/rtu/mbrtu_m.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3*10465441SEvalZero  * Copyright (c) 2013 China Beijing Armink <[email protected]>
4*10465441SEvalZero  * All rights reserved.
5*10465441SEvalZero  *
6*10465441SEvalZero  * Redistribution and use in source and binary forms, with or without
7*10465441SEvalZero  * modification, are permitted provided that the following conditions
8*10465441SEvalZero  * are met:
9*10465441SEvalZero  * 1. Redistributions of source code must retain the above copyright
10*10465441SEvalZero  *    notice, this list of conditions and the following disclaimer.
11*10465441SEvalZero  * 2. Redistributions in binary form must reproduce the above copyright
12*10465441SEvalZero  *    notice, this list of conditions and the following disclaimer in the
13*10465441SEvalZero  *    documentation and/or other materials provided with the distribution.
14*10465441SEvalZero  * 3. The name of the author may not be used to endorse or promote products
15*10465441SEvalZero  *    derived from this software without specific prior written permission.
16*10465441SEvalZero  *
17*10465441SEvalZero  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18*10465441SEvalZero  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19*10465441SEvalZero  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*10465441SEvalZero  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21*10465441SEvalZero  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22*10465441SEvalZero  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23*10465441SEvalZero  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24*10465441SEvalZero  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25*10465441SEvalZero  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26*10465441SEvalZero  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*10465441SEvalZero  *
28*10465441SEvalZero  * File: $Id: mbrtu_m.c,v 1.60 2013/08/17 11:42:56 Armink Add Master Functions $
29*10465441SEvalZero  */
30*10465441SEvalZero 
31*10465441SEvalZero /* ----------------------- System includes ----------------------------------*/
32*10465441SEvalZero #include "stdlib.h"
33*10465441SEvalZero #include "string.h"
34*10465441SEvalZero 
35*10465441SEvalZero /* ----------------------- Platform includes --------------------------------*/
36*10465441SEvalZero #include "port.h"
37*10465441SEvalZero 
38*10465441SEvalZero /* ----------------------- Modbus includes ----------------------------------*/
39*10465441SEvalZero #include "mb.h"
40*10465441SEvalZero #include "mb_m.h"
41*10465441SEvalZero #include "mbrtu.h"
42*10465441SEvalZero #include "mbframe.h"
43*10465441SEvalZero 
44*10465441SEvalZero #include "mbcrc.h"
45*10465441SEvalZero #include "mbport.h"
46*10465441SEvalZero 
47*10465441SEvalZero #if MB_MASTER_RTU_ENABLED > 0
48*10465441SEvalZero /* ----------------------- Defines ------------------------------------------*/
49*10465441SEvalZero #define MB_SER_PDU_SIZE_MIN     4       /*!< Minimum size of a Modbus RTU frame. */
50*10465441SEvalZero #define MB_SER_PDU_SIZE_MAX     256     /*!< Maximum size of a Modbus RTU frame. */
51*10465441SEvalZero #define MB_SER_PDU_SIZE_CRC     2       /*!< Size of CRC field in PDU. */
52*10465441SEvalZero #define MB_SER_PDU_ADDR_OFF     0       /*!< Offset of slave address in Ser-PDU. */
53*10465441SEvalZero #define MB_SER_PDU_PDU_OFF      1       /*!< Offset of Modbus-PDU in Ser-PDU. */
54*10465441SEvalZero 
55*10465441SEvalZero /* ----------------------- Type definitions ---------------------------------*/
56*10465441SEvalZero typedef enum
57*10465441SEvalZero {
58*10465441SEvalZero     STATE_M_RX_INIT,              /*!< Receiver is in initial state. */
59*10465441SEvalZero     STATE_M_RX_IDLE,              /*!< Receiver is in idle state. */
60*10465441SEvalZero     STATE_M_RX_RCV,               /*!< Frame is beeing received. */
61*10465441SEvalZero     STATE_M_RX_ERROR,              /*!< If the frame is invalid. */
62*10465441SEvalZero } eMBMasterRcvState;
63*10465441SEvalZero 
64*10465441SEvalZero typedef enum
65*10465441SEvalZero {
66*10465441SEvalZero     STATE_M_TX_IDLE,              /*!< Transmitter is in idle state. */
67*10465441SEvalZero     STATE_M_TX_XMIT,              /*!< Transmitter is in transfer state. */
68*10465441SEvalZero     STATE_M_TX_XFWR,              /*!< Transmitter is in transfer finish and wait receive state. */
69*10465441SEvalZero } eMBMasterSndState;
70*10465441SEvalZero 
71*10465441SEvalZero /* ----------------------- Static variables ---------------------------------*/
72*10465441SEvalZero static volatile eMBMasterSndState eSndState;
73*10465441SEvalZero static volatile eMBMasterRcvState eRcvState;
74*10465441SEvalZero 
75*10465441SEvalZero static volatile UCHAR  ucMasterRTUSndBuf[MB_PDU_SIZE_MAX];
76*10465441SEvalZero static volatile UCHAR  ucMasterRTURcvBuf[MB_SER_PDU_SIZE_MAX];
77*10465441SEvalZero static volatile USHORT usMasterSendPDULength;
78*10465441SEvalZero 
79*10465441SEvalZero static volatile UCHAR *pucMasterSndBufferCur;
80*10465441SEvalZero static volatile USHORT usMasterSndBufferCount;
81*10465441SEvalZero 
82*10465441SEvalZero static volatile USHORT usMasterRcvBufferPos;
83*10465441SEvalZero static volatile BOOL   xFrameIsBroadcast = FALSE;
84*10465441SEvalZero 
85*10465441SEvalZero static volatile eMBMasterTimerMode eMasterCurTimerMode;
86*10465441SEvalZero 
87*10465441SEvalZero /* ----------------------- Start implementation -----------------------------*/
88*10465441SEvalZero eMBErrorCode
eMBMasterRTUInit(UCHAR ucPort,ULONG ulBaudRate,eMBParity eParity)89*10465441SEvalZero eMBMasterRTUInit(UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity )
90*10465441SEvalZero {
91*10465441SEvalZero     eMBErrorCode    eStatus = MB_ENOERR;
92*10465441SEvalZero     ULONG           usTimerT35_50us;
93*10465441SEvalZero 
94*10465441SEvalZero     ENTER_CRITICAL_SECTION(  );
95*10465441SEvalZero 
96*10465441SEvalZero     /* Modbus RTU uses 8 Databits. */
97*10465441SEvalZero     if( xMBMasterPortSerialInit( ucPort, ulBaudRate, 8, eParity ) != TRUE )
98*10465441SEvalZero     {
99*10465441SEvalZero         eStatus = MB_EPORTERR;
100*10465441SEvalZero     }
101*10465441SEvalZero     else
102*10465441SEvalZero     {
103*10465441SEvalZero         /* If baudrate > 19200 then we should use the fixed timer values
104*10465441SEvalZero          * t35 = 1750us. Otherwise t35 must be 3.5 times the character time.
105*10465441SEvalZero          */
106*10465441SEvalZero         if( ulBaudRate > 19200 )
107*10465441SEvalZero         {
108*10465441SEvalZero             usTimerT35_50us = 35;       /* 1800us. */
109*10465441SEvalZero         }
110*10465441SEvalZero         else
111*10465441SEvalZero         {
112*10465441SEvalZero             /* The timer reload value for a character is given by:
113*10465441SEvalZero              *
114*10465441SEvalZero              * ChTimeValue = Ticks_per_1s / ( Baudrate / 11 )
115*10465441SEvalZero              *             = 11 * Ticks_per_1s / Baudrate
116*10465441SEvalZero              *             = 220000 / Baudrate
117*10465441SEvalZero              * The reload for t3.5 is 1.5 times this value and similary
118*10465441SEvalZero              * for t3.5.
119*10465441SEvalZero              */
120*10465441SEvalZero             usTimerT35_50us = ( 7UL * 220000UL ) / ( 2UL * ulBaudRate );
121*10465441SEvalZero         }
122*10465441SEvalZero         if( xMBMasterPortTimersInit( ( USHORT ) usTimerT35_50us ) != TRUE )
123*10465441SEvalZero         {
124*10465441SEvalZero             eStatus = MB_EPORTERR;
125*10465441SEvalZero         }
126*10465441SEvalZero     }
127*10465441SEvalZero     EXIT_CRITICAL_SECTION(  );
128*10465441SEvalZero 
129*10465441SEvalZero     return eStatus;
130*10465441SEvalZero }
131*10465441SEvalZero 
132*10465441SEvalZero void
eMBMasterRTUStart(void)133*10465441SEvalZero eMBMasterRTUStart( void )
134*10465441SEvalZero {
135*10465441SEvalZero     ENTER_CRITICAL_SECTION(  );
136*10465441SEvalZero     /* Initially the receiver is in the state STATE_M_RX_INIT. we start
137*10465441SEvalZero      * the timer and if no character is received within t3.5 we change
138*10465441SEvalZero      * to STATE_M_RX_IDLE. This makes sure that we delay startup of the
139*10465441SEvalZero      * modbus protocol stack until the bus is free.
140*10465441SEvalZero      */
141*10465441SEvalZero     eRcvState = STATE_M_RX_INIT;
142*10465441SEvalZero     vMBMasterPortSerialEnable( TRUE, FALSE );
143*10465441SEvalZero     vMBMasterPortTimersT35Enable(  );
144*10465441SEvalZero 
145*10465441SEvalZero     EXIT_CRITICAL_SECTION(  );
146*10465441SEvalZero }
147*10465441SEvalZero 
148*10465441SEvalZero void
eMBMasterRTUStop(void)149*10465441SEvalZero eMBMasterRTUStop( void )
150*10465441SEvalZero {
151*10465441SEvalZero     ENTER_CRITICAL_SECTION(  );
152*10465441SEvalZero     vMBMasterPortSerialEnable( FALSE, FALSE );
153*10465441SEvalZero     vMBMasterPortTimersDisable(  );
154*10465441SEvalZero     EXIT_CRITICAL_SECTION(  );
155*10465441SEvalZero }
156*10465441SEvalZero 
157*10465441SEvalZero eMBErrorCode
eMBMasterRTUReceive(UCHAR * pucRcvAddress,UCHAR ** pucFrame,USHORT * pusLength)158*10465441SEvalZero eMBMasterRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
159*10465441SEvalZero {
160*10465441SEvalZero     eMBErrorCode    eStatus = MB_ENOERR;
161*10465441SEvalZero 
162*10465441SEvalZero     ENTER_CRITICAL_SECTION(  );
163*10465441SEvalZero     RT_ASSERT( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX );
164*10465441SEvalZero 
165*10465441SEvalZero     /* Length and CRC check */
166*10465441SEvalZero     if( ( usMasterRcvBufferPos >= MB_SER_PDU_SIZE_MIN )
167*10465441SEvalZero         && ( usMBCRC16( ( UCHAR * ) ucMasterRTURcvBuf, usMasterRcvBufferPos ) == 0 ) )
168*10465441SEvalZero     {
169*10465441SEvalZero         /* Save the address field. All frames are passed to the upper layed
170*10465441SEvalZero          * and the decision if a frame is used is done there.
171*10465441SEvalZero          */
172*10465441SEvalZero         *pucRcvAddress = ucMasterRTURcvBuf[MB_SER_PDU_ADDR_OFF];
173*10465441SEvalZero 
174*10465441SEvalZero         /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
175*10465441SEvalZero          * size of address field and CRC checksum.
176*10465441SEvalZero          */
177*10465441SEvalZero         *pusLength = ( USHORT )( usMasterRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC );
178*10465441SEvalZero 
179*10465441SEvalZero         /* Return the start of the Modbus PDU to the caller. */
180*10465441SEvalZero         *pucFrame = ( UCHAR * ) & ucMasterRTURcvBuf[MB_SER_PDU_PDU_OFF];
181*10465441SEvalZero     }
182*10465441SEvalZero     else
183*10465441SEvalZero     {
184*10465441SEvalZero         eStatus = MB_EIO;
185*10465441SEvalZero     }
186*10465441SEvalZero 
187*10465441SEvalZero     EXIT_CRITICAL_SECTION(  );
188*10465441SEvalZero     return eStatus;
189*10465441SEvalZero }
190*10465441SEvalZero 
191*10465441SEvalZero eMBErrorCode
eMBMasterRTUSend(UCHAR ucSlaveAddress,const UCHAR * pucFrame,USHORT usLength)192*10465441SEvalZero eMBMasterRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
193*10465441SEvalZero {
194*10465441SEvalZero     eMBErrorCode    eStatus = MB_ENOERR;
195*10465441SEvalZero     USHORT          usCRC16;
196*10465441SEvalZero 
197*10465441SEvalZero     if ( ucSlaveAddress > MB_MASTER_TOTAL_SLAVE_NUM ) return MB_EINVAL;
198*10465441SEvalZero 
199*10465441SEvalZero     ENTER_CRITICAL_SECTION(  );
200*10465441SEvalZero 
201*10465441SEvalZero     /* Check if the receiver is still in idle state. If not we where to
202*10465441SEvalZero      * slow with processing the received frame and the master sent another
203*10465441SEvalZero      * frame on the network. We have to abort sending the frame.
204*10465441SEvalZero      */
205*10465441SEvalZero     if( eRcvState == STATE_M_RX_IDLE )
206*10465441SEvalZero     {
207*10465441SEvalZero         /* First byte before the Modbus-PDU is the slave address. */
208*10465441SEvalZero         pucMasterSndBufferCur = ( UCHAR * ) pucFrame - 1;
209*10465441SEvalZero         usMasterSndBufferCount = 1;
210*10465441SEvalZero 
211*10465441SEvalZero         /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */
212*10465441SEvalZero         pucMasterSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress;
213*10465441SEvalZero         usMasterSndBufferCount += usLength;
214*10465441SEvalZero 
215*10465441SEvalZero         /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */
216*10465441SEvalZero         usCRC16 = usMBCRC16( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount );
217*10465441SEvalZero         ucMasterRTUSndBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF );
218*10465441SEvalZero         ucMasterRTUSndBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 );
219*10465441SEvalZero 
220*10465441SEvalZero         /* Activate the transmitter. */
221*10465441SEvalZero         eSndState = STATE_M_TX_XMIT;
222*10465441SEvalZero         vMBMasterPortSerialEnable( FALSE, TRUE );
223*10465441SEvalZero     }
224*10465441SEvalZero     else
225*10465441SEvalZero     {
226*10465441SEvalZero         eStatus = MB_EIO;
227*10465441SEvalZero     }
228*10465441SEvalZero     EXIT_CRITICAL_SECTION(  );
229*10465441SEvalZero     return eStatus;
230*10465441SEvalZero }
231*10465441SEvalZero 
232*10465441SEvalZero BOOL
xMBMasterRTUReceiveFSM(void)233*10465441SEvalZero xMBMasterRTUReceiveFSM( void )
234*10465441SEvalZero {
235*10465441SEvalZero     BOOL            xTaskNeedSwitch = FALSE;
236*10465441SEvalZero     UCHAR           ucByte;
237*10465441SEvalZero 
238*10465441SEvalZero     RT_ASSERT(( eSndState == STATE_M_TX_IDLE ) || ( eSndState == STATE_M_TX_XFWR ));
239*10465441SEvalZero 
240*10465441SEvalZero     /* Always read the character. */
241*10465441SEvalZero     ( void )xMBMasterPortSerialGetByte( ( CHAR * ) & ucByte );
242*10465441SEvalZero 
243*10465441SEvalZero     switch ( eRcvState )
244*10465441SEvalZero     {
245*10465441SEvalZero         /* If we have received a character in the init state we have to
246*10465441SEvalZero          * wait until the frame is finished.
247*10465441SEvalZero          */
248*10465441SEvalZero     case STATE_M_RX_INIT:
249*10465441SEvalZero         vMBMasterPortTimersT35Enable( );
250*10465441SEvalZero         break;
251*10465441SEvalZero 
252*10465441SEvalZero         /* In the error state we wait until all characters in the
253*10465441SEvalZero          * damaged frame are transmitted.
254*10465441SEvalZero          */
255*10465441SEvalZero     case STATE_M_RX_ERROR:
256*10465441SEvalZero         vMBMasterPortTimersT35Enable( );
257*10465441SEvalZero         break;
258*10465441SEvalZero 
259*10465441SEvalZero         /* In the idle state we wait for a new character. If a character
260*10465441SEvalZero          * is received the t1.5 and t3.5 timers are started and the
261*10465441SEvalZero          * receiver is in the state STATE_RX_RECEIVCE and disable early
262*10465441SEvalZero          * the timer of respond timeout .
263*10465441SEvalZero          */
264*10465441SEvalZero     case STATE_M_RX_IDLE:
265*10465441SEvalZero     	/* In time of respond timeout,the receiver receive a frame.
266*10465441SEvalZero     	 * Disable timer of respond timeout and change the transmiter state to idle.
267*10465441SEvalZero     	 */
268*10465441SEvalZero     	vMBMasterPortTimersDisable( );
269*10465441SEvalZero     	eSndState = STATE_M_TX_IDLE;
270*10465441SEvalZero 
271*10465441SEvalZero         usMasterRcvBufferPos = 0;
272*10465441SEvalZero         ucMasterRTURcvBuf[usMasterRcvBufferPos++] = ucByte;
273*10465441SEvalZero         eRcvState = STATE_M_RX_RCV;
274*10465441SEvalZero 
275*10465441SEvalZero         /* Enable t3.5 timers. */
276*10465441SEvalZero         vMBMasterPortTimersT35Enable( );
277*10465441SEvalZero         break;
278*10465441SEvalZero 
279*10465441SEvalZero         /* We are currently receiving a frame. Reset the timer after
280*10465441SEvalZero          * every character received. If more than the maximum possible
281*10465441SEvalZero          * number of bytes in a modbus frame is received the frame is
282*10465441SEvalZero          * ignored.
283*10465441SEvalZero          */
284*10465441SEvalZero     case STATE_M_RX_RCV:
285*10465441SEvalZero         if( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX )
286*10465441SEvalZero         {
287*10465441SEvalZero             ucMasterRTURcvBuf[usMasterRcvBufferPos++] = ucByte;
288*10465441SEvalZero         }
289*10465441SEvalZero         else
290*10465441SEvalZero         {
291*10465441SEvalZero             eRcvState = STATE_M_RX_ERROR;
292*10465441SEvalZero         }
293*10465441SEvalZero         vMBMasterPortTimersT35Enable();
294*10465441SEvalZero         break;
295*10465441SEvalZero     }
296*10465441SEvalZero     return xTaskNeedSwitch;
297*10465441SEvalZero }
298*10465441SEvalZero 
299*10465441SEvalZero BOOL
xMBMasterRTUTransmitFSM(void)300*10465441SEvalZero xMBMasterRTUTransmitFSM( void )
301*10465441SEvalZero {
302*10465441SEvalZero     BOOL            xNeedPoll = FALSE;
303*10465441SEvalZero 
304*10465441SEvalZero     RT_ASSERT( eRcvState == STATE_M_RX_IDLE );
305*10465441SEvalZero 
306*10465441SEvalZero     switch ( eSndState )
307*10465441SEvalZero     {
308*10465441SEvalZero         /* We should not get a transmitter event if the transmitter is in
309*10465441SEvalZero          * idle state.  */
310*10465441SEvalZero     case STATE_M_TX_IDLE:
311*10465441SEvalZero         /* enable receiver/disable transmitter. */
312*10465441SEvalZero         vMBMasterPortSerialEnable( TRUE, FALSE );
313*10465441SEvalZero         break;
314*10465441SEvalZero 
315*10465441SEvalZero     case STATE_M_TX_XMIT:
316*10465441SEvalZero         /* check if we are finished. */
317*10465441SEvalZero         if( usMasterSndBufferCount != 0 )
318*10465441SEvalZero         {
319*10465441SEvalZero             xMBMasterPortSerialPutByte( ( CHAR )*pucMasterSndBufferCur );
320*10465441SEvalZero             pucMasterSndBufferCur++;  /* next byte in sendbuffer. */
321*10465441SEvalZero             usMasterSndBufferCount--;
322*10465441SEvalZero         }
323*10465441SEvalZero         else
324*10465441SEvalZero         {
325*10465441SEvalZero             xFrameIsBroadcast = ( ucMasterRTUSndBuf[MB_SER_PDU_ADDR_OFF] == MB_ADDRESS_BROADCAST ) ? TRUE : FALSE;
326*10465441SEvalZero             /* Disable transmitter. This prevents another transmit buffer
327*10465441SEvalZero              * empty interrupt. */
328*10465441SEvalZero             vMBMasterPortSerialEnable( TRUE, FALSE );
329*10465441SEvalZero             eSndState = STATE_M_TX_XFWR;
330*10465441SEvalZero             /* If the frame is broadcast ,master will enable timer of convert delay,
331*10465441SEvalZero              * else master will enable timer of respond timeout. */
332*10465441SEvalZero             if ( xFrameIsBroadcast == TRUE )
333*10465441SEvalZero             {
334*10465441SEvalZero             	vMBMasterPortTimersConvertDelayEnable( );
335*10465441SEvalZero             }
336*10465441SEvalZero             else
337*10465441SEvalZero             {
338*10465441SEvalZero             	vMBMasterPortTimersRespondTimeoutEnable( );
339*10465441SEvalZero             }
340*10465441SEvalZero         }
341*10465441SEvalZero         break;
342*10465441SEvalZero     }
343*10465441SEvalZero 
344*10465441SEvalZero     return xNeedPoll;
345*10465441SEvalZero }
346*10465441SEvalZero 
347*10465441SEvalZero BOOL
xMBMasterRTUTimerExpired(void)348*10465441SEvalZero xMBMasterRTUTimerExpired(void)
349*10465441SEvalZero {
350*10465441SEvalZero 	BOOL xNeedPoll = FALSE;
351*10465441SEvalZero 
352*10465441SEvalZero 	switch (eRcvState)
353*10465441SEvalZero 	{
354*10465441SEvalZero 		/* Timer t35 expired. Startup phase is finished. */
355*10465441SEvalZero 	case STATE_M_RX_INIT:
356*10465441SEvalZero 		xNeedPoll = xMBMasterPortEventPost(EV_MASTER_READY);
357*10465441SEvalZero 		break;
358*10465441SEvalZero 
359*10465441SEvalZero 		/* A frame was received and t35 expired. Notify the listener that
360*10465441SEvalZero 		 * a new frame was received. */
361*10465441SEvalZero 	case STATE_M_RX_RCV:
362*10465441SEvalZero 		xNeedPoll = xMBMasterPortEventPost(EV_MASTER_FRAME_RECEIVED);
363*10465441SEvalZero 		break;
364*10465441SEvalZero 
365*10465441SEvalZero 		/* An error occured while receiving the frame. */
366*10465441SEvalZero 	case STATE_M_RX_ERROR:
367*10465441SEvalZero 		vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
368*10465441SEvalZero 		xNeedPoll = xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
369*10465441SEvalZero 		break;
370*10465441SEvalZero 
371*10465441SEvalZero 		/* Function called in an illegal state. */
372*10465441SEvalZero 	default:
373*10465441SEvalZero 		RT_ASSERT(
374*10465441SEvalZero 				( eRcvState == STATE_M_RX_INIT ) || ( eRcvState == STATE_M_RX_RCV ) ||
375*10465441SEvalZero 				( eRcvState == STATE_M_RX_ERROR ) || ( eRcvState == STATE_M_RX_IDLE ));
376*10465441SEvalZero 		break;
377*10465441SEvalZero 	}
378*10465441SEvalZero 	eRcvState = STATE_M_RX_IDLE;
379*10465441SEvalZero 
380*10465441SEvalZero 	switch (eSndState)
381*10465441SEvalZero 	{
382*10465441SEvalZero 		/* A frame was send finish and convert delay or respond timeout expired.
383*10465441SEvalZero 		 * If the frame is broadcast,The master will idle,and if the frame is not
384*10465441SEvalZero 		 * broadcast.Notify the listener process error.*/
385*10465441SEvalZero 	case STATE_M_TX_XFWR:
386*10465441SEvalZero 		if ( xFrameIsBroadcast == FALSE ) {
387*10465441SEvalZero 			vMBMasterSetErrorType(EV_ERROR_RESPOND_TIMEOUT);
388*10465441SEvalZero 			xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS);
389*10465441SEvalZero 		}
390*10465441SEvalZero 		break;
391*10465441SEvalZero 		/* Function called in an illegal state. */
392*10465441SEvalZero 	default:
393*10465441SEvalZero 		RT_ASSERT(
394*10465441SEvalZero 				( eSndState == STATE_M_TX_XFWR ) || ( eSndState == STATE_M_TX_IDLE ));
395*10465441SEvalZero 		break;
396*10465441SEvalZero 	}
397*10465441SEvalZero 	eSndState = STATE_M_TX_IDLE;
398*10465441SEvalZero 
399*10465441SEvalZero 	vMBMasterPortTimersDisable( );
400*10465441SEvalZero 	/* If timer mode is convert delay, the master event then turns EV_MASTER_EXECUTE status. */
401*10465441SEvalZero 	if (eMasterCurTimerMode == MB_TMODE_CONVERT_DELAY) {
402*10465441SEvalZero 		xNeedPoll = xMBMasterPortEventPost( EV_MASTER_EXECUTE );
403*10465441SEvalZero 	}
404*10465441SEvalZero 
405*10465441SEvalZero 	return xNeedPoll;
406*10465441SEvalZero }
407*10465441SEvalZero 
408*10465441SEvalZero /* Get Modbus Master send RTU's buffer address pointer.*/
vMBMasterGetRTUSndBuf(UCHAR ** pucFrame)409*10465441SEvalZero void vMBMasterGetRTUSndBuf( UCHAR ** pucFrame )
410*10465441SEvalZero {
411*10465441SEvalZero 	*pucFrame = ( UCHAR * ) ucMasterRTUSndBuf;
412*10465441SEvalZero }
413*10465441SEvalZero 
414*10465441SEvalZero /* Get Modbus Master send PDU's buffer address pointer.*/
vMBMasterGetPDUSndBuf(UCHAR ** pucFrame)415*10465441SEvalZero void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame )
416*10465441SEvalZero {
417*10465441SEvalZero 	*pucFrame = ( UCHAR * ) &ucMasterRTUSndBuf[MB_SER_PDU_PDU_OFF];
418*10465441SEvalZero }
419*10465441SEvalZero 
420*10465441SEvalZero /* Set Modbus Master send PDU's buffer length.*/
vMBMasterSetPDUSndLength(USHORT SendPDULength)421*10465441SEvalZero void vMBMasterSetPDUSndLength( USHORT SendPDULength )
422*10465441SEvalZero {
423*10465441SEvalZero 	usMasterSendPDULength = SendPDULength;
424*10465441SEvalZero }
425*10465441SEvalZero 
426*10465441SEvalZero /* Get Modbus Master send PDU's buffer length.*/
usMBMasterGetPDUSndLength(void)427*10465441SEvalZero USHORT usMBMasterGetPDUSndLength( void )
428*10465441SEvalZero {
429*10465441SEvalZero 	return usMasterSendPDULength;
430*10465441SEvalZero }
431*10465441SEvalZero 
432*10465441SEvalZero /* Set Modbus Master current timer mode.*/
vMBMasterSetCurTimerMode(eMBMasterTimerMode eMBTimerMode)433*10465441SEvalZero void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode )
434*10465441SEvalZero {
435*10465441SEvalZero 	eMasterCurTimerMode = eMBTimerMode;
436*10465441SEvalZero }
437*10465441SEvalZero 
438*10465441SEvalZero /* The master request is broadcast? */
xMBMasterRequestIsBroadcast(void)439*10465441SEvalZero BOOL xMBMasterRequestIsBroadcast( void ){
440*10465441SEvalZero 	return xFrameIsBroadcast;
441*10465441SEvalZero }
442*10465441SEvalZero #endif
443*10465441SEvalZero 
444