mbrtuslv.c 8.2 KB

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