mbrtumast.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <gfambrtumst.h>
  4. /////////////////////////////////////////////////////////////////////////////
  5. #define MODBUS_MASTER_RX_TIMEOUT_US 500000 // slave to master response timeout
  6. /////////////////////////////////////////////////////////////////////////////
  7. typedef struct _GFA_MODBUS_RTU_MASTER
  8. {
  9. HFIFO hFifoRX;
  10. HFIFO hFifoTX;
  11. uint8_t curSlaveID;
  12. uint8_t curFunc;
  13. uint32_t nTID;
  14. int nRxErr;
  15. GFA_MODBUS_RTU_MST_STATES state;
  16. GFA_MODBUS_RTU_MST_STATES oldstate;
  17. MODBUS_RTU_ADU adu;
  18. PFN_GFA_MASTER_RAW_REQUEST_COMPLETE pfnRawReqComplete;
  19. void *pParam;
  20. size_t nCbDataExpected;
  21. size_t nCbRx;
  22. uint64_t nRxTimeoutUs;
  23. uint64_t nTimerUs;
  24. GFA_MODBUS_MASTER_APP_INTERFACE appItf;
  25. GFA_MODBUS_PROTOCOL_TIMEOUTS mpt;
  26. }GFA_MODBUS_RTU_MASTER, *LPGFA_MODBUS_RTU_MASTER;
  27. typedef const GFA_MODBUS_RTU_MASTER *LPCGFA_MODBUS_RTU_MASTER;
  28. /////////////////////////////////////////////////////////////////////////////
  29. static GFA_MODBUS_RTU_MASTER g_mbMast = {0};
  30. /////////////////////////////////////////////////////////////////////////////
  31. static bool _ValidateADU(LPGFA_MODBUS_RTU_MASTER pMst)
  32. {
  33. if(pMst->nRxErr)
  34. {
  35. if(pMst->nRxErr != GFA_MB_MST_ERROR_SLAVE_ERROR)
  36. return false;
  37. }
  38. if(!GfaBufVerifyCRC(&pMst->adu, pMst->nCbDataExpected + 2, &pMst->adu.pdu.b[pMst->nCbDataExpected]))
  39. {
  40. pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_INVALID_CRC;
  41. return false;
  42. }
  43. return true;
  44. }
  45. /////////////////////////////////////////////////////////////////////////////
  46. static bool _TimerElapsed(LPGFA_MODBUS_RTU_MASTER pMst)
  47. {
  48. struct timeval tv;
  49. return pMst->nTimerUs < GfaSystickTimeval2Us(GfaSystickGetUsClock(&tv));
  50. }
  51. /////////////////////////////////////////////////////////////////////////////
  52. static void _RespTimerTrigger(LPGFA_MODBUS_RTU_MASTER pMst)
  53. {
  54. struct timeval tv;
  55. pMst->nTimerUs = GfaSystickTimeval2Us(GfaSystickGetUsClock(&tv)) + pMst->nRxTimeoutUs;
  56. }
  57. /////////////////////////////////////////////////////////////////////////////
  58. static void _CharTimerTrigger(LPGFA_MODBUS_RTU_MASTER pMst)
  59. {
  60. struct timeval tv;
  61. pMst->nTimerUs = GfaSystickTimeval2Us(GfaSystickGetUsClock(&tv)) + pMst->mpt.nCharTimeoutUs;
  62. }
  63. /////////////////////////////////////////////////////////////////////////////
  64. static void _FrameTimerTrigger(LPGFA_MODBUS_RTU_MASTER pMst)
  65. {
  66. struct timeval tv;
  67. pMst->nTimerUs = GfaSystickTimeval2Us(GfaSystickGetUsClock(&tv)) + pMst->mpt.nFrameTimeoutUs;
  68. }
  69. /////////////////////////////////////////////////////////////////////////////
  70. static bool _PeekStateChange(LPGFA_MODBUS_RTU_MASTER pMst)
  71. {
  72. if(pMst->oldstate != pMst->state)
  73. {
  74. if(pMst->appItf.pfnStateChanged)
  75. (*pMst->appItf.pfnStateChanged)(pMst->state, pMst->oldstate);
  76. pMst->oldstate = pMst->state;
  77. return true;
  78. }
  79. return false;
  80. }
  81. /////////////////////////////////////////////////////////////////////////////
  82. /////////////////////////////////////////////////////////////////////////////
  83. /////////////////////////////////////////////////////////////////////////////
  84. HMBRTUMST GfaModbusRTUMstCreate(LPCGFA_MODBUS_RTU_MASTER_PARAMETERS pmap)
  85. {
  86. if(!pmap || !pmap->hFifoRX || !pmap->hFifoTX)
  87. return NULL;
  88. LPGFA_MODBUS_RTU_MASTER pMst = &g_mbMast;
  89. memset(pMst, 0, sizeof(GFA_MODBUS_RTU_MASTER));
  90. memcpy(&pMst->mpt, &pmap->mpt, sizeof(GFA_MODBUS_PROTOCOL_TIMEOUTS));
  91. memcpy(&pMst->appItf, &pmap->appItf, sizeof(GFA_MODBUS_MASTER_APP_INTERFACE));
  92. pMst->oldstate = MB_RTU_MST_Void;
  93. pMst->hFifoRX = pmap->hFifoRX;
  94. pMst->hFifoTX = pmap->hFifoTX;
  95. pMst->nRxTimeoutUs = pmap->nRxTimeoutUs;
  96. return (HMBRTUMST)pMst;
  97. }
  98. /////////////////////////////////////////////////////////////////////////////
  99. void GfaModbusRTUMstRelease(HMBRTUMST hMbMst)
  100. {
  101. if(hMbMst)
  102. {
  103. LPGFA_MODBUS_RTU_MASTER pMst = (LPGFA_MODBUS_RTU_MASTER)hMbMst;
  104. memset(pMst, 0, sizeof(GFA_MODBUS_RTU_MASTER));
  105. pMst->state = MB_RTU_MST_Void;
  106. }
  107. }
  108. /////////////////////////////////////////////////////////////////////////////
  109. bool GfaModbusRTUMstStateMachine(HMBRTUMST hMbMst)
  110. {
  111. uint8_t b;
  112. LPGFA_MODBUS_RTU_MASTER pMst = (LPGFA_MODBUS_RTU_MASTER)hMbMst;
  113. if(!pMst)
  114. return false;
  115. switch(pMst->state)
  116. {
  117. case MB_RTU_MST_Idle:
  118. _PeekStateChange(pMst);
  119. break;
  120. case MB_RTU_MST_TxStart:
  121. _PeekStateChange(pMst);
  122. if( _TimerElapsed(pMst) &&
  123. GfaMbFifoTxPrepare(pMst->hFifoTX, false))
  124. {
  125. if(pMst->appItf.pfnPreTx)
  126. (*pMst->appItf.pfnPreTx)(pMst->nTID, pMst->curSlaveID);
  127. GfaMbFifoClearFlags(pMst->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true);
  128. GfaMbFifoSetFlags(pMst->hFifoTX, MB_RTU_FLAG_TRANSMIT_IN_PROGRESS, false);
  129. GfaMbFifoTxStart(pMst->hFifoTX, true);
  130. pMst->state = MB_RTU_MST_TxWaitEnd;
  131. // fall through to next state
  132. }
  133. else
  134. break;
  135. case MB_RTU_MST_TxWaitEnd:
  136. _PeekStateChange(pMst);
  137. if(!GfaMbFifoMatchFlags(pMst->hFifoTX, MB_RTU_FLAG_TRANSMIT_IN_PROGRESS, true))
  138. {
  139. pMst->state = MB_RTU_MST_TxDone;
  140. // fall through to next state
  141. }
  142. else
  143. break;
  144. case MB_RTU_MST_TxDone:
  145. _PeekStateChange(pMst);
  146. pMst->state = MB_RTU_MST_WaitRxFifo;
  147. _RespTimerTrigger(pMst);
  148. if(pMst->appItf.pfnPostTx)
  149. (*pMst->appItf.pfnPostTx)(pMst->nTID, pMst->curSlaveID);
  150. // fall through to next state
  151. case MB_RTU_MST_WaitRxFifo:
  152. _PeekStateChange(pMst);
  153. if(GfaMbFifoPeek(pMst->hFifoRX, true))
  154. {
  155. GfaMbFifoClearFlags(pMst->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true);
  156. pMst->state = MB_RTU_MST_RxSlvID;
  157. if(pMst->appItf.pfnRxStart)
  158. (*pMst->appItf.pfnRxStart)(pMst->nTID);
  159. // fall through to next state
  160. }
  161. else
  162. {
  163. if(_TimerElapsed(pMst))
  164. {
  165. pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_RESPONSE_TIMEOUT;
  166. pMst->state = MB_RTU_MST_ReportError;
  167. }
  168. break;
  169. }
  170. case MB_RTU_MST_RxSlvID:
  171. _PeekStateChange(pMst);
  172. if(!GfaMbFifoPop(pMst->hFifoRX, &b, true))
  173. {
  174. pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_RESPONSE_TIMEOUT;
  175. pMst->state = MB_RTU_MST_ReportError;
  176. break;
  177. }
  178. else if(pMst->curSlaveID != b)
  179. {
  180. GfaMbFifoSetFlags(pMst->hFifoRX, MB_RTU_FLAG_IGNORE_FRAME, true);
  181. GfaMbFifoReset(pMst->hFifoRX, true);
  182. pMst->nRxErr = GFA_MB_MST_ERROR_INVALID_SLAVE_ID;
  183. pMst->state = MB_RTU_MST_ReportError;
  184. break;
  185. }
  186. pMst->adu.slaveID = b;
  187. pMst->state = MB_RTU_MST_RxFunc;
  188. _CharTimerTrigger(pMst);
  189. // fall through to next state
  190. case MB_RTU_MST_RxFunc:
  191. _PeekStateChange(pMst);
  192. if(!GfaMbFifoPop(pMst->hFifoRX, &b, true))
  193. {
  194. if( GfaMbFifoMatchFlags(pMst->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true) ||
  195. _TimerElapsed(pMst))
  196. {
  197. pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_CHAR_TIMEOUT;
  198. pMst->state = MB_RTU_MST_ReportError;
  199. }
  200. break;
  201. }
  202. else if(b & MB_FUNC_ERROR_FLAG)
  203. {
  204. pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_ERROR;
  205. pMst->adu.pdu.func = b;
  206. pMst->state = MB_RTU_MST_RxError;
  207. break;
  208. }
  209. else if(b != pMst->curFunc)
  210. {
  211. pMst->nRxErr = GFA_MB_MST_ERROR_INVALID_FUNCTION;
  212. pMst->state = MB_RTU_MST_ReportError;
  213. break;
  214. }
  215. else
  216. {
  217. pMst->adu.pdu.func = b;
  218. pMst->nCbRx = 0;
  219. pMst->state = MB_RTU_MST_RxData;
  220. _CharTimerTrigger(pMst);
  221. // fall through to next state
  222. }
  223. case MB_RTU_MST_RxData:
  224. _PeekStateChange(pMst);
  225. while(pMst->nCbRx < pMst->nCbDataExpected)
  226. {
  227. if(GfaMbFifoPop(pMst->hFifoRX, &b, true))
  228. {
  229. pMst->adu.pdu.b[pMst->nCbRx++] = b;
  230. _CharTimerTrigger(pMst);
  231. }
  232. else
  233. {
  234. if( GfaMbFifoMatchFlags(pMst->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true) ||
  235. _TimerElapsed(pMst))
  236. {
  237. pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_CHAR_TIMEOUT;
  238. pMst->state = MB_RTU_MST_ReportError;
  239. }
  240. break;
  241. }
  242. }
  243. if(pMst->nCbRx == pMst->nCbDataExpected)
  244. {
  245. pMst->nCbRx = 0;
  246. pMst->state = MB_RTU_MST_RxCRC;
  247. _CharTimerTrigger(pMst);
  248. // fall through to next state
  249. }
  250. else
  251. break;
  252. case MB_RTU_MST_RxCRC:
  253. _PeekStateChange(pMst);
  254. while(pMst->nCbRx < sizeof(uint16_t))
  255. {
  256. if(GfaMbFifoPop(pMst->hFifoRX, &b, true))
  257. {
  258. pMst->adu.pdu.b[pMst->nCbDataExpected + pMst->nCbRx++] = b;
  259. _CharTimerTrigger(pMst);
  260. }
  261. else
  262. {
  263. if( GfaMbFifoMatchFlags(pMst->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true) ||
  264. _TimerElapsed(pMst))
  265. {
  266. pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_CHAR_TIMEOUT;
  267. pMst->state = MB_RTU_MST_ReportError;
  268. }
  269. break;
  270. }
  271. }
  272. if(pMst->nCbRx == sizeof(uint16_t))
  273. {
  274. pMst->nCbRx = 0;
  275. pMst->state = MB_RTU_MST_RxFinalize;
  276. // fall through to next state
  277. }
  278. else
  279. break;
  280. case MB_RTU_MST_RxFinalize:
  281. _PeekStateChange(pMst);
  282. _FrameTimerTrigger(pMst);
  283. if(_ValidateADU(pMst))
  284. {
  285. if(pMst->appItf.pfnRxEnd)
  286. (*pMst->appItf.pfnRxEnd)(pMst->nTID);
  287. (*pMst->pfnRawReqComplete)(pMst->nTID, pMst->curSlaveID, pMst->nRxErr, &pMst->adu, pMst->nCbDataExpected, pMst->pParam);
  288. pMst->state = MB_RTU_MST_Idle;
  289. break;
  290. }
  291. pMst->state = MB_RTU_MST_ReportError;
  292. break;
  293. case MB_RTU_MST_RxError:
  294. _PeekStateChange(pMst);
  295. if(!GfaMbFifoPop(pMst->hFifoRX, &b, true))
  296. {
  297. if( GfaMbFifoMatchFlags(pMst->hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, true) ||
  298. _TimerElapsed(pMst))
  299. {
  300. pMst->nRxErr = GFA_MB_MST_ERROR_SLAVE_CHAR_TIMEOUT;
  301. pMst->state = MB_RTU_MST_ReportError;
  302. }
  303. break;
  304. }
  305. pMst->adu.pdu.b[0] = b;
  306. pMst->nCbDataExpected = 1;
  307. pMst->state = MB_RTU_MST_RxCRC;
  308. _CharTimerTrigger(pMst);
  309. break;
  310. case MB_RTU_MST_ReportError:
  311. _PeekStateChange(pMst);
  312. _FrameTimerTrigger(pMst);
  313. if(pMst->appItf.pfnRxEnd)
  314. (*pMst->appItf.pfnRxEnd)(pMst->nTID);
  315. (*pMst->pfnRawReqComplete)(pMst->nTID, pMst->curSlaveID, pMst->nRxErr, NULL, 0, pMst->pParam);
  316. pMst->state = MB_RTU_MST_Idle;
  317. break;
  318. default:
  319. return false;
  320. }
  321. return true;
  322. }
  323. GFA_MODBUS_RTU_MST_STATES GfaModbusRTUMstGetState(HMBRTUMST hMbMst)
  324. {
  325. LPGFA_MODBUS_RTU_MASTER pMst = (LPGFA_MODBUS_RTU_MASTER)hMbMst;
  326. if(!pMst)
  327. return MB_RTU_MST_Void;
  328. return pMst->state;
  329. }
  330. /////////////////////////////////////////////////////////////////////////////
  331. /////////////////////////////////////////////////////////////////////////////
  332. /////////////////////////////////////////////////////////////////////////////
  333. static void _OnRawReadRegistersComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, LPCMODBUS_RTU_ADU padu, size_t nCbData, void *pParam)
  334. {
  335. if(pParam)
  336. {
  337. PFN_GFA_MASTER_READ_REGISTERS_COMPLETE pfnReadRegsComplete = (PFN_GFA_MASTER_READ_REGISTERS_COMPLETE)pParam;
  338. uint16_t regs[MODBUS_MAX_READ_REGISTERS];
  339. const void *pRegs = NULL;
  340. size_t nCntRegs = 0;
  341. if(err)
  342. {
  343. if(err == GFA_MB_MST_ERROR_SLAVE_ERROR && padu)
  344. err |= ((uint16_t)padu->pdu.b[0] << 8);
  345. }
  346. else
  347. {
  348. if((nCntRegs = (size_t)padu->pdu.b[0] / sizeof(uint16_t)) <= MODBUS_MAX_READ_REGISTERS)
  349. {
  350. GfaBufCpyUnaligned_uint16(regs, &padu->pdu.b[1], nCntRegs);
  351. pRegs = regs;
  352. }
  353. else
  354. {
  355. pRegs = NULL;
  356. nCntRegs = 0;
  357. err = GFA_MB_MST_ERROR_SLAVE_INVALID_DATA;
  358. }
  359. }
  360. (*pfnReadRegsComplete)(nTID, nSlvID, err, pRegs, nCntRegs);
  361. }
  362. }
  363. /////////////////////////////////////////////////////////////////////////////
  364. static void _OnRawWriteRegistersComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, LPCMODBUS_RTU_ADU padu, size_t nCbData, void *pParam)
  365. {
  366. if(pParam)
  367. {
  368. PFN_GFA_MASTER_WRITE_REGISTERS_COMPLETE pfnWriteRegsComplete = (PFN_GFA_MASTER_WRITE_REGISTERS_COMPLETE)pParam;
  369. uint16_t nStart = 0, nWritten = 0;
  370. if(err)
  371. {
  372. if(err == GFA_MB_MST_ERROR_SLAVE_ERROR && padu)
  373. err |= ((uint16_t)padu->pdu.b[0] << 8);
  374. }
  375. else
  376. {
  377. nStart = GfaBufGetUnaligned_uint16(padu->pdu.b);
  378. nWritten = GfaBufGetUnaligned_uint16(&padu->pdu.b[2]);
  379. }
  380. (*pfnWriteRegsComplete)(nTID, nSlvID, err, nStart, nWritten);
  381. }
  382. }
  383. /////////////////////////////////////////////////////////////////////////////
  384. static void _OnRawPresetSingleRegisterComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, LPCMODBUS_RTU_ADU padu, size_t nCbData, void *pParam)
  385. {
  386. if(pParam)
  387. {
  388. PFN_GFA_MASTER_PRESET_SINGLE_REGISTER_COMPLETE pfnPresetRegComplete = (PFN_GFA_MASTER_PRESET_SINGLE_REGISTER_COMPLETE)pParam;
  389. if(err)
  390. {
  391. if(err == GFA_MB_MST_ERROR_SLAVE_ERROR && padu)
  392. err |= ((uint16_t)padu->pdu.b[0] << 8);
  393. }
  394. (*pfnPresetRegComplete)(nTID, nSlvID, err);
  395. }
  396. }
  397. /////////////////////////////////////////////////////////////////////////////
  398. static void _OnRawDiagnosisComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, LPCMODBUS_RTU_ADU padu, size_t nCbData, void *pParam)
  399. {
  400. if(pParam)
  401. {
  402. PFN_GFA_MASTER_DIAGNOSIS_COMPLETE pfnDiagComplete = (PFN_GFA_MASTER_DIAGNOSIS_COMPLETE)pParam;
  403. uint16_t nSubFunc = 0, nData = 0;
  404. if(err)
  405. {
  406. if(err == GFA_MB_MST_ERROR_SLAVE_ERROR && padu)
  407. err |= ((uint16_t)padu->pdu.b[0] << 8);
  408. }
  409. else
  410. {
  411. nSubFunc = GfaBufGetUnaligned_uint16(padu->pdu.b);
  412. nData = GfaBufGetUnaligned_uint16(&padu->pdu.b[2]);
  413. }
  414. (*pfnDiagComplete)(nTID, nSlvID, err, nSubFunc, nData);
  415. }
  416. }
  417. /////////////////////////////////////////////////////////////////////////////
  418. static void _OnRawReportSlaveIDComplete(uint32_t nTID, uint8_t nSlvID, uint16_t err, LPCMODBUS_RTU_ADU padu, size_t nCbData, void *pParam)
  419. {
  420. if(pParam)
  421. {
  422. PFN_GFA_MASTER_REPORT_SLAVE_ID_COMPLETE pfnRepSlvIDComplete = (PFN_GFA_MASTER_REPORT_SLAVE_ID_COMPLETE)pParam;
  423. const void *pData = NULL;
  424. size_t nData = 0;
  425. if(err)
  426. {
  427. if(err == GFA_MB_MST_ERROR_SLAVE_ERROR && padu)
  428. err |= ((uint16_t)padu->pdu.b[0] << 8);
  429. }
  430. else
  431. {
  432. pData = &padu->pdu.b[1];
  433. nData = padu->pdu.b[0];
  434. }
  435. (*pfnRepSlvIDComplete)(nTID, nSlvID, err, pData, nData);
  436. }
  437. }
  438. /////////////////////////////////////////////////////////////////////////////
  439. static size_t _SubFunctionResponseLength(uint16_t nSubFunc)
  440. {
  441. size_t nRet = 0;
  442. switch(nSubFunc)
  443. {
  444. case MB_SUBFUNC_RETURN_QUERY_DATA:
  445. case MB_SUBFUNC_RESTART_COMM_OPTION:
  446. case MB_SUBFUNC_RETURN_DIAGNOSTIC_REGISTER:
  447. case MB_SUBFUNC_CLEAR_CTRS_AND_DIAGNOSTIC_REG:
  448. case MB_SUBFUNC_RETURN_BUS_MESSAGE_COUNT:
  449. case MB_SUBFUNC_RETURN_BUS_COMM_ERROR_COUNT:
  450. case MB_SUBFUNC_RETURN_BUS_EXCEPTION_ERROR_COUNT:
  451. case MB_SUBFUNC_RETURN_SLAVE_MESSAGE_COUNT:
  452. case MB_SUBFUNC_RETURN_SLAVE_NO_RESPONSE_COUNT:
  453. case MB_SUBFUNC_RETURN_SLAVE_NAK_COUNT:
  454. case MB_SUBFUNC_RETURN_SLAVE_BUSY_COUNT:
  455. case MB_SUBFUNC_RETURN_BUS_CHAR_OVERRUN_COUNT:
  456. case MB_SUBFUNC_RETURN_OVERRUN_ERROR_COUNT:
  457. case MB_SUBFUNC_CLEAR_OVERRUN_COUNTER_AND_FLAG:
  458. nRet = 4;
  459. break;
  460. // case MB_SUBFUNC_FORCE_LISTEN_ONLY_MODE:
  461. default:
  462. nRet = (size_t)-1;
  463. break;
  464. }
  465. return nRet;
  466. }
  467. /////////////////////////////////////////////////////////////////////////////
  468. /////////////////////////////////////////////////////////////////////////////
  469. /////////////////////////////////////////////////////////////////////////////
  470. 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)
  471. {
  472. uint16_t nCRC;
  473. LPGFA_MODBUS_RTU_MASTER pMst = (LPGFA_MODBUS_RTU_MASTER)hMbMst;
  474. if(!pMst || nCbData > MODBUS_MAX_DATA_PAYLOAD || nCbDataExpected > MODBUS_MAX_DATA_PAYLOAD || !pfnRawReqComplete)
  475. return false;
  476. if(!nSlvID || nSlvID > MODBUS_MAX_SLAVE_ID)
  477. return false;
  478. if(pMst->state != MB_RTU_MST_Idle)
  479. return false;
  480. pMst->nTID = nTID;
  481. pMst->curSlaveID = nSlvID;
  482. pMst->curFunc = nFunc;
  483. pMst->nCbDataExpected = nCbDataExpected;
  484. pMst->pfnRawReqComplete = pfnRawReqComplete;
  485. pMst->pParam = pParam;
  486. pMst->nRxErr = 0;
  487. GfaMbFifoReset(pMst->hFifoTX, false);
  488. GfaMbFifoReset(pMst->hFifoRX, false);
  489. GfaMbFifoPush(pMst->hFifoTX, nSlvID, false);
  490. GfaMbFifoPush(pMst->hFifoTX, nFunc, false);
  491. if(pData && nCbData)
  492. GfaMbFifoWrite(pMst->hFifoTX, pData, nCbData, false);
  493. nCRC = GfaMbFifoCalcCRC(pMst->hFifoTX, false);
  494. GfaMbFifoWrite(pMst->hFifoTX, &nCRC, sizeof(nCRC), false);
  495. pMst->state = MB_RTU_MST_TxStart;
  496. return true;
  497. }
  498. bool GfaModbusRTUMstReadHoldingRegisters(HMBRTUMST hMbMst, uint32_t nTID, uint8_t nSlvID, uint16_t nRegStart, uint16_t nRegCount, PFN_GFA_MASTER_READ_REGISTERS_COMPLETE pfnReadRegsComplete)
  499. {
  500. uint8_t buf[4];
  501. if(!pfnReadRegsComplete)
  502. return false;
  503. GfaBufSetUnaligned_uint16(buf, nRegStart);
  504. GfaBufSetUnaligned_uint16(&buf[2], nRegCount);
  505. return GfaModbusRTUMstSendRawRequest(hMbMst, nTID, nSlvID, MB_FUNC_READ_HOLDING_REGISTERS, buf, sizeof(buf), 1 + nRegCount * sizeof(uint16_t), _OnRawReadRegistersComplete, pfnReadRegsComplete);
  506. }
  507. /////////////////////////////////////////////////////////////////////////////
  508. bool GfaModbusRTUMstReadInputRegisters(HMBRTUMST hMbMst, uint32_t nTID, uint8_t nSlvID, uint16_t nRegStart, uint16_t nRegCount, PFN_GFA_MASTER_READ_REGISTERS_COMPLETE pfnReadRegsComplete)
  509. {
  510. uint8_t buf[4];
  511. if(!pfnReadRegsComplete)
  512. return false;
  513. GfaBufSetUnaligned_uint16(buf, nRegStart);
  514. GfaBufSetUnaligned_uint16(&buf[2], nRegCount);
  515. return GfaModbusRTUMstSendRawRequest(hMbMst, nTID, nSlvID, MB_FUNC_READ_INPUT_REGISTERS, buf, sizeof(buf), 1 + nRegCount * sizeof(uint16_t), _OnRawReadRegistersComplete, pfnReadRegsComplete);
  516. }
  517. /////////////////////////////////////////////////////////////////////////////
  518. 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)
  519. {
  520. uint8_t buf[MODBUS_MAX_WRITE_REGISTERS * sizeof(uint16_t)];
  521. const uint8_t *pData = (const uint8_t*)pRegData;
  522. size_t nCbData = 0;
  523. if(!pfnWriteRegsComplete)
  524. return false;
  525. if(nRegCount > MODBUS_MAX_WRITE_REGISTERS)
  526. return false;
  527. GfaBufSetUnaligned_uint16(&buf[nCbData], nRegStart);
  528. nCbData += 2;
  529. GfaBufSetUnaligned_uint16(&buf[nCbData], nRegCount);
  530. nCbData += 2;
  531. buf[nCbData++] = (uint8_t)(nRegCount * sizeof(uint16_t));
  532. GfaBufCpyUnaligned_uint16(&buf[nCbData], pData, nRegCount);
  533. nCbData += nRegCount * sizeof(uint16_t);
  534. return GfaModbusRTUMstSendRawRequest(hMbMst, nTID, nSlvID, MB_FUNC_WRITE_MULTIPLE_REGISTERS, buf, nCbData, 2 * sizeof(uint16_t), _OnRawWriteRegistersComplete, pfnWriteRegsComplete);
  535. }
  536. /////////////////////////////////////////////////////////////////////////////
  537. bool GfaModbusRTUMstPresetSingleRegister(HMBRTUMST hMbMst, uint32_t nTID, uint8_t nSlvID, uint16_t nRegAddr, uint16_t nRegVal, PFN_GFA_MASTER_PRESET_SINGLE_REGISTER_COMPLETE pfnPresetRegComplete)
  538. {
  539. uint8_t buf[4];
  540. if(!pfnPresetRegComplete)
  541. return false;
  542. GfaBufSetUnaligned_uint16(buf, nRegAddr);
  543. GfaBufSetUnaligned_uint16(&buf[2], nRegVal);
  544. return GfaModbusRTUMstSendRawRequest(hMbMst, nTID, nSlvID, MB_FUNC_PRESET_SINGLE_REGISTER, buf, sizeof(buf), 4, _OnRawPresetSingleRegisterComplete, pfnPresetRegComplete);
  545. }
  546. bool GfaModbusRTUMstDiagnosis(HMBRTUMST hMbMst, uint32_t nTID, uint8_t nSlvID, uint16_t nSubFunc, uint16_t nData, PFN_GFA_MASTER_DIAGNOSIS_COMPLETE pfnDiagComplete)
  547. {
  548. uint8_t buf[4];
  549. if(!pfnDiagComplete)
  550. return false;
  551. GfaBufSetUnaligned_uint16(buf, nSubFunc);
  552. GfaBufSetUnaligned_uint16(&buf[2], nData);
  553. size_t nResponseLength = _SubFunctionResponseLength(nSubFunc);
  554. if(nResponseLength == (size_t)-1)
  555. return false;
  556. return GfaModbusRTUMstSendRawRequest(hMbMst, nTID, nSlvID, MB_FUNC_DIAGNOSTIC, buf, sizeof(buf), nResponseLength, _OnRawDiagnosisComplete, pfnDiagComplete);
  557. }
  558. /////////////////////////////////////////////////////////////////////////////
  559. bool GfaModbusRTUMstReportSlaveID(HMBRTUMST hMbMst, uint32_t nTID, uint8_t nSlvID, size_t nCbDataExpected, PFN_GFA_MASTER_REPORT_SLAVE_ID_COMPLETE pfnRepSlvIDComplete)
  560. {
  561. if(!pfnRepSlvIDComplete)
  562. return false;
  563. return GfaModbusRTUMstSendRawRequest(hMbMst, nTID, nSlvID, MB_FUNC_REPORT_SLAVE_ID, NULL, 0, nCbDataExpected, _OnRawReportSlaveIDComplete, pfnRepSlvIDComplete);
  564. }