mbreq.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. #include <string.h>
  2. #include "gfambrtuslv.h"
  3. #include "gfambrtuslv_priv.h"
  4. #include "driverlib/sw_crc.h"
  5. /////////////////////////////////////////////////////////////////////////////
  6. /////////////////////////////////////////////////////////////////////////////
  7. /////////////////////////////////////////////////////////////////////////////
  8. size_t GfaModbusRequestGetDataInfoLength(LPCGFA_MODBUS_RTU_SLAVE pSlv)
  9. {
  10. size_t nRet;
  11. switch(pSlv->adu.pdu.func)
  12. {
  13. case MB_FUNC_READ_HOLDING_REGISTERS:
  14. case MB_FUNC_READ_INPUT_REGISTERS:
  15. nRet = 4;
  16. break;
  17. case MB_FUNC_PRESET_SINGLE_REGISTER:
  18. nRet = 2;
  19. break;
  20. case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
  21. nRet = 5;
  22. break;
  23. case MB_FUNC_DIAGNOSTIC:
  24. nRet = 2;
  25. break;
  26. default:
  27. nRet = 0;
  28. break;
  29. }
  30. return nRet;
  31. }
  32. /////////////////////////////////////////////////////////////////////////////
  33. size_t GfaModbusRequestGetDataPayloadLength(LPCGFA_MODBUS_RTU_SLAVE pSlv)
  34. {
  35. size_t nRet;
  36. switch(pSlv->adu.pdu.func)
  37. {
  38. case MB_FUNC_READ_HOLDING_REGISTERS:
  39. case MB_FUNC_READ_INPUT_REGISTERS:
  40. nRet = 0;
  41. break;
  42. case MB_FUNC_PRESET_SINGLE_REGISTER:
  43. nRet = 2;
  44. break;
  45. case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
  46. nRet = (size_t)pSlv->adu.pdu.b[4];
  47. break;
  48. case MB_FUNC_DIAGNOSTIC:
  49. nRet = 2;
  50. break;
  51. default:
  52. nRet = 0;
  53. break;
  54. }
  55. return nRet;
  56. }
  57. /////////////////////////////////////////////////////////////////////////////
  58. bool GfaModbusRequestFunctionKnown(uint8_t func)
  59. {
  60. switch(func)
  61. {
  62. case MB_FUNC_READ_HOLDING_REGISTERS:
  63. case MB_FUNC_READ_INPUT_REGISTERS:
  64. case MB_FUNC_PRESET_SINGLE_REGISTER:
  65. case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
  66. case MB_FUNC_DIAGNOSTIC:
  67. return true;
  68. default:
  69. return false;
  70. }
  71. }
  72. /////////////////////////////////////////////////////////////////////////////
  73. bool GfaModbusRequestSubFunctionKnown(uint16_t subfunc)
  74. {
  75. switch(subfunc)
  76. {
  77. case MB_SUBFUNC_RETURN_QUERY_DATA:
  78. case MB_SUBFUNC_CLEAR_CTRS_AND_DIAGNOSTIC_REG:
  79. case MB_SUBFUNC_RETURN_BUS_MESSAGE_COUNT:
  80. case MB_SUBFUNC_RETURN_BUS_COMM_ERROR_COUNT:
  81. case MB_SUBFUNC_RETURN_BUS_EXCEPTION_ERROR_COUNT:
  82. case MB_SUBFUNC_RETURN_SLAVE_MESSAGE_COUNT:
  83. return true;
  84. default:
  85. return false;
  86. }
  87. }
  88. bool GfaModbusRequestVerifyCRC(const void *pData, size_t nCbData, const void *pCRC)
  89. {
  90. uint16_t nCrc = Crc16(0xFFFF, (const uint8_t*)pData, nCbData);
  91. const uint8_t *pCrc = (const uint8_t*)pCRC;
  92. return ((pCrc[0] == (uint8_t)(nCrc & 0xff)) &&
  93. (pCrc[1] == (uint8_t)(nCrc >> 8)));
  94. }
  95. void GfaModbusRequestSetCRC(const void *pData, size_t nCbData, void *pCRC)
  96. {
  97. uint16_t nCrc = Crc16(0xFFFF, (const uint8_t*)pData, nCbData);
  98. uint8_t *pCrc = (uint8_t*)pCRC;
  99. pCrc[0] = (uint8_t)(nCrc & 0xff);
  100. pCrc[1] = (uint8_t)(nCrc >> 8);
  101. }
  102. /////////////////////////////////////////////////////////////////////////////
  103. size_t GfaModbusRequestReadRegisters(uint8_t func, LPGFA_MODBUS_REGISTER pRegMap, LPGFA_MODBUS_SLAVE_APP_INTERFACE pAppItf, void *pBuf, uint8_t *pnCbWritten)
  104. {
  105. uint8_t *p = (uint8_t*)pBuf;
  106. uint16_t nRegsRead = 0, nPhyStart;
  107. uint16_t nRegStart = GfaBufGetUnaligned_uint16(&p[0]);
  108. uint16_t nRegCount = GfaBufGetUnaligned_uint16(&p[2]);
  109. if(pAppItf->pfnMapRegAddr)
  110. {
  111. if((nPhyStart = (*pAppItf->pfnMapRegAddr)(nRegStart)) == (uint16_t)-1)
  112. {
  113. *p = MB_ERROR_ILLEGAL_DATA_ADDRESS;
  114. *pnCbWritten = 1;
  115. return 0;
  116. }
  117. }
  118. else
  119. {
  120. nPhyStart = nRegStart;
  121. }
  122. if(nRegCount > MODBUS_MAX_READ_REGISTERS)
  123. {
  124. *p = MB_ERROR_ILLEGAL_DATA_VALUE;
  125. *pnCbWritten = 1;
  126. return 0;
  127. }
  128. if((nPhyStart + nRegCount) > pRegMap->nCountRegs)
  129. nRegCount = pRegMap->nCountRegs - nPhyStart;
  130. *p++ = nRegCount * sizeof(uint16_t);
  131. if(pAppItf->pfnPreRead)
  132. (*pAppItf->pfnPreRead)(func, nPhyStart, nRegCount);
  133. for(nRegsRead = 0; nRegsRead < nRegCount; nRegsRead++, nPhyStart++)
  134. {
  135. GfaBufSetUnaligned_uint16(p, pRegMap->pRegs[nPhyStart]);
  136. p += sizeof(uint16_t);
  137. }
  138. if(pAppItf->pfnPostRead)
  139. (*pAppItf->pfnPostRead)(func, nPhyStart, nRegsRead);
  140. *pnCbWritten = 1 + nRegsRead * sizeof(uint16_t);
  141. return nRegsRead;
  142. }
  143. /////////////////////////////////////////////////////////////////////////////
  144. size_t GfaModbusRequestWriteRegisters(uint8_t func, LPGFA_MODBUS_REGISTER pRegMap, LPGFA_MODBUS_SLAVE_APP_INTERFACE pAppItf, void *pBuf, uint8_t *pnCbWritten)
  145. {
  146. uint8_t *p = (uint8_t*)pBuf;
  147. uint16_t nRegsWritten = 0, nPhyStart;
  148. uint16_t nRegStart = GfaBufGetUnaligned_uint16(&p[0]);
  149. uint16_t nRegCount = GfaBufGetUnaligned_uint16(&p[2]);
  150. uint16_t nCbToWrite = (uint16_t)p[4];
  151. if(pAppItf->pfnMapRegAddr)
  152. {
  153. if((nPhyStart = (*pAppItf->pfnMapRegAddr)(nRegStart)) == (uint16_t)-1)
  154. {
  155. *p = MB_ERROR_ILLEGAL_DATA_ADDRESS;
  156. *pnCbWritten = 1;
  157. return 0;
  158. }
  159. }
  160. else
  161. {
  162. nPhyStart = nRegStart;
  163. }
  164. if(nRegCount > MODBUS_MAX_READ_REGISTERS)
  165. {
  166. *p = MB_ERROR_ILLEGAL_DATA_VALUE;
  167. *pnCbWritten = 1;
  168. return 0;
  169. }
  170. else if(nRegCount != nCbToWrite / sizeof(uint16_t))
  171. {
  172. *p = MB_ERROR_ILLEGAL_DATA_VALUE;
  173. *pnCbWritten = 1;
  174. return 0;
  175. }
  176. p += 1 + 2 * sizeof(uint16_t);
  177. if((nPhyStart + nRegCount) > pRegMap->nCountRegs)
  178. nRegCount = pRegMap->nCountRegs - nPhyStart;
  179. if(pAppItf->pfnPreWrite)
  180. (*pAppItf->pfnPreWrite)(func, nPhyStart, nRegCount);
  181. for(nRegsWritten = 0; nRegsWritten < nRegCount; nRegsWritten++, nPhyStart++)
  182. {
  183. pRegMap->pRegs[nPhyStart] = GfaBufGetUnaligned_uint16(p);
  184. p += sizeof(uint16_t);
  185. }
  186. if(pAppItf->pfnPostWrite)
  187. (*pAppItf->pfnPostWrite)(func, nPhyStart, nRegsWritten);
  188. p = (uint8_t*)pBuf;
  189. GfaBufSetUnaligned_uint16(p, nRegStart);
  190. p += sizeof(uint16_t);
  191. GfaBufSetUnaligned_uint16(p, nRegCount);
  192. p += sizeof(uint16_t);
  193. *pnCbWritten = 2 * sizeof(uint16_t);
  194. return nRegsWritten;
  195. }
  196. /////////////////////////////////////////////////////////////////////////////
  197. size_t GfaModbusRequestWriteSingleRegister(uint8_t func, LPGFA_MODBUS_REGISTER pRegMap, LPGFA_MODBUS_SLAVE_APP_INTERFACE pAppItf, void *pBuf, uint8_t *pnCbWritten)
  198. {
  199. uint8_t *p = (uint8_t*)pBuf;
  200. uint16_t nPhyStart, nRegAddr = GfaBufGetUnaligned_uint16(&p[0]);
  201. if(pAppItf->pfnMapRegAddr)
  202. {
  203. if((nPhyStart = (*pAppItf->pfnMapRegAddr)(nRegAddr)) == (uint16_t)-1)
  204. {
  205. *p = MB_ERROR_ILLEGAL_DATA_ADDRESS;
  206. *pnCbWritten = 1;
  207. return 0;
  208. }
  209. }
  210. else
  211. {
  212. nPhyStart = nRegAddr;
  213. }
  214. if(nPhyStart >= pRegMap->nCountRegs)
  215. {
  216. *p = MB_ERROR_ILLEGAL_DATA_ADDRESS;
  217. *pnCbWritten = 1;
  218. return 0;
  219. }
  220. p += sizeof(uint16_t);
  221. if(pAppItf->pfnPreWrite)
  222. (*pAppItf->pfnPreWrite)(func, nPhyStart, 1);
  223. pRegMap->pRegs[nPhyStart] = GfaBufGetUnaligned_uint16(p);
  224. if(pAppItf->pfnPostWrite)
  225. (*pAppItf->pfnPostWrite)(func, nPhyStart, 1);
  226. *pnCbWritten = 2 * sizeof(uint16_t);
  227. return 1;
  228. }
  229. /////////////////////////////////////////////////////////////////////////////
  230. size_t GfaModbusRequestDiagnostic(LPGFA_MODBUS_RTU_SLAVE pSlv, uint8_t *pnCbWritten)
  231. {
  232. uint8_t *p = pSlv->adu.pdu.b;
  233. uint16_t nVal, nSubFunc = GfaBufGetUnaligned_uint16(p);
  234. p += sizeof(uint16_t);
  235. switch(nSubFunc)
  236. {
  237. case MB_SUBFUNC_RETURN_QUERY_DATA:
  238. *pnCbWritten = 2 * sizeof(uint16_t); // Echo Request Data
  239. break;
  240. case MB_SUBFUNC_CLEAR_CTRS_AND_DIAGNOSTIC_REG:
  241. memset(&pSlv->diag, 0, sizeof(pSlv->diag));
  242. *pnCbWritten = 2 * sizeof(uint16_t); // Echo Request Data
  243. break;
  244. case MB_SUBFUNC_RETURN_BUS_MESSAGE_COUNT:
  245. nVal = (uint16_t)(pSlv->diag.nBusMsgCount & 0xFFFF);
  246. GfaBufSetUnaligned_uint16(p, nVal);
  247. *pnCbWritten = 2 * sizeof(uint16_t);
  248. break;
  249. case MB_SUBFUNC_RETURN_BUS_COMM_ERROR_COUNT:
  250. nVal = (uint16_t)(pSlv->diag.nCrcErrCount & 0xFFFF);
  251. GfaBufSetUnaligned_uint16(p, nVal);
  252. *pnCbWritten = 2 * sizeof(uint16_t);
  253. break;
  254. case MB_SUBFUNC_RETURN_BUS_EXCEPTION_ERROR_COUNT:
  255. nVal = (uint16_t)(pSlv->diag.nExcErrCount & 0xFFFF);
  256. GfaBufSetUnaligned_uint16(p, nVal);
  257. *pnCbWritten = 2 * sizeof(uint16_t);
  258. break;
  259. case MB_SUBFUNC_RETURN_SLAVE_MESSAGE_COUNT:
  260. nVal = (uint16_t)(pSlv->diag.nSlvMsgCount & 0xFFFF);
  261. GfaBufSetUnaligned_uint16(p, nVal);
  262. *pnCbWritten = 2 * sizeof(uint16_t);
  263. break;
  264. default:
  265. pSlv->adu.pdu.b[0] = MB_ERROR_ILLEGAL_FUNCTION;
  266. *pnCbWritten = 1;
  267. break;
  268. }
  269. return *pnCbWritten;
  270. }
  271. /////////////////////////////////////////////////////////////////////////////
  272. size_t GfaModbusRequestCreateExceptionResponse(LPMODBUS_RTU_PDU pPdu, uint8_t nExceptionCode)
  273. {
  274. pPdu->func |= MB_FUNC_ERROR_FLAG;
  275. pPdu->b[0] = nExceptionCode;
  276. return 1;
  277. }
  278. /////////////////////////////////////////////////////////////////////////////
  279. /////////////////////////////////////////////////////////////////////////////
  280. /////////////////////////////////////////////////////////////////////////////
  281. bool GfaModbusRequestHandler(LPGFA_MODBUS_RTU_SLAVE pSlv, size_t *pnCbData, bool *pbIsException)
  282. {
  283. uint8_t nCbWritten;
  284. bool bSendResponse = true;
  285. *pnCbData = 0;
  286. *pbIsException = false;
  287. switch(pSlv->adu.pdu.func)
  288. {
  289. case MB_FUNC_READ_HOLDING_REGISTERS:
  290. if(!GfaModbusRequestReadRegisters(pSlv->adu.pdu.func, &pSlv->regMap, &pSlv->appItf, pSlv->adu.pdu.b, &nCbWritten))
  291. {
  292. pSlv->adu.pdu.func |= MB_FUNC_ERROR_FLAG;
  293. *pbIsException = true;
  294. }
  295. *pnCbData = nCbWritten;
  296. break;
  297. case MB_FUNC_PRESET_SINGLE_REGISTER:
  298. if(!GfaModbusRequestWriteSingleRegister(pSlv->adu.pdu.func, &pSlv->regMap, &pSlv->appItf, pSlv->adu.pdu.b, &nCbWritten))
  299. {
  300. pSlv->adu.pdu.func |= MB_FUNC_ERROR_FLAG;
  301. *pbIsException = true;
  302. }
  303. *pnCbData = nCbWritten;
  304. break;
  305. case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
  306. if(!GfaModbusRequestWriteRegisters(pSlv->adu.pdu.func, &pSlv->regMap, &pSlv->appItf, pSlv->adu.pdu.b, &nCbWritten))
  307. {
  308. pSlv->adu.pdu.func |= MB_FUNC_ERROR_FLAG;
  309. *pbIsException = true;
  310. }
  311. *pnCbData = nCbWritten;
  312. break;
  313. case MB_FUNC_DIAGNOSTIC:
  314. if(!GfaModbusRequestDiagnostic(pSlv, &nCbWritten))
  315. {
  316. pSlv->adu.pdu.func |= MB_FUNC_ERROR_FLAG;
  317. *pbIsException = true;
  318. }
  319. *pnCbData = nCbWritten;
  320. break;
  321. default:
  322. *pnCbData = GfaModbusRequestCreateExceptionResponse(&pSlv->adu.pdu, MB_ERROR_ILLEGAL_FUNCTION);
  323. *pbIsException = true;
  324. break;
  325. }
  326. return bSendResponse;
  327. }