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 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 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 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 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 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 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 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 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