123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- #include <stdlib.h>
- #include <string.h>
- #include "gfambrtuslv.h"
- #include "gfambrtuslv_priv.h"
- #include "driverlib/sw_crc.h"
- #include "inc/hw_memmap.h"
- /////////////////////////////////////////////////////////////////////////////
- static GFA_MODBUS_RTU_SLAVE g_mbSlv;
- /////////////////////////////////////////////////////////////////////////////
- static bool _PeekStateChange(LPGFA_MODBUS_RTU_SLAVE pSlv)
- {
- if(pSlv->oldstate != pSlv->state)
- {
- if(pSlv->appItf.pfnStateChanged)
- (*pSlv->appItf.pfnStateChanged)(pSlv->state, pSlv->oldstate);
- pSlv->oldstate = pSlv->state;
- return true;
- }
- return false;
- }
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- HMBRTUSLV GfaModbusRTUSlvCreate(LPCGFA_MODBUS_RTU_SLAVE_PARAMETERS pslp)
- {
- if(!pslp)
- return NULL;
- if(!pslp->slaveID || pslp->slaveID > MODBUS_MAX_SLAVE_ID)
- return NULL;
- if(!pslp->hFifoRX || !pslp->hFifoTX || !pslp->regMap.pRegs || !pslp->regMap.nCountRegs)
- return NULL;
- LPGFA_MODBUS_RTU_SLAVE pSlv = &g_mbSlv;
- memset(pSlv, 0, sizeof(GFA_MODBUS_RTU_SLAVE));
- pSlv->state = MB_RTU_SLV_Idle;
- pSlv->oldstate = MB_RTU_SLV_Void;
- pSlv->slaveID = pslp->slaveID;
- pSlv->hFifoRX = pslp->hFifoRX;
- pSlv->hFifoTX = pslp->hFifoTX;
- memcpy(&pSlv->regMap, &pslp->regMap, sizeof(GFA_MODBUS_REGISTER));
- memcpy(&pSlv->appItf, &pslp->appItf, sizeof(GFA_MODBUS_SLAVE_APP_INTERFACE));
- return (HMBRTUSLV)pSlv;
- }
- /////////////////////////////////////////////////////////////////////////////
- void GfaModbusRTUSlvRelease(HMBRTUSLV hMbSlv)
- {
- }
- /////////////////////////////////////////////////////////////////////////////
- bool GfaModbusRTUSlvSetID(HMBRTUSLV hMbSlv, uint8_t newID)
- {
- LPGFA_MODBUS_RTU_SLAVE pSlv = (LPGFA_MODBUS_RTU_SLAVE)hMbSlv;
- if(!newID || newID > MODBUS_MAX_SLAVE_ID)
- return false;
- if(pSlv->newSlaveID != newID)
- pSlv->newSlaveID = newID;
- return true;
- }
- /////////////////////////////////////////////////////////////////////////////
- bool GfaModbusRTUSlvStateMachine(HMBRTUSLV hMbSlv)
- {
- static int nReEnterSTM = 0;
- uint8_t b;
- size_t nRead;
- LPGFA_MODBUS_RTU_SLAVE pSlv = (LPGFA_MODBUS_RTU_SLAVE)hMbSlv;
- ++nReEnterSTM;
- switch(pSlv->state)
- {
- case MB_RTU_SLV_Idle:
- nReEnterSTM = 0;
- _PeekStateChange(pSlv);
- if(pSlv->newSlaveID)
- {
- pSlv->slaveID = pSlv->newSlaveID;
- pSlv->newSlaveID = 0;
- }
- if(!GfaMbFifoMatchFlags(pSlv->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true))
- break;
- pSlv->state = MB_RTU_SLV_RxSlvID;
- pSlv->nCbToRead = 0;
- pSlv->nCbToWrite = 0;
- pSlv->nDataPtr = 0;
- pSlv->bCRCOk = false;
- GfaMbFifoClearFlags(pSlv->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true);
- // fall through
- case MB_RTU_SLV_RxSlvID:
- _PeekStateChange(pSlv);
- if(!GfaMbFifoPop(pSlv->hFifoRX, &b, true))
- {
- if(GfaMbFifoMatchFlags(pSlv->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true))
- pSlv->state = MB_RTU_SLV_Idle;
- break;
- }
- if(pSlv->slaveID != b) // ignore broadcasts as well
- {
- GfaMbFifoSetFlags(pSlv->hFifoRX, MB_RTU_FLAG_IGNORE_FRAME, true);
- GfaMbFifoReset(pSlv->hFifoRX, true);
- pSlv->state = MB_RTU_SLV_Idle;
- ++pSlv->diag.nBusMsgCount;
- break;
- }
- pSlv->adu.slaveID = b;
- pSlv->state = MB_RTU_SLV_RxFunc;
- ++pSlv->diag.nBusMsgCount;
- // fall through
- case MB_RTU_SLV_RxFunc:
- _PeekStateChange(pSlv);
- if(!GfaMbFifoPop(pSlv->hFifoRX, &b, true))
- {
- if(GfaMbFifoMatchFlags(pSlv->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true))
- pSlv->state = MB_RTU_SLV_Idle;
- break;
- }
- else if(!GfaModbusRequestFunctionKnown(b))
- {
- pSlv->adu.pdu.func = b;
- GfaMbFifoSetFlags(pSlv->hFifoRX, MB_RTU_FLAG_IGNORE_FRAME, true);
- GfaMbFifoReset(pSlv->hFifoRX, true);
- GfaModbusRequestCreateExceptionResponse(&pSlv->adu.pdu, MB_ERROR_ILLEGAL_FUNCTION);
- GfaBufSetCRC(&pSlv->adu, 3, &pSlv->adu.pdu.b[1]);
- pSlv->nCbToWrite = 5;
- pSlv->state = MB_RTU_SLV_TxStart;
- ++pSlv->diag.nExcErrCount;
- break;
- }
- pSlv->adu.pdu.func = b;
- pSlv->state = MB_RTU_SLV_RxDataInfo;
- pSlv->nCbToRead = GfaModbusRequestGetDataInfoLength(pSlv);
- // fall through
- case MB_RTU_SLV_RxDataInfo:
- _PeekStateChange(pSlv);
- if(pSlv->nCbToRead)
- {
- if(!(nRead = GfaMbFifoRead(pSlv->hFifoRX, &pSlv->adu.pdu.b[pSlv->nDataPtr], pSlv->nCbToRead, true)))
- {
- if(GfaMbFifoMatchFlags(pSlv->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true))
- pSlv->state = MB_RTU_SLV_Idle;
- break;
- }
- pSlv->nDataPtr += nRead;
- pSlv->nCbToRead -= nRead;
- }
- if(pSlv->nCbToRead)
- break;
- else
- {
- if(pSlv->adu.pdu.func == MB_FUNC_DIAGNOSTIC)
- {
- pSlv->nSubFunc = GfaBufGetUnaligned_uint16(pSlv->adu.pdu.b);
- if(!GfaModbusRequestSubFunctionKnown(pSlv->nSubFunc))
- {
- pSlv->adu.pdu.func = b;
- GfaMbFifoSetFlags(pSlv->hFifoRX, MB_RTU_FLAG_IGNORE_FRAME, true);
- GfaMbFifoReset(pSlv->hFifoRX, true);
- GfaModbusRequestCreateExceptionResponse(&pSlv->adu.pdu, MB_ERROR_ILLEGAL_FUNCTION);
- GfaBufSetCRC(&pSlv->adu, 3, &pSlv->adu.pdu.b[1]);
- pSlv->nCbToWrite = 5;
- pSlv->state = MB_RTU_SLV_TxStart;
- ++pSlv->diag.nExcErrCount;
- break;
- }
- }
- pSlv->state = MB_RTU_SLV_RxDataPayload;
- pSlv->nCbToRead = GfaModbusRequestGetDataPayloadLength(pSlv);
- // fall through
- }
- case MB_RTU_SLV_RxDataPayload:
- _PeekStateChange(pSlv);
- if(pSlv->nCbToRead)
- {
- if(!(nRead = GfaMbFifoRead(pSlv->hFifoRX, &pSlv->adu.pdu.b[pSlv->nDataPtr], pSlv->nCbToRead, true)))
- {
- if(GfaMbFifoMatchFlags(pSlv->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true))
- pSlv->state = MB_RTU_SLV_Idle;
- break;
- }
- pSlv->nDataPtr += nRead;
- pSlv->nCbToRead -= nRead;
- }
- if(pSlv->nCbToRead)
- break;
- else
- {
- pSlv->state = MB_RTU_SLV_RxCRC;
- pSlv->nCbToRead = 2;
- // fall through
- }
- case MB_RTU_SLV_RxCRC:
- _PeekStateChange(pSlv);
- if(pSlv->nCbToRead)
- {
- if(!(nRead = GfaMbFifoRead(pSlv->hFifoRX, &pSlv->adu.pdu.b[pSlv->nDataPtr], pSlv->nCbToRead, true)))
- {
- if(GfaMbFifoMatchFlags(pSlv->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true))
- pSlv->state = MB_RTU_SLV_Idle;
- break;
- }
- pSlv->nDataPtr += nRead;
- pSlv->nCbToRead -= nRead;
- }
- if(pSlv->nCbToRead)
- break;
- else
- {
- pSlv->bCRCOk = GfaBufVerifyCRC(&pSlv->adu, pSlv->nDataPtr, &pSlv->adu.pdu.b[pSlv->nDataPtr - 2]);
- pSlv->state = MB_RTU_SLV_RxComplete;
- // fall through
- }
- case MB_RTU_SLV_RxComplete:
- _PeekStateChange(pSlv);
- if(pSlv->bCRCOk)
- {
- bool bIsExeption;
- size_t nCbData = 0;
- ++pSlv->diag.nSlvMsgCount;
- if(GfaModbusRequestHandler(pSlv, &nCbData, &bIsExeption))
- {
- GfaBufSetCRC(&pSlv->adu, nCbData + 2, &pSlv->adu.pdu.b[nCbData]);
- pSlv->nCbToWrite = nCbData + 4;
- pSlv->state = MB_RTU_SLV_TxStart;
- if(bIsExeption)
- ++pSlv->diag.nExcErrCount;
- GfaMbFifoRxFinalize(pSlv->hFifoRX, true);
- // fall through
- }
- else
- {
- pSlv->state = MB_RTU_SLV_Idle; // nothing to send
- break;
- }
- }
- else
- {
- ++pSlv->diag.nCrcErrCount; // CRC Error!!!
- pSlv->state = MB_RTU_SLV_Idle; // silently ignore frame
- break;
- }
- case MB_RTU_SLV_TxStart:
- _PeekStateChange(pSlv);
- if( GfaMbFifoEmpty(pSlv->hFifoTX, true) &&
- GfaMbFifoTxPrepare(pSlv->hFifoTX, true))
- {
- GfaMbFifoSetFlags(pSlv->hFifoTX, MB_RTU_FLAG_TRANSMIT_IN_PROGRESS, true);
- GfaMbFifoWrite(pSlv->hFifoTX, &pSlv->adu, pSlv->nCbToWrite, true);
- if(pSlv->appItf.pfnPreTransmit)
- (*pSlv->appItf.pfnPreTransmit)(&pSlv->adu);
- GfaMbFifoTxStart(pSlv->hFifoTX, false);
- pSlv->state = MB_RTU_SLV_TxWaitEnd;
- // fall through
- }
- else
- break;
- case MB_RTU_SLV_TxWaitEnd:
- _PeekStateChange(pSlv);
- if(!GfaMbFifoMatchFlags(pSlv->hFifoTX, MB_RTU_FLAG_TRANSMIT_IN_PROGRESS, true))
- {
- if(pSlv->appItf.pfnPostTransmit)
- (*pSlv->appItf.pfnPostTransmit)(&pSlv->adu);
- pSlv->state = MB_RTU_SLV_Idle;
- }
- break;
- default:
- return false;
- }
- if(pSlv->nMaxReEnterSTM < nReEnterSTM)
- pSlv->nMaxReEnterSTM = nReEnterSTM;
- return true;
- }
|