123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- #include <string.h>
- #include "gfambrtuslv.h"
- #include "gfambrtuslv_priv.h"
- #include "driverlib/sw_crc.h"
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- size_t GfaModbusRequestGetDataInfoLength(LPCGFA_MODBUS_RTU_SLAVE pSlv)
- {
- size_t nRet;
- switch(pSlv->adu.pdu.func)
- {
- case MB_FUNC_READ_HOLDING_REGISTERS:
- case MB_FUNC_READ_INPUT_REGISTERS:
- nRet = 4;
- break;
- case MB_FUNC_PRESET_SINGLE_REGISTER:
- nRet = 2;
- break;
- case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
- nRet = 5;
- break;
- case MB_FUNC_DIAGNOSTIC:
- nRet = 2;
- break;
- default:
- nRet = 0;
- break;
- }
- return nRet;
- }
- /////////////////////////////////////////////////////////////////////////////
- size_t GfaModbusRequestGetDataPayloadLength(LPCGFA_MODBUS_RTU_SLAVE pSlv)
- {
- size_t nRet;
- switch(pSlv->adu.pdu.func)
- {
- case MB_FUNC_READ_HOLDING_REGISTERS:
- case MB_FUNC_READ_INPUT_REGISTERS:
- nRet = 0;
- break;
- case MB_FUNC_PRESET_SINGLE_REGISTER:
- nRet = 2;
- break;
- case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
- nRet = (size_t)pSlv->adu.pdu.b[4];
- break;
- case MB_FUNC_DIAGNOSTIC:
- nRet = 2;
- break;
- default:
- nRet = 0;
- break;
- }
- return nRet;
- }
- /////////////////////////////////////////////////////////////////////////////
- bool GfaModbusRequestFunctionKnown(uint8_t func)
- {
- switch(func)
- {
- case MB_FUNC_READ_HOLDING_REGISTERS:
- case MB_FUNC_READ_INPUT_REGISTERS:
- case MB_FUNC_PRESET_SINGLE_REGISTER:
- case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
- case MB_FUNC_DIAGNOSTIC:
- return true;
- default:
- return false;
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- bool GfaModbusRequestSubFunctionKnown(uint16_t subfunc)
- {
- switch(subfunc)
- {
- case MB_SUBFUNC_RETURN_QUERY_DATA:
- 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:
- return true;
- default:
- return false;
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- size_t GfaModbusRequestReadRegisters(uint8_t func, LPGFA_MODBUS_REGISTER pRegMap, LPGFA_MODBUS_SLAVE_APP_INTERFACE pAppItf, void *pBuf, uint8_t *pnCbWritten)
- {
- uint8_t *p = (uint8_t*)pBuf;
- uint16_t nRegsRead = 0, nPhyStart;
- uint16_t nRegStart = GfaBufGetUnaligned_uint16(&p[0]);
- uint16_t nRegCount = GfaBufGetUnaligned_uint16(&p[2]);
- if(pAppItf->pfnMapRegAddr)
- {
- if((nPhyStart = (*pAppItf->pfnMapRegAddr)(nRegStart)) == (uint16_t)-1)
- {
- *p = MB_ERROR_ILLEGAL_DATA_ADDRESS;
- *pnCbWritten = 1;
- return 0;
- }
- }
- else
- {
- nPhyStart = nRegStart;
- }
- if(nRegCount > MODBUS_MAX_READ_REGISTERS)
- {
- *p = MB_ERROR_ILLEGAL_DATA_VALUE;
- *pnCbWritten = 1;
- return 0;
- }
- if((nPhyStart + nRegCount) > pRegMap->nCountRegs)
- nRegCount = pRegMap->nCountRegs - nPhyStart;
- *p++ = nRegCount * sizeof(uint16_t);
- if(pAppItf->pfnPreRead)
- (*pAppItf->pfnPreRead)(func, nPhyStart, nRegCount);
- for(nRegsRead = 0; nRegsRead < nRegCount; nRegsRead++, nPhyStart++)
- {
- GfaBufSetUnaligned_uint16(p, pRegMap->pRegs[nPhyStart]);
- p += sizeof(uint16_t);
- }
- if(pAppItf->pfnPostRead)
- (*pAppItf->pfnPostRead)(func, nPhyStart, nRegsRead);
- *pnCbWritten = 1 + nRegsRead * sizeof(uint16_t);
- return nRegsRead;
- }
- /////////////////////////////////////////////////////////////////////////////
- size_t GfaModbusRequestWriteRegisters(uint8_t func, LPGFA_MODBUS_REGISTER pRegMap, LPGFA_MODBUS_SLAVE_APP_INTERFACE pAppItf, void *pBuf, uint8_t *pnCbWritten)
- {
- uint8_t *p = (uint8_t*)pBuf;
- uint16_t nRegsWritten = 0, nPhyStart;
- uint16_t nRegStart = GfaBufGetUnaligned_uint16(&p[0]);
- uint16_t nRegCount = GfaBufGetUnaligned_uint16(&p[2]);
- uint16_t nCbToWrite = (uint16_t)p[4];
- if(pAppItf->pfnMapRegAddr)
- {
- if((nPhyStart = (*pAppItf->pfnMapRegAddr)(nRegStart)) == (uint16_t)-1)
- {
- *p = MB_ERROR_ILLEGAL_DATA_ADDRESS;
- *pnCbWritten = 1;
- return 0;
- }
- }
- else
- {
- nPhyStart = nRegStart;
- }
- if(nRegCount > MODBUS_MAX_READ_REGISTERS)
- {
- *p = MB_ERROR_ILLEGAL_DATA_VALUE;
- *pnCbWritten = 1;
- return 0;
- }
- else if(nRegCount != nCbToWrite / sizeof(uint16_t))
- {
- *p = MB_ERROR_ILLEGAL_DATA_VALUE;
- *pnCbWritten = 1;
- return 0;
- }
- p += 1 + 2 * sizeof(uint16_t);
- if((nPhyStart + nRegCount) > pRegMap->nCountRegs)
- nRegCount = pRegMap->nCountRegs - nPhyStart;
- if(pAppItf->pfnPreWrite)
- (*pAppItf->pfnPreWrite)(func, nPhyStart, nRegCount);
- for(nRegsWritten = 0; nRegsWritten < nRegCount; nRegsWritten++, nPhyStart++)
- {
- pRegMap->pRegs[nPhyStart] = GfaBufGetUnaligned_uint16(p);
- p += sizeof(uint16_t);
- }
- if(pAppItf->pfnPostWrite)
- (*pAppItf->pfnPostWrite)(func, nPhyStart, nRegsWritten);
- p = (uint8_t*)pBuf;
- GfaBufSetUnaligned_uint16(p, nRegStart);
- p += sizeof(uint16_t);
- GfaBufSetUnaligned_uint16(p, nRegCount);
- p += sizeof(uint16_t);
- *pnCbWritten = 2 * sizeof(uint16_t);
- return nRegsWritten;
- }
- /////////////////////////////////////////////////////////////////////////////
- size_t GfaModbusRequestWriteSingleRegister(uint8_t func, LPGFA_MODBUS_REGISTER pRegMap, LPGFA_MODBUS_SLAVE_APP_INTERFACE pAppItf, void *pBuf, uint8_t *pnCbWritten)
- {
- uint8_t *p = (uint8_t*)pBuf;
- uint16_t nPhyStart, nRegAddr = GfaBufGetUnaligned_uint16(&p[0]);
- if(pAppItf->pfnMapRegAddr)
- {
- if((nPhyStart = (*pAppItf->pfnMapRegAddr)(nRegAddr)) == (uint16_t)-1)
- {
- *p = MB_ERROR_ILLEGAL_DATA_ADDRESS;
- *pnCbWritten = 1;
- return 0;
- }
- }
- else
- {
- nPhyStart = nRegAddr;
- }
- if(nPhyStart >= pRegMap->nCountRegs)
- {
- *p = MB_ERROR_ILLEGAL_DATA_ADDRESS;
- *pnCbWritten = 1;
- return 0;
- }
- p += sizeof(uint16_t);
- if(pAppItf->pfnPreWrite)
- (*pAppItf->pfnPreWrite)(func, nPhyStart, 1);
- pRegMap->pRegs[nPhyStart] = GfaBufGetUnaligned_uint16(p);
- if(pAppItf->pfnPostWrite)
- (*pAppItf->pfnPostWrite)(func, nPhyStart, 1);
- *pnCbWritten = 2 * sizeof(uint16_t);
- return 1;
- }
- /////////////////////////////////////////////////////////////////////////////
- size_t GfaModbusRequestDiagnostic(LPGFA_MODBUS_RTU_SLAVE pSlv, uint8_t *pnCbWritten)
- {
- uint8_t *p = pSlv->adu.pdu.b;
- uint16_t nVal, nSubFunc = GfaBufGetUnaligned_uint16(p);
- p += sizeof(uint16_t);
- switch(nSubFunc)
- {
- case MB_SUBFUNC_RETURN_QUERY_DATA:
- *pnCbWritten = 2 * sizeof(uint16_t); // Echo Request Data
- break;
- case MB_SUBFUNC_CLEAR_CTRS_AND_DIAGNOSTIC_REG:
- memset(&pSlv->diag, 0, sizeof(pSlv->diag));
- *pnCbWritten = 2 * sizeof(uint16_t); // Echo Request Data
- break;
- case MB_SUBFUNC_RETURN_BUS_MESSAGE_COUNT:
- nVal = (uint16_t)(pSlv->diag.nBusMsgCount & 0xFFFF);
- GfaBufSetUnaligned_uint16(p, nVal);
- *pnCbWritten = 2 * sizeof(uint16_t);
- break;
- case MB_SUBFUNC_RETURN_BUS_COMM_ERROR_COUNT:
- nVal = (uint16_t)(pSlv->diag.nCrcErrCount & 0xFFFF);
- GfaBufSetUnaligned_uint16(p, nVal);
- *pnCbWritten = 2 * sizeof(uint16_t);
- break;
- case MB_SUBFUNC_RETURN_BUS_EXCEPTION_ERROR_COUNT:
- nVal = (uint16_t)(pSlv->diag.nExcErrCount & 0xFFFF);
- GfaBufSetUnaligned_uint16(p, nVal);
- *pnCbWritten = 2 * sizeof(uint16_t);
- break;
- case MB_SUBFUNC_RETURN_SLAVE_MESSAGE_COUNT:
- nVal = (uint16_t)(pSlv->diag.nSlvMsgCount & 0xFFFF);
- GfaBufSetUnaligned_uint16(p, nVal);
- *pnCbWritten = 2 * sizeof(uint16_t);
- break;
- default:
- pSlv->adu.pdu.b[0] = MB_ERROR_ILLEGAL_FUNCTION;
- *pnCbWritten = 1;
- break;
- }
- return *pnCbWritten;
- }
- /////////////////////////////////////////////////////////////////////////////
- size_t GfaModbusRequestCreateExceptionResponse(LPMODBUS_RTU_PDU pPdu, uint8_t nExceptionCode)
- {
- pPdu->func |= MB_FUNC_ERROR_FLAG;
- pPdu->b[0] = nExceptionCode;
- return 1;
- }
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- bool GfaModbusRequestHandler(LPGFA_MODBUS_RTU_SLAVE pSlv, size_t *pnCbData, bool *pbIsException)
- {
- uint8_t nCbWritten;
- bool bSendResponse = true;
- *pnCbData = 0;
- *pbIsException = false;
- switch(pSlv->adu.pdu.func)
- {
- case MB_FUNC_READ_HOLDING_REGISTERS:
- if(!GfaModbusRequestReadRegisters(pSlv->adu.pdu.func, &pSlv->regMap, &pSlv->appItf, pSlv->adu.pdu.b, &nCbWritten))
- {
- pSlv->adu.pdu.func |= MB_FUNC_ERROR_FLAG;
- *pbIsException = true;
- }
- *pnCbData = nCbWritten;
- break;
- case MB_FUNC_PRESET_SINGLE_REGISTER:
- if(!GfaModbusRequestWriteSingleRegister(pSlv->adu.pdu.func, &pSlv->regMap, &pSlv->appItf, pSlv->adu.pdu.b, &nCbWritten))
- {
- pSlv->adu.pdu.func |= MB_FUNC_ERROR_FLAG;
- *pbIsException = true;
- }
- *pnCbData = nCbWritten;
- break;
- case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
- if(!GfaModbusRequestWriteRegisters(pSlv->adu.pdu.func, &pSlv->regMap, &pSlv->appItf, pSlv->adu.pdu.b, &nCbWritten))
- {
- pSlv->adu.pdu.func |= MB_FUNC_ERROR_FLAG;
- *pbIsException = true;
- }
- *pnCbData = nCbWritten;
- break;
- case MB_FUNC_DIAGNOSTIC:
- if(!GfaModbusRequestDiagnostic(pSlv, &nCbWritten))
- {
- pSlv->adu.pdu.func |= MB_FUNC_ERROR_FLAG;
- *pbIsException = true;
- }
- *pnCbData = nCbWritten;
- break;
- default:
- *pnCbData = GfaModbusRequestCreateExceptionResponse(&pSlv->adu.pdu, MB_ERROR_ILLEGAL_FUNCTION);
- *pbIsException = true;
- break;
- }
- return bSendResponse;
- }
|