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.
 
 
 
 
 
 

617 line
21 KiB

  1. #include "plc_device.h"
  2. #include "plsr_core.h"
  3. #include "plsr_job.h"
  4. #include "plsr_persistence.h"
  5. #include <stdio.h>
  6. #include <string.h>
  7. #define TEST_WORD_CAPACITY (3000U)
  8. #define TEST_BIT_CAPACITY (128U)
  9. typedef struct
  10. {
  11. uint16_t words[3][TEST_WORD_CAPACITY];
  12. uint8_t bits[3][TEST_BIT_CAPACITY];
  13. } TEST_MEMORY;
  14. static int TestFailures;
  15. static int TestChecks;
  16. #define CHECK(condition) \
  17. do \
  18. { \
  19. TestChecks++; \
  20. if (!(condition)) \
  21. { \
  22. TestFailures++; \
  23. (void)printf("FAIL line %d: %s\n", __LINE__, #condition); \
  24. } \
  25. } while (0)
  26. static uint8_t TestValidateWords(void *context,
  27. PLSR_DEVICE_TYPE device,
  28. uint32_t firstAddress,
  29. uint32_t wordCount)
  30. {
  31. (void)context;
  32. if ((device > PLSR_DEVICE_FD) || (wordCount == 0UL))
  33. {
  34. return 0U;
  35. }
  36. return (((uint64_t)firstAddress + wordCount) <= TEST_WORD_CAPACITY)
  37. ? 1U
  38. : 0U;
  39. }
  40. static uint8_t TestReadWord(void *context,
  41. PLSR_DEVICE_TYPE device,
  42. uint32_t address,
  43. uint16_t *value)
  44. {
  45. TEST_MEMORY *memory = (TEST_MEMORY *)context;
  46. if ((memory == NULL) || (value == NULL) || (device > PLSR_DEVICE_FD)
  47. || (address >= TEST_WORD_CAPACITY))
  48. {
  49. return 0U;
  50. }
  51. *value = memory->words[device][address];
  52. return 1U;
  53. }
  54. static uint8_t TestReadBit(void *context,
  55. PLSR_DEVICE_TYPE device,
  56. uint32_t address,
  57. uint8_t *value)
  58. {
  59. TEST_MEMORY *memory = (TEST_MEMORY *)context;
  60. uint8_t index;
  61. if ((memory == NULL) || (value == NULL) || (device < PLSR_DEVICE_X)
  62. || (device > PLSR_DEVICE_HM) || (address >= TEST_BIT_CAPACITY))
  63. {
  64. return 0U;
  65. }
  66. index = (uint8_t)(device - PLSR_DEVICE_X);
  67. *value = memory->bits[index][address];
  68. return 1U;
  69. }
  70. static void TestWriteDword(TEST_MEMORY *memory,
  71. PLSR_DEVICE_TYPE device,
  72. uint32_t address,
  73. int32_t value)
  74. {
  75. uint32_t raw = (uint32_t)value;
  76. memory->words[device][address] = (uint16_t)(raw & 0xFFFFUL);
  77. memory->words[device][address + 1UL] = (uint16_t)(raw >> 16U);
  78. }
  79. static void TestWriteSfdDword(uint16_t address, uint32_t value)
  80. {
  81. CHECK(PlcDeviceWriteSfd(address, (int32_t)(value & 0xFFFFUL))
  82. == PLC_DEVICE_OK);
  83. CHECK(PlcDeviceWriteSfd((uint16_t)(address + 1U),
  84. (int32_t)(value >> 16U))
  85. == PLC_DEVICE_OK);
  86. }
  87. static void TestConfigureAxis0K1(void)
  88. {
  89. CHECK(PlcDeviceWriteSfd(900U, 0) == PLC_DEVICE_OK);
  90. CHECK(PlcDeviceWriteSfd(906U, 4) == PLC_DEVICE_OK);
  91. CHECK(PlcDeviceWriteSfd(907U, 10) == PLC_DEVICE_OK);
  92. TestWriteSfdDword(950U, 1000UL);
  93. CHECK(PlcDeviceWriteSfd(952U, 100) == PLC_DEVICE_OK);
  94. CHECK(PlcDeviceWriteSfd(953U, 120) == PLC_DEVICE_OK);
  95. CHECK(PlcDeviceWriteSfd(954U, 10) == PLC_DEVICE_OK);
  96. CHECK(PlcDeviceWriteSfd(955U, 0) == PLC_DEVICE_OK);
  97. TestWriteSfdDword(956U, 100000UL);
  98. TestWriteSfdDword(958U, 120000UL);
  99. TestWriteSfdDword(960U, 500UL);
  100. CHECK(PlcDeviceWriteSfd(962U, 50) == PLC_DEVICE_OK);
  101. CHECK(PlcDeviceWriteSfd(963U, 20) == PLC_DEVICE_OK);
  102. CHECK(PlcDeviceWriteSfd(964U, 0) == PLC_DEVICE_OK);
  103. TestWriteSfdDword(966U, 2000UL);
  104. TestWriteSfdDword(968U, 200UL);
  105. }
  106. static void TestBuildValidBlocks(TEST_MEMORY *memory)
  107. {
  108. (void)memset(memory, 0, sizeof(*memory));
  109. TestWriteDword(memory, PLSR_DEVICE_D, 100U, 2);
  110. TestWriteDword(memory, PLSR_DEVICE_D, 110U, 150000);
  111. TestWriteDword(memory, PLSR_DEVICE_D, 112U, 100);
  112. memory->words[PLSR_DEVICE_D][114U] = 0U;
  113. TestWriteDword(memory, PLSR_DEVICE_D, 115U, 0);
  114. memory->words[PLSR_DEVICE_D][117U] = 0U;
  115. TestWriteDword(memory, PLSR_DEVICE_D, 118U, 0);
  116. TestWriteDword(memory, PLSR_DEVICE_D, 120U, 0);
  117. TestWriteDword(memory, PLSR_DEVICE_D, 122U, -50);
  118. memory->words[PLSR_DEVICE_D][124U] = 0x0100U;
  119. TestWriteDword(memory, PLSR_DEVICE_D, 125U, 0);
  120. memory->words[PLSR_DEVICE_D][127U] = 0U;
  121. TestWriteDword(memory, PLSR_DEVICE_D, 128U, 2);
  122. TestWriteDword(memory, PLSR_DEVICE_D, 200U, 0);
  123. TestWriteDword(memory, PLSR_DEVICE_D, 202U, 0);
  124. TestWriteDword(memory, PLSR_DEVICE_HD, 10U, 1);
  125. }
  126. static PLSR_CALL TestMakeCall(TEST_MEMORY *memory)
  127. {
  128. PLSR_CALL call;
  129. (void)memset(&call, 0, sizeof(call));
  130. call.sequence = 77UL;
  131. call.source.context = memory;
  132. call.source.validateWords = TestValidateWords;
  133. call.source.readWord = TestReadWord;
  134. call.source.readBit = TestReadBit;
  135. call.s0.device = PLSR_DEVICE_D;
  136. call.s0.address = 100UL;
  137. call.s1.device = PLSR_DEVICE_D;
  138. call.s1.address = 200UL;
  139. call.s2.type = PLSR_OPERAND_CONSTANT;
  140. call.s2.constant = 1;
  141. call.dAxis = 0U;
  142. call.outputModeOverride = PLSR_OUTPUT_MODE_FROM_SFD;
  143. return call;
  144. }
  145. static void TestValidSnapshotAndLiveFrequency(void)
  146. {
  147. TEST_MEMORY memory;
  148. PLSR_CALL call;
  149. PLSR_PARSE_CONTEXT context;
  150. PLSR_JOB_SNAPSHOT snapshot;
  151. PLSR_PARSE_DETAIL detail;
  152. uint32_t frequency;
  153. uint8_t clamped;
  154. TestBuildValidBlocks(&memory);
  155. call = TestMakeCall(&memory);
  156. context.logicalPosition = 0;
  157. context.positionValid = 0U;
  158. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  159. == PLSR_RESULT_OK);
  160. CHECK(detail.result == PLSR_RESULT_OK);
  161. CHECK(snapshot.segmentCount == 2U);
  162. CHECK(snapshot.startSegment == 1U);
  163. CHECK(snapshot.s2Set == 1U);
  164. CHECK(snapshot.outputMode == PLSR_OUTPUT_PULSE_DIR);
  165. CHECK(snapshot.directionPoint == 4U);
  166. CHECK(snapshot.s2.defaultSpeed == 1000UL);
  167. CHECK(snapshot.s2.maximumSpeed == 100000UL);
  168. CHECK(snapshot.s2.startSpeed == 100000UL);
  169. CHECK(snapshot.speedClamped == 1U);
  170. CHECK(snapshot.segments[0].targetFrequency == 100000UL);
  171. CHECK((snapshot.segments[0].flags & PLSR_SEGMENT_FLAG_SPEED_CLAMPED)
  172. != 0U);
  173. CHECK(snapshot.segments[1].targetFrequency == 1000UL);
  174. CHECK((snapshot.segments[1].flags & PLSR_SEGMENT_FLAG_DEFAULT_SPEED)
  175. != 0U);
  176. CHECK((snapshot.segments[1].flags & PLSR_SEGMENT_FLAG_SELF_LOOP) != 0U);
  177. CHECK(snapshot.hasSelfLoop == 1U);
  178. CHECK(snapshot.initialDirectionPositive == 1U);
  179. TestWriteDword(&memory, PLSR_DEVICE_D, 112U, 9999);
  180. CHECK(snapshot.segments[0].pulseOrTarget == 100);
  181. TestWriteDword(&memory, PLSR_DEVICE_D, 110U, 2500);
  182. CHECK(PlsrResolveLiveFrequency(&snapshot, 1U, &frequency, &clamped)
  183. == PLSR_RESULT_OK);
  184. CHECK(frequency == 2500UL);
  185. CHECK(clamped == 0U);
  186. TestWriteDword(&memory, PLSR_DEVICE_D, 110U, 200000);
  187. CHECK(PlsrResolveLiveFrequency(&snapshot, 1U, &frequency, &clamped)
  188. == PLSR_RESULT_OK);
  189. CHECK(frequency == 100000UL);
  190. CHECK(clamped == 1U);
  191. call.s2.type = PLSR_OPERAND_DATA;
  192. call.s2.data.device = PLSR_DEVICE_HD;
  193. call.s2.data.address = 10UL;
  194. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  195. == PLSR_RESULT_OK);
  196. CHECK(snapshot.s2Set == 1U);
  197. }
  198. static void TestValidationFailures(void)
  199. {
  200. TEST_MEMORY memory;
  201. PLSR_CALL call;
  202. PLSR_PARSE_CONTEXT context = {0, 0U};
  203. PLSR_JOB_SNAPSHOT snapshot;
  204. PLSR_PARSE_DETAIL detail;
  205. TestBuildValidBlocks(&memory);
  206. call = TestMakeCall(&memory);
  207. call.s1.address = 120UL;
  208. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  209. == PLSR_RESULT_BLOCK_OVERLAP);
  210. TestBuildValidBlocks(&memory);
  211. call = TestMakeCall(&memory);
  212. memory.words[PLSR_DEVICE_D][103U] = 1U;
  213. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  214. == PLSR_RESULT_RESERVED_NOT_ZERO);
  215. CHECK(detail.address == 103UL);
  216. TestBuildValidBlocks(&memory);
  217. call = TestMakeCall(&memory);
  218. TestWriteDword(&memory, PLSR_DEVICE_D, 100U, 101);
  219. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  220. == PLSR_RESULT_SEGMENT_OVERFLOW);
  221. TestBuildValidBlocks(&memory);
  222. call = TestMakeCall(&memory);
  223. TestWriteDword(&memory, PLSR_DEVICE_D, 110U, -1);
  224. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  225. == PLSR_RESULT_INVALID_FREQUENCY);
  226. CHECK(detail.segment == 1U);
  227. TestBuildValidBlocks(&memory);
  228. call = TestMakeCall(&memory);
  229. memory.words[PLSR_DEVICE_D][124U] = 0x0405U;
  230. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  231. == PLSR_RESULT_INVALID_WAIT);
  232. TestBuildValidBlocks(&memory);
  233. call = TestMakeCall(&memory);
  234. TestWriteDword(&memory, PLSR_DEVICE_D, 128U, 3);
  235. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  236. == PLSR_RESULT_INVALID_JUMP);
  237. TestBuildValidBlocks(&memory);
  238. call = TestMakeCall(&memory);
  239. TestWriteDword(&memory, PLSR_DEVICE_D, 118U, 2);
  240. TestWriteDword(&memory, PLSR_DEVICE_D, 128U, 1);
  241. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  242. == PLSR_RESULT_PATH_CYCLE);
  243. TestBuildValidBlocks(&memory);
  244. call = TestMakeCall(&memory);
  245. TestWriteDword(&memory, PLSR_DEVICE_D, 200U, 1);
  246. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  247. == PLSR_RESULT_POSITION_INVALID);
  248. TestBuildValidBlocks(&memory);
  249. call = TestMakeCall(&memory);
  250. call.s0.address = UINT32_MAX - 5UL;
  251. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  252. == PLSR_RESULT_ADDRESS_OVERFLOW);
  253. TestBuildValidBlocks(&memory);
  254. call = TestMakeCall(&memory);
  255. call.s2.constant = 5;
  256. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  257. == PLSR_RESULT_INVALID_S2);
  258. TestBuildValidBlocks(&memory);
  259. call = TestMakeCall(&memory);
  260. CHECK(PlcDeviceWriteSfd(962U, 356) == PLC_DEVICE_OK);
  261. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  262. == PLSR_RESULT_INVALID_S2);
  263. CHECK(PlcDeviceWriteSfd(962U, 50) == PLC_DEVICE_OK);
  264. CHECK(PlcDeviceWriteSfd(964U, 1) == PLC_DEVICE_OK);
  265. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  266. == PLSR_RESULT_INVALID_S2);
  267. CHECK(PlcDeviceWriteSfd(964U, 0) == PLC_DEVICE_OK);
  268. }
  269. static void TestDynamicReferences(void)
  270. {
  271. TEST_MEMORY memory;
  272. PLSR_CALL call;
  273. PLSR_PARSE_CONTEXT context = {0, 0U};
  274. PLSR_JOB_SNAPSHOT snapshot;
  275. PLSR_PARSE_DETAIL detail;
  276. TestBuildValidBlocks(&memory);
  277. call = TestMakeCall(&memory);
  278. memory.words[PLSR_DEVICE_D][124U] = 0x0101U;
  279. TestWriteDword(&memory, PLSR_DEVICE_D, 125U, 300);
  280. TestWriteDword(&memory, PLSR_DEVICE_D, 300U, 25);
  281. memory.words[PLSR_DEVICE_D][127U] = 1U;
  282. TestWriteDword(&memory, PLSR_DEVICE_D, 128U, 302);
  283. TestWriteDword(&memory, PLSR_DEVICE_D, 302U, 2);
  284. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  285. == PLSR_RESULT_OK);
  286. CHECK(snapshot.segments[1].waitSource == PLSR_VALUE_D);
  287. CHECK(snapshot.segments[1].waitValueOrAddress == 300);
  288. CHECK(snapshot.segments[1].jumpSource == PLSR_VALUE_D);
  289. CHECK(snapshot.segments[1].jumpValueOrAddress == 302);
  290. memory.words[PLSR_DEVICE_D][124U] = 0x0404U;
  291. TestWriteDword(&memory, PLSR_DEVICE_D, 125U, 7);
  292. memory.bits[0][7U] = 1U;
  293. memory.words[PLSR_DEVICE_D][127U] = 0U;
  294. TestWriteDword(&memory, PLSR_DEVICE_D, 128U, 2);
  295. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  296. == PLSR_RESULT_OK);
  297. }
  298. static void TestOutputAndDivider(void)
  299. {
  300. TEST_MEMORY memory;
  301. PLSR_CALL call;
  302. PLSR_PARSE_CONTEXT context = {0, 0U};
  303. PLSR_JOB_SNAPSHOT snapshot;
  304. PLSR_PARSE_DETAIL detail;
  305. uint16_t psc;
  306. uint16_t arr;
  307. TestBuildValidBlocks(&memory);
  308. call = TestMakeCall(&memory);
  309. CHECK(PlcDeviceWriteSfd(900U, (1U << 13U)) == PLC_DEVICE_OK);
  310. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  311. == PLSR_RESULT_OK);
  312. CHECK(snapshot.outputMode == PLSR_OUTPUT_AB);
  313. CHECK(snapshot.pairedTimerClockHz == 84000000UL);
  314. CHECK(PlsrCalculateTimerDivider(168000000UL, 1UL, &psc, &arr)
  315. == PLSR_RESULT_OK);
  316. CHECK(PlsrCalculateTimerDivider(84000000UL, 100000UL, &psc, &arr)
  317. == PLSR_RESULT_OK);
  318. CHECK(PlsrCalculateTimerDivider(84000000UL, 0UL, &psc, &arr)
  319. == PLSR_RESULT_INVALID_ARGUMENT);
  320. CHECK(PlsrCalculateTimerDivider(1UL, 100000UL, &psc, &arr)
  321. == PLSR_RESULT_DIVIDER_UNREPRESENTABLE);
  322. CHECK(PlcDeviceWriteSfd(900U, 0) == PLC_DEVICE_OK);
  323. }
  324. static void TestEquivalentSnapshot(void)
  325. {
  326. TEST_MEMORY memory;
  327. PLSR_CALL call;
  328. PLSR_PARSE_CONTEXT context = {0, 1U};
  329. PLSR_JOB_SNAPSHOT snapshot;
  330. PLSR_PARSE_DETAIL detail;
  331. uint32_t liveFrequency;
  332. uint8_t clamped;
  333. TestBuildValidBlocks(&memory);
  334. TestWriteDword(&memory, PLSR_DEVICE_D, 110U, 40000);
  335. call = TestMakeCall(&memory);
  336. CHECK(PlcDeviceWriteSfd(900U, (1U << 8U)) == PLC_DEVICE_OK);
  337. TestWriteSfdDword(902U, 3UL);
  338. TestWriteSfdDword(904U, 2UL);
  339. TestWriteSfdDword(956U, 60000UL);
  340. TestWriteSfdDword(958U, 0UL);
  341. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  342. == PLSR_RESULT_OK);
  343. CHECK(snapshot.equivalent.unitCode == 1U);
  344. CHECK(snapshot.equivalent.pulsesPerRevolution == 3UL);
  345. CHECK(snapshot.equivalent.movementPerRevolution == 2UL);
  346. CHECK(snapshot.inputDefaultSpeed == 1000UL);
  347. CHECK(snapshot.inputMaximumSpeed == 60000UL);
  348. CHECK(snapshot.s2.defaultSpeed == 1500UL);
  349. CHECK(snapshot.s2.maximumSpeed == 90000UL);
  350. CHECK(snapshot.segments[0].targetFrequency == 60000UL);
  351. CHECK(snapshot.segments[1].targetFrequency == 1500UL);
  352. TestWriteDword(&memory, PLSR_DEVICE_D, 110U, 20000);
  353. CHECK(PlsrResolveLiveFrequency(&snapshot,
  354. 1U,
  355. &liveFrequency,
  356. &clamped) == PLSR_RESULT_OK);
  357. CHECK(liveFrequency == 30000UL);
  358. CHECK(clamped == 0U);
  359. TestWriteSfdDword(902U, 0UL);
  360. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  361. == PLSR_RESULT_INVALID_S2);
  362. CHECK(detail.address == 902U);
  363. TestConfigureAxis0K1();
  364. }
  365. static void TestLimitSnapshot(void)
  366. {
  367. TEST_MEMORY memory;
  368. PLSR_CALL call;
  369. PLSR_PARSE_CONTEXT context = {0, 1U};
  370. PLSR_JOB_SNAPSHOT snapshot;
  371. PLSR_PARSE_DETAIL detail;
  372. TestBuildValidBlocks(&memory);
  373. call = TestMakeCall(&memory);
  374. CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK);
  375. CHECK(PlcDeviceWriteSfd(912U, (1U << 2U) | (1U << 3U))
  376. == PLC_DEVICE_OK);
  377. CHECK(PlcDeviceWriteSfd(915U, 0x0703U) == PLC_DEVICE_OK);
  378. TestWriteSfdDword(930U, 100UL);
  379. TestWriteSfdDword(932U, (uint32_t)(int32_t)-100);
  380. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  381. == PLSR_RESULT_OK);
  382. CHECK(snapshot.limits.softLimitEnabled == 1U);
  383. CHECK(snapshot.limits.positiveSoftLimitPulses == 100);
  384. CHECK(snapshot.limits.negativeSoftLimitPulses == -100);
  385. CHECK(snapshot.limits.positiveInputPoint == 3U);
  386. CHECK(snapshot.limits.negativeInputPoint == 7U);
  387. CHECK(snapshot.limits.positiveInputActiveLow == 1U);
  388. CHECK(snapshot.limits.negativeInputActiveLow == 1U);
  389. TestWriteSfdDword(930U, (uint32_t)(int32_t)-100);
  390. TestWriteSfdDword(932U, 100UL);
  391. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  392. == PLSR_RESULT_INVALID_S2);
  393. CHECK(detail.address == 930U);
  394. TestConfigureAxis0K1();
  395. CHECK(PlcDeviceWriteSfd(912U, 0U) == PLC_DEVICE_OK);
  396. CHECK(PlcDeviceWriteSfd(915U, 0xFFFFU) == PLC_DEVICE_OK);
  397. TestWriteSfdDword(930U, 0UL);
  398. TestWriteSfdDword(932U, 0UL);
  399. }
  400. static void TestCompatibleParseErrors(void)
  401. {
  402. TEST_MEMORY memory;
  403. PLSR_CALL call;
  404. int32_t code;
  405. int32_t block;
  406. PlsrPersistenceTestResetStorage();
  407. CHECK(PlcDeviceInit() == PLC_DEVICE_OK);
  408. TestConfigureAxis0K1();
  409. CHECK(PlsrInit() == PLSR_RESULT_OK);
  410. TestBuildValidBlocks(&memory);
  411. call = TestMakeCall(&memory);
  412. TestWriteDword(&memory, PLSR_DEVICE_D, 110U, -1);
  413. call.sequence = 700UL;
  414. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  415. PlsrProcess();
  416. CHECK(PlcDeviceReadSd(1010U, &code) == PLC_DEVICE_OK);
  417. CHECK(PlcDeviceReadSd(1011U, &block) == PLC_DEVICE_OK);
  418. CHECK(code == 1);
  419. CHECK(block == 1);
  420. TestWriteDword(&memory, PLSR_DEVICE_D, 110U, 1000);
  421. call.s2.constant = 5;
  422. call.sequence = 701UL;
  423. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  424. PlsrProcess();
  425. CHECK(PlcDeviceReadSd(1010U, &code) == PLC_DEVICE_OK);
  426. CHECK(code == 3);
  427. call.s2.constant = 1;
  428. CHECK(PlcDeviceWriteSfd(962U, 0U) == PLC_DEVICE_OK);
  429. call.sequence = 702UL;
  430. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  431. PlsrProcess();
  432. CHECK(PlcDeviceReadSd(1010U, &code) == PLC_DEVICE_OK);
  433. CHECK(code == 15);
  434. CHECK(PlcDeviceWriteSfd(962U, 50U) == PLC_DEVICE_OK);
  435. CHECK(PlcDeviceWriteSfd(963U, 101U) == PLC_DEVICE_OK);
  436. call.sequence = 703UL;
  437. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  438. PlsrProcess();
  439. CHECK(PlcDeviceReadSd(1010U, &code) == PLC_DEVICE_OK);
  440. CHECK(code == 16);
  441. CHECK(PlcDeviceWriteSfd(963U, 0U) == PLC_DEVICE_OK);
  442. CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK);
  443. TestWriteSfdDword(930U, 0UL);
  444. TestWriteSfdDword(932U, 0UL);
  445. call.sequence = 704UL;
  446. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  447. PlsrProcess();
  448. CHECK(PlcDeviceReadSd(1010U, &code) == PLC_DEVICE_OK);
  449. CHECK(code == 4);
  450. CHECK(PlcDeviceWriteSfd(900U, 0U) == PLC_DEVICE_OK);
  451. CHECK(PlcDeviceWriteSfd(906U, 0xFFU) == PLC_DEVICE_OK);
  452. call.sequence = 705UL;
  453. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  454. PlsrProcess();
  455. CHECK(PlcDeviceReadSd(1010U, &code) == PLC_DEVICE_OK);
  456. CHECK(code == 26);
  457. TestConfigureAxis0K1();
  458. }
  459. static void TestCoreSubmission(void)
  460. {
  461. TEST_MEMORY memory;
  462. PLSR_CALL call;
  463. PLSR_STATUS status;
  464. PLSR_PARSE_DETAIL detail;
  465. TestBuildValidBlocks(&memory);
  466. call = TestMakeCall(&memory);
  467. call.sequence = 500UL;
  468. CHECK(PlsrInit() == PLSR_RESULT_OK);
  469. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  470. PlsrProcess();
  471. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  472. CHECK(status.lastCommandResult == PLSR_RESULT_OK);
  473. CHECK(status.state == PLSR_STATE_ACCEL);
  474. CHECK(status.jobValid == 1U);
  475. CHECK(status.segmentCount == 2U);
  476. CHECK(status.startSegment == 1U);
  477. CHECK(status.s2Set == 1U);
  478. CHECK(status.speedClamped == 1U);
  479. CHECK(PlsrGetLastParseDetail(0U, &detail) == PLSR_RESULT_OK);
  480. CHECK(detail.result == PLSR_RESULT_OK);
  481. }
  482. static void TestDefaultSfdStartable(void)
  483. {
  484. TEST_MEMORY memory;
  485. PLSR_CALL call;
  486. PLSR_STATUS status;
  487. /* 全新 Flash:默认 S2 参数(FOLLOW=50、最大速度=100000 等)应可直接启动。 */
  488. PlsrPersistenceTestResetStorage();
  489. CHECK(PlcDeviceInit() == PLC_DEVICE_OK);
  490. CHECK(PlcDeviceGetLastSfdLoadResult() == PLSR_PERSISTENCE_DEFAULTED);
  491. TestBuildValidBlocks(&memory);
  492. call = TestMakeCall(&memory);
  493. call.sequence = 600UL;
  494. /* 方向端子是接线参数,未配置(0xFF)时 PULSE/DIR 应报资源错误。 */
  495. CHECK(PlsrInit() == PLSR_RESULT_OK);
  496. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  497. PlsrProcess();
  498. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  499. CHECK(status.lastCommandResult == PLSR_RESULT_INVALID_RESOURCE);
  500. CHECK(status.state == PLSR_STATE_IDLE);
  501. /* 用户配置方向端子后,其余出厂默认参数应能直接启动。 */
  502. CHECK(PlcDeviceWriteSfd(906U, 4) == PLC_DEVICE_OK);
  503. call.sequence = 601UL;
  504. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  505. PlsrProcess();
  506. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  507. CHECK(status.lastCommandResult == PLSR_RESULT_OK);
  508. CHECK(status.state == PLSR_STATE_ACCEL);
  509. CHECK(status.jobValid == 1U);
  510. CHECK(status.s2Set == 1U);
  511. CHECK(status.speedClamped == 1U);
  512. CHECK(status.directionPoint == 4U);
  513. /* 回到 IDLE,避免资源泄漏影响后续。 */
  514. CHECK(PlsrPostCommand(&(PLSR_COMMAND){602U, 0U, PLSR_CMD_STOP_IMMEDIATE, 0})
  515. == PLSR_RESULT_QUEUED);
  516. PlsrProcess();
  517. CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
  518. == PLSR_RESULT_OK);
  519. PlsrProcess();
  520. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  521. CHECK(status.state == PLSR_STATE_STOPPED);
  522. }
  523. int main(void)
  524. {
  525. PlsrPersistenceTestResetStorage();
  526. CHECK(PlcDeviceInit() == PLC_DEVICE_OK);
  527. TestConfigureAxis0K1();
  528. TestValidSnapshotAndLiveFrequency();
  529. TestValidationFailures();
  530. TestDynamicReferences();
  531. TestOutputAndDivider();
  532. TestEquivalentSnapshot();
  533. TestLimitSnapshot();
  534. TestCompatibleParseErrors();
  535. TestDefaultSfdStartable();
  536. TestCoreSubmission();
  537. if (TestFailures != 0)
  538. {
  539. (void)printf("FAIL: %d of %d PLSR job checks failed\n",
  540. TestFailures,
  541. TestChecks);
  542. return 1;
  543. }
  544. (void)printf("PASS: %d PLSR job checks\n", TestChecks);
  545. return 0;
  546. }