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