Modified version of ModbusTCP

Dependencies:   EthernetNetIf mbed

Committer:
paleskyjp
Date:
Thu Mar 15 15:28:14 2012 +0000
Revision:
3:d7d7c67f21fa
Parent:
0:62be54b8975d
eMBRegCoilsCB was corrected.
(Implementation of writing single coil was wrong.)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
paleskyjp 0:62be54b8975d 1 /*
paleskyjp 0:62be54b8975d 2 * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
paleskyjp 0:62be54b8975d 3 * Copyright (c) 2006 Christian Walter <wolti@sil.at>
paleskyjp 0:62be54b8975d 4 * All rights reserved.
paleskyjp 0:62be54b8975d 5 *
paleskyjp 0:62be54b8975d 6 * Redistribution and use in source and binary forms, with or without
paleskyjp 0:62be54b8975d 7 * modification, are permitted provided that the following conditions
paleskyjp 0:62be54b8975d 8 * are met:
paleskyjp 0:62be54b8975d 9 * 1. Redistributions of source code must retain the above copyright
paleskyjp 0:62be54b8975d 10 * notice, this list of conditions and the following disclaimer.
paleskyjp 0:62be54b8975d 11 * 2. Redistributions in binary form must reproduce the above copyright
paleskyjp 0:62be54b8975d 12 * notice, this list of conditions and the following disclaimer in the
paleskyjp 0:62be54b8975d 13 * documentation and/or other materials provided with the distribution.
paleskyjp 0:62be54b8975d 14 * 3. The name of the author may not be used to endorse or promote products
paleskyjp 0:62be54b8975d 15 * derived from this software without specific prior written permission.
paleskyjp 0:62be54b8975d 16 *
paleskyjp 0:62be54b8975d 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
paleskyjp 0:62be54b8975d 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
paleskyjp 0:62be54b8975d 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
paleskyjp 0:62be54b8975d 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
paleskyjp 0:62be54b8975d 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
paleskyjp 0:62be54b8975d 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
paleskyjp 0:62be54b8975d 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
paleskyjp 0:62be54b8975d 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
paleskyjp 0:62be54b8975d 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
paleskyjp 0:62be54b8975d 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
paleskyjp 0:62be54b8975d 27 *
paleskyjp 0:62be54b8975d 28 * File: $Id: mb.c,v 1.27 2007/02/18 23:45:41 wolti Exp $
paleskyjp 0:62be54b8975d 29 */
paleskyjp 0:62be54b8975d 30
paleskyjp 0:62be54b8975d 31 /* ----------------------- System includes ----------------------------------*/
paleskyjp 0:62be54b8975d 32 #include "stdlib.h"
paleskyjp 0:62be54b8975d 33 #include "string.h"
paleskyjp 0:62be54b8975d 34
paleskyjp 0:62be54b8975d 35 /* ----------------------- Platform includes --------------------------------*/
paleskyjp 0:62be54b8975d 36 #include "port.h"
paleskyjp 0:62be54b8975d 37
paleskyjp 0:62be54b8975d 38 /* ----------------------- Modbus includes ----------------------------------*/
paleskyjp 0:62be54b8975d 39 #include "mb.h"
paleskyjp 0:62be54b8975d 40 #include "mbconfig.h"
paleskyjp 0:62be54b8975d 41 #include "mbframe.h"
paleskyjp 0:62be54b8975d 42 #include "mbproto.h"
paleskyjp 0:62be54b8975d 43 #include "mbfunc.h"
paleskyjp 0:62be54b8975d 44 #include "mbport.h"
paleskyjp 0:62be54b8975d 45 #if MB_RTU_ENABLED == 1
paleskyjp 0:62be54b8975d 46 #include "mbrtu.h"
paleskyjp 0:62be54b8975d 47 #endif
paleskyjp 0:62be54b8975d 48 #if MB_ASCII_ENABLED == 1
paleskyjp 0:62be54b8975d 49 #include "mbascii.h"
paleskyjp 0:62be54b8975d 50 #endif
paleskyjp 0:62be54b8975d 51 #if MB_TCP_ENABLED == 1
paleskyjp 0:62be54b8975d 52 #include "mbtcp.h"
paleskyjp 0:62be54b8975d 53 #endif
paleskyjp 0:62be54b8975d 54
paleskyjp 0:62be54b8975d 55 #ifndef MB_PORT_HAS_CLOSE
paleskyjp 0:62be54b8975d 56 #define MB_PORT_HAS_CLOSE 0
paleskyjp 0:62be54b8975d 57 #endif
paleskyjp 0:62be54b8975d 58
paleskyjp 0:62be54b8975d 59 /* ----------------------- Static variables ---------------------------------*/
paleskyjp 0:62be54b8975d 60
paleskyjp 0:62be54b8975d 61
paleskyjp 0:62be54b8975d 62 static UCHAR ucMBAddress;
paleskyjp 0:62be54b8975d 63 static eMBMode eMBCurrentMode;
paleskyjp 0:62be54b8975d 64
paleskyjp 0:62be54b8975d 65 static enum {
paleskyjp 0:62be54b8975d 66 STATE_ENABLED,
paleskyjp 0:62be54b8975d 67 STATE_DISABLED,
paleskyjp 0:62be54b8975d 68 STATE_NOT_INITIALIZED
paleskyjp 0:62be54b8975d 69 } eMBState = STATE_NOT_INITIALIZED;
paleskyjp 0:62be54b8975d 70
paleskyjp 0:62be54b8975d 71 /* Functions pointer which are initialized in eMBInit( ). Depending on the
paleskyjp 0:62be54b8975d 72 * mode (RTU or ASCII) the are set to the correct implementations.
paleskyjp 0:62be54b8975d 73 */
paleskyjp 0:62be54b8975d 74 static peMBFrameSend peMBFrameSendCur;
paleskyjp 0:62be54b8975d 75 static pvMBFrameStart pvMBFrameStartCur;
paleskyjp 0:62be54b8975d 76 static pvMBFrameStop pvMBFrameStopCur;
paleskyjp 0:62be54b8975d 77 static peMBFrameReceive peMBFrameReceiveCur;
paleskyjp 0:62be54b8975d 78 static pvMBFrameClose pvMBFrameCloseCur;
paleskyjp 0:62be54b8975d 79
paleskyjp 0:62be54b8975d 80 /* Callback functions required by the porting layer. They are called when
paleskyjp 0:62be54b8975d 81 * an external event has happend which includes a timeout or the reception
paleskyjp 0:62be54b8975d 82 * or transmission of a character.
paleskyjp 0:62be54b8975d 83 */
paleskyjp 0:62be54b8975d 84 BOOL( *pxMBFrameCBByteReceived ) ( void );
paleskyjp 0:62be54b8975d 85 BOOL( *pxMBFrameCBTransmitterEmpty ) ( void );
paleskyjp 0:62be54b8975d 86 BOOL( *pxMBPortCBTimerExpired ) ( void );
paleskyjp 0:62be54b8975d 87
paleskyjp 0:62be54b8975d 88 BOOL( *pxMBFrameCBReceiveFSMCur ) ( void );
paleskyjp 0:62be54b8975d 89 BOOL( *pxMBFrameCBTransmitFSMCur ) ( void );
paleskyjp 0:62be54b8975d 90
paleskyjp 0:62be54b8975d 91 /* An array of Modbus functions handlers which associates Modbus function
paleskyjp 0:62be54b8975d 92 * codes with implementing functions.
paleskyjp 0:62be54b8975d 93 */
paleskyjp 0:62be54b8975d 94 static xMBFunctionHandler xFuncHandlers[MB_FUNC_HANDLERS_MAX] = {
paleskyjp 0:62be54b8975d 95 #if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0
paleskyjp 0:62be54b8975d 96 {MB_FUNC_OTHER_REPORT_SLAVEID, eMBFuncReportSlaveID},
paleskyjp 0:62be54b8975d 97 #endif
paleskyjp 0:62be54b8975d 98 #if MB_FUNC_READ_INPUT_ENABLED > 0
paleskyjp 0:62be54b8975d 99 {MB_FUNC_READ_INPUT_REGISTER, eMBFuncReadInputRegister},
paleskyjp 0:62be54b8975d 100 #endif
paleskyjp 0:62be54b8975d 101 #if MB_FUNC_READ_HOLDING_ENABLED > 0
paleskyjp 0:62be54b8975d 102 {MB_FUNC_READ_HOLDING_REGISTER, eMBFuncReadHoldingRegister},
paleskyjp 0:62be54b8975d 103 #endif
paleskyjp 0:62be54b8975d 104 #if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0
paleskyjp 0:62be54b8975d 105 {MB_FUNC_WRITE_MULTIPLE_REGISTERS, eMBFuncWriteMultipleHoldingRegister},
paleskyjp 0:62be54b8975d 106 #endif
paleskyjp 0:62be54b8975d 107 #if MB_FUNC_WRITE_HOLDING_ENABLED > 0
paleskyjp 0:62be54b8975d 108 {MB_FUNC_WRITE_REGISTER, eMBFuncWriteHoldingRegister},
paleskyjp 0:62be54b8975d 109 #endif
paleskyjp 0:62be54b8975d 110 #if MB_FUNC_READWRITE_HOLDING_ENABLED > 0
paleskyjp 0:62be54b8975d 111 {MB_FUNC_READWRITE_MULTIPLE_REGISTERS, eMBFuncReadWriteMultipleHoldingRegister},
paleskyjp 0:62be54b8975d 112 #endif
paleskyjp 0:62be54b8975d 113 #if MB_FUNC_READ_COILS_ENABLED > 0
paleskyjp 0:62be54b8975d 114 {MB_FUNC_READ_COILS, eMBFuncReadCoils},
paleskyjp 0:62be54b8975d 115 #endif
paleskyjp 0:62be54b8975d 116 #if MB_FUNC_WRITE_COIL_ENABLED > 0
paleskyjp 0:62be54b8975d 117 {MB_FUNC_WRITE_SINGLE_COIL, eMBFuncWriteCoil},
paleskyjp 0:62be54b8975d 118 #endif
paleskyjp 0:62be54b8975d 119 #if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0
paleskyjp 0:62be54b8975d 120 {MB_FUNC_WRITE_MULTIPLE_COILS, eMBFuncWriteMultipleCoils},
paleskyjp 0:62be54b8975d 121 #endif
paleskyjp 0:62be54b8975d 122 #if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0
paleskyjp 0:62be54b8975d 123 {MB_FUNC_READ_DISCRETE_INPUTS, eMBFuncReadDiscreteInputs},
paleskyjp 0:62be54b8975d 124 #endif
paleskyjp 0:62be54b8975d 125 };
paleskyjp 0:62be54b8975d 126
paleskyjp 0:62be54b8975d 127 /* ----------------------- Start implementation -----------------------------*/
paleskyjp 0:62be54b8975d 128 eMBErrorCode
paleskyjp 0:62be54b8975d 129 eMBInit( eMBMode eMode, UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) {
paleskyjp 0:62be54b8975d 130 eMBErrorCode eStatus = MB_ENOERR;
paleskyjp 0:62be54b8975d 131
paleskyjp 0:62be54b8975d 132 /* check preconditions */
paleskyjp 0:62be54b8975d 133 if ( ( ucSlaveAddress == MB_ADDRESS_BROADCAST ) ||
paleskyjp 0:62be54b8975d 134 ( ucSlaveAddress < MB_ADDRESS_MIN ) || ( ucSlaveAddress > MB_ADDRESS_MAX ) ) {
paleskyjp 0:62be54b8975d 135 eStatus = MB_EINVAL;
paleskyjp 0:62be54b8975d 136 } else {
paleskyjp 0:62be54b8975d 137 ucMBAddress = ucSlaveAddress;
paleskyjp 0:62be54b8975d 138
paleskyjp 0:62be54b8975d 139 switch ( eMode ) {
paleskyjp 0:62be54b8975d 140 #if MB_RTU_ENABLED > 0
paleskyjp 0:62be54b8975d 141 case MB_RTU:
paleskyjp 0:62be54b8975d 142 pvMBFrameStartCur = eMBRTUStart;
paleskyjp 0:62be54b8975d 143 pvMBFrameStopCur = eMBRTUStop;
paleskyjp 0:62be54b8975d 144 peMBFrameSendCur = eMBRTUSend;
paleskyjp 0:62be54b8975d 145 peMBFrameReceiveCur = eMBRTUReceive;
paleskyjp 0:62be54b8975d 146 pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBPortClose : NULL;
paleskyjp 0:62be54b8975d 147 pxMBFrameCBByteReceived = xMBRTUReceiveFSM;
paleskyjp 0:62be54b8975d 148 pxMBFrameCBTransmitterEmpty = xMBRTUTransmitFSM;
paleskyjp 0:62be54b8975d 149 pxMBPortCBTimerExpired = xMBRTUTimerT35Expired;
paleskyjp 0:62be54b8975d 150
paleskyjp 0:62be54b8975d 151 eStatus = eMBRTUInit( ucMBAddress, ucPort, ulBaudRate, eParity );
paleskyjp 0:62be54b8975d 152 break;
paleskyjp 0:62be54b8975d 153 #endif
paleskyjp 0:62be54b8975d 154 #if MB_ASCII_ENABLED > 0
paleskyjp 0:62be54b8975d 155 case MB_ASCII:
paleskyjp 0:62be54b8975d 156 pvMBFrameStartCur = eMBASCIIStart;
paleskyjp 0:62be54b8975d 157 pvMBFrameStopCur = eMBASCIIStop;
paleskyjp 0:62be54b8975d 158 peMBFrameSendCur = eMBASCIISend;
paleskyjp 0:62be54b8975d 159 peMBFrameReceiveCur = eMBASCIIReceive;
paleskyjp 0:62be54b8975d 160 pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBPortClose : NULL;
paleskyjp 0:62be54b8975d 161 pxMBFrameCBByteReceived = xMBASCIIReceiveFSM;
paleskyjp 0:62be54b8975d 162 pxMBFrameCBTransmitterEmpty = xMBASCIITransmitFSM;
paleskyjp 0:62be54b8975d 163 pxMBPortCBTimerExpired = xMBASCIITimerT1SExpired;
paleskyjp 0:62be54b8975d 164
paleskyjp 0:62be54b8975d 165 eStatus = eMBASCIIInit( ucMBAddress, ucPort, ulBaudRate, eParity );
paleskyjp 0:62be54b8975d 166 break;
paleskyjp 0:62be54b8975d 167 #endif
paleskyjp 0:62be54b8975d 168 default:
paleskyjp 0:62be54b8975d 169 eStatus = MB_EINVAL;
paleskyjp 0:62be54b8975d 170 }
paleskyjp 0:62be54b8975d 171
paleskyjp 0:62be54b8975d 172 if ( eStatus == MB_ENOERR ) {
paleskyjp 0:62be54b8975d 173 if ( !xMBPortEventInit( ) ) {
paleskyjp 0:62be54b8975d 174 /* port dependent event module initalization failed. */
paleskyjp 0:62be54b8975d 175 eStatus = MB_EPORTERR;
paleskyjp 0:62be54b8975d 176 } else {
paleskyjp 0:62be54b8975d 177 eMBCurrentMode = eMode;
paleskyjp 0:62be54b8975d 178 eMBState = STATE_DISABLED;
paleskyjp 0:62be54b8975d 179 }
paleskyjp 0:62be54b8975d 180 }
paleskyjp 0:62be54b8975d 181 }
paleskyjp 0:62be54b8975d 182 return eStatus;
paleskyjp 0:62be54b8975d 183 }
paleskyjp 0:62be54b8975d 184
paleskyjp 0:62be54b8975d 185 #if MB_TCP_ENABLED > 0
paleskyjp 0:62be54b8975d 186 eMBErrorCode
paleskyjp 0:62be54b8975d 187 eMBTCPInit( USHORT ucTCPPort ) {
paleskyjp 0:62be54b8975d 188 eMBErrorCode eStatus = MB_ENOERR;
paleskyjp 0:62be54b8975d 189
paleskyjp 0:62be54b8975d 190 if ( ( eStatus = eMBTCPDoInit( ucTCPPort ) ) != MB_ENOERR ) {
paleskyjp 0:62be54b8975d 191 eMBState = STATE_DISABLED;
paleskyjp 0:62be54b8975d 192 } else if ( !xMBPortEventInit( ) ) {
paleskyjp 0:62be54b8975d 193 /* Port dependent event module initalization failed. */
paleskyjp 0:62be54b8975d 194 eStatus = MB_EPORTERR;
paleskyjp 0:62be54b8975d 195 } else {
paleskyjp 0:62be54b8975d 196 pvMBFrameStartCur = eMBTCPStart;
paleskyjp 0:62be54b8975d 197 pvMBFrameStopCur = eMBTCPStop;
paleskyjp 0:62be54b8975d 198 peMBFrameReceiveCur = eMBTCPReceive;
paleskyjp 0:62be54b8975d 199 peMBFrameSendCur = eMBTCPSend;
paleskyjp 0:62be54b8975d 200 pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBTCPPortClose : NULL;
paleskyjp 0:62be54b8975d 201 ucMBAddress = MB_TCP_PSEUDO_ADDRESS;
paleskyjp 0:62be54b8975d 202 eMBCurrentMode = MB_TCP;
paleskyjp 0:62be54b8975d 203 eMBState = STATE_DISABLED;
paleskyjp 0:62be54b8975d 204 }
paleskyjp 0:62be54b8975d 205 return eStatus;
paleskyjp 0:62be54b8975d 206 }
paleskyjp 0:62be54b8975d 207 #endif
paleskyjp 0:62be54b8975d 208
paleskyjp 0:62be54b8975d 209
paleskyjp 0:62be54b8975d 210 eMBErrorCode
paleskyjp 0:62be54b8975d 211 eMBRegisterCB( UCHAR ucFunctionCode, pxMBFunctionHandler pxHandler ) {
paleskyjp 0:62be54b8975d 212 int i;
paleskyjp 0:62be54b8975d 213 eMBErrorCode eStatus;
paleskyjp 0:62be54b8975d 214
paleskyjp 0:62be54b8975d 215 if ( ( 0 < ucFunctionCode ) && ( ucFunctionCode <= 127 ) ) {
paleskyjp 0:62be54b8975d 216 ENTER_CRITICAL_SECTION( );
paleskyjp 0:62be54b8975d 217 if ( pxHandler != NULL ) {
paleskyjp 0:62be54b8975d 218 for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) {
paleskyjp 0:62be54b8975d 219 if ( ( xFuncHandlers[i].pxHandler == NULL ) ||
paleskyjp 0:62be54b8975d 220 ( xFuncHandlers[i].pxHandler == pxHandler ) ) {
paleskyjp 0:62be54b8975d 221 xFuncHandlers[i].ucFunctionCode = ucFunctionCode;
paleskyjp 0:62be54b8975d 222 xFuncHandlers[i].pxHandler = pxHandler;
paleskyjp 0:62be54b8975d 223 break;
paleskyjp 0:62be54b8975d 224 }
paleskyjp 0:62be54b8975d 225 }
paleskyjp 0:62be54b8975d 226 eStatus = ( i != MB_FUNC_HANDLERS_MAX ) ? MB_ENOERR : MB_ENORES;
paleskyjp 0:62be54b8975d 227 } else {
paleskyjp 0:62be54b8975d 228 for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) {
paleskyjp 0:62be54b8975d 229 if ( xFuncHandlers[i].ucFunctionCode == ucFunctionCode ) {
paleskyjp 0:62be54b8975d 230 xFuncHandlers[i].ucFunctionCode = 0;
paleskyjp 0:62be54b8975d 231 xFuncHandlers[i].pxHandler = NULL;
paleskyjp 0:62be54b8975d 232 break;
paleskyjp 0:62be54b8975d 233 }
paleskyjp 0:62be54b8975d 234 }
paleskyjp 0:62be54b8975d 235 /* Remove can't fail. */
paleskyjp 0:62be54b8975d 236 eStatus = MB_ENOERR;
paleskyjp 0:62be54b8975d 237 }
paleskyjp 0:62be54b8975d 238 EXIT_CRITICAL_SECTION( );
paleskyjp 0:62be54b8975d 239 } else {
paleskyjp 0:62be54b8975d 240 eStatus = MB_EINVAL;
paleskyjp 0:62be54b8975d 241 }
paleskyjp 0:62be54b8975d 242 return eStatus;
paleskyjp 0:62be54b8975d 243 }
paleskyjp 0:62be54b8975d 244
paleskyjp 0:62be54b8975d 245
paleskyjp 0:62be54b8975d 246 eMBErrorCode
paleskyjp 0:62be54b8975d 247 eMBClose( void ) {
paleskyjp 0:62be54b8975d 248 eMBErrorCode eStatus = MB_ENOERR;
paleskyjp 0:62be54b8975d 249
paleskyjp 0:62be54b8975d 250 if ( eMBState == STATE_DISABLED ) {
paleskyjp 0:62be54b8975d 251 if ( pvMBFrameCloseCur != NULL ) {
paleskyjp 0:62be54b8975d 252 pvMBFrameCloseCur( );
paleskyjp 0:62be54b8975d 253 }
paleskyjp 0:62be54b8975d 254 } else {
paleskyjp 0:62be54b8975d 255 eStatus = MB_EILLSTATE;
paleskyjp 0:62be54b8975d 256 }
paleskyjp 0:62be54b8975d 257 return eStatus;
paleskyjp 0:62be54b8975d 258 }
paleskyjp 0:62be54b8975d 259
paleskyjp 0:62be54b8975d 260 eMBErrorCode
paleskyjp 0:62be54b8975d 261 eMBEnable( void ) {
paleskyjp 0:62be54b8975d 262 eMBErrorCode eStatus = MB_ENOERR;
paleskyjp 0:62be54b8975d 263
paleskyjp 0:62be54b8975d 264 if ( eMBState == STATE_DISABLED ) {
paleskyjp 0:62be54b8975d 265 /* Activate the protocol stack. */
paleskyjp 0:62be54b8975d 266 pvMBFrameStartCur( );
paleskyjp 0:62be54b8975d 267 eMBState = STATE_ENABLED;
paleskyjp 0:62be54b8975d 268 } else {
paleskyjp 0:62be54b8975d 269 eStatus = MB_EILLSTATE;
paleskyjp 0:62be54b8975d 270 }
paleskyjp 0:62be54b8975d 271 return eStatus;
paleskyjp 0:62be54b8975d 272 }
paleskyjp 0:62be54b8975d 273
paleskyjp 0:62be54b8975d 274 eMBErrorCode
paleskyjp 0:62be54b8975d 275 eMBDisable( void ) {
paleskyjp 0:62be54b8975d 276 eMBErrorCode eStatus;
paleskyjp 0:62be54b8975d 277
paleskyjp 0:62be54b8975d 278 if ( eMBState == STATE_ENABLED ) {
paleskyjp 0:62be54b8975d 279 pvMBFrameStopCur( );
paleskyjp 0:62be54b8975d 280 eMBState = STATE_DISABLED;
paleskyjp 0:62be54b8975d 281 eStatus = MB_ENOERR;
paleskyjp 0:62be54b8975d 282 } else if ( eMBState == STATE_DISABLED ) {
paleskyjp 0:62be54b8975d 283 eStatus = MB_ENOERR;
paleskyjp 0:62be54b8975d 284 } else {
paleskyjp 0:62be54b8975d 285 eStatus = MB_EILLSTATE;
paleskyjp 0:62be54b8975d 286 }
paleskyjp 0:62be54b8975d 287 return eStatus;
paleskyjp 0:62be54b8975d 288 }
paleskyjp 0:62be54b8975d 289
paleskyjp 0:62be54b8975d 290 eMBErrorCode
paleskyjp 0:62be54b8975d 291 eMBPoll( void ) {
paleskyjp 0:62be54b8975d 292 static UCHAR *ucMBFrame;
paleskyjp 0:62be54b8975d 293 static UCHAR ucRcvAddress;
paleskyjp 0:62be54b8975d 294 static UCHAR ucFunctionCode;
paleskyjp 0:62be54b8975d 295 static USHORT usLength;
paleskyjp 0:62be54b8975d 296 static eMBException eException;
paleskyjp 0:62be54b8975d 297
paleskyjp 0:62be54b8975d 298 int i;
paleskyjp 0:62be54b8975d 299 eMBErrorCode eStatus = MB_ENOERR;
paleskyjp 0:62be54b8975d 300 eMBEventType eEvent;
paleskyjp 0:62be54b8975d 301
paleskyjp 0:62be54b8975d 302 /* Check if the protocol stack is ready. */
paleskyjp 0:62be54b8975d 303 if ( eMBState != STATE_ENABLED ) {
paleskyjp 0:62be54b8975d 304 return MB_EILLSTATE;
paleskyjp 0:62be54b8975d 305 }
paleskyjp 0:62be54b8975d 306
paleskyjp 0:62be54b8975d 307 /* Check if there is a event available. If not return control to caller.
paleskyjp 0:62be54b8975d 308 * Otherwise we will handle the event. */
paleskyjp 0:62be54b8975d 309 if ( xMBPortEventGet( &eEvent ) == TRUE ) {
paleskyjp 0:62be54b8975d 310 switch ( eEvent ) {
paleskyjp 0:62be54b8975d 311 case EV_READY:
paleskyjp 0:62be54b8975d 312 break;
paleskyjp 0:62be54b8975d 313
paleskyjp 0:62be54b8975d 314 case EV_FRAME_RECEIVED:
paleskyjp 0:62be54b8975d 315 eStatus = peMBFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength );
paleskyjp 0:62be54b8975d 316 if ( eStatus == MB_ENOERR ) {
paleskyjp 0:62be54b8975d 317 /* Check if the frame is for us. If not ignore the frame. */
paleskyjp 0:62be54b8975d 318 if ( ( ucRcvAddress == ucMBAddress ) || ( ucRcvAddress == MB_ADDRESS_BROADCAST ) ) {
paleskyjp 0:62be54b8975d 319 ( void )xMBPortEventPost( EV_EXECUTE );
paleskyjp 0:62be54b8975d 320 }
paleskyjp 0:62be54b8975d 321 }
paleskyjp 0:62be54b8975d 322 break;
paleskyjp 0:62be54b8975d 323
paleskyjp 0:62be54b8975d 324 case EV_EXECUTE:
paleskyjp 0:62be54b8975d 325 ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
paleskyjp 0:62be54b8975d 326 eException = MB_EX_ILLEGAL_FUNCTION;
paleskyjp 0:62be54b8975d 327
paleskyjp 0:62be54b8975d 328
paleskyjp 0:62be54b8975d 329 for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) {
paleskyjp 0:62be54b8975d 330 /* No more function handlers registered. Abort. */
paleskyjp 0:62be54b8975d 331 if ( xFuncHandlers[i].ucFunctionCode == 0 ) {
paleskyjp 0:62be54b8975d 332 break;
paleskyjp 0:62be54b8975d 333 } else if ( xFuncHandlers[i].ucFunctionCode == ucFunctionCode ) {
paleskyjp 0:62be54b8975d 334 eException = xFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
paleskyjp 0:62be54b8975d 335 break;
paleskyjp 0:62be54b8975d 336 }
paleskyjp 0:62be54b8975d 337 }
paleskyjp 0:62be54b8975d 338
paleskyjp 0:62be54b8975d 339 /* If the request was not sent to the broadcast address we
paleskyjp 0:62be54b8975d 340 * return a reply. */
paleskyjp 0:62be54b8975d 341 if ( ucRcvAddress != MB_ADDRESS_BROADCAST ) {
paleskyjp 0:62be54b8975d 342 if ( eException != MB_EX_NONE ) {
paleskyjp 0:62be54b8975d 343 /* An exception occured. Build an error frame. */
paleskyjp 0:62be54b8975d 344 usLength = 0;
paleskyjp 0:62be54b8975d 345 ucMBFrame[usLength++] = ( UCHAR )( ucFunctionCode | MB_FUNC_ERROR );
paleskyjp 0:62be54b8975d 346 ucMBFrame[usLength++] = eException;
paleskyjp 0:62be54b8975d 347 }
paleskyjp 0:62be54b8975d 348 eStatus = peMBFrameSendCur( ucMBAddress, ucMBFrame, usLength );
paleskyjp 0:62be54b8975d 349 }
paleskyjp 0:62be54b8975d 350 break;
paleskyjp 0:62be54b8975d 351
paleskyjp 0:62be54b8975d 352 case EV_FRAME_SENT:
paleskyjp 0:62be54b8975d 353 break;
paleskyjp 0:62be54b8975d 354 }
paleskyjp 0:62be54b8975d 355 }
paleskyjp 0:62be54b8975d 356 return MB_ENOERR;
paleskyjp 0:62be54b8975d 357 }