Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

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