選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 
 

1260 行
44 KiB

  1. #include "plsr_job.h"
  2. #include "plc_device.h"
  3. #include "plsr_address_map.h"
  4. #include <limits.h>
  5. #include <string.h>
  6. #define PLSR_S0_HEADER_WORDS (10UL)
  7. #define PLSR_S0_SEGMENT_WORDS (10UL)
  8. #define PLSR_S1_WORDS (4UL)
  9. #define PLSR_SFD_AXIS_STRIDE (130U)
  10. #define PLSR_SFD_SET_OFFSET (50U)
  11. #define PLSR_S2_SET_WORDS (20U)
  12. #define PLSR_HSD_SET_BASE (460U)
  13. #define PLSR_TIMER_168MHZ (168000000UL)
  14. #define PLSR_TIMER_84MHZ (84000000UL)
  15. static void PlsrSetDetail(PLSR_PARSE_DETAIL *detail,
  16. PLSR_RESULT result,
  17. PLSR_PARSE_BLOCK block,
  18. uint32_t address,
  19. int32_t value,
  20. uint16_t segment)
  21. {
  22. if (detail != NULL)
  23. {
  24. detail->result = result;
  25. detail->block = block;
  26. detail->address = address;
  27. detail->value = value;
  28. detail->segment = segment;
  29. }
  30. }
  31. static uint8_t PlsrIsWordDevice(PLSR_DEVICE_TYPE device)
  32. {
  33. return ((device == PLSR_DEVICE_D) || (device == PLSR_DEVICE_HD)
  34. || (device == PLSR_DEVICE_FD))
  35. ? 1U
  36. : 0U;
  37. }
  38. static uint8_t PlsrSourceIsUsable(const PLSR_DATA_SOURCE *source)
  39. {
  40. return ((source != NULL) && (source->validateWords != NULL)
  41. && (source->readWord != NULL))
  42. ? 1U
  43. : 0U;
  44. }
  45. static PLSR_RESULT PlsrValidateRange(const PLSR_DATA_SOURCE *source,
  46. PLSR_DATA_REF reference,
  47. uint32_t wordCount,
  48. PLSR_PARSE_BLOCK block,
  49. PLSR_PARSE_DETAIL *detail)
  50. {
  51. uint64_t endAddress;
  52. if ((PlsrIsWordDevice(reference.device) == 0U) || (wordCount == 0UL))
  53. {
  54. PlsrSetDetail(detail,
  55. PLSR_RESULT_DATA_ACCESS,
  56. block,
  57. reference.address,
  58. (int32_t)reference.device,
  59. 0U);
  60. return PLSR_RESULT_DATA_ACCESS;
  61. }
  62. endAddress = (uint64_t)reference.address + (uint64_t)wordCount - 1ULL;
  63. if (endAddress > UINT32_MAX)
  64. {
  65. PlsrSetDetail(detail,
  66. PLSR_RESULT_ADDRESS_OVERFLOW,
  67. block,
  68. reference.address,
  69. (int32_t)wordCount,
  70. 0U);
  71. return PLSR_RESULT_ADDRESS_OVERFLOW;
  72. }
  73. if (source->validateWords(source->context,
  74. reference.device,
  75. reference.address,
  76. wordCount)
  77. == 0U)
  78. {
  79. PlsrSetDetail(detail,
  80. PLSR_RESULT_DATA_ACCESS,
  81. block,
  82. reference.address,
  83. (int32_t)wordCount,
  84. 0U);
  85. return PLSR_RESULT_DATA_ACCESS;
  86. }
  87. return PLSR_RESULT_OK;
  88. }
  89. static PLSR_RESULT PlsrReadWord(const PLSR_DATA_SOURCE *source,
  90. PLSR_DEVICE_TYPE device,
  91. uint32_t address,
  92. uint16_t *value,
  93. PLSR_PARSE_BLOCK block,
  94. uint16_t segment,
  95. PLSR_PARSE_DETAIL *detail)
  96. {
  97. if ((value == NULL)
  98. || (source->readWord(source->context, device, address, value) == 0U))
  99. {
  100. PlsrSetDetail(detail,
  101. PLSR_RESULT_DATA_ACCESS,
  102. block,
  103. address,
  104. 0,
  105. segment);
  106. return PLSR_RESULT_DATA_ACCESS;
  107. }
  108. return PLSR_RESULT_OK;
  109. }
  110. static PLSR_RESULT PlsrReadInt32(const PLSR_DATA_SOURCE *source,
  111. PLSR_DEVICE_TYPE device,
  112. uint32_t address,
  113. int32_t *value,
  114. PLSR_PARSE_BLOCK block,
  115. uint16_t segment,
  116. PLSR_PARSE_DETAIL *detail)
  117. {
  118. uint16_t lowWord;
  119. uint16_t highWord;
  120. PLSR_RESULT result;
  121. if (address == UINT32_MAX)
  122. {
  123. PlsrSetDetail(detail,
  124. PLSR_RESULT_ADDRESS_OVERFLOW,
  125. block,
  126. address,
  127. 2,
  128. segment);
  129. return PLSR_RESULT_ADDRESS_OVERFLOW;
  130. }
  131. result = PlsrReadWord(source,
  132. device,
  133. address,
  134. &lowWord,
  135. block,
  136. segment,
  137. detail);
  138. if (result != PLSR_RESULT_OK)
  139. {
  140. return result;
  141. }
  142. result = PlsrReadWord(source,
  143. device,
  144. address + 1UL,
  145. &highWord,
  146. block,
  147. segment,
  148. detail);
  149. if (result != PLSR_RESULT_OK)
  150. {
  151. return result;
  152. }
  153. *value = (int32_t)(((uint32_t)highWord << 16U) | (uint32_t)lowWord);
  154. return PLSR_RESULT_OK;
  155. }
  156. static uint8_t PlsrBlocksOverlap(PLSR_DATA_REF first,
  157. uint32_t firstWords,
  158. PLSR_DATA_REF second,
  159. uint32_t secondWords)
  160. {
  161. uint64_t firstEnd;
  162. uint64_t secondEnd;
  163. if (first.device != second.device)
  164. {
  165. return 0U;
  166. }
  167. firstEnd = (uint64_t)first.address + (uint64_t)firstWords - 1ULL;
  168. secondEnd = (uint64_t)second.address + (uint64_t)secondWords - 1ULL;
  169. return (((uint64_t)first.address <= secondEnd)
  170. && ((uint64_t)second.address <= firstEnd))
  171. ? 1U
  172. : 0U;
  173. }
  174. static PLSR_RESULT PlsrReadFixedWord(uint8_t useHsd,
  175. uint16_t address,
  176. uint16_t *value,
  177. PLSR_PARSE_DETAIL *detail)
  178. {
  179. PLC_DEVICE_RESULT deviceResult;
  180. deviceResult = (useHsd != 0U) ? PlcDeviceReadHsd(address, value)
  181. : PlcDeviceReadSfd(address, value);
  182. if (deviceResult != PLC_DEVICE_OK)
  183. {
  184. PlsrSetDetail(detail,
  185. PLSR_RESULT_INVALID_S2,
  186. PLSR_PARSE_BLOCK_S2,
  187. address,
  188. 0,
  189. 0U);
  190. return PLSR_RESULT_INVALID_S2;
  191. }
  192. return PLSR_RESULT_OK;
  193. }
  194. static PLSR_RESULT PlsrReadFixedDword(uint8_t useHsd,
  195. uint16_t address,
  196. uint32_t *value,
  197. PLSR_PARSE_DETAIL *detail)
  198. {
  199. uint16_t lowWord;
  200. uint16_t highWord;
  201. PLSR_RESULT result;
  202. result = PlsrReadFixedWord(useHsd, address, &lowWord, detail);
  203. if (result != PLSR_RESULT_OK)
  204. {
  205. return result;
  206. }
  207. result = PlsrReadFixedWord(useHsd,
  208. (uint16_t)(address + 1U),
  209. &highWord,
  210. detail);
  211. if (result != PLSR_RESULT_OK)
  212. {
  213. return result;
  214. }
  215. *value = ((uint32_t)highWord << 16U) | (uint32_t)lowWord;
  216. return PLSR_RESULT_OK;
  217. }
  218. PLSR_RESULT PlsrCalculateTimerDivider(uint32_t timerClockHz,
  219. uint32_t frequencyHz,
  220. uint16_t *psc,
  221. uint16_t *arr)
  222. {
  223. uint64_t minimumDivider;
  224. uint64_t periodTicks;
  225. if ((timerClockHz == 0UL) || (frequencyHz == 0UL) || (psc == NULL)
  226. || (arr == NULL))
  227. {
  228. return PLSR_RESULT_INVALID_ARGUMENT;
  229. }
  230. minimumDivider = ((uint64_t)timerClockHz
  231. + ((uint64_t)frequencyHz * 65536ULL) - 1ULL)
  232. / ((uint64_t)frequencyHz * 65536ULL);
  233. if (minimumDivider == 0ULL)
  234. {
  235. minimumDivider = 1ULL;
  236. }
  237. if (minimumDivider > 65536ULL)
  238. {
  239. return PLSR_RESULT_DIVIDER_UNREPRESENTABLE;
  240. }
  241. periodTicks = ((uint64_t)timerClockHz
  242. + ((uint64_t)frequencyHz * minimumDivider) / 2ULL)
  243. / ((uint64_t)frequencyHz * minimumDivider);
  244. if ((periodTicks < 2ULL) || (periodTicks > 65536ULL))
  245. {
  246. return PLSR_RESULT_DIVIDER_UNREPRESENTABLE;
  247. }
  248. *psc = (uint16_t)(minimumDivider - 1ULL);
  249. *arr = (uint16_t)(periodTicks - 1ULL);
  250. return PLSR_RESULT_OK;
  251. }
  252. static PLSR_RESULT PlsrValidateFrequencyDivider(
  253. const PLSR_JOB_SNAPSHOT *snapshot,
  254. uint32_t frequency,
  255. PLSR_PARSE_DETAIL *detail,
  256. uint16_t segment)
  257. {
  258. uint16_t psc;
  259. uint16_t arr;
  260. PLSR_RESULT result;
  261. result = PlsrCalculateTimerDivider(snapshot->timerClockHz,
  262. frequency,
  263. &psc,
  264. &arr);
  265. if ((result == PLSR_RESULT_OK)
  266. && (snapshot->pairedTimerClockHz != 0UL))
  267. {
  268. result = PlsrCalculateTimerDivider(snapshot->pairedTimerClockHz,
  269. frequency,
  270. &psc,
  271. &arr);
  272. }
  273. if (result != PLSR_RESULT_OK)
  274. {
  275. PlsrSetDetail(detail,
  276. PLSR_RESULT_DIVIDER_UNREPRESENTABLE,
  277. PLSR_PARSE_BLOCK_S0,
  278. snapshot->s0.address
  279. + (uint32_t)segment * PLSR_S0_SEGMENT_WORDS,
  280. (int32_t)frequency,
  281. segment);
  282. return PLSR_RESULT_DIVIDER_UNREPRESENTABLE;
  283. }
  284. return PLSR_RESULT_OK;
  285. }
  286. static PLSR_RESULT PlsrResolveOperand(const PLSR_CALL *call,
  287. const PLSR_VALUE_OPERAND *operand,
  288. int32_t *value,
  289. PLSR_PARSE_DETAIL *detail)
  290. {
  291. PLSR_RESULT result;
  292. if (operand->type == PLSR_OPERAND_CONSTANT)
  293. {
  294. *value = operand->constant;
  295. return PLSR_RESULT_OK;
  296. }
  297. if ((operand->type != PLSR_OPERAND_DATA)
  298. || (PlsrIsWordDevice(operand->data.device) == 0U))
  299. {
  300. PlsrSetDetail(detail,
  301. PLSR_RESULT_INVALID_S2,
  302. PLSR_PARSE_BLOCK_S2,
  303. operand->data.address,
  304. (int32_t)operand->type,
  305. 0U);
  306. return PLSR_RESULT_INVALID_S2;
  307. }
  308. result = PlsrValidateRange(&call->source,
  309. operand->data,
  310. 2UL,
  311. PLSR_PARSE_BLOCK_S2,
  312. detail);
  313. if (result != PLSR_RESULT_OK)
  314. {
  315. return result;
  316. }
  317. return PlsrReadInt32(&call->source,
  318. operand->data.device,
  319. operand->data.address,
  320. value,
  321. PLSR_PARSE_BLOCK_S2,
  322. 0U,
  323. detail);
  324. }
  325. static PLSR_RESULT PlsrLoadS2(const PLSR_CALL *call,
  326. PLSR_JOB_SNAPSHOT *snapshot,
  327. PLSR_PARSE_DETAIL *detail)
  328. {
  329. uint16_t commonBase;
  330. uint16_t setBase;
  331. uint16_t word;
  332. int32_t selectedSet;
  333. uint8_t useHsd;
  334. PLSR_RESULT result;
  335. result = PlsrResolveOperand(call, &call->s2, &selectedSet, detail);
  336. if (result != PLSR_RESULT_OK)
  337. {
  338. return result;
  339. }
  340. if ((selectedSet < 0) || (selectedSet > 4))
  341. {
  342. PlsrSetDetail(detail,
  343. PLSR_RESULT_INVALID_S2,
  344. PLSR_PARSE_BLOCK_S2,
  345. call->s2.data.address,
  346. selectedSet,
  347. 0U);
  348. return PLSR_RESULT_INVALID_S2;
  349. }
  350. snapshot->s2Set = (uint8_t)selectedSet;
  351. commonBase = (uint16_t)(PLSR_SFD_CONFIG_START
  352. + (uint16_t)call->dAxis
  353. * PLSR_SFD_AXIS_STRIDE);
  354. if (snapshot->s2Set == 0U)
  355. {
  356. useHsd = 1U;
  357. setBase = (uint16_t)(PLSR_HSD_SET_BASE
  358. + (uint16_t)call->dAxis * PLSR_S2_SET_WORDS);
  359. }
  360. else
  361. {
  362. useHsd = 0U;
  363. setBase = (uint16_t)(commonBase + PLSR_SFD_SET_OFFSET
  364. + (uint16_t)(snapshot->s2Set - 1U)
  365. * PLSR_S2_SET_WORDS);
  366. }
  367. result = PlsrReadFixedDword(useHsd,
  368. setBase,
  369. &snapshot->s2.defaultSpeed,
  370. detail);
  371. if (result != PLSR_RESULT_OK) return result;
  372. result = PlsrReadFixedWord(useHsd,
  373. (uint16_t)(setBase + 2U),
  374. &snapshot->s2.accelerationMs,
  375. detail);
  376. if (result != PLSR_RESULT_OK) return result;
  377. result = PlsrReadFixedWord(useHsd,
  378. (uint16_t)(setBase + 3U),
  379. &snapshot->s2.decelerationMs,
  380. detail);
  381. if (result != PLSR_RESULT_OK) return result;
  382. result = PlsrReadFixedWord(useHsd,
  383. (uint16_t)(setBase + 4U),
  384. &snapshot->s2.gapAccelerationMs,
  385. detail);
  386. if (result != PLSR_RESULT_OK) return result;
  387. result = PlsrReadFixedWord(useHsd,
  388. (uint16_t)(setBase + 5U),
  389. &word,
  390. detail);
  391. if (result != PLSR_RESULT_OK) return result;
  392. snapshot->s2.curveMode = (uint8_t)(word & 0x03U);
  393. result = PlsrReadFixedDword(useHsd,
  394. (uint16_t)(setBase + 6U),
  395. &snapshot->s2.maximumSpeed,
  396. detail);
  397. if (result != PLSR_RESULT_OK) return result;
  398. result = PlsrReadFixedDword(useHsd,
  399. (uint16_t)(setBase + 8U),
  400. &snapshot->s2.startSpeed,
  401. detail);
  402. if (result != PLSR_RESULT_OK) return result;
  403. result = PlsrReadFixedDword(useHsd,
  404. (uint16_t)(setBase + 10U),
  405. &snapshot->s2.stopSpeed,
  406. detail);
  407. if (result != PLSR_RESULT_OK) return result;
  408. result = PlsrReadFixedWord(useHsd,
  409. (uint16_t)(setBase + 12U),
  410. &word,
  411. detail);
  412. if (result != PLSR_RESULT_OK) return result;
  413. if ((word < 1U) || (word > 100U))
  414. {
  415. PlsrSetDetail(detail,
  416. PLSR_RESULT_INVALID_S2,
  417. PLSR_PARSE_BLOCK_S2,
  418. (uint16_t)(setBase + 12U),
  419. word,
  420. 0U);
  421. return PLSR_RESULT_INVALID_S2;
  422. }
  423. snapshot->s2.follow = (uint8_t)word;
  424. result = PlsrReadFixedWord(useHsd,
  425. (uint16_t)(setBase + 13U),
  426. &word,
  427. detail);
  428. if (result != PLSR_RESULT_OK) return result;
  429. if (word > 100U)
  430. {
  431. PlsrSetDetail(detail,
  432. PLSR_RESULT_INVALID_S2,
  433. PLSR_PARSE_BLOCK_S2,
  434. (uint16_t)(setBase + 13U),
  435. word,
  436. 0U);
  437. return PLSR_RESULT_INVALID_S2;
  438. }
  439. snapshot->s2.feedforwardPercent = (uint8_t)word;
  440. result = PlsrReadFixedWord(useHsd,
  441. (uint16_t)(setBase + 14U),
  442. &word,
  443. detail);
  444. if (result != PLSR_RESULT_OK) return result;
  445. snapshot->s2.refreshCode = (uint8_t)(word & 0x03U);
  446. result = PlsrReadFixedDword(useHsd,
  447. (uint16_t)(setBase + 16U),
  448. &snapshot->s2.zrnHighSpeed,
  449. detail);
  450. if (result != PLSR_RESULT_OK) return result;
  451. result = PlsrReadFixedDword(useHsd,
  452. (uint16_t)(setBase + 18U),
  453. &snapshot->s2.zrnCrawlSpeed,
  454. detail);
  455. if (result != PLSR_RESULT_OK) return result;
  456. result = PlsrReadFixedWord(0U, commonBase, &word, detail);
  457. if (result != PLSR_RESULT_OK) return result;
  458. snapshot->directionActiveHigh = ((word & (1U << 1U)) != 0U) ? 1U : 0U;
  459. if (call->outputModeOverride == PLSR_OUTPUT_MODE_FROM_SFD)
  460. {
  461. snapshot->outputMode = ((word & (1U << 13U)) != 0U)
  462. ? (uint8_t)PLSR_OUTPUT_AB
  463. : (uint8_t)PLSR_OUTPUT_PULSE_DIR;
  464. }
  465. else if (call->outputModeOverride <= (uint8_t)PLSR_OUTPUT_CW_CCW)
  466. {
  467. snapshot->outputMode = call->outputModeOverride;
  468. }
  469. else
  470. {
  471. PlsrSetDetail(detail,
  472. PLSR_RESULT_INVALID_RESOURCE,
  473. PLSR_PARSE_BLOCK_OUTPUT,
  474. commonBase,
  475. call->outputModeOverride,
  476. 0U);
  477. return PLSR_RESULT_INVALID_RESOURCE;
  478. }
  479. result = PlsrReadFixedWord(0U,
  480. (uint16_t)(commonBase + 6U),
  481. &word,
  482. detail);
  483. if (result != PLSR_RESULT_OK) return result;
  484. if (word > UINT8_MAX)
  485. {
  486. PlsrSetDetail(detail,
  487. PLSR_RESULT_INVALID_RESOURCE,
  488. PLSR_PARSE_BLOCK_OUTPUT,
  489. (uint16_t)(commonBase + 6U),
  490. word,
  491. 0U);
  492. return PLSR_RESULT_INVALID_RESOURCE;
  493. }
  494. snapshot->directionPoint = (uint8_t)word;
  495. result = PlsrReadFixedWord(0U,
  496. (uint16_t)(commonBase + 7U),
  497. &snapshot->s2.directionDelayMs,
  498. detail);
  499. if (result != PLSR_RESULT_OK) return result;
  500. if ((snapshot->s2.maximumSpeed < PLSR_FREQUENCY_MIN_HZ)
  501. || (snapshot->s2.maximumSpeed > PLSR_FREQUENCY_MAX_HZ)
  502. || (snapshot->s2.curveMode > 2U) || (snapshot->s2.follow < 1U)
  503. || (snapshot->s2.follow > 100U)
  504. || (snapshot->s2.feedforwardPercent > 100U)
  505. || ((snapshot->s2.refreshCode != 0U)
  506. && (snapshot->s2.refreshCode != 2U)))
  507. {
  508. PlsrSetDetail(detail,
  509. PLSR_RESULT_INVALID_S2,
  510. PLSR_PARSE_BLOCK_S2,
  511. setBase,
  512. (int32_t)snapshot->s2.maximumSpeed,
  513. 0U);
  514. return PLSR_RESULT_INVALID_S2;
  515. }
  516. if (snapshot->s2.startSpeed > snapshot->s2.maximumSpeed)
  517. {
  518. snapshot->s2.startSpeed = snapshot->s2.maximumSpeed;
  519. snapshot->speedClamped = 1U;
  520. }
  521. if (snapshot->s2.stopSpeed > snapshot->s2.maximumSpeed)
  522. {
  523. snapshot->s2.stopSpeed = snapshot->s2.maximumSpeed;
  524. snapshot->speedClamped = 1U;
  525. }
  526. return PLSR_RESULT_OK;
  527. }
  528. static PLSR_RESULT PlsrValidateVariableReference(
  529. const PLSR_CALL *call,
  530. uint8_t sourceCode,
  531. int32_t addressValue,
  532. uint8_t bitReference,
  533. int32_t *currentValue,
  534. PLSR_PARSE_BLOCK block,
  535. uint16_t segment,
  536. PLSR_PARSE_DETAIL *detail)
  537. {
  538. PLSR_DEVICE_TYPE device;
  539. PLSR_DATA_REF reference;
  540. uint8_t bitValue;
  541. PLSR_RESULT result;
  542. if ((sourceCode == 0U) || (sourceCode > 6U) || (addressValue < 0))
  543. {
  544. PlsrSetDetail(detail,
  545. (block == PLSR_PARSE_BLOCK_S0)
  546. ? PLSR_RESULT_INVALID_WAIT
  547. : PLSR_RESULT_DATA_ACCESS,
  548. block,
  549. (uint32_t)addressValue,
  550. sourceCode,
  551. segment);
  552. return (block == PLSR_PARSE_BLOCK_S0) ? PLSR_RESULT_INVALID_WAIT
  553. : PLSR_RESULT_DATA_ACCESS;
  554. }
  555. device = (PLSR_DEVICE_TYPE)(sourceCode - 1U);
  556. if (bitReference != 0U)
  557. {
  558. if ((device < PLSR_DEVICE_X) || (call->source.readBit == NULL)
  559. || (call->source.readBit(call->source.context,
  560. device,
  561. (uint32_t)addressValue,
  562. &bitValue)
  563. == 0U))
  564. {
  565. PlsrSetDetail(detail,
  566. PLSR_RESULT_INVALID_WAIT,
  567. block,
  568. (uint32_t)addressValue,
  569. sourceCode,
  570. segment);
  571. return PLSR_RESULT_INVALID_WAIT;
  572. }
  573. *currentValue = (int32_t)bitValue;
  574. return PLSR_RESULT_OK;
  575. }
  576. if (PlsrIsWordDevice(device) == 0U)
  577. {
  578. PlsrSetDetail(detail,
  579. PLSR_RESULT_INVALID_WAIT,
  580. block,
  581. (uint32_t)addressValue,
  582. sourceCode,
  583. segment);
  584. return PLSR_RESULT_INVALID_WAIT;
  585. }
  586. reference.device = device;
  587. reference.address = (uint32_t)addressValue;
  588. result = PlsrValidateRange(&call->source,
  589. reference,
  590. 2UL,
  591. block,
  592. detail);
  593. if (result != PLSR_RESULT_OK)
  594. {
  595. return result;
  596. }
  597. return PlsrReadInt32(&call->source,
  598. device,
  599. reference.address,
  600. currentValue,
  601. block,
  602. segment,
  603. detail);
  604. }
  605. static PLSR_RESULT PlsrValidateWait(const PLSR_CALL *call,
  606. PLSR_SEGMENT_SNAPSHOT *segmentData,
  607. uint16_t segment,
  608. PLSR_PARSE_DETAIL *detail)
  609. {
  610. int32_t currentValue;
  611. PLSR_RESULT result;
  612. if ((segmentData->waitCondition > PLSR_WAIT_EXT_OR_COMPLETE)
  613. || (segmentData->waitSource > PLSR_VALUE_HM))
  614. {
  615. goto invalidWait;
  616. }
  617. if (segmentData->waitCondition == PLSR_WAIT_PULSE_COMPLETE)
  618. {
  619. if (segmentData->waitSource != PLSR_VALUE_CONSTANT)
  620. {
  621. goto invalidWait;
  622. }
  623. return PLSR_RESULT_OK;
  624. }
  625. if ((segmentData->waitCondition == PLSR_WAIT_TIME)
  626. || (segmentData->waitCondition == PLSR_WAIT_ACT_TIME))
  627. {
  628. if (segmentData->waitSource == PLSR_VALUE_CONSTANT)
  629. {
  630. currentValue = segmentData->waitValueOrAddress;
  631. }
  632. else
  633. {
  634. if (segmentData->waitSource > PLSR_VALUE_FD)
  635. {
  636. goto invalidWait;
  637. }
  638. result = PlsrValidateVariableReference(call,
  639. segmentData->waitSource,
  640. segmentData->waitValueOrAddress,
  641. 0U,
  642. &currentValue,
  643. PLSR_PARSE_BLOCK_S0,
  644. segment,
  645. detail);
  646. if (result != PLSR_RESULT_OK) return result;
  647. }
  648. if (currentValue < 0) goto invalidWait;
  649. return PLSR_RESULT_OK;
  650. }
  651. if (segmentData->waitCondition == PLSR_WAIT_SIGNAL)
  652. {
  653. if ((segmentData->waitSource < PLSR_VALUE_X)
  654. || (segmentData->waitSource > PLSR_VALUE_HM))
  655. {
  656. goto invalidWait;
  657. }
  658. }
  659. else if ((segmentData->waitCondition == PLSR_WAIT_EXT)
  660. || (segmentData->waitCondition == PLSR_WAIT_EXT_OR_COMPLETE))
  661. {
  662. if (segmentData->waitSource != PLSR_VALUE_X)
  663. {
  664. goto invalidWait;
  665. }
  666. }
  667. result = PlsrValidateVariableReference(call,
  668. segmentData->waitSource,
  669. segmentData->waitValueOrAddress,
  670. 1U,
  671. &currentValue,
  672. PLSR_PARSE_BLOCK_S0,
  673. segment,
  674. detail);
  675. return result;
  676. invalidWait:
  677. PlsrSetDetail(detail,
  678. PLSR_RESULT_INVALID_WAIT,
  679. PLSR_PARSE_BLOCK_S0,
  680. call->s0.address
  681. + (uint32_t)segment * PLSR_S0_SEGMENT_WORDS + 4UL,
  682. ((int32_t)segmentData->waitCondition << 8)
  683. | segmentData->waitSource,
  684. segment);
  685. return PLSR_RESULT_INVALID_WAIT;
  686. }
  687. static PLSR_RESULT PlsrValidateJump(const PLSR_CALL *call,
  688. const PLSR_JOB_SNAPSHOT *snapshot,
  689. PLSR_SEGMENT_SNAPSHOT *segmentData,
  690. uint16_t segment,
  691. int32_t *resolvedJump,
  692. PLSR_PARSE_DETAIL *detail)
  693. {
  694. PLSR_RESULT result;
  695. if (segmentData->jumpSource > PLSR_VALUE_FD)
  696. {
  697. goto invalidJump;
  698. }
  699. if (segmentData->jumpSource == PLSR_VALUE_CONSTANT)
  700. {
  701. *resolvedJump = segmentData->jumpValueOrAddress;
  702. }
  703. else
  704. {
  705. result = PlsrValidateVariableReference(call,
  706. segmentData->jumpSource,
  707. segmentData->jumpValueOrAddress,
  708. 0U,
  709. resolvedJump,
  710. PLSR_PARSE_BLOCK_NONE,
  711. segment,
  712. detail);
  713. if (result != PLSR_RESULT_OK)
  714. {
  715. PlsrSetDetail(detail,
  716. PLSR_RESULT_INVALID_JUMP,
  717. PLSR_PARSE_BLOCK_S0,
  718. (uint32_t)segmentData->jumpValueOrAddress,
  719. segmentData->jumpSource,
  720. segment);
  721. return PLSR_RESULT_INVALID_JUMP;
  722. }
  723. }
  724. if ((*resolvedJump < 0)
  725. || (*resolvedJump > (int32_t)snapshot->segmentCount))
  726. {
  727. goto invalidJump;
  728. }
  729. if (*resolvedJump == (int32_t)segment)
  730. {
  731. segmentData->flags |= PLSR_SEGMENT_FLAG_SELF_LOOP;
  732. }
  733. return PLSR_RESULT_OK;
  734. invalidJump:
  735. PlsrSetDetail(detail,
  736. PLSR_RESULT_INVALID_JUMP,
  737. PLSR_PARSE_BLOCK_S0,
  738. call->s0.address
  739. + (uint32_t)segment * PLSR_S0_SEGMENT_WORDS + 7UL,
  740. *resolvedJump,
  741. segment);
  742. return PLSR_RESULT_INVALID_JUMP;
  743. }
  744. static PLSR_RESULT PlsrCheckConstantPath(PLSR_JOB_SNAPSHOT *snapshot,
  745. PLSR_PARSE_DETAIL *detail)
  746. {
  747. uint8_t visited[PLSR_MAX_SEGMENTS];
  748. uint16_t segment = snapshot->startSegment;
  749. int32_t next;
  750. (void)memset(visited, 0, sizeof(visited));
  751. while ((segment >= 1U) && (segment <= snapshot->segmentCount))
  752. {
  753. if (visited[segment - 1U] != 0U)
  754. {
  755. PlsrSetDetail(detail,
  756. PLSR_RESULT_PATH_CYCLE,
  757. PLSR_PARSE_BLOCK_S0,
  758. snapshot->s0.address
  759. + (uint32_t)segment * PLSR_S0_SEGMENT_WORDS
  760. + 8UL,
  761. segment,
  762. segment);
  763. return PLSR_RESULT_PATH_CYCLE;
  764. }
  765. visited[segment - 1U] = 1U;
  766. if (snapshot->segments[segment - 1U].jumpSource
  767. != PLSR_VALUE_CONSTANT)
  768. {
  769. return PLSR_RESULT_OK;
  770. }
  771. next = snapshot->segments[segment - 1U].jumpValueOrAddress;
  772. if (next == (int32_t)segment)
  773. {
  774. snapshot->hasSelfLoop = 1U;
  775. return PLSR_RESULT_OK;
  776. }
  777. if (next == 0)
  778. {
  779. if (segment == snapshot->segmentCount)
  780. {
  781. return PLSR_RESULT_OK;
  782. }
  783. segment++;
  784. }
  785. else
  786. {
  787. segment = (uint16_t)next;
  788. }
  789. }
  790. return PLSR_RESULT_OK;
  791. }
  792. static PLSR_RESULT PlsrCheckInitialPosition(
  793. PLSR_JOB_SNAPSHOT *snapshot,
  794. const PLSR_PARSE_CONTEXT *context,
  795. PLSR_PARSE_DETAIL *detail)
  796. {
  797. uint8_t visited[PLSR_MAX_SEGMENTS];
  798. int64_t position = context->logicalPosition;
  799. int32_t movement;
  800. int32_t next;
  801. uint16_t segment = snapshot->startSegment;
  802. if ((snapshot->positioningMode != 0U) && (context->positionValid == 0U))
  803. {
  804. PlsrSetDetail(detail,
  805. PLSR_RESULT_POSITION_INVALID,
  806. PLSR_PARSE_BLOCK_POSITION,
  807. snapshot->s1.address,
  808. 1,
  809. 0U);
  810. return PLSR_RESULT_POSITION_INVALID;
  811. }
  812. (void)memset(visited, 0, sizeof(visited));
  813. while ((segment >= 1U) && (segment <= snapshot->segmentCount)
  814. && (visited[segment - 1U] == 0U))
  815. {
  816. PLSR_SEGMENT_SNAPSHOT *segmentData = &snapshot->segments[segment - 1U];
  817. visited[segment - 1U] = 1U;
  818. if (snapshot->positioningMode == 0U)
  819. {
  820. movement = segmentData->pulseOrTarget;
  821. if (((movement > 0) && (position > INT64_MAX - movement))
  822. || ((movement < 0) && (position < INT64_MIN - movement)))
  823. {
  824. PlsrSetDetail(detail,
  825. PLSR_RESULT_POSITION_OVERFLOW,
  826. PLSR_PARSE_BLOCK_POSITION,
  827. snapshot->s0.address
  828. + (uint32_t)segment
  829. * PLSR_S0_SEGMENT_WORDS
  830. + 2UL,
  831. movement,
  832. segment);
  833. return PLSR_RESULT_POSITION_OVERFLOW;
  834. }
  835. position += movement;
  836. }
  837. else
  838. {
  839. movement = (segmentData->pulseOrTarget > position)
  840. ? 1
  841. : ((segmentData->pulseOrTarget < position) ? -1 : 0);
  842. position = segmentData->pulseOrTarget;
  843. }
  844. if ((movement != 0) && (snapshot->initialDirectionPositive == 0U))
  845. {
  846. snapshot->initialDirectionPositive = (movement > 0) ? 2U : 1U;
  847. }
  848. if (segmentData->jumpSource != PLSR_VALUE_CONSTANT)
  849. {
  850. break;
  851. }
  852. next = segmentData->jumpValueOrAddress;
  853. if (next == (int32_t)segment)
  854. {
  855. break;
  856. }
  857. if (next == 0)
  858. {
  859. if (segment == snapshot->segmentCount) break;
  860. segment++;
  861. }
  862. else
  863. {
  864. segment = (uint16_t)next;
  865. }
  866. }
  867. snapshot->initialDirectionPositive =
  868. (snapshot->initialDirectionPositive == 2U) ? 1U : 0U;
  869. return PLSR_RESULT_OK;
  870. }
  871. PLSR_RESULT PlsrBuildJobSnapshot(const PLSR_CALL *call,
  872. const PLSR_PARSE_CONTEXT *context,
  873. PLSR_JOB_SNAPSHOT *snapshot,
  874. PLSR_PARSE_DETAIL *detail)
  875. {
  876. uint64_t s0Words64;
  877. uint32_t s0Words;
  878. uint32_t segmentBase;
  879. int32_t intValue;
  880. int32_t resolvedJump;
  881. uint16_t word;
  882. uint16_t segment;
  883. uint8_t index;
  884. PLSR_RESULT result;
  885. if ((call == NULL) || (context == NULL) || (snapshot == NULL)
  886. || (PlsrSourceIsUsable(&call->source) == 0U))
  887. {
  888. return PLSR_RESULT_INVALID_ARGUMENT;
  889. }
  890. if (call->dAxis >= PLSR_AXIS_COUNT)
  891. {
  892. return PLSR_RESULT_INVALID_AXIS;
  893. }
  894. (void)memset(snapshot, 0, sizeof(*snapshot));
  895. if (detail != NULL) (void)memset(detail, 0, sizeof(*detail));
  896. snapshot->source = call->source;
  897. snapshot->s0 = call->s0;
  898. snapshot->s1 = call->s1;
  899. snapshot->dAxis = call->dAxis;
  900. snapshot->timerClockHz = ((call->dAxis == 0U) || (call->dAxis == 2U))
  901. ? PLSR_TIMER_168MHZ
  902. : PLSR_TIMER_84MHZ;
  903. result = PlsrValidateRange(&call->source,
  904. call->s0,
  905. PLSR_S0_HEADER_WORDS,
  906. PLSR_PARSE_BLOCK_S0,
  907. detail);
  908. if (result != PLSR_RESULT_OK) return result;
  909. result = PlsrReadInt32(&call->source,
  910. call->s0.device,
  911. call->s0.address,
  912. &intValue,
  913. PLSR_PARSE_BLOCK_S0,
  914. 0U,
  915. detail);
  916. if ((result != PLSR_RESULT_OK) || (intValue < 1)
  917. || (intValue > (int32_t)PLSR_MAX_SEGMENTS))
  918. {
  919. if (result == PLSR_RESULT_OK)
  920. {
  921. PlsrSetDetail(detail,
  922. PLSR_RESULT_SEGMENT_OVERFLOW,
  923. PLSR_PARSE_BLOCK_S0,
  924. call->s0.address,
  925. intValue,
  926. 0U);
  927. result = PLSR_RESULT_SEGMENT_OVERFLOW;
  928. }
  929. return result;
  930. }
  931. snapshot->segmentCount = (uint16_t)intValue;
  932. s0Words64 = (uint64_t)snapshot->segmentCount * PLSR_S0_SEGMENT_WORDS
  933. + PLSR_S0_HEADER_WORDS;
  934. if (s0Words64 > UINT32_MAX)
  935. {
  936. return PLSR_RESULT_ADDRESS_OVERFLOW;
  937. }
  938. s0Words = (uint32_t)s0Words64;
  939. result = PlsrValidateRange(&call->source,
  940. call->s0,
  941. s0Words,
  942. PLSR_PARSE_BLOCK_S0,
  943. detail);
  944. if (result != PLSR_RESULT_OK) return result;
  945. result = PlsrValidateRange(&call->source,
  946. call->s1,
  947. PLSR_S1_WORDS,
  948. PLSR_PARSE_BLOCK_S1,
  949. detail);
  950. if (result != PLSR_RESULT_OK) return result;
  951. if (PlsrBlocksOverlap(call->s0, s0Words, call->s1, PLSR_S1_WORDS) != 0U)
  952. {
  953. PlsrSetDetail(detail,
  954. PLSR_RESULT_BLOCK_OVERLAP,
  955. PLSR_PARSE_BLOCK_S1,
  956. call->s1.address,
  957. (int32_t)s0Words,
  958. 0U);
  959. return PLSR_RESULT_BLOCK_OVERLAP;
  960. }
  961. for (index = 2U; index < 10U; index++)
  962. {
  963. result = PlsrReadWord(&call->source,
  964. call->s0.device,
  965. call->s0.address + index,
  966. &word,
  967. PLSR_PARSE_BLOCK_S0,
  968. 0U,
  969. detail);
  970. if (result != PLSR_RESULT_OK) return result;
  971. if (word != 0U)
  972. {
  973. PlsrSetDetail(detail,
  974. PLSR_RESULT_RESERVED_NOT_ZERO,
  975. PLSR_PARSE_BLOCK_S0,
  976. call->s0.address + index,
  977. word,
  978. 0U);
  979. return PLSR_RESULT_RESERVED_NOT_ZERO;
  980. }
  981. }
  982. result = PlsrReadInt32(&call->source,
  983. call->s1.device,
  984. call->s1.address,
  985. &intValue,
  986. PLSR_PARSE_BLOCK_S1,
  987. 0U,
  988. detail);
  989. if (result != PLSR_RESULT_OK) return result;
  990. if ((intValue < 0) || (intValue > 1))
  991. {
  992. PlsrSetDetail(detail,
  993. PLSR_RESULT_INVALID_POSITION_MODE,
  994. PLSR_PARSE_BLOCK_S1,
  995. call->s1.address,
  996. intValue,
  997. 0U);
  998. return PLSR_RESULT_INVALID_POSITION_MODE;
  999. }
  1000. snapshot->positioningMode = (uint8_t)intValue;
  1001. result = PlsrReadInt32(&call->source,
  1002. call->s1.device,
  1003. call->s1.address + 2UL,
  1004. &intValue,
  1005. PLSR_PARSE_BLOCK_S1,
  1006. 0U,
  1007. detail);
  1008. if (result != PLSR_RESULT_OK) return result;
  1009. if ((intValue < 0) || (intValue > snapshot->segmentCount))
  1010. {
  1011. PlsrSetDetail(detail,
  1012. PLSR_RESULT_INVALID_ARGUMENT,
  1013. PLSR_PARSE_BLOCK_S1,
  1014. call->s1.address + 2UL,
  1015. intValue,
  1016. 0U);
  1017. return PLSR_RESULT_INVALID_ARGUMENT;
  1018. }
  1019. snapshot->startSegment = (intValue <= 1) ? 1U : (uint16_t)intValue;
  1020. result = PlsrLoadS2(call, snapshot, detail);
  1021. if (result != PLSR_RESULT_OK) return result;
  1022. if ((snapshot->outputMode == PLSR_OUTPUT_AB)
  1023. || (snapshot->outputMode == PLSR_OUTPUT_CW_CCW))
  1024. {
  1025. if ((call->dAxis != 0U) && (call->dAxis != 2U))
  1026. {
  1027. PlsrSetDetail(detail,
  1028. PLSR_RESULT_INVALID_RESOURCE,
  1029. PLSR_PARSE_BLOCK_OUTPUT,
  1030. call->dAxis,
  1031. snapshot->outputMode,
  1032. 0U);
  1033. return PLSR_RESULT_INVALID_RESOURCE;
  1034. }
  1035. snapshot->pairedTimerClockHz = PLSR_TIMER_84MHZ;
  1036. }
  1037. for (segment = 1U; segment <= snapshot->segmentCount; segment++)
  1038. {
  1039. PLSR_SEGMENT_SNAPSHOT *segmentData = &snapshot->segments[segment - 1U];
  1040. segmentBase = call->s0.address
  1041. + (uint32_t)segment * PLSR_S0_SEGMENT_WORDS;
  1042. result = PlsrReadInt32(&call->source,
  1043. call->s0.device,
  1044. segmentBase,
  1045. &intValue,
  1046. PLSR_PARSE_BLOCK_S0,
  1047. segment,
  1048. detail);
  1049. if (result != PLSR_RESULT_OK) return result;
  1050. if (intValue < 0)
  1051. {
  1052. PlsrSetDetail(detail,
  1053. PLSR_RESULT_INVALID_FREQUENCY,
  1054. PLSR_PARSE_BLOCK_S0,
  1055. segmentBase,
  1056. intValue,
  1057. segment);
  1058. return PLSR_RESULT_INVALID_FREQUENCY;
  1059. }
  1060. segmentData->targetFrequency = (uint32_t)intValue;
  1061. result = PlsrReadInt32(&call->source,
  1062. call->s0.device,
  1063. segmentBase + 2UL,
  1064. &segmentData->pulseOrTarget,
  1065. PLSR_PARSE_BLOCK_S0,
  1066. segment,
  1067. detail);
  1068. if (result != PLSR_RESULT_OK) return result;
  1069. result = PlsrReadWord(&call->source,
  1070. call->s0.device,
  1071. segmentBase + 4UL,
  1072. &word,
  1073. PLSR_PARSE_BLOCK_S0,
  1074. segment,
  1075. detail);
  1076. if (result != PLSR_RESULT_OK) return result;
  1077. segmentData->waitSource = (uint8_t)(word & 0xFFU);
  1078. segmentData->waitCondition = (uint8_t)(word >> 8U);
  1079. result = PlsrReadInt32(&call->source,
  1080. call->s0.device,
  1081. segmentBase + 5UL,
  1082. &segmentData->waitValueOrAddress,
  1083. PLSR_PARSE_BLOCK_S0,
  1084. segment,
  1085. detail);
  1086. if (result != PLSR_RESULT_OK) return result;
  1087. result = PlsrReadWord(&call->source,
  1088. call->s0.device,
  1089. segmentBase + 7UL,
  1090. &word,
  1091. PLSR_PARSE_BLOCK_S0,
  1092. segment,
  1093. detail);
  1094. if (result != PLSR_RESULT_OK) return result;
  1095. if ((word & 0xFF00U) != 0U)
  1096. {
  1097. PlsrSetDetail(detail,
  1098. PLSR_RESULT_RESERVED_NOT_ZERO,
  1099. PLSR_PARSE_BLOCK_S0,
  1100. segmentBase + 7UL,
  1101. word,
  1102. segment);
  1103. return PLSR_RESULT_RESERVED_NOT_ZERO;
  1104. }
  1105. segmentData->jumpSource = (uint8_t)(word & 0xFFU);
  1106. result = PlsrReadInt32(&call->source,
  1107. call->s0.device,
  1108. segmentBase + 8UL,
  1109. &segmentData->jumpValueOrAddress,
  1110. PLSR_PARSE_BLOCK_S0,
  1111. segment,
  1112. detail);
  1113. if (result != PLSR_RESULT_OK) return result;
  1114. if ((snapshot->positioningMode == 0U)
  1115. && (segmentData->pulseOrTarget == 0))
  1116. {
  1117. segmentData->flags |= PLSR_SEGMENT_FLAG_ZERO_PULSE;
  1118. segmentData->targetFrequency = 0UL;
  1119. }
  1120. else if (segmentData->targetFrequency == 0UL)
  1121. {
  1122. if (snapshot->s2.defaultSpeed == 0UL)
  1123. {
  1124. PlsrSetDetail(detail,
  1125. PLSR_RESULT_INVALID_FREQUENCY,
  1126. PLSR_PARSE_BLOCK_S2,
  1127. 0UL,
  1128. 0,
  1129. segment);
  1130. return PLSR_RESULT_INVALID_FREQUENCY;
  1131. }
  1132. segmentData->targetFrequency = snapshot->s2.defaultSpeed;
  1133. segmentData->flags |= PLSR_SEGMENT_FLAG_DEFAULT_SPEED;
  1134. }
  1135. if (segmentData->targetFrequency > snapshot->s2.maximumSpeed)
  1136. {
  1137. segmentData->targetFrequency = snapshot->s2.maximumSpeed;
  1138. segmentData->flags |= PLSR_SEGMENT_FLAG_SPEED_CLAMPED;
  1139. snapshot->speedClamped = 1U;
  1140. }
  1141. if (segmentData->targetFrequency != 0UL)
  1142. {
  1143. result = PlsrValidateFrequencyDivider(snapshot,
  1144. segmentData->targetFrequency,
  1145. detail,
  1146. segment);
  1147. if (result != PLSR_RESULT_OK) return result;
  1148. }
  1149. result = PlsrValidateWait(call, segmentData, segment, detail);
  1150. if (result != PLSR_RESULT_OK) return result;
  1151. result = PlsrValidateJump(call,
  1152. snapshot,
  1153. segmentData,
  1154. segment,
  1155. &resolvedJump,
  1156. detail);
  1157. if (result != PLSR_RESULT_OK) return result;
  1158. }
  1159. result = PlsrCheckConstantPath(snapshot, detail);
  1160. if (result != PLSR_RESULT_OK) return result;
  1161. result = PlsrCheckInitialPosition(snapshot, context, detail);
  1162. if (result != PLSR_RESULT_OK) return result;
  1163. if (detail != NULL) detail->result = PLSR_RESULT_OK;
  1164. return PLSR_RESULT_OK;
  1165. }
  1166. PLSR_RESULT PlsrResolveLiveFrequency(const PLSR_JOB_SNAPSHOT *snapshot,
  1167. uint16_t segment,
  1168. uint32_t *frequency,
  1169. uint8_t *clamped)
  1170. {
  1171. int32_t rawFrequency;
  1172. uint32_t segmentAddress;
  1173. PLSR_RESULT result;
  1174. if ((snapshot == NULL) || (frequency == NULL) || (clamped == NULL)
  1175. || (segment < 1U) || (segment > snapshot->segmentCount))
  1176. {
  1177. return PLSR_RESULT_INVALID_ARGUMENT;
  1178. }
  1179. if ((snapshot->segments[segment - 1U].flags
  1180. & PLSR_SEGMENT_FLAG_ZERO_PULSE)
  1181. != 0U)
  1182. {
  1183. *frequency = 0UL;
  1184. *clamped = 0U;
  1185. return PLSR_RESULT_OK;
  1186. }
  1187. segmentAddress = snapshot->s0.address
  1188. + (uint32_t)segment * PLSR_S0_SEGMENT_WORDS;
  1189. result = PlsrReadInt32(&snapshot->source,
  1190. snapshot->s0.device,
  1191. segmentAddress,
  1192. &rawFrequency,
  1193. PLSR_PARSE_BLOCK_S0,
  1194. segment,
  1195. NULL);
  1196. if (result != PLSR_RESULT_OK) return result;
  1197. if (rawFrequency < 0) return PLSR_RESULT_INVALID_FREQUENCY;
  1198. *frequency = (rawFrequency == 0) ? snapshot->s2.defaultSpeed
  1199. : (uint32_t)rawFrequency;
  1200. *clamped = 0U;
  1201. if (*frequency > snapshot->s2.maximumSpeed)
  1202. {
  1203. *frequency = snapshot->s2.maximumSpeed;
  1204. *clamped = 1U;
  1205. }
  1206. if (*frequency == 0UL) return PLSR_RESULT_INVALID_FREQUENCY;
  1207. return PlsrValidateFrequencyDivider(snapshot, *frequency, NULL, segment);
  1208. }