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.
 
 
 
 
 
 

1162 lines
35 KiB

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