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.
 
 
 
 
 
 

1329 lines
41 KiB

  1. #include "plsr_core.h"
  2. #include "plc_device.h"
  3. #include "plsr_address_map.h"
  4. #include "plsr_path.h"
  5. #include "plsr_resource.h"
  6. #include <string.h>
  7. #ifndef PLSR_HOST_TEST
  8. #include "stm32f4xx.h"
  9. #include "ucos_ii.h"
  10. #endif
  11. typedef struct
  12. {
  13. PLSR_STATE state;
  14. PLSR_OUTPUT_MODE outputMode;
  15. PLSR_ERROR error;
  16. PLSR_STOP_REASON stopReason;
  17. PLSR_STATE pendingTerminal;
  18. PLSR_RESOURCE_LEASE lease;
  19. PLSR_JOB_SNAPSHOT job;
  20. PLSR_PARSE_DETAIL parseDetail;
  21. volatile uint32_t pendingEvents;
  22. uint32_t lastCommandSequence;
  23. PLSR_RESULT lastCommandResult;
  24. uint32_t illegalTransitionCount;
  25. int64_t logicalPosition;
  26. int64_t totalPulses;
  27. PLSR_PATH_CONTEXT path;
  28. uint8_t hasLastCommand;
  29. uint8_t done;
  30. uint8_t directionPositive;
  31. uint8_t immediateStopPending;
  32. uint8_t positionValid;
  33. uint8_t jobValid;
  34. uint8_t positionOverflow;
  35. } PLSR_AXIS;
  36. typedef struct
  37. {
  38. PLSR_COMMAND command;
  39. PLSR_START_REQUEST start;
  40. PLSR_CALL call;
  41. uint32_t ticket;
  42. uint8_t hasStart;
  43. uint8_t hasCall;
  44. uint8_t occupied;
  45. } PLSR_COMMAND_SLOT;
  46. static PLSR_AXIS PlsrAxes[PLSR_AXIS_COUNT];
  47. static PLSR_COMMAND_SLOT PlsrCommandQueue[PLSR_COMMAND_QUEUE_DEPTH];
  48. static uint32_t PlsrNextTicket;
  49. static uint8_t PlsrInitialized;
  50. static PLSR_JOB_SNAPSHOT PlsrJobScratch;
  51. static uint32_t PlsrCoreEnterCritical(void)
  52. {
  53. #ifdef PLSR_HOST_TEST
  54. return 0UL;
  55. #else
  56. uint32_t interruptState = __get_PRIMASK();
  57. __disable_irq();
  58. __DMB();
  59. return interruptState;
  60. #endif
  61. }
  62. static void PlsrCoreExitCritical(uint32_t interruptState)
  63. {
  64. #ifdef PLSR_HOST_TEST
  65. (void)interruptState;
  66. #else
  67. __DMB();
  68. if (interruptState == 0UL)
  69. {
  70. __enable_irq();
  71. }
  72. #endif
  73. }
  74. static uint8_t PlsrStateIsBusy(PLSR_STATE state)
  75. {
  76. return ((state == PLSR_STATE_ACCEL) || (state == PLSR_STATE_RUN)
  77. || (state == PLSR_STATE_DECEL) || (state == PLSR_STATE_WAIT)
  78. || (state == PLSR_STATE_PAUSED))
  79. ? 1U
  80. : 0U;
  81. }
  82. static uint8_t PlsrStateIsPulseActive(PLSR_STATE state)
  83. {
  84. return ((state == PLSR_STATE_ACCEL) || (state == PLSR_STATE_RUN)
  85. || (state == PLSR_STATE_DECEL))
  86. ? 1U
  87. : 0U;
  88. }
  89. static void PlsrPublishAxis(uint8_t axis)
  90. {
  91. PLSR_AXIS *axisObject = &PlsrAxes[axis];
  92. uint8_t compatibleRun;
  93. compatibleRun = (uint8_t)((PlsrStateIsPulseActive(axisObject->state) != 0U)
  94. || (axisObject->state == PLSR_STATE_WAIT));
  95. (void)PlcDevicePublishSm(axis,
  96. compatibleRun,
  97. axisObject->directionPositive);
  98. }
  99. static void PlsrSetStopReason(PLSR_AXIS *axis,
  100. PLSR_STOP_REASON stopReason)
  101. {
  102. if (stopReason > axis->stopReason)
  103. {
  104. axis->stopReason = stopReason;
  105. }
  106. }
  107. /* 将 64 位逻辑位置发布为 HSD 的 32 位兼容值:
  108. * 超出 INT32 范围时回绕(与信捷 32 位寄存器一致)并置溢出诊断标志。 */
  109. static void PlsrPublishPosition(uint8_t axis, PLSR_AXIS *axisObject)
  110. {
  111. int32_t compatValue;
  112. if ((axisObject->logicalPosition > INT32_MAX)
  113. || (axisObject->logicalPosition < INT32_MIN))
  114. {
  115. axisObject->positionOverflow = 1U;
  116. }
  117. compatValue = (int32_t)(uint32_t)axisObject->logicalPosition;
  118. (void)PlcDevicePublishHsdDword(
  119. (uint16_t)((uint16_t)axis * PLSR_HSD_RUNTIME_AXIS_COUNT),
  120. compatValue);
  121. }
  122. static uint8_t PlsrTransitionIsAllowed(PLSR_STATE current,
  123. PLSR_STATE target)
  124. {
  125. if (current == target)
  126. {
  127. return 1U;
  128. }
  129. if (target == PLSR_STATE_ERROR)
  130. {
  131. return 1U;
  132. }
  133. switch (current)
  134. {
  135. case PLSR_STATE_UNINITIALIZED:
  136. return (target == PLSR_STATE_IDLE) ? 1U : 0U;
  137. case PLSR_STATE_IDLE:
  138. case PLSR_STATE_COMPLETED:
  139. case PLSR_STATE_STOPPED:
  140. return ((target == PLSR_STATE_ACCEL)
  141. || (target == PLSR_STATE_WAIT)
  142. || (target == PLSR_STATE_COMPLETED))
  143. ? 1U
  144. : 0U;
  145. case PLSR_STATE_ACCEL:
  146. case PLSR_STATE_RUN:
  147. return ((target == PLSR_STATE_ACCEL)
  148. || (target == PLSR_STATE_RUN)
  149. || (target == PLSR_STATE_DECEL)
  150. || (target == PLSR_STATE_WAIT)
  151. || (target == PLSR_STATE_COMPLETED)
  152. || (target == PLSR_STATE_STOPPED))
  153. ? 1U
  154. : 0U;
  155. case PLSR_STATE_DECEL:
  156. return ((target == PLSR_STATE_ACCEL)
  157. || (target == PLSR_STATE_RUN)
  158. || (target == PLSR_STATE_WAIT)
  159. || (target == PLSR_STATE_PAUSED)
  160. || (target == PLSR_STATE_COMPLETED)
  161. || (target == PLSR_STATE_STOPPED))
  162. ? 1U
  163. : 0U;
  164. case PLSR_STATE_WAIT:
  165. return ((target == PLSR_STATE_ACCEL)
  166. || (target == PLSR_STATE_RUN)
  167. || (target == PLSR_STATE_PAUSED)
  168. || (target == PLSR_STATE_COMPLETED)
  169. || (target == PLSR_STATE_STOPPED))
  170. ? 1U
  171. : 0U;
  172. case PLSR_STATE_PAUSED:
  173. return ((target == PLSR_STATE_ACCEL)
  174. || (target == PLSR_STATE_RUN)
  175. || (target == PLSR_STATE_STOPPED))
  176. ? 1U
  177. : 0U;
  178. case PLSR_STATE_ERROR:
  179. return (target == PLSR_STATE_IDLE) ? 1U : 0U;
  180. default:
  181. return 0U;
  182. }
  183. }
  184. PLSR_RESULT PlsrStateTransition(uint8_t axis,
  185. PLSR_STATE target,
  186. PLSR_TRANSITION_REASON reason)
  187. {
  188. PLSR_AXIS *axisObject;
  189. (void)reason;
  190. if (axis >= PLSR_AXIS_COUNT)
  191. {
  192. return PLSR_RESULT_INVALID_AXIS;
  193. }
  194. if ((uint32_t)target > (uint32_t)PLSR_STATE_ERROR)
  195. {
  196. return PLSR_RESULT_INVALID_ARGUMENT;
  197. }
  198. axisObject = &PlsrAxes[axis];
  199. if (PlsrTransitionIsAllowed(axisObject->state, target) == 0U)
  200. {
  201. axisObject->illegalTransitionCount++;
  202. axisObject->error = PLSR_ERROR_ILLEGAL_TRANSITION;
  203. axisObject->stopReason = PLSR_STOP_REASON_FAULT;
  204. axisObject->done = 0U;
  205. axisObject->state = PLSR_STATE_ERROR;
  206. axisObject->pendingTerminal = PLSR_STATE_UNINITIALIZED;
  207. axisObject->immediateStopPending = 0U;
  208. PlsrResourceRelease(&axisObject->lease);
  209. PlsrPublishAxis(axis);
  210. return PLSR_RESULT_INVALID_STATE;
  211. }
  212. axisObject->state = target;
  213. if (target == PLSR_STATE_COMPLETED)
  214. {
  215. axisObject->done = 1U;
  216. }
  217. if ((target == PLSR_STATE_COMPLETED) || (target == PLSR_STATE_STOPPED)
  218. || (target == PLSR_STATE_ERROR))
  219. {
  220. axisObject->pendingTerminal = PLSR_STATE_UNINITIALIZED;
  221. axisObject->immediateStopPending = 0U;
  222. PlsrPathTerminate(&axisObject->path);
  223. PlsrResourceRelease(&axisObject->lease);
  224. /* 运动已结束:记录 lastBusy=0,保证掉电后恢复时位置仍可信。 */
  225. (void)PlcDeviceSetHsdCheckpointMeta(axisObject->positionValid, 0U);
  226. (void)PlcDeviceCheckpointHsd();
  227. }
  228. PlsrPublishAxis(axis);
  229. return PLSR_RESULT_OK;
  230. }
  231. static uint8_t PlsrCommandPriority(PLSR_COMMAND_OPCODE opcode)
  232. {
  233. switch (opcode)
  234. {
  235. case PLSR_CMD_STOP_IMMEDIATE:
  236. return 0U;
  237. case PLSR_CMD_STOP_DECEL:
  238. return 1U;
  239. case PLSR_CMD_PAUSE:
  240. return 2U;
  241. case PLSR_CMD_RESUME:
  242. return 3U;
  243. default:
  244. return 4U;
  245. }
  246. }
  247. static PLSR_RESULT PlsrQueueCommand(const PLSR_COMMAND *command,
  248. const PLSR_START_REQUEST *start,
  249. const PLSR_CALL *call)
  250. {
  251. uint32_t interruptState;
  252. uint8_t freeSlot = PLSR_COMMAND_QUEUE_DEPTH;
  253. uint8_t index;
  254. interruptState = PlsrCoreEnterCritical();
  255. if ((PlsrAxes[command->axis].hasLastCommand != 0U)
  256. && (PlsrAxes[command->axis].lastCommandSequence == command->sequence))
  257. {
  258. PLSR_RESULT result = PlsrAxes[command->axis].lastCommandResult;
  259. PlsrCoreExitCritical(interruptState);
  260. return result;
  261. }
  262. for (index = 0U; index < PLSR_COMMAND_QUEUE_DEPTH; index++)
  263. {
  264. if (PlsrCommandQueue[index].occupied != 0U)
  265. {
  266. if ((PlsrCommandQueue[index].command.axis == command->axis)
  267. && (PlsrCommandQueue[index].command.sequence
  268. == command->sequence))
  269. {
  270. PlsrCoreExitCritical(interruptState);
  271. return PLSR_RESULT_QUEUED;
  272. }
  273. }
  274. else if (freeSlot == PLSR_COMMAND_QUEUE_DEPTH)
  275. {
  276. freeSlot = index;
  277. }
  278. }
  279. if (freeSlot == PLSR_COMMAND_QUEUE_DEPTH)
  280. {
  281. PlsrCoreExitCritical(interruptState);
  282. return PLSR_RESULT_QUEUE_FULL;
  283. }
  284. PlsrCommandQueue[freeSlot].command = *command;
  285. if (start != NULL)
  286. {
  287. PlsrCommandQueue[freeSlot].start = *start;
  288. PlsrCommandQueue[freeSlot].hasStart = 1U;
  289. }
  290. else
  291. {
  292. (void)memset(&PlsrCommandQueue[freeSlot].start,
  293. 0,
  294. sizeof(PlsrCommandQueue[freeSlot].start));
  295. PlsrCommandQueue[freeSlot].hasStart = 0U;
  296. }
  297. if (call != NULL)
  298. {
  299. PlsrCommandQueue[freeSlot].call = *call;
  300. PlsrCommandQueue[freeSlot].hasCall = 1U;
  301. }
  302. else
  303. {
  304. (void)memset(&PlsrCommandQueue[freeSlot].call,
  305. 0,
  306. sizeof(PlsrCommandQueue[freeSlot].call));
  307. PlsrCommandQueue[freeSlot].hasCall = 0U;
  308. }
  309. PlsrCommandQueue[freeSlot].ticket = PlsrNextTicket++;
  310. PlsrCommandQueue[freeSlot].occupied = 1U;
  311. PlsrCoreExitCritical(interruptState);
  312. return PLSR_RESULT_QUEUED;
  313. }
  314. static uint8_t PlsrPopHighestPriorityCommand(PLSR_COMMAND_SLOT *slot)
  315. {
  316. uint32_t interruptState;
  317. uint32_t selectedTicket = 0UL;
  318. uint8_t selectedPriority = 0xFFU;
  319. uint8_t selected = PLSR_COMMAND_QUEUE_DEPTH;
  320. uint8_t index;
  321. uint8_t priority;
  322. interruptState = PlsrCoreEnterCritical();
  323. for (index = 0U; index < PLSR_COMMAND_QUEUE_DEPTH; index++)
  324. {
  325. if (PlsrCommandQueue[index].occupied == 0U)
  326. {
  327. continue;
  328. }
  329. priority = PlsrCommandPriority(PlsrCommandQueue[index].command.opcode);
  330. if ((selected == PLSR_COMMAND_QUEUE_DEPTH)
  331. || (priority < selectedPriority)
  332. || ((priority == selectedPriority)
  333. && ((int32_t)(PlsrCommandQueue[index].ticket
  334. - selectedTicket)
  335. < 0)))
  336. {
  337. selected = index;
  338. selectedPriority = priority;
  339. selectedTicket = PlsrCommandQueue[index].ticket;
  340. }
  341. }
  342. if (selected == PLSR_COMMAND_QUEUE_DEPTH)
  343. {
  344. PlsrCoreExitCritical(interruptState);
  345. return 0U;
  346. }
  347. *slot = PlsrCommandQueue[selected];
  348. PlsrCommandQueue[selected].occupied = 0U;
  349. PlsrCoreExitCritical(interruptState);
  350. return 1U;
  351. }
  352. #ifdef PLSR_HOST_TEST
  353. PLSR_RESULT PlsrPostStart(const PLSR_START_REQUEST *request)
  354. {
  355. PLSR_COMMAND command;
  356. if (request == NULL)
  357. {
  358. return PLSR_RESULT_INVALID_ARGUMENT;
  359. }
  360. if (request->axis >= PLSR_AXIS_COUNT)
  361. {
  362. return PLSR_RESULT_INVALID_AXIS;
  363. }
  364. if (PlsrInitialized == 0U)
  365. {
  366. return PLSR_RESULT_INVALID_STATE;
  367. }
  368. command.sequence = request->sequence;
  369. command.axis = request->axis;
  370. command.opcode = PLSR_CMD_START;
  371. command.argument = 0;
  372. return PlsrQueueCommand(&command, request, NULL);
  373. }
  374. #endif /* PLSR_HOST_TEST */
  375. PLSR_RESULT PlsrPostCall(const PLSR_CALL *call)
  376. {
  377. PLSR_COMMAND command;
  378. if (call == NULL)
  379. {
  380. return PLSR_RESULT_INVALID_ARGUMENT;
  381. }
  382. if (call->dAxis >= PLSR_AXIS_COUNT)
  383. {
  384. return PLSR_RESULT_INVALID_AXIS;
  385. }
  386. if (PlsrInitialized == 0U)
  387. {
  388. return PLSR_RESULT_INVALID_STATE;
  389. }
  390. command.sequence = call->sequence;
  391. command.axis = call->dAxis;
  392. command.opcode = PLSR_CMD_START;
  393. command.argument = 0;
  394. return PlsrQueueCommand(&command, NULL, call);
  395. }
  396. PLSR_RESULT PlsrPostCommand(const PLSR_COMMAND *command)
  397. {
  398. if (command == NULL)
  399. {
  400. return PLSR_RESULT_INVALID_ARGUMENT;
  401. }
  402. if (command->axis >= PLSR_AXIS_COUNT)
  403. {
  404. return PLSR_RESULT_INVALID_AXIS;
  405. }
  406. if (((uint32_t)command->opcode > (uint32_t)PLSR_CMD_SELF_TEST)
  407. || (command->opcode == PLSR_CMD_START))
  408. {
  409. return PLSR_RESULT_INVALID_ARGUMENT;
  410. }
  411. if (PlsrInitialized == 0U)
  412. {
  413. return PLSR_RESULT_INVALID_STATE;
  414. }
  415. return PlsrQueueCommand(command, NULL, NULL);
  416. }
  417. PLSR_RESULT PlsrPostEvent(uint8_t axis, uint32_t eventMask)
  418. {
  419. uint32_t interruptState;
  420. if (axis >= PLSR_AXIS_COUNT)
  421. {
  422. return PLSR_RESULT_INVALID_AXIS;
  423. }
  424. if ((eventMask == 0UL) || ((eventMask & ~PLSR_EVENT_ALL_MASK) != 0UL))
  425. {
  426. return PLSR_RESULT_INVALID_ARGUMENT;
  427. }
  428. interruptState = PlsrCoreEnterCritical();
  429. PlsrAxes[axis].pendingEvents |= eventMask;
  430. PlsrCoreExitCritical(interruptState);
  431. return PLSR_RESULT_OK;
  432. }
  433. static uint32_t PlsrTakeEvents(uint8_t axis, uint32_t mask)
  434. {
  435. uint32_t interruptState;
  436. uint32_t events;
  437. interruptState = PlsrCoreEnterCritical();
  438. events = PlsrAxes[axis].pendingEvents & mask;
  439. PlsrAxes[axis].pendingEvents &= ~events;
  440. PlsrCoreExitCritical(interruptState);
  441. return events;
  442. }
  443. static uint8_t PlsrAnyAxisBusy(void)
  444. {
  445. uint8_t axis;
  446. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  447. {
  448. if (PlsrStateIsBusy(PlsrAxes[axis].state) != 0U)
  449. {
  450. return 1U;
  451. }
  452. }
  453. return 0U;
  454. }
  455. static PLSR_RESULT PlsrStartAxis(PLSR_AXIS *axisObject,
  456. const PLSR_START_REQUEST *start)
  457. {
  458. PLSR_RESOURCE_REQUEST resourceRequest;
  459. PLSR_RESULT result;
  460. if ((axisObject->state != PLSR_STATE_IDLE)
  461. && (axisObject->state != PLSR_STATE_COMPLETED)
  462. && (axisObject->state != PLSR_STATE_STOPPED))
  463. {
  464. return PLSR_RESULT_INVALID_STATE;
  465. }
  466. resourceRequest.ownerAxis = start->axis;
  467. resourceRequest.outputMode = start->outputMode;
  468. resourceRequest.dAxis = start->axis;
  469. resourceRequest.directionPoint = start->directionPoint;
  470. result = PlsrResourceReserve(&resourceRequest, &axisObject->lease);
  471. if (result != PLSR_RESULT_OK)
  472. {
  473. axisObject->error = (result == PLSR_RESULT_RESOURCE_CONFLICT)
  474. ? PLSR_ERROR_RESOURCE_CONFLICT
  475. : PLSR_ERROR_INVALID_RESOURCE;
  476. return result;
  477. }
  478. axisObject->outputMode = start->outputMode;
  479. axisObject->directionPositive = (start->directionPositive != 0U) ? 1U : 0U;
  480. axisObject->error = PLSR_ERROR_NONE;
  481. axisObject->stopReason = PLSR_STOP_REASON_NONE;
  482. axisObject->pendingTerminal = PLSR_STATE_UNINITIALIZED;
  483. axisObject->immediateStopPending = 0U;
  484. axisObject->done = 0U;
  485. axisObject->jobValid = 0U;
  486. result = PlsrStateTransition(start->axis,
  487. PLSR_STATE_ACCEL,
  488. PLSR_TRANSITION_START);
  489. if (result != PLSR_RESULT_OK)
  490. {
  491. PlsrResourceRelease(&axisObject->lease);
  492. }
  493. else
  494. {
  495. /* 运动开始:掉电恢复时据此判定"断电时在运动中"。 */
  496. (void)PlcDeviceSetHsdCheckpointMeta(axisObject->positionValid, 1U);
  497. (void)PlcDeviceCheckpointHsd();
  498. }
  499. return result;
  500. }
  501. static PLSR_RESULT PlsrStartCall(PLSR_AXIS *axisObject,
  502. const PLSR_CALL *call)
  503. {
  504. PLSR_RESOURCE_REQUEST resourceRequest;
  505. PLSR_PARSE_CONTEXT parseContext;
  506. PLSR_RESULT result;
  507. if ((axisObject->state != PLSR_STATE_IDLE)
  508. && (axisObject->state != PLSR_STATE_COMPLETED)
  509. && (axisObject->state != PLSR_STATE_STOPPED))
  510. {
  511. return PLSR_RESULT_INVALID_STATE;
  512. }
  513. parseContext.logicalPosition = axisObject->logicalPosition;
  514. parseContext.positionValid = axisObject->positionValid;
  515. result = PlsrBuildJobSnapshot(call,
  516. &parseContext,
  517. &PlsrJobScratch,
  518. &axisObject->parseDetail);
  519. if (result != PLSR_RESULT_OK)
  520. {
  521. return result;
  522. }
  523. resourceRequest.ownerAxis = call->dAxis;
  524. resourceRequest.outputMode =
  525. (PLSR_OUTPUT_MODE)PlsrJobScratch.outputMode;
  526. resourceRequest.dAxis = call->dAxis;
  527. resourceRequest.directionPoint = PlsrJobScratch.directionPoint;
  528. result = PlsrResourceReserve(&resourceRequest, &axisObject->lease);
  529. if (result != PLSR_RESULT_OK)
  530. {
  531. axisObject->error = (result == PLSR_RESULT_RESOURCE_CONFLICT)
  532. ? PLSR_ERROR_RESOURCE_CONFLICT
  533. : PLSR_ERROR_INVALID_RESOURCE;
  534. axisObject->parseDetail.result = result;
  535. axisObject->parseDetail.block = PLSR_PARSE_BLOCK_OUTPUT;
  536. return result;
  537. }
  538. axisObject->job = PlsrJobScratch;
  539. axisObject->jobValid = 1U;
  540. axisObject->outputMode = (PLSR_OUTPUT_MODE)axisObject->job.outputMode;
  541. axisObject->directionPositive = axisObject->job.initialDirectionPositive;
  542. axisObject->error = PLSR_ERROR_NONE;
  543. axisObject->stopReason = PLSR_STOP_REASON_NONE;
  544. axisObject->pendingTerminal = PLSR_STATE_UNINITIALIZED;
  545. axisObject->immediateStopPending = 0U;
  546. axisObject->done = 0U;
  547. PlsrPathBegin(&axisObject->path,
  548. &axisObject->job,
  549. axisObject->logicalPosition);
  550. if (axisObject->path.jobEnded != 0U)
  551. {
  552. /* 起点就是零脉冲且跳转链已结束(任务无实际脉冲)。 */
  553. axisObject->stopReason = PLSR_STOP_REASON_NORMAL_COMPLETE;
  554. (void)PlsrStateTransition(call->dAxis,
  555. PLSR_STATE_COMPLETED,
  556. PLSR_TRANSITION_JOB_COMPLETE);
  557. axisObject->jobValid = 0U;
  558. return PLSR_RESULT_OK;
  559. }
  560. result = PlsrStateTransition(call->dAxis,
  561. PLSR_STATE_ACCEL,
  562. PLSR_TRANSITION_START);
  563. if (result != PLSR_RESULT_OK)
  564. {
  565. axisObject->jobValid = 0U;
  566. PlsrResourceRelease(&axisObject->lease);
  567. }
  568. else
  569. {
  570. /* 运动开始:掉电恢复时据此判定"断电时在运动中"。 */
  571. (void)PlcDeviceSetHsdCheckpointMeta(axisObject->positionValid, 1U);
  572. (void)PlcDeviceCheckpointHsd();
  573. }
  574. return result;
  575. }
  576. static PLSR_RESULT PlsrStopImmediate(uint8_t axis)
  577. {
  578. PLSR_AXIS *axisObject = &PlsrAxes[axis];
  579. if ((axisObject->state == PLSR_STATE_IDLE)
  580. || (axisObject->state == PLSR_STATE_COMPLETED)
  581. || (axisObject->state == PLSR_STATE_STOPPED))
  582. {
  583. return PLSR_RESULT_OK;
  584. }
  585. if (axisObject->state == PLSR_STATE_ERROR)
  586. {
  587. return PLSR_RESULT_INVALID_STATE;
  588. }
  589. if (axisObject->immediateStopPending != 0U)
  590. {
  591. return PLSR_RESULT_OK;
  592. }
  593. PlsrSetStopReason(axisObject, PLSR_STOP_REASON_STOP_IMMEDIATE);
  594. axisObject->pendingTerminal = PLSR_STATE_STOPPED;
  595. PlsrPathTerminate(&axisObject->path);
  596. if ((axisObject->state == PLSR_STATE_WAIT)
  597. || (axisObject->state == PLSR_STATE_PAUSED))
  598. {
  599. return PlsrStateTransition(axis,
  600. PLSR_STATE_STOPPED,
  601. PLSR_TRANSITION_STOP);
  602. }
  603. axisObject->immediateStopPending = 1U;
  604. return PLSR_RESULT_OK;
  605. }
  606. static PLSR_RESULT PlsrStopDecel(uint8_t axis)
  607. {
  608. PLSR_AXIS *axisObject = &PlsrAxes[axis];
  609. if ((axisObject->state == PLSR_STATE_IDLE)
  610. || (axisObject->state == PLSR_STATE_COMPLETED)
  611. || (axisObject->state == PLSR_STATE_STOPPED))
  612. {
  613. return PLSR_RESULT_OK;
  614. }
  615. if (axisObject->state == PLSR_STATE_ERROR)
  616. {
  617. return PLSR_RESULT_INVALID_STATE;
  618. }
  619. if (axisObject->stopReason >= PLSR_STOP_REASON_STOP_IMMEDIATE)
  620. {
  621. return PLSR_RESULT_OK;
  622. }
  623. PlsrSetStopReason(axisObject, PLSR_STOP_REASON_STOP_DECEL);
  624. axisObject->pendingTerminal = PLSR_STATE_STOPPED;
  625. PlsrPathTerminate(&axisObject->path);
  626. if ((axisObject->state == PLSR_STATE_WAIT)
  627. || (axisObject->state == PLSR_STATE_PAUSED))
  628. {
  629. return PlsrStateTransition(axis,
  630. PLSR_STATE_STOPPED,
  631. PLSR_TRANSITION_STOP);
  632. }
  633. if (axisObject->state == PLSR_STATE_DECEL)
  634. {
  635. return PLSR_RESULT_OK;
  636. }
  637. return PlsrStateTransition(axis,
  638. PLSR_STATE_DECEL,
  639. PLSR_TRANSITION_DECEL_REQUEST);
  640. }
  641. static PLSR_RESULT PlsrPause(uint8_t axis)
  642. {
  643. PLSR_AXIS *axisObject = &PlsrAxes[axis];
  644. if (axisObject->state == PLSR_STATE_PAUSED)
  645. {
  646. return PLSR_RESULT_OK;
  647. }
  648. if (axisObject->stopReason >= PLSR_STOP_REASON_STOP_DECEL)
  649. {
  650. return PLSR_RESULT_BUSY;
  651. }
  652. if (axisObject->state == PLSR_STATE_WAIT)
  653. {
  654. PlsrSetStopReason(axisObject, PLSR_STOP_REASON_PAUSE);
  655. PlsrPathTerminate(&axisObject->path);
  656. return PlsrStateTransition(axis,
  657. PLSR_STATE_PAUSED,
  658. PLSR_TRANSITION_DECEL_COMPLETE);
  659. }
  660. if ((axisObject->state != PLSR_STATE_ACCEL)
  661. && (axisObject->state != PLSR_STATE_RUN)
  662. && (axisObject->state != PLSR_STATE_DECEL))
  663. {
  664. return PLSR_RESULT_INVALID_STATE;
  665. }
  666. PlsrSetStopReason(axisObject, PLSR_STOP_REASON_PAUSE);
  667. axisObject->pendingTerminal = PLSR_STATE_PAUSED;
  668. PlsrPathTerminate(&axisObject->path);
  669. if (axisObject->state == PLSR_STATE_DECEL)
  670. {
  671. return PLSR_RESULT_OK;
  672. }
  673. return PlsrStateTransition(axis,
  674. PLSR_STATE_DECEL,
  675. PLSR_TRANSITION_DECEL_REQUEST);
  676. }
  677. static PLSR_RESULT PlsrExecuteCommand(const PLSR_COMMAND_SLOT *slot)
  678. {
  679. PLSR_AXIS *axisObject = &PlsrAxes[slot->command.axis];
  680. PLC_DEVICE_RESULT deviceResult;
  681. PLSR_RESULT result;
  682. switch (slot->command.opcode)
  683. {
  684. case PLSR_CMD_START:
  685. if (slot->hasCall != 0U)
  686. {
  687. result = PlsrStartCall(axisObject, &slot->call);
  688. }
  689. else
  690. {
  691. result = (slot->hasStart != 0U)
  692. ? PlsrStartAxis(axisObject, &slot->start)
  693. : PLSR_RESULT_INVALID_ARGUMENT;
  694. }
  695. break;
  696. case PLSR_CMD_STOP_DECEL:
  697. result = PlsrStopDecel(slot->command.axis);
  698. break;
  699. case PLSR_CMD_STOP_IMMEDIATE:
  700. result = PlsrStopImmediate(slot->command.axis);
  701. break;
  702. case PLSR_CMD_PAUSE:
  703. result = PlsrPause(slot->command.axis);
  704. break;
  705. case PLSR_CMD_RESUME:
  706. if (axisObject->state != PLSR_STATE_PAUSED)
  707. {
  708. result = PLSR_RESULT_INVALID_STATE;
  709. }
  710. else
  711. {
  712. axisObject->stopReason = PLSR_STOP_REASON_NONE;
  713. axisObject->pendingTerminal = PLSR_STATE_UNINITIALIZED;
  714. result = PlsrStateTransition(slot->command.axis,
  715. PLSR_STATE_ACCEL,
  716. PLSR_TRANSITION_WAIT_COMPLETE);
  717. }
  718. break;
  719. case PLSR_CMD_SET_POSITION:
  720. if (PlsrStateIsBusy(axisObject->state) != 0U)
  721. {
  722. result = PLSR_RESULT_BUSY;
  723. }
  724. else
  725. {
  726. axisObject->logicalPosition = slot->command.argument;
  727. axisObject->positionValid = 1U;
  728. axisObject->positionOverflow = 0U;
  729. PlsrPublishPosition(slot->command.axis, axisObject);
  730. (void)PlcDeviceSetHsdCheckpointMeta(1U, 0U);
  731. (void)PlcDeviceCheckpointHsd();
  732. result = PLSR_RESULT_OK;
  733. }
  734. break;
  735. case PLSR_CMD_CLEAR_POSITION:
  736. if (PlsrStateIsBusy(axisObject->state) != 0U)
  737. {
  738. result = PLSR_RESULT_BUSY;
  739. }
  740. else
  741. {
  742. axisObject->logicalPosition = 0;
  743. axisObject->positionValid = 1U;
  744. axisObject->positionOverflow = 0U;
  745. PlsrPublishPosition(slot->command.axis, axisObject);
  746. (void)PlcDeviceSetHsdCheckpointMeta(1U, 0U);
  747. (void)PlcDeviceCheckpointHsd();
  748. result = PLSR_RESULT_OK;
  749. }
  750. break;
  751. case PLSR_CMD_CLEAR_TOTAL:
  752. if (PlsrStateIsBusy(axisObject->state) != 0U)
  753. {
  754. result = PLSR_RESULT_BUSY;
  755. }
  756. else
  757. {
  758. axisObject->totalPulses = 0;
  759. result = PLSR_RESULT_OK;
  760. }
  761. break;
  762. case PLSR_CMD_SAVE_CONFIG:
  763. if (PlsrAnyAxisBusy() != 0U)
  764. {
  765. result = PLSR_RESULT_BUSY;
  766. }
  767. else
  768. {
  769. deviceResult = PlcDeviceSaveSfd();
  770. result = (deviceResult == PLC_DEVICE_OK)
  771. ? PLSR_RESULT_OK
  772. : PLSR_RESULT_PERSISTENCE_ERROR;
  773. }
  774. break;
  775. case PLSR_CMD_LOAD_CONFIG:
  776. if (PlsrAnyAxisBusy() != 0U)
  777. {
  778. result = PLSR_RESULT_BUSY;
  779. }
  780. else
  781. {
  782. deviceResult = PlcDeviceLoadSfd();
  783. result = (deviceResult == PLC_DEVICE_OK)
  784. ? PLSR_RESULT_OK
  785. : PLSR_RESULT_PERSISTENCE_ERROR;
  786. }
  787. break;
  788. case PLSR_CMD_RESET_ERROR:
  789. if (axisObject->state != PLSR_STATE_ERROR)
  790. {
  791. result = PLSR_RESULT_INVALID_STATE;
  792. }
  793. else
  794. {
  795. axisObject->error = PLSR_ERROR_NONE;
  796. axisObject->stopReason = PLSR_STOP_REASON_NONE;
  797. axisObject->done = 0U;
  798. result = PlsrStateTransition(slot->command.axis,
  799. PLSR_STATE_IDLE,
  800. PLSR_TRANSITION_RESET_ERROR);
  801. }
  802. break;
  803. case PLSR_CMD_SELF_TEST:
  804. result = ((PlsrAnyAxisBusy() == 0U)
  805. && (PlsrResourceCheckInvariant() != 0U))
  806. ? PLSR_RESULT_OK
  807. : PLSR_RESULT_BUSY;
  808. break;
  809. default:
  810. result = PLSR_RESULT_INVALID_ARGUMENT;
  811. break;
  812. }
  813. axisObject->lastCommandSequence = slot->command.sequence;
  814. axisObject->lastCommandResult = result;
  815. axisObject->hasLastCommand = 1U;
  816. PlsrPublishAxis(slot->command.axis);
  817. return result;
  818. }
  819. static void PlsrProcessCriticalEvents(uint8_t axis, uint32_t events)
  820. {
  821. PLSR_AXIS *axisObject = &PlsrAxes[axis];
  822. if ((events & PLSR_EVENT_SOFTWARE_EMERGENCY) != 0UL)
  823. {
  824. if (PlsrStateIsBusy(axisObject->state) != 0U)
  825. {
  826. PlsrSetStopReason(axisObject,
  827. PLSR_STOP_REASON_SOFTWARE_EMERGENCY);
  828. axisObject->done = 0U;
  829. PlsrPathTerminate(&axisObject->path);
  830. (void)PlsrStateTransition(axis,
  831. PLSR_STATE_STOPPED,
  832. PLSR_TRANSITION_STOP);
  833. }
  834. return;
  835. }
  836. if ((events & PLSR_EVENT_LIMIT_POSITIVE) != 0UL)
  837. {
  838. if ((axisObject->directionPositive != 0U)
  839. && (PlsrStateIsBusy(axisObject->state) != 0U))
  840. {
  841. axisObject->error = PLSR_ERROR_LIMIT_POSITIVE;
  842. PlsrSetStopReason(axisObject,
  843. PLSR_STOP_REASON_LIMIT_POSITIVE);
  844. axisObject->pendingTerminal = PLSR_STATE_STOPPED;
  845. PlsrPathTerminate(&axisObject->path);
  846. if ((axisObject->state == PLSR_STATE_WAIT)
  847. || (axisObject->state == PLSR_STATE_PAUSED))
  848. {
  849. (void)PlsrStateTransition(axis,
  850. PLSR_STATE_STOPPED,
  851. PLSR_TRANSITION_STOP);
  852. }
  853. else if (axisObject->state != PLSR_STATE_DECEL)
  854. {
  855. (void)PlsrStateTransition(axis,
  856. PLSR_STATE_DECEL,
  857. PLSR_TRANSITION_DECEL_REQUEST);
  858. }
  859. }
  860. return;
  861. }
  862. if ((events & PLSR_EVENT_LIMIT_NEGATIVE) != 0UL)
  863. {
  864. if ((axisObject->directionPositive == 0U)
  865. && (PlsrStateIsBusy(axisObject->state) != 0U))
  866. {
  867. axisObject->error = PLSR_ERROR_LIMIT_NEGATIVE;
  868. PlsrSetStopReason(axisObject,
  869. PLSR_STOP_REASON_LIMIT_NEGATIVE);
  870. axisObject->pendingTerminal = PLSR_STATE_STOPPED;
  871. PlsrPathTerminate(&axisObject->path);
  872. if ((axisObject->state == PLSR_STATE_WAIT)
  873. || (axisObject->state == PLSR_STATE_PAUSED))
  874. {
  875. (void)PlsrStateTransition(axis,
  876. PLSR_STATE_STOPPED,
  877. PLSR_TRANSITION_STOP);
  878. }
  879. else if (axisObject->state != PLSR_STATE_DECEL)
  880. {
  881. (void)PlsrStateTransition(axis,
  882. PLSR_STATE_DECEL,
  883. PLSR_TRANSITION_DECEL_REQUEST);
  884. }
  885. }
  886. return;
  887. }
  888. if ((events & (PLSR_EVENT_TIMER_FAULT | PLSR_EVENT_COUNTER_FAULT)) != 0UL)
  889. {
  890. axisObject->error = ((events & PLSR_EVENT_TIMER_FAULT) != 0UL)
  891. ? PLSR_ERROR_TIMER_FAULT
  892. : PLSR_ERROR_COUNTER_FAULT;
  893. PlsrSetStopReason(axisObject, PLSR_STOP_REASON_FAULT);
  894. axisObject->done = 0U;
  895. PlsrPathTerminate(&axisObject->path);
  896. (void)PlsrStateTransition(axis,
  897. PLSR_STATE_ERROR,
  898. PLSR_TRANSITION_FAULT);
  899. }
  900. }
  901. /* 应用路径执行器的动作:段间推进、进入等待、结束、让出、错误。 */
  902. static void PlsrApplyPathAction(uint8_t axis, PLSR_PATH_ACTION action)
  903. {
  904. PLSR_AXIS *axisObject = &PlsrAxes[axis];
  905. switch (action)
  906. {
  907. case PLSR_PATH_ACTION_NEXT_SEGMENT:
  908. if (axisObject->state == PLSR_STATE_WAIT)
  909. {
  910. (void)PlsrStateTransition(axis,
  911. PLSR_STATE_ACCEL,
  912. PLSR_TRANSITION_WAIT_COMPLETE);
  913. }
  914. else if ((axisObject->state == PLSR_STATE_ACCEL)
  915. || (axisObject->state == PLSR_STATE_RUN)
  916. || (axisObject->state == PLSR_STATE_DECEL))
  917. {
  918. (void)PlsrStateTransition(axis,
  919. PLSR_STATE_ACCEL,
  920. PLSR_TRANSITION_START);
  921. }
  922. break;
  923. case PLSR_PATH_ACTION_ENTER_WAIT:
  924. if ((axisObject->state == PLSR_STATE_ACCEL)
  925. || (axisObject->state == PLSR_STATE_RUN))
  926. {
  927. (void)PlsrStateTransition(axis,
  928. PLSR_STATE_WAIT,
  929. PLSR_TRANSITION_WAIT_BEGIN);
  930. }
  931. break;
  932. case PLSR_PATH_ACTION_JOB_COMPLETE:
  933. if (PlsrStateIsBusy(axisObject->state) != 0U)
  934. {
  935. axisObject->stopReason = PLSR_STOP_REASON_NORMAL_COMPLETE;
  936. (void)PlsrStateTransition(axis,
  937. PLSR_STATE_COMPLETED,
  938. PLSR_TRANSITION_JOB_COMPLETE);
  939. }
  940. break;
  941. case PLSR_PATH_ACTION_YIELD:
  942. /* 预算耗尽:本轮不再推进,下个 tick 由 PlsrPathTick 恢复。 */
  943. break;
  944. case PLSR_PATH_ACTION_ERROR:
  945. axisObject->error = PLSR_ERROR_INTERNAL;
  946. PlsrSetStopReason(axisObject, PLSR_STOP_REASON_FAULT);
  947. axisObject->done = 0U;
  948. (void)PlsrStateTransition(axis,
  949. PLSR_STATE_ERROR,
  950. PLSR_TRANSITION_FAULT);
  951. break;
  952. default:
  953. break;
  954. }
  955. }
  956. static void PlsrProcessNormalEvents(uint8_t axis, uint32_t events)
  957. {
  958. PLSR_AXIS *axisObject = &PlsrAxes[axis];
  959. if (((events & PLSR_EVENT_STOP_IMMEDIATE_DONE) != 0UL)
  960. && (axisObject->immediateStopPending != 0U))
  961. {
  962. (void)PlsrStateTransition(axis,
  963. PLSR_STATE_STOPPED,
  964. PLSR_TRANSITION_STOP);
  965. return;
  966. }
  967. if (((events & PLSR_EVENT_ACCEL_COMPLETE) != 0UL)
  968. && (axisObject->state == PLSR_STATE_ACCEL)
  969. && (axisObject->immediateStopPending == 0U))
  970. {
  971. (void)PlsrStateTransition(axis,
  972. PLSR_STATE_RUN,
  973. PLSR_TRANSITION_ACCEL_COMPLETE);
  974. }
  975. if (((events & PLSR_EVENT_DECEL_COMPLETE) != 0UL)
  976. && (axisObject->state == PLSR_STATE_DECEL))
  977. {
  978. if (axisObject->pendingTerminal == PLSR_STATE_PAUSED)
  979. {
  980. (void)PlsrStateTransition(axis,
  981. PLSR_STATE_PAUSED,
  982. PLSR_TRANSITION_DECEL_COMPLETE);
  983. }
  984. else if (axisObject->pendingTerminal == PLSR_STATE_STOPPED)
  985. {
  986. (void)PlsrStateTransition(axis,
  987. PLSR_STATE_STOPPED,
  988. PLSR_TRANSITION_DECEL_COMPLETE);
  989. }
  990. else
  991. {
  992. (void)PlsrStateTransition(axis,
  993. PLSR_STATE_RUN,
  994. PLSR_TRANSITION_DECEL_COMPLETE);
  995. }
  996. }
  997. if (((events & PLSR_EVENT_WAIT_BEGIN) != 0UL)
  998. && ((axisObject->state == PLSR_STATE_ACCEL)
  999. || (axisObject->state == PLSR_STATE_RUN)))
  1000. {
  1001. (void)PlsrStateTransition(axis,
  1002. PLSR_STATE_WAIT,
  1003. PLSR_TRANSITION_WAIT_BEGIN);
  1004. }
  1005. if (((events & PLSR_EVENT_WAIT_COMPLETE) != 0UL)
  1006. && (axisObject->state == PLSR_STATE_WAIT))
  1007. {
  1008. (void)PlsrStateTransition(axis,
  1009. PLSR_STATE_ACCEL,
  1010. PLSR_TRANSITION_WAIT_COMPLETE);
  1011. }
  1012. if (((events & PLSR_EVENT_SEGMENT_COMPLETE) != 0UL)
  1013. && (axisObject->state == PLSR_STATE_RUN)
  1014. && (axisObject->pendingTerminal == PLSR_STATE_UNINITIALIZED)
  1015. && (axisObject->immediateStopPending == 0U))
  1016. {
  1017. PLSR_PATH_ACTION action = PlsrPathOnSegmentDone(
  1018. &axisObject->path,
  1019. &axisObject->job,
  1020. axisObject->logicalPosition);
  1021. PlsrApplyPathAction(axis, action);
  1022. }
  1023. if (((events & PLSR_EVENT_JOB_COMPLETE) != 0UL)
  1024. && (PlsrStateIsBusy(axisObject->state) != 0U)
  1025. && (axisObject->pendingTerminal == PLSR_STATE_UNINITIALIZED)
  1026. && (axisObject->immediateStopPending == 0U))
  1027. {
  1028. axisObject->stopReason = PLSR_STOP_REASON_NORMAL_COMPLETE;
  1029. (void)PlsrStateTransition(axis,
  1030. PLSR_STATE_COMPLETED,
  1031. PLSR_TRANSITION_JOB_COMPLETE);
  1032. }
  1033. }
  1034. PLSR_RESULT PlsrInit(void)
  1035. {
  1036. int32_t restoredPosition;
  1037. uint8_t restoredPositionValid;
  1038. uint8_t restoredLastBusy;
  1039. uint8_t axis;
  1040. (void)memset(PlsrAxes, 0, sizeof(PlsrAxes));
  1041. (void)memset(PlsrCommandQueue, 0, sizeof(PlsrCommandQueue));
  1042. PlsrNextTicket = 0UL;
  1043. PlsrResourceInit();
  1044. PlsrInitialized = 1U;
  1045. restoredPositionValid = PlcDeviceGetRestoredHsdPositionValid();
  1046. restoredLastBusy = PlcDeviceGetRestoredHsdLastBusy();
  1047. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  1048. {
  1049. PlsrAxes[axis].state = PLSR_STATE_UNINITIALIZED;
  1050. PlsrAxes[axis].pendingTerminal = PLSR_STATE_UNINITIALIZED;
  1051. PlsrAxes[axis].lease.directionPoint = PLSR_DIRECTION_POINT_NONE;
  1052. if (PlcDeviceReadHsdDword(
  1053. (uint16_t)(axis * PLSR_HSD_RUNTIME_AXIS_COUNT),
  1054. &restoredPosition) == PLC_DEVICE_OK)
  1055. {
  1056. PlsrAxes[axis].logicalPosition = restoredPosition;
  1057. }
  1058. /* 只有上次正常停机且保存了位置有效标志,才允许绝对定位;
  1059. * 运动中掉电(lastBusy=1)时位置不可信。 */
  1060. if ((restoredPositionValid != 0U) && (restoredLastBusy == 0U))
  1061. {
  1062. PlsrAxes[axis].positionValid = 1U;
  1063. }
  1064. if (PlsrStateTransition(axis,
  1065. PLSR_STATE_IDLE,
  1066. PLSR_TRANSITION_INITIALIZED)
  1067. != PLSR_RESULT_OK)
  1068. {
  1069. return PLSR_RESULT_INTERNAL_ERROR;
  1070. }
  1071. }
  1072. return PLSR_RESULT_OK;
  1073. }
  1074. void PlsrProcess(void)
  1075. {
  1076. PLSR_COMMAND_SLOT slot;
  1077. uint32_t events;
  1078. uint8_t processedCommands = 0U;
  1079. uint8_t axis;
  1080. if (PlsrInitialized == 0U)
  1081. {
  1082. return;
  1083. }
  1084. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  1085. {
  1086. events = PlsrTakeEvents(axis, PLSR_EVENT_CRITICAL_MASK);
  1087. if (events != 0UL)
  1088. {
  1089. PlsrProcessCriticalEvents(axis, events);
  1090. }
  1091. }
  1092. while ((processedCommands < PLSR_COMMAND_QUEUE_DEPTH)
  1093. && (PlsrPopHighestPriorityCommand(&slot) != 0U))
  1094. {
  1095. (void)PlsrExecuteCommand(&slot);
  1096. processedCommands++;
  1097. }
  1098. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  1099. {
  1100. events = PlsrTakeEvents(axis,
  1101. PLSR_EVENT_ALL_MASK
  1102. & ~PLSR_EVENT_CRITICAL_MASK);
  1103. if (events != 0UL)
  1104. {
  1105. PlsrProcessNormalEvents(axis, events);
  1106. }
  1107. }
  1108. /* 1ms tick:路径执行器推进(WAIT/ACT 计时、信号/EXT 轮询、跳转链)。 */
  1109. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  1110. {
  1111. PLSR_AXIS *axisObject = &PlsrAxes[axis];
  1112. PLSR_PATH_ACTION action;
  1113. if (PlsrStateIsBusy(axisObject->state) == 0U)
  1114. {
  1115. continue;
  1116. }
  1117. action = PlsrPathTick(&axisObject->path,
  1118. &axisObject->job,
  1119. axisObject->logicalPosition);
  1120. if (action != PLSR_PATH_ACTION_NONE)
  1121. {
  1122. PlsrApplyPathAction(axis, action);
  1123. }
  1124. }
  1125. }
  1126. void PlsrTask(void *argument)
  1127. {
  1128. (void)argument;
  1129. #ifdef PLSR_HOST_TEST
  1130. PlsrProcess();
  1131. #else
  1132. while (1)
  1133. {
  1134. PlsrProcess();
  1135. OSTimeDly(1U);
  1136. }
  1137. #endif
  1138. }
  1139. PLSR_RESULT PlsrGetStatus(uint8_t axis, PLSR_STATUS *status)
  1140. {
  1141. PLSR_AXIS *axisObject;
  1142. uint32_t interruptState;
  1143. if (axis >= PLSR_AXIS_COUNT)
  1144. {
  1145. return PLSR_RESULT_INVALID_AXIS;
  1146. }
  1147. if (status == NULL)
  1148. {
  1149. return PLSR_RESULT_INVALID_ARGUMENT;
  1150. }
  1151. interruptState = PlsrCoreEnterCritical();
  1152. axisObject = &PlsrAxes[axis];
  1153. status->state = axisObject->state;
  1154. status->outputMode = axisObject->outputMode;
  1155. status->error = axisObject->error;
  1156. status->stopReason = axisObject->stopReason;
  1157. status->lastCommandResult = axisObject->lastCommandResult;
  1158. status->lastCommandSequence = axisObject->lastCommandSequence;
  1159. status->illegalTransitionCount = axisObject->illegalTransitionCount;
  1160. status->pendingEvents = axisObject->pendingEvents;
  1161. status->logicalPosition = axisObject->logicalPosition;
  1162. status->totalPulses = axisObject->totalPulses;
  1163. status->busy = PlsrStateIsBusy(axisObject->state);
  1164. status->pulseActive = PlsrStateIsPulseActive(axisObject->state);
  1165. status->done = axisObject->done;
  1166. status->wait = (axisObject->state == PLSR_STATE_WAIT) ? 1U : 0U;
  1167. status->directionPositive = axisObject->directionPositive;
  1168. status->highResourceMask = axisObject->lease.highMask;
  1169. status->directionPoint = (axisObject->lease.valid != 0U)
  1170. ? axisObject->lease.directionPoint
  1171. : PLSR_DIRECTION_POINT_NONE;
  1172. status->positionValid = axisObject->positionValid;
  1173. status->jobValid = axisObject->jobValid;
  1174. status->positionOverflow = axisObject->positionOverflow;
  1175. status->s2Set = (axisObject->jobValid != 0U) ? axisObject->job.s2Set : 0U;
  1176. status->speedClamped = (axisObject->jobValid != 0U)
  1177. ? axisObject->job.speedClamped
  1178. : 0U;
  1179. status->segmentCount = (axisObject->jobValid != 0U)
  1180. ? axisObject->job.segmentCount
  1181. : 0U;
  1182. status->startSegment = (axisObject->jobValid != 0U)
  1183. ? axisObject->job.startSegment
  1184. : 0U;
  1185. status->currentSegment = (axisObject->jobValid != 0U)
  1186. ? PlsrPathGetCurrentSegment(
  1187. &axisObject->path)
  1188. : 0U;
  1189. PlsrCoreExitCritical(interruptState);
  1190. return PLSR_RESULT_OK;
  1191. }
  1192. PLSR_RESULT PlsrGetLastParseDetail(uint8_t axis,
  1193. PLSR_PARSE_DETAIL *detail)
  1194. {
  1195. uint32_t interruptState;
  1196. if (axis >= PLSR_AXIS_COUNT)
  1197. {
  1198. return PLSR_RESULT_INVALID_AXIS;
  1199. }
  1200. if (detail == NULL)
  1201. {
  1202. return PLSR_RESULT_INVALID_ARGUMENT;
  1203. }
  1204. interruptState = PlsrCoreEnterCritical();
  1205. *detail = PlsrAxes[axis].parseDetail;
  1206. PlsrCoreExitCritical(interruptState);
  1207. return PLSR_RESULT_OK;
  1208. }