No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

1454 líneas
46 KiB

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