Forking https://os.mbed.com/users/cam/code/Modbus/ to work for NUCLEO 64 boards

Fork of Cam's original FreeModbus port (https://os.mbed.com/users/cam/code/Modbus/)

Change: - Serial implementation to work for NUCLEO 64 boards and receive interrupts instead of timer. (see `portserial.cpp`)

Added: - Custom RTU mode. Allows for external implementation of packet receiving and sending. Sends and receives packets as whole frames (address + PDU) (i.e. this was added for a custom LoRa implementation). implement `xMBRTUCustGetPDU` and `xMBRTUCustSendResponse` (see `mbport.h`) and call `eMBRTUCustomInit( address )`. implementations need to be fully initialised as `eMBRTUCustomInit` only sets the address and nothing else.

Committer:
danielmckinnell
Date:
Tue Aug 04 04:42:52 2020 +0000
Revision:
4:7621103c5a40
Parent:
3:4cda95d7b6c5
RTU Serial updates

Who changed what in which revision?

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