xref: /nrf52832-nimble/rt-thread/components/net/freemodbus/modbus/functions/mbfuncholding_m.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2  * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3  * Copyright (C) 2013 Armink <[email protected]>
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: mbfuncholding_m.c,v 1.60 2013/09/02 14:13:40 Armink Add Master Functions  Exp $
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 #include "mb.h"
40 #include "mb_m.h"
41 #include "mbframe.h"
42 #include "mbproto.h"
43 #include "mbconfig.h"
44 
45 /* ----------------------- Defines ------------------------------------------*/
46 #define MB_PDU_REQ_READ_ADDR_OFF                ( MB_PDU_DATA_OFF + 0 )
47 #define MB_PDU_REQ_READ_REGCNT_OFF              ( MB_PDU_DATA_OFF + 2 )
48 #define MB_PDU_REQ_READ_SIZE                    ( 4 )
49 #define MB_PDU_FUNC_READ_REGCNT_MAX             ( 0x007D )
50 #define MB_PDU_FUNC_READ_BYTECNT_OFF            ( MB_PDU_DATA_OFF + 0 )
51 #define MB_PDU_FUNC_READ_VALUES_OFF             ( MB_PDU_DATA_OFF + 1 )
52 #define MB_PDU_FUNC_READ_SIZE_MIN               ( 1 )
53 
54 #define MB_PDU_REQ_WRITE_ADDR_OFF               ( MB_PDU_DATA_OFF + 0)
55 #define MB_PDU_REQ_WRITE_VALUE_OFF              ( MB_PDU_DATA_OFF + 2 )
56 #define MB_PDU_REQ_WRITE_SIZE                   ( 4 )
57 #define MB_PDU_FUNC_WRITE_ADDR_OFF              ( MB_PDU_DATA_OFF + 0)
58 #define MB_PDU_FUNC_WRITE_VALUE_OFF             ( MB_PDU_DATA_OFF + 2 )
59 #define MB_PDU_FUNC_WRITE_SIZE                  ( 4 )
60 
61 #define MB_PDU_REQ_WRITE_MUL_ADDR_OFF           ( MB_PDU_DATA_OFF + 0 )
62 #define MB_PDU_REQ_WRITE_MUL_REGCNT_OFF         ( MB_PDU_DATA_OFF + 2 )
63 #define MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF        ( MB_PDU_DATA_OFF + 4 )
64 #define MB_PDU_REQ_WRITE_MUL_VALUES_OFF         ( MB_PDU_DATA_OFF + 5 )
65 #define MB_PDU_REQ_WRITE_MUL_SIZE_MIN           ( 5 )
66 #define MB_PDU_REQ_WRITE_MUL_REGCNT_MAX         ( 0x0078 )
67 #define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF          ( MB_PDU_DATA_OFF + 0 )
68 #define MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF        ( MB_PDU_DATA_OFF + 2 )
69 #define MB_PDU_FUNC_WRITE_MUL_SIZE              ( 4 )
70 
71 #define MB_PDU_REQ_READWRITE_READ_ADDR_OFF      ( MB_PDU_DATA_OFF + 0 )
72 #define MB_PDU_REQ_READWRITE_READ_REGCNT_OFF    ( MB_PDU_DATA_OFF + 2 )
73 #define MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF     ( MB_PDU_DATA_OFF + 4 )
74 #define MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF   ( MB_PDU_DATA_OFF + 6 )
75 #define MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF  ( MB_PDU_DATA_OFF + 8 )
76 #define MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF   ( MB_PDU_DATA_OFF + 9 )
77 #define MB_PDU_REQ_READWRITE_SIZE_MIN           ( 9 )
78 #define MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF  ( MB_PDU_DATA_OFF + 0 )
79 #define MB_PDU_FUNC_READWRITE_READ_VALUES_OFF   ( MB_PDU_DATA_OFF + 1 )
80 #define MB_PDU_FUNC_READWRITE_SIZE_MIN          ( 1 )
81 
82 /* ----------------------- Static functions ---------------------------------*/
83 eMBException    prveMBError2Exception( eMBErrorCode eErrorCode );
84 
85 /* ----------------------- Start implementation -----------------------------*/
86 #if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
87 #if MB_FUNC_WRITE_HOLDING_ENABLED > 0
88 
89 /**
90  * This function will request write holding register.
91  *
92  * @param ucSndAddr salve address
93  * @param usRegAddr register start address
94  * @param usRegData register data to be written
95  * @param lTimeOut timeout (-1 will waiting forever)
96  *
97  * @return error code
98  */
99 eMBMasterReqErrCode
eMBMasterReqWriteHoldingRegister(UCHAR ucSndAddr,USHORT usRegAddr,USHORT usRegData,LONG lTimeOut)100 eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut )
101 {
102     UCHAR                 *ucMBFrame;
103     eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
104 
105     if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
106     else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
107     else
108     {
109 		vMBMasterGetPDUSndBuf(&ucMBFrame);
110 		vMBMasterSetDestAddress(ucSndAddr);
111 		ucMBFrame[MB_PDU_FUNC_OFF]                = MB_FUNC_WRITE_REGISTER;
112 		ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF]      = usRegAddr >> 8;
113 		ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1]  = usRegAddr;
114 		ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF]     = usRegData >> 8;
115 		ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usRegData ;
116 		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE );
117 		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
118 		eErrStatus = eMBMasterWaitRequestFinish( );
119     }
120     return eErrStatus;
121 }
122 
123 eMBException
eMBMasterFuncWriteHoldingRegister(UCHAR * pucFrame,USHORT * usLen)124 eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
125 {
126     USHORT          usRegAddress;
127     eMBException    eStatus = MB_EX_NONE;
128     eMBErrorCode    eRegStatus;
129 
130     if( *usLen == ( MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_SIZE ) )
131     {
132         usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 );
133         usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] );
134         usRegAddress++;
135 
136         /* Make callback to update the value. */
137         eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF],
138                                       usRegAddress, 1, MB_REG_WRITE );
139 
140         /* If an error occured convert it into a Modbus exception. */
141         if( eRegStatus != MB_ENOERR )
142         {
143             eStatus = prveMBError2Exception( eRegStatus );
144         }
145     }
146     else
147     {
148         /* Can't be a valid request because the length is incorrect. */
149         eStatus = MB_EX_ILLEGAL_DATA_VALUE;
150     }
151     return eStatus;
152 }
153 #endif
154 
155 #if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0
156 
157 /**
158  * This function will request write multiple holding register.
159  *
160  * @param ucSndAddr salve address
161  * @param usRegAddr register start address
162  * @param usNRegs register total number
163  * @param pusDataBuffer data to be written
164  * @param lTimeOut timeout (-1 will waiting forever)
165  *
166  * @return error code
167  */
168 eMBMasterReqErrCode
eMBMasterReqWriteMultipleHoldingRegister(UCHAR ucSndAddr,USHORT usRegAddr,USHORT usNRegs,USHORT * pusDataBuffer,LONG lTimeOut)169 eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr,
170 		USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut )
171 {
172     UCHAR                 *ucMBFrame;
173     USHORT                 usRegIndex = 0;
174     eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
175 
176     if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
177     else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
178     else
179     {
180 		vMBMasterGetPDUSndBuf(&ucMBFrame);
181 		vMBMasterSetDestAddress(ucSndAddr);
182 		ucMBFrame[MB_PDU_FUNC_OFF]                     = MB_FUNC_WRITE_MULTIPLE_REGISTERS;
183 		ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF]       = usRegAddr >> 8;
184 		ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1]   = usRegAddr;
185 		ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF]     = usNRegs >> 8;
186 		ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1] = usNRegs ;
187 		ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF]    = usNRegs * 2;
188 		ucMBFrame += MB_PDU_REQ_WRITE_MUL_VALUES_OFF;
189 		while( usNRegs > usRegIndex)
190 		{
191 			*ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8;
192 			*ucMBFrame++ = pusDataBuffer[usRegIndex++] ;
193 		}
194 		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + 2*usNRegs );
195 		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
196 		eErrStatus = eMBMasterWaitRequestFinish( );
197     }
198     return eErrStatus;
199 }
200 
201 eMBException
eMBMasterFuncWriteMultipleHoldingRegister(UCHAR * pucFrame,USHORT * usLen)202 eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
203 {
204     UCHAR          *ucMBFrame;
205     USHORT          usRegAddress;
206     USHORT          usRegCount;
207     UCHAR           ucRegByteCount;
208 
209     eMBException    eStatus = MB_EX_NONE;
210     eMBErrorCode    eRegStatus;
211 
212     /* If this request is broadcast, the *usLen is not need check. */
213     if( ( *usLen == MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() )
214     {
215 		vMBMasterGetPDUSndBuf(&ucMBFrame);
216         usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] << 8 );
217         usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] );
218         usRegAddress++;
219 
220         usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF] << 8 );
221         usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1] );
222 
223         ucRegByteCount = ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF];
224 
225         if( ucRegByteCount == 2 * usRegCount )
226         {
227             /* Make callback to update the register values. */
228             eRegStatus =
229                 eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
230                                  usRegAddress, usRegCount, MB_REG_WRITE );
231 
232             /* If an error occured convert it into a Modbus exception. */
233             if( eRegStatus != MB_ENOERR )
234             {
235                 eStatus = prveMBError2Exception( eRegStatus );
236             }
237         }
238         else
239         {
240             eStatus = MB_EX_ILLEGAL_DATA_VALUE;
241         }
242     }
243     else
244     {
245         /* Can't be a valid request because the length is incorrect. */
246         eStatus = MB_EX_ILLEGAL_DATA_VALUE;
247     }
248     return eStatus;
249 }
250 #endif
251 
252 #if MB_FUNC_READ_HOLDING_ENABLED > 0
253 
254 /**
255  * This function will request read holding register.
256  *
257  * @param ucSndAddr salve address
258  * @param usRegAddr register start address
259  * @param usNRegs register total number
260  * @param lTimeOut timeout (-1 will waiting forever)
261  *
262  * @return error code
263  */
264 eMBMasterReqErrCode
eMBMasterReqReadHoldingRegister(UCHAR ucSndAddr,USHORT usRegAddr,USHORT usNRegs,LONG lTimeOut)265 eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut )
266 {
267     UCHAR                 *ucMBFrame;
268     eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
269 
270     if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
271     else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
272     else
273     {
274 		vMBMasterGetPDUSndBuf(&ucMBFrame);
275 		vMBMasterSetDestAddress(ucSndAddr);
276 		ucMBFrame[MB_PDU_FUNC_OFF]                = MB_FUNC_READ_HOLDING_REGISTER;
277 		ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF]       = usRegAddr >> 8;
278 		ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1]   = usRegAddr;
279 		ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF]     = usNRegs >> 8;
280 		ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs;
281 		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
282 		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
283 		eErrStatus = eMBMasterWaitRequestFinish( );
284     }
285     return eErrStatus;
286 }
287 
288 eMBException
eMBMasterFuncReadHoldingRegister(UCHAR * pucFrame,USHORT * usLen)289 eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
290 {
291     UCHAR          *ucMBFrame;
292     USHORT          usRegAddress;
293     USHORT          usRegCount;
294 
295     eMBException    eStatus = MB_EX_NONE;
296     eMBErrorCode    eRegStatus;
297 
298     /* If this request is broadcast, and it's read mode. This request don't need execute. */
299     if ( xMBMasterRequestIsBroadcast() )
300     {
301     	eStatus = MB_EX_NONE;
302     }
303     else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
304     {
305 		vMBMasterGetPDUSndBuf(&ucMBFrame);
306         usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
307         usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] );
308         usRegAddress++;
309 
310         usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 );
311         usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
312 
313         /* Check if the number of registers to read is valid. If not
314          * return Modbus illegal data value exception.
315          */
316         if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) )
317         {
318             /* Make callback to fill the buffer. */
319             eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount, MB_REG_READ );
320             /* If an error occured convert it into a Modbus exception. */
321             if( eRegStatus != MB_ENOERR )
322             {
323                 eStatus = prveMBError2Exception( eRegStatus );
324             }
325         }
326         else
327         {
328             eStatus = MB_EX_ILLEGAL_DATA_VALUE;
329         }
330     }
331     else
332     {
333         /* Can't be a valid request because the length is incorrect. */
334         eStatus = MB_EX_ILLEGAL_DATA_VALUE;
335     }
336     return eStatus;
337 }
338 
339 #endif
340 
341 #if MB_FUNC_READWRITE_HOLDING_ENABLED > 0
342 
343 /**
344  * This function will request read and write holding register.
345  *
346  * @param ucSndAddr salve address
347  * @param usReadRegAddr read register start address
348  * @param usNReadRegs read register total number
349  * @param pusDataBuffer data to be written
350  * @param usWriteRegAddr write register start address
351  * @param usNWriteRegs write register total number
352  * @param lTimeOut timeout (-1 will waiting forever)
353  *
354  * @return error code
355  */
356 eMBMasterReqErrCode
eMBMasterReqReadWriteMultipleHoldingRegister(UCHAR ucSndAddr,USHORT usReadRegAddr,USHORT usNReadRegs,USHORT * pusDataBuffer,USHORT usWriteRegAddr,USHORT usNWriteRegs,LONG lTimeOut)357 eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
358 		USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer,
359 		USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut )
360 {
361     UCHAR                 *ucMBFrame;
362     USHORT                 usRegIndex = 0;
363     eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
364 
365     if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
366     else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
367     else
368     {
369 		vMBMasterGetPDUSndBuf(&ucMBFrame);
370 		vMBMasterSetDestAddress(ucSndAddr);
371 		ucMBFrame[MB_PDU_FUNC_OFF]                           = MB_FUNC_READWRITE_MULTIPLE_REGISTERS;
372 		ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF]        = usReadRegAddr >> 8;
373 		ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1]    = usReadRegAddr;
374 		ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF]      = usNReadRegs >> 8;
375 		ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1]  = usNReadRegs ;
376 		ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF]       = usWriteRegAddr >> 8;
377 		ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1]   = usWriteRegAddr;
378 		ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF]     = usNWriteRegs >> 8;
379 		ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] = usNWriteRegs ;
380 		ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF]    = usNWriteRegs * 2;
381 		ucMBFrame += MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF;
382 		while( usNWriteRegs > usRegIndex)
383 		{
384 			*ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8;
385 			*ucMBFrame++ = pusDataBuffer[usRegIndex++] ;
386 		}
387 		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READWRITE_SIZE_MIN + 2*usNWriteRegs );
388 		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
389 		eErrStatus = eMBMasterWaitRequestFinish( );
390     }
391     return eErrStatus;
392 }
393 
394 eMBException
eMBMasterFuncReadWriteMultipleHoldingRegister(UCHAR * pucFrame,USHORT * usLen)395 eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
396 {
397     USHORT          usRegReadAddress;
398     USHORT          usRegReadCount;
399     USHORT          usRegWriteAddress;
400     USHORT          usRegWriteCount;
401     UCHAR          *ucMBFrame;
402 
403     eMBException    eStatus = MB_EX_NONE;
404     eMBErrorCode    eRegStatus;
405 
406     /* If this request is broadcast, and it's read mode. This request don't need execute. */
407     if ( xMBMasterRequestIsBroadcast() )
408     {
409     	eStatus = MB_EX_NONE;
410     }
411     else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READWRITE_SIZE_MIN )
412     {
413     	vMBMasterGetPDUSndBuf(&ucMBFrame);
414         usRegReadAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] << 8U );
415         usRegReadAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1] );
416         usRegReadAddress++;
417 
418         usRegReadCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF] << 8U );
419         usRegReadCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1] );
420 
421         usRegWriteAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF] << 8U );
422         usRegWriteAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1] );
423         usRegWriteAddress++;
424 
425         usRegWriteCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF] << 8U );
426         usRegWriteCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] );
427 
428         if( ( 2 * usRegReadCount ) == pucFrame[MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF] )
429         {
430             /* Make callback to update the register values. */
431             eRegStatus = eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF],
432                                            usRegWriteAddress, usRegWriteCount, MB_REG_WRITE );
433 
434             if( eRegStatus == MB_ENOERR )
435             {
436                 /* Make the read callback. */
437 				eRegStatus = eMBMasterRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF],
438 						                      usRegReadAddress, usRegReadCount, MB_REG_READ);
439             }
440             if( eRegStatus != MB_ENOERR )
441             {
442                 eStatus = prveMBError2Exception( eRegStatus );
443             }
444         }
445         else
446         {
447             eStatus = MB_EX_ILLEGAL_DATA_VALUE;
448         }
449     }
450     return eStatus;
451 }
452 
453 #endif
454 #endif
455 
456