You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

571 regels
20 KiB

  1. #include "plsr_modbus_control.h"
  2. #include "modbus_data_store.h"
  3. #include "plsr_address_map.h"
  4. #include "plsr_core.h"
  5. #include "plsr_job.h"
  6. #include "plsr_modbus_data.h"
  7. #include <stddef.h>
  8. #include <string.h>
  9. #define PLSR_MODBUS_MAGIC_LOW (0x504CU)
  10. #define PLSR_MODBUS_MAGIC_HIGH (0x5352U)
  11. #define PLSR_MODBUS_CAPABILITIES (0x0007U)
  12. #define PLSR_MODBUS_CALL_REQUEST_WORDS (16UL)
  13. #define PLSR_MODBUS_CALL_RESPONSE_WORDS (12UL)
  14. #define PLSR_MODBUS_COMMAND_REQUEST_WORDS (8UL)
  15. #define PLSR_MODBUS_COMMAND_RESPONSE_WORDS (8UL)
  16. #define PLSR_MODBUS_S0_HEADER_WORDS (10UL)
  17. #define PLSR_MODBUS_S0_SEGMENT_WORDS (10UL)
  18. #define PLSR_MODBUS_S1_WORDS (4UL)
  19. #define PLSR_MODBUS_HASH_OFFSET (2166136261UL)
  20. #define PLSR_MODBUS_HASH_PRIME (16777619UL)
  21. typedef struct
  22. {
  23. PLSR_CALL call;
  24. uint32_t fingerprint;
  25. uint8_t valid;
  26. } PLSR_MODBUS_COMMITTED_CALL;
  27. static uint16_t PlsrModbusBaseAddress;
  28. static uint8_t PlsrModbusEnabled;
  29. static uint32_t PlsrModbusLastCallRequestSequence;
  30. static uint32_t PlsrModbusLastCommandRequestSequence;
  31. static uint32_t PlsrModbusStatusGeneration[PLSR_AXIS_COUNT];
  32. static PLSR_MODBUS_COMMITTED_CALL PlsrModbusCommitted[PLSR_AXIS_COUNT];
  33. static uint16_t PlsrModbusStatusWords[PLSR_AXIS_COUNT]
  34. [PLSR_MODBUS_AXIS_STATUS_WORDS];
  35. static const uint16_t PlsrModbusZeroWindow[PLSR_MODBUS_WINDOW_WORDS] = {0U};
  36. static void PlsrModbusPutU32(uint16_t *words,
  37. uint32_t offset,
  38. uint32_t value)
  39. {
  40. words[offset] = (uint16_t)(value & 0xFFFFUL);
  41. words[offset + 1UL] = (uint16_t)(value >> 16U);
  42. }
  43. static void PlsrModbusPutU64(uint16_t *words,
  44. uint32_t offset,
  45. uint64_t value)
  46. {
  47. words[offset] = (uint16_t)(value & 0xFFFFULL);
  48. words[offset + 1UL] = (uint16_t)((value >> 16U) & 0xFFFFULL);
  49. words[offset + 2UL] = (uint16_t)((value >> 32U) & 0xFFFFULL);
  50. words[offset + 3UL] = (uint16_t)(value >> 48U);
  51. }
  52. static uint32_t PlsrModbusGetU32(const uint16_t *words, uint32_t offset)
  53. {
  54. return ((uint32_t)words[offset + 1UL] << 16U) | words[offset];
  55. }
  56. static uint64_t PlsrModbusGetU64(const uint16_t *words, uint32_t offset)
  57. {
  58. return ((uint64_t)words[offset + 3UL] << 48U)
  59. | ((uint64_t)words[offset + 2UL] << 32U)
  60. | ((uint64_t)words[offset + 1UL] << 16U)
  61. | words[offset];
  62. }
  63. static uint8_t PlsrModbusReadWords(uint32_t offset,
  64. uint16_t *words,
  65. uint32_t wordCount)
  66. {
  67. uint32_t index;
  68. if (words == NULL)
  69. {
  70. return 0U;
  71. }
  72. for (index = 0UL; index < wordCount; index++)
  73. {
  74. if (ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  75. (uint32_t)PlsrModbusBaseAddress + offset + index,
  76. &words[index]) == 0U)
  77. {
  78. return 0U;
  79. }
  80. }
  81. return 1U;
  82. }
  83. static uint8_t PlsrModbusRangesOverlap(uint32_t firstA,
  84. uint32_t countA,
  85. uint32_t firstB,
  86. uint32_t countB)
  87. {
  88. return ((firstA < (firstB + countB)) && (firstB < (firstA + countA)))
  89. ? 1U
  90. : 0U;
  91. }
  92. static uint32_t PlsrModbusHashWord(uint32_t hash, uint16_t value)
  93. {
  94. hash ^= (uint8_t)(value & 0x00FFU);
  95. hash *= PLSR_MODBUS_HASH_PRIME;
  96. hash ^= (uint8_t)(value >> 8U);
  97. hash *= PLSR_MODBUS_HASH_PRIME;
  98. return hash;
  99. }
  100. static uint32_t PlsrModbusHashU32(uint32_t hash, uint32_t value)
  101. {
  102. hash = PlsrModbusHashWord(hash, (uint16_t)(value & 0xFFFFUL));
  103. return PlsrModbusHashWord(hash, (uint16_t)(value >> 16U));
  104. }
  105. static PLSR_RESULT PlsrModbusFingerprintCall(const PLSR_CALL *call,
  106. uint32_t *fingerprint)
  107. {
  108. uint16_t word;
  109. int32_t segmentCount;
  110. uint32_t s0Words;
  111. uint32_t index;
  112. uint32_t hash = PLSR_MODBUS_HASH_OFFSET;
  113. if ((call == NULL) || (fingerprint == NULL)
  114. || (call->source.readDword == NULL)
  115. || (call->source.readWord == NULL)
  116. || (call->source.validateWords == NULL))
  117. {
  118. return PLSR_RESULT_INVALID_ARGUMENT;
  119. }
  120. if (call->source.readDword(call->source.context,
  121. call->s0.device,
  122. call->s0.address,
  123. &segmentCount) == 0U)
  124. {
  125. return PLSR_RESULT_DATA_ACCESS;
  126. }
  127. if ((segmentCount < 1) || (segmentCount > (int32_t)PLSR_MAX_SEGMENTS))
  128. {
  129. return PLSR_RESULT_SEGMENT_OVERFLOW;
  130. }
  131. s0Words = PLSR_MODBUS_S0_HEADER_WORDS
  132. + (uint32_t)segmentCount * PLSR_MODBUS_S0_SEGMENT_WORDS;
  133. if ((call->source.validateWords(call->source.context,
  134. call->s0.device,
  135. call->s0.address,
  136. s0Words) == 0U)
  137. || (call->source.validateWords(call->source.context,
  138. call->s1.device,
  139. call->s1.address,
  140. PLSR_MODBUS_S1_WORDS) == 0U))
  141. {
  142. return PLSR_RESULT_DATA_ACCESS;
  143. }
  144. if (((call->s0.device == PLSR_DEVICE_D)
  145. && (PlsrModbusRangesOverlap(call->s0.address,
  146. s0Words,
  147. PlsrModbusBaseAddress,
  148. PLSR_MODBUS_WINDOW_WORDS) != 0U))
  149. || ((call->s1.device == PLSR_DEVICE_D)
  150. && (PlsrModbusRangesOverlap(call->s1.address,
  151. PLSR_MODBUS_S1_WORDS,
  152. PlsrModbusBaseAddress,
  153. PLSR_MODBUS_WINDOW_WORDS) != 0U)))
  154. {
  155. return PLSR_RESULT_BLOCK_OVERLAP;
  156. }
  157. hash = PlsrModbusHashWord(hash, (uint16_t)call->s0.device);
  158. hash = PlsrModbusHashU32(hash, call->s0.address);
  159. for (index = 0UL; index < s0Words; index++)
  160. {
  161. if (call->source.readWord(call->source.context,
  162. call->s0.device,
  163. call->s0.address + index,
  164. &word) == 0U)
  165. {
  166. return PLSR_RESULT_DATA_ACCESS;
  167. }
  168. hash = PlsrModbusHashWord(hash, word);
  169. }
  170. hash = PlsrModbusHashWord(hash, (uint16_t)call->s1.device);
  171. hash = PlsrModbusHashU32(hash, call->s1.address);
  172. for (index = 0UL; index < PLSR_MODBUS_S1_WORDS; index++)
  173. {
  174. if (call->source.readWord(call->source.context,
  175. call->s1.device,
  176. call->s1.address + index,
  177. &word) == 0U)
  178. {
  179. return PLSR_RESULT_DATA_ACCESS;
  180. }
  181. hash = PlsrModbusHashWord(hash, word);
  182. }
  183. hash = PlsrModbusHashWord(hash, (uint16_t)call->s2.type);
  184. hash = PlsrModbusHashWord(hash, (uint16_t)call->s2.data.device);
  185. hash = PlsrModbusHashU32(hash, call->s2.data.address);
  186. hash = PlsrModbusHashU32(hash, (uint32_t)call->s2.constant);
  187. if (call->s2.type == PLSR_OPERAND_DATA)
  188. {
  189. for (index = 0UL; index < 2UL; index++)
  190. {
  191. if (call->source.readWord(call->source.context,
  192. call->s2.data.device,
  193. call->s2.data.address + index,
  194. &word) == 0U)
  195. {
  196. return PLSR_RESULT_DATA_ACCESS;
  197. }
  198. hash = PlsrModbusHashWord(hash, word);
  199. }
  200. }
  201. hash = PlsrModbusHashWord(hash, call->dAxis);
  202. hash = PlsrModbusHashWord(hash, call->outputModeOverride);
  203. *fingerprint = hash;
  204. return PLSR_RESULT_OK;
  205. }
  206. static PLSR_RESULT PlsrModbusBuildCall(const uint16_t *request,
  207. PLSR_CALL *call)
  208. {
  209. uint16_t s2Type;
  210. uint16_t outputMode;
  211. if ((request == NULL) || (call == NULL))
  212. {
  213. return PLSR_RESULT_INVALID_ARGUMENT;
  214. }
  215. s2Type = request[8UL];
  216. outputMode = request[13UL];
  217. if ((request[2UL] > (uint16_t)PLSR_DEVICE_FD)
  218. || (request[5UL] > (uint16_t)PLSR_DEVICE_FD)
  219. || (s2Type > (uint16_t)PLSR_OPERAND_DATA)
  220. || ((s2Type == (uint16_t)PLSR_OPERAND_DATA)
  221. && (request[9UL] > (uint16_t)PLSR_DEVICE_FD))
  222. || (request[12UL] >= PLSR_AXIS_COUNT)
  223. || ((outputMode > (uint16_t)PLSR_OUTPUT_CW_CCW)
  224. && (outputMode != PLSR_OUTPUT_MODE_FROM_SFD)))
  225. {
  226. return PLSR_RESULT_INVALID_ARGUMENT;
  227. }
  228. (void)memset(call, 0, sizeof(*call));
  229. call->sequence = PlsrModbusGetU32(request, 0UL);
  230. call->s0.device = (PLSR_DEVICE_TYPE)request[2UL];
  231. call->s0.address = PlsrModbusGetU32(request, 3UL);
  232. call->s1.device = (PLSR_DEVICE_TYPE)request[5UL];
  233. call->s1.address = PlsrModbusGetU32(request, 6UL);
  234. call->s2.type = (PLSR_OPERAND_TYPE)s2Type;
  235. call->s2.data.device = (PLSR_DEVICE_TYPE)request[9UL];
  236. call->s2.data.address = PlsrModbusGetU32(request, 10UL);
  237. call->s2.constant = (int32_t)PlsrModbusGetU32(request, 10UL);
  238. call->dAxis = (uint8_t)request[12UL];
  239. call->outputModeOverride = (uint8_t)outputMode;
  240. PlsrModbusDataSourceInit(&call->source);
  241. return PLSR_RESULT_OK;
  242. }
  243. static void PlsrModbusPublishCallResponse(uint32_t sequence,
  244. uint16_t operation,
  245. PLSR_RESULT result,
  246. const PLSR_PARSE_DETAIL *detail,
  247. uint8_t committed)
  248. {
  249. uint16_t response[PLSR_MODBUS_CALL_RESPONSE_WORDS] = {0U};
  250. PlsrModbusPutU32(response, 0UL, sequence);
  251. response[2UL] = operation;
  252. response[3UL] = (uint16_t)result;
  253. if (detail != NULL)
  254. {
  255. response[4UL] = (uint16_t)detail->result;
  256. response[5UL] = (uint16_t)detail->block;
  257. PlsrModbusPutU32(response, 6UL, detail->address);
  258. PlsrModbusPutU32(response, 8UL, (uint32_t)detail->value);
  259. response[10UL] = detail->segment;
  260. }
  261. response[11UL] = committed;
  262. (void)ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  263. (uint32_t)PlsrModbusBaseAddress
  264. + PLSR_MODBUS_CALL_RESPONSE_OFFSET,
  265. response,
  266. PLSR_MODBUS_CALL_RESPONSE_WORDS);
  267. }
  268. static void PlsrModbusHandleCallRequest(void)
  269. {
  270. uint16_t request[PLSR_MODBUS_CALL_REQUEST_WORDS];
  271. PLSR_CALL call;
  272. PLSR_PARSE_DETAIL detail;
  273. PLSR_RESULT result;
  274. uint32_t sequence;
  275. uint32_t fingerprint;
  276. uint16_t operation;
  277. uint8_t axis = 0U;
  278. if (PlsrModbusReadWords(PLSR_MODBUS_CALL_REQUEST_OFFSET,
  279. request,
  280. PLSR_MODBUS_CALL_REQUEST_WORDS) == 0U)
  281. {
  282. return;
  283. }
  284. sequence = PlsrModbusGetU32(request, 0UL);
  285. if ((sequence == 0UL) || (sequence == PlsrModbusLastCallRequestSequence))
  286. {
  287. return;
  288. }
  289. PlsrModbusLastCallRequestSequence = sequence;
  290. operation = request[14UL];
  291. (void)memset(&detail, 0, sizeof(detail));
  292. result = PlsrModbusBuildCall(request, &call);
  293. if (result == PLSR_RESULT_OK)
  294. {
  295. axis = call.dAxis;
  296. }
  297. if ((result == PLSR_RESULT_OK) && (operation == PLSR_MODBUS_CALL_COMMIT))
  298. {
  299. result = PlsrValidateCall(&call, &detail);
  300. if (result == PLSR_RESULT_OK)
  301. {
  302. result = PlsrModbusFingerprintCall(&call, &fingerprint);
  303. }
  304. if (result == PLSR_RESULT_OK)
  305. {
  306. PlsrModbusCommitted[axis].call = call;
  307. PlsrModbusCommitted[axis].fingerprint = fingerprint;
  308. PlsrModbusCommitted[axis].valid = 1U;
  309. }
  310. else
  311. {
  312. PlsrModbusCommitted[axis].valid = 0U;
  313. }
  314. }
  315. else if ((result == PLSR_RESULT_OK)
  316. && (operation == PLSR_MODBUS_CALL_START))
  317. {
  318. if (PlsrModbusCommitted[axis].valid == 0U)
  319. {
  320. result = PLSR_RESULT_INVALID_STATE;
  321. }
  322. else
  323. {
  324. result = PlsrModbusFingerprintCall(
  325. &PlsrModbusCommitted[axis].call,
  326. &fingerprint);
  327. if ((result == PLSR_RESULT_OK)
  328. && (fingerprint != PlsrModbusCommitted[axis].fingerprint))
  329. {
  330. result = PLSR_RESULT_BUSY;
  331. }
  332. if (result == PLSR_RESULT_OK)
  333. {
  334. result = PlsrValidateCall(&PlsrModbusCommitted[axis].call,
  335. &detail);
  336. }
  337. if (result == PLSR_RESULT_OK)
  338. {
  339. PlsrModbusCommitted[axis].call.sequence = sequence;
  340. result = PlsrPostCall(&PlsrModbusCommitted[axis].call);
  341. }
  342. }
  343. }
  344. else if (result == PLSR_RESULT_OK)
  345. {
  346. result = PLSR_RESULT_INVALID_ARGUMENT;
  347. }
  348. PlsrModbusPublishCallResponse(
  349. sequence,
  350. operation,
  351. result,
  352. &detail,
  353. (axis < PLSR_AXIS_COUNT) ? PlsrModbusCommitted[axis].valid : 0U);
  354. }
  355. static void PlsrModbusPublishCommandResponse(uint32_t sequence,
  356. uint16_t opcode,
  357. uint16_t axis,
  358. PLSR_RESULT result)
  359. {
  360. uint16_t response[PLSR_MODBUS_COMMAND_RESPONSE_WORDS] = {0U};
  361. PlsrModbusPutU32(response, 0UL, sequence);
  362. response[2UL] = opcode;
  363. response[3UL] = axis;
  364. response[4UL] = (uint16_t)result;
  365. (void)ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  366. (uint32_t)PlsrModbusBaseAddress
  367. + PLSR_MODBUS_COMMAND_RESPONSE_OFFSET,
  368. response,
  369. PLSR_MODBUS_COMMAND_RESPONSE_WORDS);
  370. }
  371. static void PlsrModbusHandleCommandRequest(void)
  372. {
  373. uint16_t request[PLSR_MODBUS_COMMAND_REQUEST_WORDS];
  374. PLSR_COMMAND command;
  375. PLSR_RESULT result;
  376. uint32_t sequence;
  377. if (PlsrModbusReadWords(PLSR_MODBUS_COMMAND_REQUEST_OFFSET,
  378. request,
  379. PLSR_MODBUS_COMMAND_REQUEST_WORDS) == 0U)
  380. {
  381. return;
  382. }
  383. sequence = PlsrModbusGetU32(request, 0UL);
  384. if ((sequence == 0UL)
  385. || (sequence == PlsrModbusLastCommandRequestSequence))
  386. {
  387. return;
  388. }
  389. PlsrModbusLastCommandRequestSequence = sequence;
  390. (void)memset(&command, 0, sizeof(command));
  391. if ((request[2UL] > (uint16_t)PLSR_CMD_SELF_TEST)
  392. || (request[2UL] == (uint16_t)PLSR_CMD_START)
  393. || (request[3UL] >= PLSR_AXIS_COUNT))
  394. {
  395. result = PLSR_RESULT_INVALID_ARGUMENT;
  396. }
  397. else
  398. {
  399. command.sequence = sequence;
  400. command.opcode = (PLSR_COMMAND_OPCODE)request[2UL];
  401. command.axis = (uint8_t)request[3UL];
  402. command.argument = (int64_t)PlsrModbusGetU64(request, 4UL);
  403. result = PlsrPostCommand(&command);
  404. }
  405. PlsrModbusPublishCommandResponse(sequence,
  406. request[2UL],
  407. request[3UL],
  408. result);
  409. }
  410. static void PlsrModbusPublishAxisStatus(uint8_t axis)
  411. {
  412. PLSR_STATUS status;
  413. uint16_t *words = PlsrModbusStatusWords[axis];
  414. uint32_t flags = 0UL;
  415. uint32_t generation;
  416. if (PlsrGetStatus(axis, &status) != PLSR_RESULT_OK)
  417. {
  418. return;
  419. }
  420. generation = PlsrModbusStatusGeneration[axis] + 2UL;
  421. if (generation == 0UL)
  422. {
  423. generation = 2UL;
  424. }
  425. PlsrModbusStatusGeneration[axis] = generation;
  426. (void)memset(words, 0, sizeof(PlsrModbusStatusWords[axis]));
  427. if (status.busy != 0U) flags |= (1UL << 0U);
  428. if (status.pulseActive != 0U) flags |= (1UL << 1U);
  429. if (status.done != 0U) flags |= (1UL << 2U);
  430. if (status.wait != 0U) flags |= (1UL << 3U);
  431. if (status.directionPositive != 0U) flags |= (1UL << 4U);
  432. if (status.positionValid != 0U) flags |= (1UL << 5U);
  433. if (status.jobValid != 0U) flags |= (1UL << 6U);
  434. if (status.speedClamped != 0U) flags |= (1UL << 7U);
  435. if (status.positionOverflow != 0U) flags |= (1UL << 8U);
  436. if (status.positiveLimitActive != 0U) flags |= (1UL << 9U);
  437. if (status.negativeLimitActive != 0U) flags |= (1UL << 10U);
  438. if (status.emergencyLatched != 0U) flags |= (1UL << 11U);
  439. if (status.backlashActive != 0U) flags |= (1UL << 12U);
  440. PlsrModbusPutU32(words, 0UL, generation);
  441. words[2UL] = (uint16_t)status.state;
  442. PlsrModbusPutU32(words, 3UL, flags);
  443. words[5UL] = (uint16_t)status.outputMode;
  444. words[6UL] = (uint16_t)status.error;
  445. words[7UL] = (uint16_t)status.stopReason;
  446. words[8UL] = (uint16_t)status.lastCommandResult;
  447. words[9UL] = status.s2Set;
  448. PlsrModbusPutU32(words, 10UL, status.lastCommandSequence);
  449. PlsrModbusPutU32(words, 12UL, status.illegalTransitionCount);
  450. PlsrModbusPutU32(words, 14UL, status.pendingEvents);
  451. PlsrModbusPutU64(words, 16UL, (uint64_t)status.logicalPosition);
  452. PlsrModbusPutU64(words, 20UL, (uint64_t)status.taskPulses);
  453. PlsrModbusPutU64(words, 24UL, (uint64_t)status.totalPulses);
  454. PlsrModbusPutU64(words, 28UL, status.physicalPulses);
  455. words[32UL] = status.segmentCount;
  456. words[33UL] = status.startSegment;
  457. words[34UL] = status.currentSegment;
  458. words[35UL] = status.directionPoint;
  459. words[36UL] = status.highResourceMask;
  460. PlsrModbusPutU32(words, 38UL, status.currentFrequencyHz);
  461. PlsrModbusPutU32(words, 40UL, status.targetFrequencyHz);
  462. PlsrModbusPutU32(words, 42UL, status.liveFrequencyRejectCount);
  463. words[44UL] = (uint16_t)status.lastLiveFrequencyResult;
  464. PlsrModbusPutU32(words, 46UL, generation);
  465. (void)ModbusDataWriteWords(
  466. MODBUS_DATA_DEVICE_D,
  467. (uint32_t)PlsrModbusBaseAddress + PLSR_MODBUS_AXIS_STATUS_OFFSET
  468. + (uint32_t)axis * PLSR_MODBUS_AXIS_STATUS_WORDS,
  469. words,
  470. PLSR_MODBUS_AXIS_STATUS_WORDS);
  471. }
  472. PLSR_RESULT PlsrModbusControlInit(uint16_t baseAddress)
  473. {
  474. uint16_t header[8] = {0U};
  475. if (ModbusDataValidateWords(MODBUS_DATA_DEVICE_D,
  476. baseAddress,
  477. PLSR_MODBUS_WINDOW_WORDS) == 0U)
  478. {
  479. return PLSR_RESULT_DATA_ACCESS;
  480. }
  481. PlsrModbusBaseAddress = baseAddress;
  482. PlsrModbusEnabled = 0U;
  483. PlsrModbusLastCallRequestSequence = 0UL;
  484. PlsrModbusLastCommandRequestSequence = 0UL;
  485. (void)memset(PlsrModbusCommitted, 0, sizeof(PlsrModbusCommitted));
  486. (void)memset(PlsrModbusStatusGeneration,
  487. 0,
  488. sizeof(PlsrModbusStatusGeneration));
  489. if (ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  490. baseAddress,
  491. PlsrModbusZeroWindow,
  492. PLSR_MODBUS_WINDOW_WORDS) == 0U)
  493. {
  494. return PLSR_RESULT_DATA_ACCESS;
  495. }
  496. header[0UL] = PLSR_MODBUS_MAGIC_LOW;
  497. header[1UL] = PLSR_MODBUS_MAGIC_HIGH;
  498. header[2UL] = PLSR_MODBUS_PROTOCOL_VERSION;
  499. header[3UL] = (uint16_t)PLSR_MODBUS_WINDOW_WORDS;
  500. header[4UL] = PLSR_MODBUS_CAPABILITIES;
  501. if (ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  502. baseAddress,
  503. header,
  504. 8UL) == 0U)
  505. {
  506. return PLSR_RESULT_DATA_ACCESS;
  507. }
  508. PlsrModbusEnabled = 1U;
  509. PlsrModbusControlPoll();
  510. return PLSR_RESULT_OK;
  511. }
  512. void PlsrModbusControlPoll(void)
  513. {
  514. uint8_t axis;
  515. if (PlsrModbusEnabled == 0U)
  516. {
  517. return;
  518. }
  519. PlsrModbusHandleCallRequest();
  520. PlsrModbusHandleCommandRequest();
  521. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  522. {
  523. PlsrModbusPublishAxisStatus(axis);
  524. }
  525. }
  526. uint8_t PlsrModbusControlIsEnabled(void)
  527. {
  528. return PlsrModbusEnabled;
  529. }
  530. uint16_t PlsrModbusControlGetBaseAddress(void)
  531. {
  532. return PlsrModbusBaseAddress;
  533. }