123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659 |
- #include <stdlib.h>
- #include <string.h>
- #include <gfambrtumst.h>
- /////////////////////////////////////////////////////////////////////////////
- #define MODBUS_MASTER_RX_TIMEOUT_US 500000 // slave to master response timeout
- /////////////////////////////////////////////////////////////////////////////
- typedef struct _GFA_MODBUS_RTU_MASTER
- {
- HFIFO hFifoRX;
- HFIFO hFifoTX;
- uint8_t curSlaveID;
- uint8_t curFunc;
- uint32_t nTID;
- int nRxErr;
- GFA_MODBUS_RTU_MST_STATES state;
- GFA_MODBUS_RTU_MST_STATES oldstate;
- MODBUS_RTU_ADU adu;
- PFN_GFA_MASTER_RAW_REQUEST_COMPLETE pfnRawReqComplete;
- void *pParam;
- size_t nCbDataExpected;
- size_t nCbRx;
- uint64_t nRxTimeoutUs;
- uint64_t nTimerUs;
- GFA_MODBUS_MASTER_APP_INTERFACE appItf;
- GFA_MODBUS_PROTOCOL_TIMEOUTS mpt;
- }GFA_MODBUS_RTU_MASTER, *LPGFA_MODBUS_RTU_MASTER;
- typedef const GFA_MODBUS_RTU_MASTER *LPCGFA_MODBUS_RTU_MASTER;
- /////////////////////////////////////////////////////////////////////////////
- static GFA_MODBUS_RTU_MASTER g_mbMast = {0};
- /////////////////////////////////////////////////////////////////////////////
- static bool _ValidateADU(LPGFA_MODBUS_RTU_MASTER pMst)
- {
- if(pMst->nRxErr)
- {
- if(pMst->nRxErr != GFA_MB_MST_ERROR_SLAVE_ERROR)
- return false;
- }
- if(!GfaBufVerifyCRC(&pMst->adu, pMst->nCbDataExpected + 2, &pMst->adu.pdu.b[pMst->nCbDataExpected]))
- {
- pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_INVALID_CRC;
- return false;
- }
- return true;
- }
- /////////////////////////////////////////////////////////////////////////////
- static bool _TimerElapsed(LPGFA_MODBUS_RTU_MASTER pMst)
- {
- struct timeval tv;
- return pMst->nTimerUs < GfaSystickTimeval2Us(GfaSystickGetUsClock(&tv));
- }
- /////////////////////////////////////////////////////////////////////////////
- static void _RespTimerTrigger(LPGFA_MODBUS_RTU_MASTER pMst)
- {
- struct timeval tv;
- pMst->nTimerUs = GfaSystickTimeval2Us(GfaSystickGetUsClock(&tv)) + pMst->nRxTimeoutUs;
- }
- /////////////////////////////////////////////////////////////////////////////
- static void _CharTimerTrigger(LPGFA_MODBUS_RTU_MASTER pMst)
- {
- struct timeval tv;
- pMst->nTimerUs = GfaSystickTimeval2Us(GfaSystickGetUsClock(&tv)) + pMst->mpt.nCharTimeoutUs;
- }
- /////////////////////////////////////////////////////////////////////////////
- static void _FrameTimerTrigger(LPGFA_MODBUS_RTU_MASTER pMst)
- {
- struct timeval tv;
- pMst->nTimerUs = GfaSystickTimeval2Us(GfaSystickGetUsClock(&tv)) + pMst->mpt.nFrameTimeoutUs;
- }
- /////////////////////////////////////////////////////////////////////////////
- static bool _PeekStateChange(LPGFA_MODBUS_RTU_MASTER pMst)
- {
- if(pMst->oldstate != pMst->state)
- {
- if(pMst->appItf.pfnStateChanged)
- (*pMst->appItf.pfnStateChanged)(pMst->state, pMst->oldstate);
- pMst->oldstate = pMst->state;
- return true;
- }
- return false;
- }
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- HMBRTUMST GfaModbusRTUMstCreate(LPCGFA_MODBUS_RTU_MASTER_PARAMETERS pmap)
- {
- if(!pmap || !pmap->hFifoRX || !pmap->hFifoTX)
- return NULL;
- LPGFA_MODBUS_RTU_MASTER pMst = &g_mbMast;
- memset(pMst, 0, sizeof(GFA_MODBUS_RTU_MASTER));
- memcpy(&pMst->mpt, &pmap->mpt, sizeof(GFA_MODBUS_PROTOCOL_TIMEOUTS));
- memcpy(&pMst->appItf, &pmap->appItf, sizeof(GFA_MODBUS_MASTER_APP_INTERFACE));
- pMst->oldstate = MB_RTU_MST_Void;
- pMst->hFifoRX = pmap->hFifoRX;
- pMst->hFifoTX = pmap->hFifoTX;
- pMst->nRxTimeoutUs = pmap->nRxTimeoutUs;
- return (HMBRTUMST)pMst;
- }
- /////////////////////////////////////////////////////////////////////////////
- void GfaModbusRTUMstRelease(HMBRTUMST hMbMst)
- {
- if(hMbMst)
- {
- LPGFA_MODBUS_RTU_MASTER pMst = (LPGFA_MODBUS_RTU_MASTER)hMbMst;
- memset(pMst, 0, sizeof(GFA_MODBUS_RTU_MASTER));
- pMst->state = MB_RTU_MST_Void;
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- bool GfaModbusRTUMstStateMachine(HMBRTUMST hMbMst)
- {
- uint8_t b;
- LPGFA_MODBUS_RTU_MASTER pMst = (LPGFA_MODBUS_RTU_MASTER)hMbMst;
- if(!pMst)
- return false;
- switch(pMst->state)
- {
- case MB_RTU_MST_Idle:
- _PeekStateChange(pMst);
- break;
- case MB_RTU_MST_TxStart:
- _PeekStateChange(pMst);
- if( _TimerElapsed(pMst) &&
- GfaMbFifoTxPrepare(pMst->hFifoTX, false))
- {
- if(pMst->appItf.pfnPreTx)
- (*pMst->appItf.pfnPreTx)(pMst->nTID, pMst->curSlaveID);
- GfaMbFifoClearFlags(pMst->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true);
- GfaMbFifoSetFlags(pMst->hFifoTX, MB_RTU_FLAG_TRANSMIT_IN_PROGRESS, false);
- GfaMbFifoTxStart(pMst->hFifoTX, true);
- pMst->state = MB_RTU_MST_TxWaitEnd;
- // fall through to next state
- }
- else
- break;
- case MB_RTU_MST_TxWaitEnd:
- _PeekStateChange(pMst);
- if(!GfaMbFifoMatchFlags(pMst->hFifoTX, MB_RTU_FLAG_TRANSMIT_IN_PROGRESS, true))
- {
- pMst->state = MB_RTU_MST_TxDone;
- // fall through to next state
- }
- else
- break;
- case MB_RTU_MST_TxDone:
- _PeekStateChange(pMst);
- pMst->state = MB_RTU_MST_WaitRxFifo;
- _RespTimerTrigger(pMst);
- if(pMst->appItf.pfnPostTx)
- (*pMst->appItf.pfnPostTx)(pMst->nTID, pMst->curSlaveID);
- // fall through to next state
- case MB_RTU_MST_WaitRxFifo:
- _PeekStateChange(pMst);
- if(GfaMbFifoPeek(pMst->hFifoRX, true))
- {
- GfaMbFifoClearFlags(pMst->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true);
- pMst->state = MB_RTU_MST_RxSlvID;
- if(pMst->appItf.pfnRxStart)
- (*pMst->appItf.pfnRxStart)(pMst->nTID);
- // fall through to next state
- }
- else
- {
- if(_TimerElapsed(pMst))
- {
- pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_RESPONSE_TIMEOUT;
- pMst->state = MB_RTU_MST_ReportError;
- }
- break;
- }
- case MB_RTU_MST_RxSlvID:
- _PeekStateChange(pMst);
- if(!GfaMbFifoPop(pMst->hFifoRX, &b, true))
- {
- pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_RESPONSE_TIMEOUT;
- pMst->state = MB_RTU_MST_ReportError;
- break;
- }
- else if(pMst->curSlaveID != b)
- {
- GfaMbFifoSetFlags(pMst->hFifoRX, MB_RTU_FLAG_IGNORE_FRAME, true);
- GfaMbFifoReset(pMst->hFifoRX, true);
- pMst->nRxErr = GFA_MB_MST_ERROR_INVALID_SLAVE_ID;
- pMst->state = MB_RTU_MST_ReportError;
- break;
- }
- pMst->adu.slaveID = b;
- pMst->state = MB_RTU_MST_RxFunc;
- _CharTimerTrigger(pMst);
- // fall through to next state
- case MB_RTU_MST_RxFunc:
- _PeekStateChange(pMst);
- if(!GfaMbFifoPop(pMst->hFifoRX, &b, true))
- {
- if( GfaMbFifoMatchFlags(pMst->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true) ||
- _TimerElapsed(pMst))
- {
- pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_CHAR_TIMEOUT;
- pMst->state = MB_RTU_MST_ReportError;
- }
- break;
- }
- else if(b & MB_FUNC_ERROR_FLAG)
- {
- pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_ERROR;
- pMst->adu.pdu.func = b;
- pMst->state = MB_RTU_MST_RxError;
- break;
- }
- else if(b != pMst->curFunc)
- {
- pMst->nRxErr = GFA_MB_MST_ERROR_INVALID_FUNCTION;
- pMst->state = MB_RTU_MST_ReportError;
- break;
- }
- else
- {
- pMst->adu.pdu.func = b;
- pMst->nCbRx = 0;
- pMst->state = MB_RTU_MST_RxData;
- _CharTimerTrigger(pMst);
- // fall through to next state
- }
- case MB_RTU_MST_RxData:
- _PeekStateChange(pMst);
- while(pMst->nCbRx < pMst->nCbDataExpected)
- {
- if(GfaMbFifoPop(pMst->hFifoRX, &b, true))
- {
- pMst->adu.pdu.b[pMst->nCbRx++] = b;
- _CharTimerTrigger(pMst);
- }
- else
- {
- if( GfaMbFifoMatchFlags(pMst->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true) ||
- _TimerElapsed(pMst))
- {
- pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_CHAR_TIMEOUT;
- pMst->state = MB_RTU_MST_ReportError;
- }
- break;
- }
- }
- if(pMst->nCbRx == pMst->nCbDataExpected)
- {
- pMst->nCbRx = 0;
- pMst->state = MB_RTU_MST_RxCRC;
- _CharTimerTrigger(pMst);
- // fall through to next state
- }
- else
- break;
- case MB_RTU_MST_RxCRC:
- _PeekStateChange(pMst);
- while(pMst->nCbRx < sizeof(uint16_t))
- {
- if(GfaMbFifoPop(pMst->hFifoRX, &b, true))
- {
- pMst->adu.pdu.b[pMst->nCbDataExpected + pMst->nCbRx++] = b;
- _CharTimerTrigger(pMst);
- }
- else
- {
- if( GfaMbFifoMatchFlags(pMst->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true) ||
- _TimerElapsed(pMst))
- {
- pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_CHAR_TIMEOUT;
- pMst->state = MB_RTU_MST_ReportError;
- }
- break;
- }
- }
- if(pMst->nCbRx == sizeof(uint16_t))
- {
- pMst->nCbRx = 0;
- pMst->state = MB_RTU_MST_RxFinalize;
- // fall through to next state
- }
- else
- break;
- case MB_RTU_MST_RxFinalize:
- _PeekStateChange(pMst);
- _FrameTimerTrigger(pMst);
- if(_ValidateADU(pMst))
- {
- if(pMst->appItf.pfnRxEnd)
- (*pMst->appItf.pfnRxEnd)(pMst->nTID);
- (*pMst->pfnRawReqComplete)(pMst->nTID, pMst->curSlaveID, pMst->nRxErr, &pMst->adu, pMst->nCbDataExpected, pMst->pParam);
- pMst->state = MB_RTU_MST_Idle;
- break;
- }
- pMst->state = MB_RTU_MST_ReportError;
- break;
- case MB_RTU_MST_RxError:
- _PeekStateChange(pMst);
- if(!GfaMbFifoPop(pMst->hFifoRX, &b, true))
- {
- if( GfaMbFifoMatchFlags(pMst->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true) ||
- _TimerElapsed(pMst))
- {
- pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_CHAR_TIMEOUT;
- pMst->state = MB_RTU_MST_ReportError;
- }
- break;
- }
- pMst->adu.pdu.b[0] = b;
- pMst->nCbDataExpected = 1;
- pMst->state = MB_RTU_MST_RxCRC;
- _CharTimerTrigger(pMst);
- break;
- case MB_RTU_MST_ReportError:
- _PeekStateChange(pMst);
- _FrameTimerTrigger(pMst);
- if(pMst->appItf.pfnRxEnd)
- (*pMst->appItf.pfnRxEnd)(pMst->nTID);
- (*pMst->pfnRawReqComplete)(pMst->nTID, pMst->curSlaveID, pMst->nRxErr, NULL, 0, pMst->pParam);
- pMst->state = MB_RTU_MST_Idle;
- break;
- default:
- return false;
- }
- return true;
- }
- GFA_MODBUS_RTU_MST_STATES GfaModbusRTUMstGetState(HMBRTUMST hMbMst)
- {
- LPGFA_MODBUS_RTU_MASTER pMst = (LPGFA_MODBUS_RTU_MASTER)hMbMst;
- if(!pMst)
- return MB_RTU_MST_Void;
- return pMst->state;
- }
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- static void _OnRawReadRegistersComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, LPCMODBUS_RTU_ADU padu, size_t nCbData, void *pParam)
- {
- if(pParam)
- {
- PFN_GFA_MASTER_READ_REGISTERS_COMPLETE pfnReadRegsComplete = (PFN_GFA_MASTER_READ_REGISTERS_COMPLETE)pParam;
- uint16_t regs[MODBUS_MAX_READ_REGISTERS];
- const void *pRegs = NULL;
- size_t nCntRegs = 0;
- if(err)
- {
- if(err == GFA_MB_MST_ERROR_SLAVE_ERROR && padu)
- err |= ((uint16_t)padu->pdu.b[0] << 8);
- }
- else
- {
- if((nCntRegs = (size_t)padu->pdu.b[0] / sizeof(uint16_t)) <= MODBUS_MAX_READ_REGISTERS)
- {
- GfaBufCpyUnaligned_uint16(regs, &padu->pdu.b[1], nCntRegs);
- pRegs = regs;
- }
- else
- {
- pRegs = NULL;
- nCntRegs = 0;
- err = GFA_MB_MST_ERROR_SLAVE_INVALID_DATA;
- }
- }
- (*pfnReadRegsComplete)(nTID, nSlvID, err, pRegs, nCntRegs);
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- static void _OnRawWriteRegistersComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, LPCMODBUS_RTU_ADU padu, size_t nCbData, void *pParam)
- {
- if(pParam)
- {
- PFN_GFA_MASTER_WRITE_REGISTERS_COMPLETE pfnWriteRegsComplete = (PFN_GFA_MASTER_WRITE_REGISTERS_COMPLETE)pParam;
- uint16_t nStart = 0, nWritten = 0;
- if(err)
- {
- if(err == GFA_MB_MST_ERROR_SLAVE_ERROR && padu)
- err |= ((uint16_t)padu->pdu.b[0] << 8);
- }
- else
- {
- nStart = GfaBufGetUnaligned_uint16(padu->pdu.b);
- nWritten = GfaBufGetUnaligned_uint16(&padu->pdu.b[2]);
- }
- (*pfnWriteRegsComplete)(nTID, nSlvID, err, nStart, nWritten);
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- static void _OnRawPresetSingleRegisterComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, LPCMODBUS_RTU_ADU padu, size_t nCbData, void *pParam)
- {
- if(pParam)
- {
- PFN_GFA_MASTER_PRESET_SINGLE_REGISTER_COMPLETE pfnPresetRegComplete = (PFN_GFA_MASTER_PRESET_SINGLE_REGISTER_COMPLETE)pParam;
- if(err)
- {
- if(err == GFA_MB_MST_ERROR_SLAVE_ERROR && padu)
- err |= ((uint16_t)padu->pdu.b[0] << 8);
- }
- (*pfnPresetRegComplete)(nTID, nSlvID, err);
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- static void _OnRawDiagnosisComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, LPCMODBUS_RTU_ADU padu, size_t nCbData, void *pParam)
- {
- if(pParam)
- {
- PFN_GFA_MASTER_DIAGNOSIS_COMPLETE pfnDiagComplete = (PFN_GFA_MASTER_DIAGNOSIS_COMPLETE)pParam;
- uint16_t nSubFunc = 0, nData = 0;
- if(err)
- {
- if(err == GFA_MB_MST_ERROR_SLAVE_ERROR && padu)
- err |= ((uint16_t)padu->pdu.b[0] << 8);
- }
- else
- {
- nSubFunc = GfaBufGetUnaligned_uint16(padu->pdu.b);
- nData = GfaBufGetUnaligned_uint16(&padu->pdu.b[2]);
- }
- (*pfnDiagComplete)(nTID, nSlvID, err, nSubFunc, nData);
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- static void _OnRawReportSlaveIDComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, LPCMODBUS_RTU_ADU padu, size_t nCbData, void *pParam)
- {
- if(pParam)
- {
- PFN_GFA_MASTER_REPORT_SLAVE_ID_COMPLETE pfnRepSlvIDComplete = (PFN_GFA_MASTER_REPORT_SLAVE_ID_COMPLETE)pParam;
- const void *pData = NULL;
- size_t nData = 0;
- if(err)
- {
- if(err == GFA_MB_MST_ERROR_SLAVE_ERROR && padu)
- err |= ((uint16_t)padu->pdu.b[0] << 8);
- }
- else
- {
- pData = &padu->pdu.b[1];
- nData = padu->pdu.b[0];
- }
- (*pfnRepSlvIDComplete)(nTID, nSlvID, err, pData, nData);
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- static size_t _SubFunctionResponseLength(uint16_t nSubFunc)
- {
- size_t nRet = 0;
- switch(nSubFunc)
- {
- case MB_SUBFUNC_RETURN_QUERY_DATA:
- case MB_SUBFUNC_RESTART_COMM_OPTION:
- case MB_SUBFUNC_RETURN_DIAGNOSTIC_REGISTER:
- case MB_SUBFUNC_CLEAR_CTRS_AND_DIAGNOSTIC_REG:
- case MB_SUBFUNC_RETURN_BUS_MESSAGE_COUNT:
- case MB_SUBFUNC_RETURN_BUS_COMM_ERROR_COUNT:
- case MB_SUBFUNC_RETURN_BUS_EXCEPTION_ERROR_COUNT:
- case MB_SUBFUNC_RETURN_SLAVE_MESSAGE_COUNT:
- case MB_SUBFUNC_RETURN_SLAVE_NO_RESPONSE_COUNT:
- case MB_SUBFUNC_RETURN_SLAVE_NAK_COUNT:
- case MB_SUBFUNC_RETURN_SLAVE_BUSY_COUNT:
- case MB_SUBFUNC_RETURN_BUS_CHAR_OVERRUN_COUNT:
- case MB_SUBFUNC_RETURN_OVERRUN_ERROR_COUNT:
- case MB_SUBFUNC_CLEAR_OVERRUN_COUNTER_AND_FLAG:
- nRet = 4;
- break;
- // case MB_SUBFUNC_FORCE_LISTEN_ONLY_MODE:
- default:
- nRet = (size_t)-1;
- break;
- }
- return nRet;
- }
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- bool GfaModbusRTUMstSendRawRequest(HMBRTUMST hMbMst, uint32_t nTID, uint8_t nSlvID, uint8_t nFunc, const void *pData, size_t nCbData, size_t nCbDataExpected, PFN_GFA_MASTER_RAW_REQUEST_COMPLETE pfnRawReqComplete, void *pParam)
- {
- uint16_t nCRC;
- LPGFA_MODBUS_RTU_MASTER pMst = (LPGFA_MODBUS_RTU_MASTER)hMbMst;
- if(!pMst || nCbData > MODBUS_MAX_DATA_PAYLOAD || nCbDataExpected > MODBUS_MAX_DATA_PAYLOAD || !pfnRawReqComplete)
- return false;
- if(!nSlvID || nSlvID > MODBUS_MAX_SLAVE_ID)
- return false;
- if(pMst->state != MB_RTU_MST_Idle)
- return false;
- pMst->nTID = nTID;
- pMst->curSlaveID = nSlvID;
- pMst->curFunc = nFunc;
- pMst->nCbDataExpected = nCbDataExpected;
- pMst->pfnRawReqComplete = pfnRawReqComplete;
- pMst->pParam = pParam;
- pMst->nRxErr = 0;
- GfaMbFifoReset(pMst->hFifoTX, false);
- GfaMbFifoReset(pMst->hFifoRX, false);
- GfaMbFifoPush(pMst->hFifoTX, nSlvID, false);
- GfaMbFifoPush(pMst->hFifoTX, nFunc, false);
- if(pData && nCbData)
- GfaMbFifoWrite(pMst->hFifoTX, pData, nCbData, false);
- nCRC = GfaMbFifoCalcCRC(pMst->hFifoTX, false);
- GfaMbFifoWrite(pMst->hFifoTX, &nCRC, sizeof(nCRC), false);
- pMst->state = MB_RTU_MST_TxStart;
- return true;
- }
- bool GfaModbusRTUMstReadHoldingRegisters(HMBRTUMST hMbMst, uint32_t nTID, uint8_t nSlvID, uint16_t nRegStart, uint16_t nRegCount, PFN_GFA_MASTER_READ_REGISTERS_COMPLETE pfnReadRegsComplete)
- {
- uint8_t buf[4];
- if(!pfnReadRegsComplete)
- return false;
- GfaBufSetUnaligned_uint16(buf, nRegStart);
- GfaBufSetUnaligned_uint16(&buf[2], nRegCount);
- return GfaModbusRTUMstSendRawRequest(hMbMst, nTID, nSlvID, MB_FUNC_READ_HOLDING_REGISTERS, buf, sizeof(buf), 1 + nRegCount * sizeof(uint16_t), _OnRawReadRegistersComplete, pfnReadRegsComplete);
- }
- /////////////////////////////////////////////////////////////////////////////
- bool GfaModbusRTUMstReadInputRegisters(HMBRTUMST hMbMst, uint32_t nTID, uint8_t nSlvID, uint16_t nRegStart, uint16_t nRegCount, PFN_GFA_MASTER_READ_REGISTERS_COMPLETE pfnReadRegsComplete)
- {
- uint8_t buf[4];
- if(!pfnReadRegsComplete)
- return false;
- GfaBufSetUnaligned_uint16(buf, nRegStart);
- GfaBufSetUnaligned_uint16(&buf[2], nRegCount);
- return GfaModbusRTUMstSendRawRequest(hMbMst, nTID, nSlvID, MB_FUNC_READ_INPUT_REGISTERS, buf, sizeof(buf), 1 + nRegCount * sizeof(uint16_t), _OnRawReadRegistersComplete, pfnReadRegsComplete);
- }
- /////////////////////////////////////////////////////////////////////////////
- bool GfaModbusRTUMstWriteMultipleRegisters(HMBRTUMST hMbMst, uint32_t nTID, uint8_t nSlvID, uint16_t nRegStart, uint16_t nRegCount, const void *pRegData, PFN_GFA_MASTER_WRITE_REGISTERS_COMPLETE pfnWriteRegsComplete)
- {
- uint8_t buf[MODBUS_MAX_WRITE_REGISTERS * sizeof(uint16_t)];
- const uint8_t *pData = (const uint8_t*)pRegData;
- size_t nCbData = 0;
- if(!pfnWriteRegsComplete)
- return false;
- if(nRegCount > MODBUS_MAX_WRITE_REGISTERS)
- return false;
- GfaBufSetUnaligned_uint16(&buf[nCbData], nRegStart);
- nCbData += 2;
- GfaBufSetUnaligned_uint16(&buf[nCbData], nRegCount);
- nCbData += 2;
- buf[nCbData++] = (uint8_t)(nRegCount * sizeof(uint16_t));
- GfaBufCpyUnaligned_uint16(&buf[nCbData], pData, nRegCount);
- nCbData += nRegCount * sizeof(uint16_t);
- return GfaModbusRTUMstSendRawRequest(hMbMst, nTID, nSlvID, MB_FUNC_WRITE_MULTIPLE_REGISTERS, buf, nCbData, 2 * sizeof(uint16_t), _OnRawWriteRegistersComplete, pfnWriteRegsComplete);
- }
- /////////////////////////////////////////////////////////////////////////////
- bool GfaModbusRTUMstPresetSingleRegister(HMBRTUMST hMbMst, uint32_t nTID, uint8_t nSlvID, uint16_t nRegAddr, uint16_t nRegVal, PFN_GFA_MASTER_PRESET_SINGLE_REGISTER_COMPLETE pfnPresetRegComplete)
- {
- uint8_t buf[4];
- if(!pfnPresetRegComplete)
- return false;
- GfaBufSetUnaligned_uint16(buf, nRegAddr);
- GfaBufSetUnaligned_uint16(&buf[2], nRegVal);
- return GfaModbusRTUMstSendRawRequest(hMbMst, nTID, nSlvID, MB_FUNC_PRESET_SINGLE_REGISTER, buf, sizeof(buf), 4, _OnRawPresetSingleRegisterComplete, pfnPresetRegComplete);
- }
- bool GfaModbusRTUMstDiagnosis(HMBRTUMST hMbMst, uint32_t nTID, uint8_t nSlvID, uint16_t nSubFunc, uint16_t nData, PFN_GFA_MASTER_DIAGNOSIS_COMPLETE pfnDiagComplete)
- {
- uint8_t buf[4];
- if(!pfnDiagComplete)
- return false;
- GfaBufSetUnaligned_uint16(buf, nSubFunc);
- GfaBufSetUnaligned_uint16(&buf[2], nData);
- size_t nResponseLength = _SubFunctionResponseLength(nSubFunc);
- if(nResponseLength == (size_t)-1)
- return false;
- return GfaModbusRTUMstSendRawRequest(hMbMst, nTID, nSlvID, MB_FUNC_DIAGNOSTIC, buf, sizeof(buf), nResponseLength, _OnRawDiagnosisComplete, pfnDiagComplete);
- }
- /////////////////////////////////////////////////////////////////////////////
- bool GfaModbusRTUMstReportSlaveID(HMBRTUMST hMbMst, uint32_t nTID, uint8_t nSlvID, size_t nCbDataExpected, PFN_GFA_MASTER_REPORT_SLAVE_ID_COMPLETE pfnRepSlvIDComplete)
- {
- if(!pfnRepSlvIDComplete)
- return false;
- return GfaModbusRTUMstSendRawRequest(hMbMst, nTID, nSlvID, MB_FUNC_REPORT_SLAVE_ID, NULL, 0, nCbDataExpected, _OnRawReportSlaveIDComplete, pfnRepSlvIDComplete);
- }
|