Jason Engelman / Mbed 2 deprecated Modbus

Dependencies:   mbed

Committer:
tecnosys
Date:
Tue Oct 05 11:51:06 2010 +0000
Revision:
0:7b5d37a81b6b

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tecnosys 0:7b5d37a81b6b 1 /*
tecnosys 0:7b5d37a81b6b 2 * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
tecnosys 0:7b5d37a81b6b 3 * Copyright (c) 2006 Christian Walter <wolti@sil.at>
tecnosys 0:7b5d37a81b6b 4 * All rights reserved.
tecnosys 0:7b5d37a81b6b 5 *
tecnosys 0:7b5d37a81b6b 6 * Redistribution and use in source and binary forms, with or without
tecnosys 0:7b5d37a81b6b 7 * modification, are permitted provided that the following conditions
tecnosys 0:7b5d37a81b6b 8 * are met:
tecnosys 0:7b5d37a81b6b 9 * 1. Redistributions of source code must retain the above copyright
tecnosys 0:7b5d37a81b6b 10 * notice, this list of conditions and the following disclaimer.
tecnosys 0:7b5d37a81b6b 11 * 2. Redistributions in binary form must reproduce the above copyright
tecnosys 0:7b5d37a81b6b 12 * notice, this list of conditions and the following disclaimer in the
tecnosys 0:7b5d37a81b6b 13 * documentation and/or other materials provided with the distribution.
tecnosys 0:7b5d37a81b6b 14 * 3. The name of the author may not be used to endorse or promote products
tecnosys 0:7b5d37a81b6b 15 * derived from this software without specific prior written permission.
tecnosys 0:7b5d37a81b6b 16 *
tecnosys 0:7b5d37a81b6b 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
tecnosys 0:7b5d37a81b6b 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
tecnosys 0:7b5d37a81b6b 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
tecnosys 0:7b5d37a81b6b 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
tecnosys 0:7b5d37a81b6b 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
tecnosys 0:7b5d37a81b6b 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
tecnosys 0:7b5d37a81b6b 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
tecnosys 0:7b5d37a81b6b 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
tecnosys 0:7b5d37a81b6b 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
tecnosys 0:7b5d37a81b6b 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
tecnosys 0:7b5d37a81b6b 27 *
tecnosys 0:7b5d37a81b6b 28 * File: $Id: mbrtu.c,v 1.18 2007/09/12 10:15:56 wolti Exp $
tecnosys 0:7b5d37a81b6b 29 */
tecnosys 0:7b5d37a81b6b 30
tecnosys 0:7b5d37a81b6b 31 /* ----------------------- System includes ----------------------------------*/
tecnosys 0:7b5d37a81b6b 32 #include "stdlib.h"
tecnosys 0:7b5d37a81b6b 33 #include "string.h"
tecnosys 0:7b5d37a81b6b 34
tecnosys 0:7b5d37a81b6b 35 /* ----------------------- Platform includes --------------------------------*/
tecnosys 0:7b5d37a81b6b 36 #include "port.h"
tecnosys 0:7b5d37a81b6b 37
tecnosys 0:7b5d37a81b6b 38 /* ----------------------- Modbus includes ----------------------------------*/
tecnosys 0:7b5d37a81b6b 39 #include "mb.h"
tecnosys 0:7b5d37a81b6b 40 #include "mbrtu.h"
tecnosys 0:7b5d37a81b6b 41 #include "mbframe.h"
tecnosys 0:7b5d37a81b6b 42
tecnosys 0:7b5d37a81b6b 43 #include "mbcrc.h"
tecnosys 0:7b5d37a81b6b 44 #include "mbport.h"
tecnosys 0:7b5d37a81b6b 45
tecnosys 0:7b5d37a81b6b 46 /* ----------------------- Defines ------------------------------------------*/
tecnosys 0:7b5d37a81b6b 47 #define MB_SER_PDU_SIZE_MIN 4 /*!< Minimum size of a Modbus RTU frame. */
tecnosys 0:7b5d37a81b6b 48 #define MB_SER_PDU_SIZE_MAX 256 /*!< Maximum size of a Modbus RTU frame. */
tecnosys 0:7b5d37a81b6b 49 #define MB_SER_PDU_SIZE_CRC 2 /*!< Size of CRC field in PDU. */
tecnosys 0:7b5d37a81b6b 50 #define MB_SER_PDU_ADDR_OFF 0 /*!< Offset of slave address in Ser-PDU. */
tecnosys 0:7b5d37a81b6b 51 #define MB_SER_PDU_PDU_OFF 1 /*!< Offset of Modbus-PDU in Ser-PDU. */
tecnosys 0:7b5d37a81b6b 52
tecnosys 0:7b5d37a81b6b 53 /* ----------------------- Type definitions ---------------------------------*/
tecnosys 0:7b5d37a81b6b 54 typedef enum
tecnosys 0:7b5d37a81b6b 55 {
tecnosys 0:7b5d37a81b6b 56 STATE_RX_INIT, /*!< Receiver is in initial state. */
tecnosys 0:7b5d37a81b6b 57 STATE_RX_IDLE, /*!< Receiver is in idle state. */
tecnosys 0:7b5d37a81b6b 58 STATE_RX_RCV, /*!< Frame is beeing received. */
tecnosys 0:7b5d37a81b6b 59 STATE_RX_ERROR /*!< If the frame is invalid. */
tecnosys 0:7b5d37a81b6b 60 } eMBRcvState;
tecnosys 0:7b5d37a81b6b 61
tecnosys 0:7b5d37a81b6b 62 typedef enum
tecnosys 0:7b5d37a81b6b 63 {
tecnosys 0:7b5d37a81b6b 64 STATE_TX_IDLE, /*!< Transmitter is in idle state. */
tecnosys 0:7b5d37a81b6b 65 STATE_TX_XMIT /*!< Transmitter is in transfer state. */
tecnosys 0:7b5d37a81b6b 66 } eMBSndState;
tecnosys 0:7b5d37a81b6b 67
tecnosys 0:7b5d37a81b6b 68 /* ----------------------- Static variables ---------------------------------*/
tecnosys 0:7b5d37a81b6b 69 static volatile eMBSndState eSndState;
tecnosys 0:7b5d37a81b6b 70 static volatile eMBRcvState eRcvState;
tecnosys 0:7b5d37a81b6b 71
tecnosys 0:7b5d37a81b6b 72 volatile UCHAR ucRTUBuf[MB_SER_PDU_SIZE_MAX];
tecnosys 0:7b5d37a81b6b 73
tecnosys 0:7b5d37a81b6b 74 static volatile UCHAR *pucSndBufferCur;
tecnosys 0:7b5d37a81b6b 75 static volatile USHORT usSndBufferCount;
tecnosys 0:7b5d37a81b6b 76
tecnosys 0:7b5d37a81b6b 77 static volatile USHORT usRcvBufferPos;
tecnosys 0:7b5d37a81b6b 78
tecnosys 0:7b5d37a81b6b 79 /* ----------------------- Start implementation -----------------------------*/
tecnosys 0:7b5d37a81b6b 80 eMBErrorCode
tecnosys 0:7b5d37a81b6b 81 eMBRTUInit( UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity )
tecnosys 0:7b5d37a81b6b 82 {
tecnosys 0:7b5d37a81b6b 83 eMBErrorCode eStatus = MB_ENOERR;
tecnosys 0:7b5d37a81b6b 84 ULONG usTimerT35_50us;
tecnosys 0:7b5d37a81b6b 85
tecnosys 0:7b5d37a81b6b 86 ( void )ucSlaveAddress;
tecnosys 0:7b5d37a81b6b 87 ENTER_CRITICAL_SECTION( );
tecnosys 0:7b5d37a81b6b 88
tecnosys 0:7b5d37a81b6b 89 /* Modbus RTU uses 8 Databits. */
tecnosys 0:7b5d37a81b6b 90 if( xMBPortSerialInit( ucPort, ulBaudRate, 8, eParity ) != TRUE )
tecnosys 0:7b5d37a81b6b 91 {
tecnosys 0:7b5d37a81b6b 92 eStatus = MB_EPORTERR;
tecnosys 0:7b5d37a81b6b 93 }
tecnosys 0:7b5d37a81b6b 94 else
tecnosys 0:7b5d37a81b6b 95 {
tecnosys 0:7b5d37a81b6b 96 /* If baudrate > 19200 then we should use the fixed timer values
tecnosys 0:7b5d37a81b6b 97 * t35 = 1750us. Otherwise t35 must be 3.5 times the character time.
tecnosys 0:7b5d37a81b6b 98 */
tecnosys 0:7b5d37a81b6b 99 if( ulBaudRate > 19200 )
tecnosys 0:7b5d37a81b6b 100 {
tecnosys 0:7b5d37a81b6b 101 usTimerT35_50us = 35; /* 1800us. */
tecnosys 0:7b5d37a81b6b 102 }
tecnosys 0:7b5d37a81b6b 103 else
tecnosys 0:7b5d37a81b6b 104 {
tecnosys 0:7b5d37a81b6b 105 /* The timer reload value for a character is given by:
tecnosys 0:7b5d37a81b6b 106 *
tecnosys 0:7b5d37a81b6b 107 * ChTimeValue = Ticks_per_1s / ( Baudrate / 11 )
tecnosys 0:7b5d37a81b6b 108 * = 11 * Ticks_per_1s / Baudrate
tecnosys 0:7b5d37a81b6b 109 * = 220000 / Baudrate
tecnosys 0:7b5d37a81b6b 110 * The reload for t3.5 is 1.5 times this value and similary
tecnosys 0:7b5d37a81b6b 111 * for t3.5.
tecnosys 0:7b5d37a81b6b 112 */
tecnosys 0:7b5d37a81b6b 113 usTimerT35_50us = ( 7UL * 220000UL ) / ( 2UL * ulBaudRate );
tecnosys 0:7b5d37a81b6b 114 }
tecnosys 0:7b5d37a81b6b 115 if( xMBPortTimersInit( ( USHORT ) usTimerT35_50us ) != TRUE )
tecnosys 0:7b5d37a81b6b 116 {
tecnosys 0:7b5d37a81b6b 117 eStatus = MB_EPORTERR;
tecnosys 0:7b5d37a81b6b 118 }
tecnosys 0:7b5d37a81b6b 119 }
tecnosys 0:7b5d37a81b6b 120 EXIT_CRITICAL_SECTION( );
tecnosys 0:7b5d37a81b6b 121
tecnosys 0:7b5d37a81b6b 122 return eStatus;
tecnosys 0:7b5d37a81b6b 123 }
tecnosys 0:7b5d37a81b6b 124
tecnosys 0:7b5d37a81b6b 125 void
tecnosys 0:7b5d37a81b6b 126 eMBRTUStart( void )
tecnosys 0:7b5d37a81b6b 127 {
tecnosys 0:7b5d37a81b6b 128 ENTER_CRITICAL_SECTION( );
tecnosys 0:7b5d37a81b6b 129 /* Initially the receiver is in the state STATE_RX_INIT. we start
tecnosys 0:7b5d37a81b6b 130 * the timer and if no character is received within t3.5 we change
tecnosys 0:7b5d37a81b6b 131 * to STATE_RX_IDLE. This makes sure that we delay startup of the
tecnosys 0:7b5d37a81b6b 132 * modbus protocol stack until the bus is free.
tecnosys 0:7b5d37a81b6b 133 */
tecnosys 0:7b5d37a81b6b 134 eRcvState = STATE_RX_INIT;
tecnosys 0:7b5d37a81b6b 135 vMBPortSerialEnable( TRUE, FALSE );
tecnosys 0:7b5d37a81b6b 136 vMBPortTimersEnable( );
tecnosys 0:7b5d37a81b6b 137 EXIT_CRITICAL_SECTION( );
tecnosys 0:7b5d37a81b6b 138 }
tecnosys 0:7b5d37a81b6b 139
tecnosys 0:7b5d37a81b6b 140 void
tecnosys 0:7b5d37a81b6b 141 eMBRTUStop( void )
tecnosys 0:7b5d37a81b6b 142 {
tecnosys 0:7b5d37a81b6b 143 ENTER_CRITICAL_SECTION( );
tecnosys 0:7b5d37a81b6b 144 vMBPortSerialEnable( FALSE, FALSE );
tecnosys 0:7b5d37a81b6b 145 vMBPortTimersDisable( );
tecnosys 0:7b5d37a81b6b 146 EXIT_CRITICAL_SECTION( );
tecnosys 0:7b5d37a81b6b 147 }
tecnosys 0:7b5d37a81b6b 148
tecnosys 0:7b5d37a81b6b 149 eMBErrorCode
tecnosys 0:7b5d37a81b6b 150 eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
tecnosys 0:7b5d37a81b6b 151 {
tecnosys 0:7b5d37a81b6b 152 BOOL xFrameReceived = FALSE;
tecnosys 0:7b5d37a81b6b 153 eMBErrorCode eStatus = MB_ENOERR;
tecnosys 0:7b5d37a81b6b 154
tecnosys 0:7b5d37a81b6b 155 ENTER_CRITICAL_SECTION( );
tecnosys 0:7b5d37a81b6b 156 assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX );
tecnosys 0:7b5d37a81b6b 157
tecnosys 0:7b5d37a81b6b 158 /* Length and CRC check */
tecnosys 0:7b5d37a81b6b 159 if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN )
tecnosys 0:7b5d37a81b6b 160 && ( usMBCRC16( ( UCHAR * ) ucRTUBuf, usRcvBufferPos ) == 0 ) )
tecnosys 0:7b5d37a81b6b 161 {
tecnosys 0:7b5d37a81b6b 162 /* Save the address field. All frames are passed to the upper layer
tecnosys 0:7b5d37a81b6b 163 * and the decision if a frame is used is done there.
tecnosys 0:7b5d37a81b6b 164 */
tecnosys 0:7b5d37a81b6b 165 *pucRcvAddress = ucRTUBuf[MB_SER_PDU_ADDR_OFF];
tecnosys 0:7b5d37a81b6b 166
tecnosys 0:7b5d37a81b6b 167 /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
tecnosys 0:7b5d37a81b6b 168 * size of address field and CRC checksum.
tecnosys 0:7b5d37a81b6b 169 */
tecnosys 0:7b5d37a81b6b 170 *pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC );
tecnosys 0:7b5d37a81b6b 171
tecnosys 0:7b5d37a81b6b 172 /* Return the start of the Modbus PDU to the caller. */
tecnosys 0:7b5d37a81b6b 173 *pucFrame = ( UCHAR * ) & ucRTUBuf[MB_SER_PDU_PDU_OFF];
tecnosys 0:7b5d37a81b6b 174 xFrameReceived = TRUE;
tecnosys 0:7b5d37a81b6b 175
tecnosys 0:7b5d37a81b6b 176 // Added by Cam
tecnosys 0:7b5d37a81b6b 177 // Now that the poll routine knows about the received frame,
tecnosys 0:7b5d37a81b6b 178 // clear the receive buffer position ready for the next frame received
tecnosys 0:7b5d37a81b6b 179 usRcvBufferPos = 0;
tecnosys 0:7b5d37a81b6b 180
tecnosys 0:7b5d37a81b6b 181 }
tecnosys 0:7b5d37a81b6b 182 else
tecnosys 0:7b5d37a81b6b 183 {
tecnosys 0:7b5d37a81b6b 184 eStatus = MB_EIO;
tecnosys 0:7b5d37a81b6b 185 }
tecnosys 0:7b5d37a81b6b 186
tecnosys 0:7b5d37a81b6b 187 EXIT_CRITICAL_SECTION( );
tecnosys 0:7b5d37a81b6b 188 return eStatus;
tecnosys 0:7b5d37a81b6b 189 }
tecnosys 0:7b5d37a81b6b 190
tecnosys 0:7b5d37a81b6b 191 eMBErrorCode
tecnosys 0:7b5d37a81b6b 192 eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
tecnosys 0:7b5d37a81b6b 193 {
tecnosys 0:7b5d37a81b6b 194 eMBErrorCode eStatus = MB_ENOERR;
tecnosys 0:7b5d37a81b6b 195 USHORT usCRC16;
tecnosys 0:7b5d37a81b6b 196
tecnosys 0:7b5d37a81b6b 197 ENTER_CRITICAL_SECTION( );
tecnosys 0:7b5d37a81b6b 198
tecnosys 0:7b5d37a81b6b 199 /* Check if the receiver is still in idle state. If not we where to
tecnosys 0:7b5d37a81b6b 200 * slow with processing the received frame and the master sent another
tecnosys 0:7b5d37a81b6b 201 * frame on the network. We have to abort sending the frame.
tecnosys 0:7b5d37a81b6b 202 */
tecnosys 0:7b5d37a81b6b 203 if( eRcvState == STATE_RX_IDLE )
tecnosys 0:7b5d37a81b6b 204 {
tecnosys 0:7b5d37a81b6b 205 /* First byte before the Modbus-PDU is the slave address. */
tecnosys 0:7b5d37a81b6b 206 pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
tecnosys 0:7b5d37a81b6b 207 usSndBufferCount = 1;
tecnosys 0:7b5d37a81b6b 208
tecnosys 0:7b5d37a81b6b 209 /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */
tecnosys 0:7b5d37a81b6b 210 pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress;
tecnosys 0:7b5d37a81b6b 211 usSndBufferCount += usLength;
tecnosys 0:7b5d37a81b6b 212
tecnosys 0:7b5d37a81b6b 213 /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */
tecnosys 0:7b5d37a81b6b 214 usCRC16 = usMBCRC16( ( UCHAR * ) pucSndBufferCur, usSndBufferCount );
tecnosys 0:7b5d37a81b6b 215 ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF );
tecnosys 0:7b5d37a81b6b 216 ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 );
tecnosys 0:7b5d37a81b6b 217
tecnosys 0:7b5d37a81b6b 218 /* Activate the transmitter. */
tecnosys 0:7b5d37a81b6b 219 eSndState = STATE_TX_XMIT;
tecnosys 0:7b5d37a81b6b 220 vMBPortSerialEnable( FALSE, TRUE );
tecnosys 0:7b5d37a81b6b 221 }
tecnosys 0:7b5d37a81b6b 222 else
tecnosys 0:7b5d37a81b6b 223 {
tecnosys 0:7b5d37a81b6b 224 eStatus = MB_EIO;
tecnosys 0:7b5d37a81b6b 225 }
tecnosys 0:7b5d37a81b6b 226 EXIT_CRITICAL_SECTION( );
tecnosys 0:7b5d37a81b6b 227 return eStatus;
tecnosys 0:7b5d37a81b6b 228 }
tecnosys 0:7b5d37a81b6b 229
tecnosys 0:7b5d37a81b6b 230 BOOL
tecnosys 0:7b5d37a81b6b 231 xMBRTUReceiveFSM( void )
tecnosys 0:7b5d37a81b6b 232 {
tecnosys 0:7b5d37a81b6b 233 BOOL xTaskNeedSwitch = FALSE;
tecnosys 0:7b5d37a81b6b 234 UCHAR ucByte;
tecnosys 0:7b5d37a81b6b 235
tecnosys 0:7b5d37a81b6b 236 assert( eSndState == STATE_TX_IDLE );
tecnosys 0:7b5d37a81b6b 237
tecnosys 0:7b5d37a81b6b 238 /* Always read the character. */
tecnosys 0:7b5d37a81b6b 239 ( void )xMBPortSerialGetByte( ( CHAR * ) & ucByte );
tecnosys 0:7b5d37a81b6b 240
tecnosys 0:7b5d37a81b6b 241 switch ( eRcvState )
tecnosys 0:7b5d37a81b6b 242 {
tecnosys 0:7b5d37a81b6b 243 /* If we have received a character in the init state we have to
tecnosys 0:7b5d37a81b6b 244 * wait until the frame is finished.
tecnosys 0:7b5d37a81b6b 245 */
tecnosys 0:7b5d37a81b6b 246 case STATE_RX_INIT:
tecnosys 0:7b5d37a81b6b 247 vMBPortTimersEnable( );
tecnosys 0:7b5d37a81b6b 248 break;
tecnosys 0:7b5d37a81b6b 249
tecnosys 0:7b5d37a81b6b 250 /* In the error state we wait until all characters in the
tecnosys 0:7b5d37a81b6b 251 * damaged frame are transmitted.
tecnosys 0:7b5d37a81b6b 252 */
tecnosys 0:7b5d37a81b6b 253 case STATE_RX_ERROR:
tecnosys 0:7b5d37a81b6b 254 vMBPortTimersEnable( );
tecnosys 0:7b5d37a81b6b 255 break;
tecnosys 0:7b5d37a81b6b 256
tecnosys 0:7b5d37a81b6b 257 /* In the idle state we wait for a new character. If a character
tecnosys 0:7b5d37a81b6b 258 * is received the t1.5 and t3.5 timers are started and the
tecnosys 0:7b5d37a81b6b 259 * receiver is in the state STATE_RX_RECEIVE.
tecnosys 0:7b5d37a81b6b 260 */
tecnosys 0:7b5d37a81b6b 261 case STATE_RX_IDLE:
tecnosys 0:7b5d37a81b6b 262 ucRTUBuf[usRcvBufferPos++] = ucByte;
tecnosys 0:7b5d37a81b6b 263 eRcvState = STATE_RX_RCV;
tecnosys 0:7b5d37a81b6b 264
tecnosys 0:7b5d37a81b6b 265 /* Enable t3.5 timers. */
tecnosys 0:7b5d37a81b6b 266 vMBPortTimersEnable( );
tecnosys 0:7b5d37a81b6b 267 break;
tecnosys 0:7b5d37a81b6b 268
tecnosys 0:7b5d37a81b6b 269 /* We are currently receiving a frame. Reset the timer after
tecnosys 0:7b5d37a81b6b 270 * every character received. If more than the maximum possible
tecnosys 0:7b5d37a81b6b 271 * number of bytes in a modbus frame is received the frame is
tecnosys 0:7b5d37a81b6b 272 * ignored.
tecnosys 0:7b5d37a81b6b 273 */
tecnosys 0:7b5d37a81b6b 274 case STATE_RX_RCV:
tecnosys 0:7b5d37a81b6b 275 if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX )
tecnosys 0:7b5d37a81b6b 276 {
tecnosys 0:7b5d37a81b6b 277 ucRTUBuf[usRcvBufferPos++] = ucByte;
tecnosys 0:7b5d37a81b6b 278 }
tecnosys 0:7b5d37a81b6b 279 else
tecnosys 0:7b5d37a81b6b 280 {
tecnosys 0:7b5d37a81b6b 281 eRcvState = STATE_RX_ERROR;
tecnosys 0:7b5d37a81b6b 282 }
tecnosys 0:7b5d37a81b6b 283 vMBPortTimersEnable( );
tecnosys 0:7b5d37a81b6b 284 break;
tecnosys 0:7b5d37a81b6b 285 }
tecnosys 0:7b5d37a81b6b 286 return xTaskNeedSwitch;
tecnosys 0:7b5d37a81b6b 287 }
tecnosys 0:7b5d37a81b6b 288
tecnosys 0:7b5d37a81b6b 289 BOOL
tecnosys 0:7b5d37a81b6b 290 xMBRTUTransmitFSM( void )
tecnosys 0:7b5d37a81b6b 291 {
tecnosys 0:7b5d37a81b6b 292 BOOL xNeedPoll = FALSE;
tecnosys 0:7b5d37a81b6b 293
tecnosys 0:7b5d37a81b6b 294 assert( eRcvState == STATE_RX_IDLE );
tecnosys 0:7b5d37a81b6b 295 switch ( eSndState )
tecnosys 0:7b5d37a81b6b 296 {
tecnosys 0:7b5d37a81b6b 297 /* We should not get a transmitter event if the transmitter is in
tecnosys 0:7b5d37a81b6b 298 * idle state. */
tecnosys 0:7b5d37a81b6b 299 case STATE_TX_IDLE:
tecnosys 0:7b5d37a81b6b 300 /* enable receiver/disable transmitter. */
tecnosys 0:7b5d37a81b6b 301 vMBPortSerialEnable( TRUE, FALSE );
tecnosys 0:7b5d37a81b6b 302 break;
tecnosys 0:7b5d37a81b6b 303
tecnosys 0:7b5d37a81b6b 304 case STATE_TX_XMIT:
tecnosys 0:7b5d37a81b6b 305 /* check if we are finished. */
tecnosys 0:7b5d37a81b6b 306 if( usSndBufferCount != 0 )
tecnosys 0:7b5d37a81b6b 307 {
tecnosys 0:7b5d37a81b6b 308 xMBPortSerialPutByte( ( CHAR )*pucSndBufferCur );
tecnosys 0:7b5d37a81b6b 309 pucSndBufferCur++; /* next byte in sendbuffer. */
tecnosys 0:7b5d37a81b6b 310 usSndBufferCount--;
tecnosys 0:7b5d37a81b6b 311 }
tecnosys 0:7b5d37a81b6b 312 else
tecnosys 0:7b5d37a81b6b 313 {
tecnosys 0:7b5d37a81b6b 314 xNeedPoll = xMBPortEventPost( EV_FRAME_SENT );
tecnosys 0:7b5d37a81b6b 315 /* Disable transmitter. This prevents another transmit buffer
tecnosys 0:7b5d37a81b6b 316 * empty interrupt. */
tecnosys 0:7b5d37a81b6b 317 vMBPortSerialEnable( TRUE, FALSE );
tecnosys 0:7b5d37a81b6b 318 eSndState = STATE_TX_IDLE;
tecnosys 0:7b5d37a81b6b 319 }
tecnosys 0:7b5d37a81b6b 320 break;
tecnosys 0:7b5d37a81b6b 321 }
tecnosys 0:7b5d37a81b6b 322
tecnosys 0:7b5d37a81b6b 323 return xNeedPoll;
tecnosys 0:7b5d37a81b6b 324 }
tecnosys 0:7b5d37a81b6b 325
tecnosys 0:7b5d37a81b6b 326 BOOL
tecnosys 0:7b5d37a81b6b 327 xMBRTUTimerT35Expired( void )
tecnosys 0:7b5d37a81b6b 328 {
tecnosys 0:7b5d37a81b6b 329 BOOL xNeedPoll = FALSE;
tecnosys 0:7b5d37a81b6b 330
tecnosys 0:7b5d37a81b6b 331 switch ( eRcvState )
tecnosys 0:7b5d37a81b6b 332 {
tecnosys 0:7b5d37a81b6b 333 /* Timer t35 expired. Startup phase is finished. */
tecnosys 0:7b5d37a81b6b 334 case STATE_RX_INIT:
tecnosys 0:7b5d37a81b6b 335 xNeedPoll = xMBPortEventPost( EV_READY );
tecnosys 0:7b5d37a81b6b 336 break;
tecnosys 0:7b5d37a81b6b 337
tecnosys 0:7b5d37a81b6b 338 /* A frame was received and t35 expired. Notify the listener that
tecnosys 0:7b5d37a81b6b 339 * a new frame was received. */
tecnosys 0:7b5d37a81b6b 340 case STATE_RX_RCV:
tecnosys 0:7b5d37a81b6b 341 xNeedPoll = xMBPortEventPost( EV_FRAME_RECEIVED );
tecnosys 0:7b5d37a81b6b 342 break;
tecnosys 0:7b5d37a81b6b 343
tecnosys 0:7b5d37a81b6b 344 /* An error occured while receiving the frame. */
tecnosys 0:7b5d37a81b6b 345 case STATE_RX_ERROR:
tecnosys 0:7b5d37a81b6b 346 break;
tecnosys 0:7b5d37a81b6b 347
tecnosys 0:7b5d37a81b6b 348 /* Function called in an illegal state. */
tecnosys 0:7b5d37a81b6b 349 default:
tecnosys 0:7b5d37a81b6b 350 assert( ( eRcvState == STATE_RX_INIT ) ||
tecnosys 0:7b5d37a81b6b 351 ( eRcvState == STATE_RX_RCV ) || ( eRcvState == STATE_RX_ERROR ) );
tecnosys 0:7b5d37a81b6b 352 }
tecnosys 0:7b5d37a81b6b 353
tecnosys 0:7b5d37a81b6b 354 vMBPortTimersDisable( );
tecnosys 0:7b5d37a81b6b 355 eRcvState = STATE_RX_IDLE;
tecnosys 0:7b5d37a81b6b 356
tecnosys 0:7b5d37a81b6b 357 return xNeedPoll;
tecnosys 0:7b5d37a81b6b 358 }