mbrtuslv.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include "gfambrtuslv.h"
  4. #include "gfambrtuslv_priv.h"
  5. #include "driverlib/sw_crc.h"
  6. #include "inc/hw_memmap.h"
  7. /////////////////////////////////////////////////////////////////////////////
  8. static GFA_MODBUS_RTU_SLAVE g_mbSlv;
  9. /////////////////////////////////////////////////////////////////////////////
  10. static bool _PeekStateChange(LPGFA_MODBUS_RTU_SLAVE pSlv)
  11. {
  12. if(pSlv->oldstate != pSlv->state)
  13. {
  14. if(pSlv->appItf.pfnStateChanged)
  15. (*pSlv->appItf.pfnStateChanged)(pSlv->state, pSlv->oldstate);
  16. pSlv->oldstate = pSlv->state;
  17. return true;
  18. }
  19. return false;
  20. }
  21. /////////////////////////////////////////////////////////////////////////////
  22. /////////////////////////////////////////////////////////////////////////////
  23. /////////////////////////////////////////////////////////////////////////////
  24. HMBRTUSLV GfaModbusRTUSlvCreate(LPCGFA_MODBUS_RTU_SLAVE_PARAMETERS pslp)
  25. {
  26. if(!pslp)
  27. return NULL;
  28. if(!pslp->slaveID || pslp->slaveID > MODBUS_MAX_SLAVE_ID)
  29. return NULL;
  30. if(!pslp->hFifoRX || !pslp->hFifoTX || !pslp->regMap.pRegs || !pslp->regMap.nCountRegs)
  31. return NULL;
  32. LPGFA_MODBUS_RTU_SLAVE pSlv = &g_mbSlv;
  33. memset(pSlv, 0, sizeof(GFA_MODBUS_RTU_SLAVE));
  34. pSlv->state = MB_RTU_SLV_Idle;
  35. pSlv->oldstate = MB_RTU_SLV_Void;
  36. pSlv->slaveID = pslp->slaveID;
  37. pSlv->hFifoRX = pslp->hFifoRX;
  38. pSlv->hFifoTX = pslp->hFifoTX;
  39. memcpy(&pSlv->regMap, &pslp->regMap, sizeof(GFA_MODBUS_REGISTER));
  40. memcpy(&pSlv->appItf, &pslp->appItf, sizeof(GFA_MODBUS_SLAVE_APP_INTERFACE));
  41. return (HMBRTUSLV)pSlv;
  42. }
  43. /////////////////////////////////////////////////////////////////////////////
  44. void GfaModbusRTUSlvRelease(HMBRTUSLV hMbSlv)
  45. {
  46. if(hMbSlv)
  47. {
  48. LPGFA_MODBUS_RTU_SLAVE pSlv = (LPGFA_MODBUS_RTU_SLAVE)hMbSlv;
  49. memset(pSlv, 0, sizeof(GFA_MODBUS_RTU_SLAVE));
  50. pSlv->state = MB_RTU_SLV_Void;
  51. }
  52. }
  53. /////////////////////////////////////////////////////////////////////////////
  54. bool GfaModbusRTUSlvSetID(HMBRTUSLV hMbSlv, uint8_t newID)
  55. {
  56. LPGFA_MODBUS_RTU_SLAVE pSlv = (LPGFA_MODBUS_RTU_SLAVE)hMbSlv;
  57. if(!pSlv)
  58. return false;
  59. if(!newID || newID > MODBUS_MAX_SLAVE_ID)
  60. return false;
  61. if(pSlv->newSlaveID != newID)
  62. pSlv->newSlaveID = newID;
  63. return true;
  64. }
  65. /////////////////////////////////////////////////////////////////////////////
  66. bool GfaModbusRTUSlvStateMachine(HMBRTUSLV hMbSlv)
  67. {
  68. static int nReEnterSTM = 0;
  69. uint8_t b;
  70. size_t nRead;
  71. LPGFA_MODBUS_RTU_SLAVE pSlv = (LPGFA_MODBUS_RTU_SLAVE)hMbSlv;
  72. if(!pSlv)
  73. return false;
  74. ++nReEnterSTM;
  75. switch(pSlv->state)
  76. {
  77. case MB_RTU_SLV_Idle:
  78. nReEnterSTM = 0;
  79. _PeekStateChange(pSlv);
  80. if(pSlv->newSlaveID)
  81. {
  82. pSlv->slaveID = pSlv->newSlaveID;
  83. pSlv->newSlaveID = 0;
  84. }
  85. if(!GfaMbFifoMatchFlags(pSlv->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true))
  86. break;
  87. pSlv->state = MB_RTU_SLV_RxSlvID;
  88. pSlv->nCbToRead = 0;
  89. pSlv->nCbToWrite = 0;
  90. pSlv->nDataPtr = 0;
  91. pSlv->bCRCOk = false;
  92. GfaMbFifoClearFlags(pSlv->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true);
  93. // fall through
  94. case MB_RTU_SLV_RxSlvID:
  95. _PeekStateChange(pSlv);
  96. if(!GfaMbFifoPop(pSlv->hFifoRX, &b, true))
  97. {
  98. if(GfaMbFifoMatchFlags(pSlv->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true))
  99. pSlv->state = MB_RTU_SLV_Idle;
  100. break;
  101. }
  102. if(pSlv->slaveID != b) // ignore broadcasts as well
  103. {
  104. GfaMbFifoSetFlags(pSlv->hFifoRX, MB_RTU_FLAG_IGNORE_FRAME, true);
  105. GfaMbFifoReset(pSlv->hFifoRX, true);
  106. pSlv->state = MB_RTU_SLV_Idle;
  107. ++pSlv->diag.nBusMsgCount;
  108. break;
  109. }
  110. pSlv->adu.slaveID = b;
  111. pSlv->state = MB_RTU_SLV_RxFunc;
  112. ++pSlv->diag.nBusMsgCount;
  113. // fall through
  114. case MB_RTU_SLV_RxFunc:
  115. _PeekStateChange(pSlv);
  116. if(!GfaMbFifoPop(pSlv->hFifoRX, &b, true))
  117. {
  118. if(GfaMbFifoMatchFlags(pSlv->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true))
  119. pSlv->state = MB_RTU_SLV_Idle;
  120. break;
  121. }
  122. else if(!GfaModbusRequestFunctionKnown(b))
  123. {
  124. pSlv->adu.pdu.func = b;
  125. GfaMbFifoSetFlags(pSlv->hFifoRX, MB_RTU_FLAG_IGNORE_FRAME, true);
  126. GfaMbFifoReset(pSlv->hFifoRX, true);
  127. GfaModbusRequestCreateExceptionResponse(&pSlv->adu.pdu, MB_ERROR_ILLEGAL_FUNCTION);
  128. GfaBufSetCRC(&pSlv->adu, 3, &pSlv->adu.pdu.b[1]);
  129. pSlv->nCbToWrite = 5;
  130. pSlv->state = MB_RTU_SLV_TxStart;
  131. ++pSlv->diag.nExcErrCount;
  132. break;
  133. }
  134. pSlv->adu.pdu.func = b;
  135. pSlv->state = MB_RTU_SLV_RxDataInfo;
  136. pSlv->nCbToRead = GfaModbusRequestGetDataInfoLength(pSlv);
  137. // fall through
  138. case MB_RTU_SLV_RxDataInfo:
  139. _PeekStateChange(pSlv);
  140. if(pSlv->nCbToRead)
  141. {
  142. if(!(nRead = GfaMbFifoRead(pSlv->hFifoRX, &pSlv->adu.pdu.b[pSlv->nDataPtr], pSlv->nCbToRead, true)))
  143. {
  144. if(GfaMbFifoMatchFlags(pSlv->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true))
  145. pSlv->state = MB_RTU_SLV_Idle;
  146. break;
  147. }
  148. pSlv->nDataPtr += nRead;
  149. pSlv->nCbToRead -= nRead;
  150. }
  151. if(pSlv->nCbToRead)
  152. break;
  153. else
  154. {
  155. if(pSlv->adu.pdu.func == MB_FUNC_DIAGNOSTIC)
  156. {
  157. pSlv->nSubFunc = GfaBufGetUnaligned_uint16(pSlv->adu.pdu.b);
  158. if(!GfaModbusRequestSubFunctionKnown(pSlv->nSubFunc))
  159. {
  160. pSlv->adu.pdu.func = b;
  161. GfaMbFifoSetFlags(pSlv->hFifoRX, MB_RTU_FLAG_IGNORE_FRAME, true);
  162. GfaMbFifoReset(pSlv->hFifoRX, true);
  163. GfaModbusRequestCreateExceptionResponse(&pSlv->adu.pdu, MB_ERROR_ILLEGAL_FUNCTION);
  164. GfaBufSetCRC(&pSlv->adu, 3, &pSlv->adu.pdu.b[1]);
  165. pSlv->nCbToWrite = 5;
  166. pSlv->state = MB_RTU_SLV_TxStart;
  167. ++pSlv->diag.nExcErrCount;
  168. break;
  169. }
  170. }
  171. pSlv->state = MB_RTU_SLV_RxDataPayload;
  172. pSlv->nCbToRead = GfaModbusRequestGetDataPayloadLength(pSlv);
  173. // fall through
  174. }
  175. case MB_RTU_SLV_RxDataPayload:
  176. _PeekStateChange(pSlv);
  177. if(pSlv->nCbToRead)
  178. {
  179. if(!(nRead = GfaMbFifoRead(pSlv->hFifoRX, &pSlv->adu.pdu.b[pSlv->nDataPtr], pSlv->nCbToRead, true)))
  180. {
  181. if(GfaMbFifoMatchFlags(pSlv->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true))
  182. pSlv->state = MB_RTU_SLV_Idle;
  183. break;
  184. }
  185. pSlv->nDataPtr += nRead;
  186. pSlv->nCbToRead -= nRead;
  187. }
  188. if(pSlv->nCbToRead)
  189. break;
  190. else
  191. {
  192. pSlv->state = MB_RTU_SLV_RxCRC;
  193. pSlv->nCbToRead = 2;
  194. // fall through
  195. }
  196. case MB_RTU_SLV_RxCRC:
  197. _PeekStateChange(pSlv);
  198. if(pSlv->nCbToRead)
  199. {
  200. if(!(nRead = GfaMbFifoRead(pSlv->hFifoRX, &pSlv->adu.pdu.b[pSlv->nDataPtr], pSlv->nCbToRead, true)))
  201. {
  202. if(GfaMbFifoMatchFlags(pSlv->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true))
  203. pSlv->state = MB_RTU_SLV_Idle;
  204. break;
  205. }
  206. pSlv->nDataPtr += nRead;
  207. pSlv->nCbToRead -= nRead;
  208. }
  209. if(pSlv->nCbToRead)
  210. break;
  211. else
  212. {
  213. pSlv->bCRCOk = GfaBufVerifyCRC(&pSlv->adu, pSlv->nDataPtr, &pSlv->adu.pdu.b[pSlv->nDataPtr - 2]);
  214. pSlv->state = MB_RTU_SLV_RxComplete;
  215. // fall through
  216. }
  217. case MB_RTU_SLV_RxComplete:
  218. _PeekStateChange(pSlv);
  219. if(pSlv->bCRCOk)
  220. {
  221. bool bIsExeption;
  222. size_t nCbData = 0;
  223. ++pSlv->diag.nSlvMsgCount;
  224. if(GfaModbusRequestHandler(pSlv, &nCbData, &bIsExeption))
  225. {
  226. GfaBufSetCRC(&pSlv->adu, nCbData + 2, &pSlv->adu.pdu.b[nCbData]);
  227. pSlv->nCbToWrite = nCbData + 4;
  228. pSlv->state = MB_RTU_SLV_TxStart;
  229. if(bIsExeption)
  230. ++pSlv->diag.nExcErrCount;
  231. GfaMbFifoRxFinalize(pSlv->hFifoRX, true);
  232. // fall through
  233. }
  234. else
  235. {
  236. pSlv->state = MB_RTU_SLV_Idle; // nothing to send
  237. break;
  238. }
  239. }
  240. else
  241. {
  242. ++pSlv->diag.nCrcErrCount; // CRC Error!!!
  243. pSlv->state = MB_RTU_SLV_Idle; // silently ignore frame
  244. break;
  245. }
  246. case MB_RTU_SLV_TxStart:
  247. _PeekStateChange(pSlv);
  248. if( GfaMbFifoEmpty(pSlv->hFifoTX, true) &&
  249. GfaMbFifoTxPrepare(pSlv->hFifoTX, true))
  250. {
  251. GfaMbFifoSetFlags(pSlv->hFifoTX, MB_RTU_FLAG_TRANSMIT_IN_PROGRESS, true);
  252. GfaMbFifoWrite(pSlv->hFifoTX, &pSlv->adu, pSlv->nCbToWrite, true);
  253. if(pSlv->appItf.pfnPreTransmit)
  254. (*pSlv->appItf.pfnPreTransmit)(&pSlv->adu);
  255. GfaMbFifoTxStart(pSlv->hFifoTX, false);
  256. pSlv->state = MB_RTU_SLV_TxWaitEnd;
  257. // fall through
  258. }
  259. else
  260. break;
  261. case MB_RTU_SLV_TxWaitEnd:
  262. _PeekStateChange(pSlv);
  263. if(!GfaMbFifoMatchFlags(pSlv->hFifoTX, MB_RTU_FLAG_TRANSMIT_IN_PROGRESS, true))
  264. {
  265. if(pSlv->appItf.pfnPostTransmit)
  266. (*pSlv->appItf.pfnPostTransmit)(&pSlv->adu);
  267. pSlv->state = MB_RTU_SLV_Idle;
  268. }
  269. break;
  270. default:
  271. return false;
  272. }
  273. if(pSlv->nMaxReEnterSTM < nReEnterSTM)
  274. pSlv->nMaxReEnterSTM = nReEnterSTM;
  275. return true;
  276. }